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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.615   ! raeburn     4: # $Id: lonparmset.pm,v 1.614 2022/05/31 14:16:29 raeburn Exp $
1.40      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.59      matthew    28: ###################################################################
                     29: ###################################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: lonparmset - Handler to set parameters for assessments and course
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
1.579     raeburn    39: lonparmset provides an interface to setting content parameters in a 
                     40: course.
1.560     damieng    41: 
                     42: It contains all the code for the "Content and Problem Settings" UI, except
                     43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
                     44: and lonblockingmenu.pm.
1.59      matthew    45: 
                     46: =head1 DESCRIPTION
                     47: 
                     48: This module sets coursewide and assessment parameters.
                     49: 
                     50: =head1 INTERNAL SUBROUTINES
                     51: 
1.416     jms        52: =over
1.59      matthew    53: 
1.416     jms        54: =item parmval()
1.59      matthew    55: 
                     56: Figure out a cascading parameter.
                     57: 
1.71      albertel   58: Inputs:  $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162     albertel   59:          $id   - a bighash Id number
1.71      albertel   60:          $def  - the resource's default value   'stupid emacs
                     61: 
1.556     raeburn    62: Returns:  A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71      albertel   63: 
1.556     raeburn    64: 18 - General Course
                     65: 17 - Map or Folder level in course (recursive) 
                     66: 16 - Map or Folder level in course (non-recursive)
                     67: 15 - resource default
                     68: 14 - map default
                     69: 13 - resource level in course
                     70: 12 - General for section
                     71: 11 - Map or Folder level for section (recursive)
                     72: 10 - Map or Folder level for section (non-recursive)
                     73: 9 - resource level in section
                     74: 8 - General for group
                     75: 7 - Map or Folder level for group (recursive)
                     76: 6 - Map or Folder level for group (non-recursive)
                     77: 5 - resource level in group
                     78: 4 - General for specific student
                     79: 3 - Map or Folder level for specific student (recursive)
                     80: 2 - Map or Folder level for specific student (non-recursive)
1.71      albertel   81: 1 - resource level for specific student
1.2       www        82: 
1.416     jms        83: =item parmval_by_symb()
                     84: 
                     85: =item reset_caches()
                     86: 
                     87: =item cacheparmhash() 
                     88: 
                     89: =item parmhash()
                     90: 
                     91: =item symbcache()
                     92: 
                     93: =item preset_defaults()
                     94: 
                     95: =item date_sanity_info()
                     96: 
                     97: =item storeparm()
                     98: 
                     99: Store a parameter by symb
                    100: 
                    101:     Takes
                    102:     - symb
                    103:     - name of parameter
                    104:     - level
                    105:     - new value
                    106:     - new type
                    107:     - username
                    108:     - userdomain
                    109: 
                    110: =item log_parmset()
                    111: 
                    112: =item storeparm_by_symb_inner()
                    113: 
                    114: =item valout()
                    115: 
                    116: Format a value for output.
                    117: 
                    118: Inputs:  $value, $type, $editable
                    119: 
                    120: Returns: $value, formatted for output.  If $type indicates it is a date,
                    121: localtime($value) is returned.
                    122: $editable will return an icon to click on
                    123: 
                    124: =item plink()
                    125: 
                    126: Produces a link anchor.
                    127: 
                    128: Inputs: $type,$dis,$value,$marker,$return,$call
                    129: 
                    130: Returns: scalar with html code for a link which will envoke the 
                    131: javascript function 'pjump'.
                    132: 
                    133: =item page_js()
                    134: 
                    135: =item startpage()
                    136: 
                    137: =item print_row()
                    138: 
                    139: =item print_td()
                    140: 
1.580     raeburn   141: =item check_other_groups()
1.416     jms       142: 
                    143: =item parm_control_group()
                    144: 
                    145: =item extractResourceInformation() : 
                    146: 
1.512     foxr      147:  extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416     jms       148: 
1.542     raeburn   149: Input: See list below
                    150: 
                    151: =over 4
1.416     jms       152: 
1.512     foxr      153: =item * B<env{'user.name'}> : Current username
1.416     jms       154: 
1.512     foxr      155: =item * B<env{'user.domain'}> : Domain of current user.
1.416     jms       156: 
1.542     raeburn   157: =item * B<env{"request.course.fn"}> : Course
                    158: 
                    159: =back
1.416     jms       160: 
1.512     foxr      161: Outputs: See list below:
1.416     jms       162: 
1.542     raeburn   163: =over 4
                    164: 
1.512     foxr      165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416     jms       166: 
1.512     foxr      167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416     jms       168: 
1.512     foxr      169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416     jms       170: 
1.512     foxr      171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416     jms       172: 
1.512     foxr      173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
                    174: 
                    175: =item * B<allmaps> (out) : hash, ???
1.416     jms       176: 
                    177: =item * B<mapp> : ??
                    178: 
                    179: =item * B<symbp> : hash, id->full sym?
                    180: 
1.512     foxr      181: =item * B<maptitles>
                    182: 
                    183: =item * B<uris>
1.416     jms       184: 
1.512     foxr      185: =item * B<keyorder>
                    186: 
                    187: =item * B<defkeytype>
1.416     jms       188: 
1.542     raeburn   189: =back
                    190: 
1.416     jms       191: =item isdateparm()
                    192: 
                    193: =item parmmenu()
                    194: 
                    195: =item partmenu()
                    196: 
                    197: =item usermenu()
                    198: 
                    199: =item displaymenu()
                    200: 
                    201: =item mapmenu()
                    202: 
                    203: =item levelmenu()
                    204: 
                    205: =item sectionmenu()
                    206: 
                    207: =item keysplit()
                    208: 
                    209: =item keysinorder()
                    210: 
                    211: =item keysinorder_bytype()
                    212: 
                    213: =item keysindisplayorder()
                    214: 
                    215: =item standardkeyorder()
                    216: 
                    217: =item assessparms() : 
                    218: 
                    219: Show assessment data and parameters.  This is a large routine that should
                    220: be simplified and shortened... someday.
                    221: 
1.513     foxr      222: Inputs: $r - the Apache request object.
                    223:   
1.416     jms       224: Returns: nothing
                    225: 
                    226: Variables used (guessed by Jeremy):
                    227: 
1.542     raeburn   228: =over
                    229: 
1.416     jms       230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
                    231: 
                    232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
                    233: 
                    234: =item * B<@catmarker> contains list of all possible parameters including part #s
                    235: 
                    236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
                    237: 
                    238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
                    239:         When storing information, store as part 0
                    240:         When requesting information, request from full part
                    241: 
1.542     raeburn   242: =back
                    243: 
1.416     jms       244: =item tablestart()
                    245: 
                    246: =item tableend()
                    247: 
                    248: =item extractuser()
                    249: 
                    250: =item parse_listdata_key()
                    251: 
                    252: =item listdata()
                    253: 
                    254: =item date_interval_selector()
                    255: 
                    256: =item get_date_interval_from_form()
                    257: 
                    258: =item default_selector()
                    259: 
                    260: =item string_selector()
                    261: 
                    262: =item dateshift()
                    263: 
                    264: =item newoverview()
                    265: 
                    266: =item secgroup_lister()
                    267: 
                    268: =item overview()
                    269: 
                    270: =item clean_parameters()
                    271: 
                    272: =item date_shift_one()
                    273: 
                    274: =item date_shift_two()
                    275: 
                    276: =item parse_key()
                    277: 
                    278: =item header()
                    279: 
                    280: Output html header for page
                    281: 
                    282: =item print_main_menu()
                    283: 
                    284: =item output_row()
                    285: 
                    286: Set portfolio metadata
                    287: 
                    288: =item order_meta_fields()
                    289: 
                    290: =item addmetafield()
                    291: 
                    292: =item setrestrictmeta()
                    293: 
                    294: =item get_added_meta_fieldnames()
                    295: 
                    296: =item get_deleted_meta_fieldnames()
                    297: 
                    298: =item defaultsetter()
                    299: 
                    300: =item components()
                    301: 
                    302: =item load_parameter_names()
                    303: 
                    304: =item parm_change_log()
                    305: 
                    306: =item handler() : 
                    307: 
1.450     raeburn   308: Main handler.  Calls &assessparms subroutine.
1.416     jms       309: 
                    310: =back
                    311: 
1.59      matthew   312: =cut
                    313: 
1.416     jms       314: ###################################################################
                    315: ###################################################################
                    316: 
                    317: package Apache::lonparmset;
                    318: 
                    319: use strict;
                    320: use Apache::lonnet;
                    321: use Apache::Constants qw(:common :http REDIRECT);
                    322: use Apache::lonhtmlcommon();
                    323: use Apache::loncommon;
                    324: use GDBM_File;
                    325: use Apache::lonhomework;
                    326: use Apache::lonxml;
                    327: use Apache::lonlocal;
                    328: use Apache::lonnavmaps;
                    329: use Apache::longroup;
                    330: use Apache::lonrss;
1.506     www       331: use HTML::Entities;
1.416     jms       332: use LONCAPA qw(:DEFAULT :match);
                    333: 
                    334: 
1.560     damieng   335: ##################################################
                    336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    337: ##################################################
                    338: 
                    339: # Page header
1.561     damieng   340: #
                    341: # @param {Apache2::RequestRec} $r - Apache request object
                    342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    343: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       344: sub startSettingsScreen {
1.531     raeburn   345:     my ($r,$mode,$crstype)=@_;
1.507     www       346: 
1.531     raeburn   347:     my $tabtext = &mt('Course Settings');
                    348:     if ($crstype eq 'Community') {
                    349:         $tabtext = &mt('Community Settings');
                    350:     } 
1.507     www       351:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    352:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   353:                                           $tabtext.
1.507     www       354:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    355: 
1.523     raeburn   356:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       357:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    358:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   359:     $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507     www       360: }
                    361: 
1.560     damieng   362: # Page footer
1.507     www       363: sub endSettingsScreen {
                    364:    my ($r)=@_;
                    365:    $r->print('</div></div></div>');
                    366: }
                    367: 
                    368: 
                    369: 
1.560     damieng   370: ##################################################
1.563     damieng   371: # (mostly) TABLE MODE
1.560     damieng   372: # (parmval is also used for the log of parameter changes)
                    373: ##################################################
                    374: 
1.566     damieng   375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   376: #
                    377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   378: # @param {string} $id - resource id or map pc
1.561     damieng   379: # @param {string} $def - the resource's default value for this parameter
                    380: # @param {string} $uname - user name
                    381: # @param {string} $udom - user domain
                    382: # @param {string} $csec - section name
                    383: # @param {string} $cgroup - group name
                    384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    385: # @returns {Array}
1.2       www       386: sub parmval {
1.275     raeburn   387:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    388:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    389:                                                            $cgroup,$courseopt);
1.201     www       390: }
                    391: 
1.561     damieng   392: # Returns an array containing
                    393: # - the most specific level that is defined for that parameter (integer)
                    394: # - an array with the level as index and the parameter value as value (when defined)
                    395: #   (level 1 is the most specific and will have precedence)
                    396: #
                    397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   398: # @param {string} $symb - resource symb or map src
1.561     damieng   399: # @param {string} $def - the resource's default value for this parameter
                    400: # @param {string} $uname - user name
                    401: # @param {string} $udom - user domain
                    402: # @param {string} $csec - section name
                    403: # @param {string} $cgroup - group name
                    404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    405: # @returns {Array}
1.201     www       406: sub parmval_by_symb {
1.275     raeburn   407:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       408: 
1.352     albertel  409:     my $useropt;
                    410:     if ($uname ne '' && $udom ne '') {
1.561     damieng   411:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  412:     }
1.200     www       413: 
1.8       www       414:     my $result='';
1.44      albertel  415:     my @outpar=();
1.2       www       416: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    417:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  418:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   419:     
                    420:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    421:     # any change should be reflected there.
                    422:     
1.201     www       423:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   424:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       425:     my $mapparm=$map.'___(all).'.$what;
1.10      www       426: 
1.269     raeburn   427:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    428:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   429:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   430:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    431: 
1.190     albertel  432:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    433:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   434:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  435:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    436: 
                    437:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    438:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   439:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  440:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       441: 
1.11      www       442: 
1.182     albertel  443: # --------------------------------------------------------- first, check course
1.11      www       444: 
1.561     damieng   445: # 18 - General Course
1.200     www       446:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   447:         $outpar[18]=$$courseopt{$courselevel};
                    448:         $result=18;
                    449:     }
                    450: 
1.561     damieng   451: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   452:     if (defined($$courseopt{$courseleveli})) {
                    453:         $outpar[17]=$$courseopt{$courseleveli};
                    454:         $result=17;
1.43      albertel  455:     }
1.11      www       456: 
1.561     damieng   457: # 16 - Map or Folder level in course (non-recursive)
1.200     www       458:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   459:         $outpar[16]=$$courseopt{$courselevelm};
                    460:         $result=16;
1.43      albertel  461:     }
1.11      www       462: 
1.182     albertel  463: # ------------------------------------------------------- second, check default
                    464: 
1.561     damieng   465: # 15 - resource default
1.556     raeburn   466:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  467: 
                    468: # ------------------------------------------------------ third, check map parms
                    469: 
1.556     raeburn   470:     
1.561     damieng   471: # 14 - map default
1.376     albertel  472:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   473:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  474: 
1.561     damieng   475: # 13 - resource level in course
1.200     www       476:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   477:         $outpar[13]=$$courseopt{$courselevelr};
                    478:         $result=13;
1.43      albertel  479:     }
1.11      www       480: 
1.182     albertel  481: # ------------------------------------------------------ fourth, back to course
1.352     albertel  482:     if ($csec ne '') {
1.561     damieng   483: # 12 - General for section
1.200     www       484:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   485:             $outpar[12]=$$courseopt{$seclevel};
                    486:             $result=12;
                    487:         }
1.561     damieng   488: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   489:         if (defined($$courseopt{$secleveli})) {
                    490:             $outpar[11]=$$courseopt{$secleveli};
                    491:             $result=11;
                    492:         }
1.561     damieng   493: # 10 - Map or Folder level for section (non-recursive)
1.200     www       494:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   495:             $outpar[10]=$$courseopt{$seclevelm};
                    496:             $result=10;
                    497:         }
1.561     damieng   498: # 9 - resource level in section
1.200     www       499:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   500:             $outpar[9]=$$courseopt{$seclevelr};
                    501:             $result=9;
                    502:         }
1.43      albertel  503:     }
1.275     raeburn   504: # ------------------------------------------------------ fifth, check course group
1.352     albertel  505:     if ($cgroup ne '') {
1.561     damieng   506: # 8 - General for group
1.269     raeburn   507:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   508:             $outpar[8]=$$courseopt{$grplevel};
                    509:             $result=8;
                    510:         }
1.561     damieng   511: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   512:         if (defined($$courseopt{$grpleveli})) {
                    513:             $outpar[7]=$$courseopt{$grpleveli};
                    514:             $result=7;
1.269     raeburn   515:         }
1.561     damieng   516: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   517:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   518:             $outpar[6]=$$courseopt{$grplevelm};
                    519:             $result=6;
1.269     raeburn   520:         }
1.561     damieng   521: # 5 - resource level in group
1.269     raeburn   522:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   523:             $outpar[5]=$$courseopt{$grplevelr};
                    524:             $result=5;
1.269     raeburn   525:         }
                    526:     }
1.11      www       527: 
1.556     raeburn   528: # ---------------------------------------------------------- sixth, check user
1.11      www       529: 
1.352     albertel  530:     if ($uname ne '') {
1.561     damieng   531: # 4 - General for specific student
                    532:         if (defined($$useropt{$courselevel})) {
                    533:             $outpar[4]=$$useropt{$courselevel};
                    534:             $result=4;
                    535:         }
1.556     raeburn   536: 
1.561     damieng   537: # 3 - Map or Folder level for specific student (recursive)
                    538:         if (defined($$useropt{$courseleveli})) {
                    539:             $outpar[3]=$$useropt{$courseleveli};
                    540:             $result=3;
                    541:         }
1.473     amueller  542: 
1.561     damieng   543: # 2 - Map or Folder level for specific student (non-recursive)
                    544:         if (defined($$useropt{$courselevelm})) {
                    545:             $outpar[2]=$$useropt{$courselevelm};
                    546:             $result=2;
                    547:         }
1.473     amueller  548: 
1.561     damieng   549: # 1 - resource level for specific student
                    550:         if (defined($$useropt{$courselevelr})) {
                    551:             $outpar[1]=$$useropt{$courselevelr};
                    552:             $result=1;
                    553:         }
1.43      albertel  554:     }
1.44      albertel  555:     return ($result,@outpar);
1.2       www       556: }
                    557: 
1.198     www       558: 
                    559: 
1.376     albertel  560: # --- Caches local to lonparmset
                    561: 
1.446     bisitz    562: 
1.561     damieng   563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  564: sub reset_caches {
                    565:     &resetparmhash();
                    566:     &resetsymbcache();
                    567:     &resetrulescache();
1.203     www       568: }
                    569: 
1.561     damieng   570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  572: {
1.561     damieng   573:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    574:     my %parmhash; # the parameter cache
                    575:     # reset map parameter hash
1.376     albertel  576:     sub resetparmhash {
1.560     damieng   577:         undef($parmhashid);
                    578:         undef(%parmhash);
1.376     albertel  579:     }
1.446     bisitz    580: 
1.561     damieng   581:     # dump the _parms.db database into %parmhash
1.376     albertel  582:     sub cacheparmhash {
1.560     damieng   583:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    584:         my %parmhashfile;
                    585:         if (tie(%parmhashfile,'GDBM_File',
                    586:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    587:             %parmhash=%parmhashfile;
                    588:             untie(%parmhashfile);
                    589:             $parmhashid=$env{'request.course.fn'};
                    590:         }
1.201     www       591:     }
1.446     bisitz    592: 
1.561     damieng   593:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  594:     sub parmhash {
1.560     damieng   595:         my ($id) = @_;
                    596:         &cacheparmhash();
                    597:         return $parmhash{$id};
1.376     albertel  598:     }
1.560     damieng   599: }
1.376     albertel  600: 
1.566     damieng   601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    602: {
1.561     damieng   603:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    604:     my %symbs; # hash id->symb
                    605:     # reset the id->symb cache
1.376     albertel  606:     sub resetsymbcache {
1.560     damieng   607:         undef($symbsid);
                    608:         undef(%symbs);
1.376     albertel  609:     }
1.446     bisitz    610: 
1.566     damieng   611:     # returns the resource symb or map src corresponding to a resource id or map pc
                    612:     # (using lonnavmaps and a cache)
1.376     albertel  613:     sub symbcache {
1.560     damieng   614:         my $id=shift;
                    615:         if ($symbsid ne $env{'request.course.id'}) {
                    616:             undef(%symbs);
                    617:         }
                    618:         if (!$symbs{$id}) {
                    619:             my $navmap = Apache::lonnavmaps::navmap->new();
                    620:             if ($id=~/\./) {
                    621:                 my $resource=$navmap->getById($id);
                    622:                 $symbs{$id}=$resource->symb();
                    623:             } else {
                    624:                 my $resource=$navmap->getByMapPc($id);
                    625:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    626:             }
                    627:             $symbsid=$env{'request.course.id'};
1.473     amueller  628:         }
1.560     damieng   629:         return $symbs{$id};
1.473     amueller  630:     }
1.560     damieng   631: }
1.201     www       632: 
1.561     damieng   633: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    634: {
1.561     damieng   635:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    636:     my %rules; # parameter default actions hash
1.376     albertel  637:     sub resetrulescache {
1.560     damieng   638:         undef($rulesid);
                    639:         undef(%rules);
1.376     albertel  640:     }
1.446     bisitz    641: 
1.561     damieng   642:     # returns the value for a given key in the parameter default action hash
1.376     albertel  643:     sub rulescache {
1.560     damieng   644:         my $id=shift;
                    645:         if ($rulesid ne $env{'request.course.id'}
                    646:             && !defined($rules{$id})) {
                    647:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    648:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    649:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    650:             $rulesid=$env{'request.course.id'};
                    651:         }
                    652:         return $rules{$id};
1.221     www       653:     }
                    654: }
                    655: 
1.416     jms       656: 
1.561     damieng   657: # Returns the values of the parameter type default action
                    658: # "default value when manually setting".
                    659: # If none is defined, ('','','','','') is returned.
                    660: #
                    661: # @param {string} $type - parameter type
                    662: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       663: sub preset_defaults {
                    664:     my $type=shift;
                    665:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   666:         # yes, there is something
                    667:         return (&rulescache($type.'_hours'),
                    668:             &rulescache($type.'_min'),
                    669:             &rulescache($type.'_sec'),
                    670:             &rulescache($type.'_value'));
1.229     www       671:     } else {
1.560     damieng   672:         # nothing there or something else
                    673:         return ('','','','','');
1.229     www       674:     }
                    675: }
                    676: 
1.416     jms       677: 
1.561     damieng   678: # Checks that a date is after enrollment start date and before
                    679: # enrollment end date.
                    680: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    681: # This is used by both overview and table modes.
                    682: #
                    683: # @param {integer} $checkdate - the date to check.
                    684: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       685: sub date_sanity_info {
                    686:    my $checkdate=shift;
                    687:    unless ($checkdate) { return ''; }
                    688:    my $result='';
                    689:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    690:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    691:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    692:          $result.='<div class="LC_warning">'
                    693:                  .&mt('After course enrollment end!')
                    694:                  .'</div>';
1.277     www       695:       }
                    696:    }
                    697:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    698:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    699:          $result.='<div class="LC_warning">'
                    700:                  .&mt('Before course enrollment start!')
                    701:                  .'</div>';
1.277     www       702:       }
                    703:    }
1.413     bisitz    704: # Preparation for additional warnings about dates in the past/future.
                    705: # An improved, more context sensitive version is recommended,
                    706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    707: #   if ($checkdate<time) {
                    708: #      $result.='<div class="LC_info">'
                    709: #              .'('.&mt('in the past').')'
                    710: #              .'</div>';
                    711: #      }
                    712: #   if ($checkdate>time) {
                    713: #      $result.='<div class="LC_info">'
                    714: #              .'('.&mt('in the future').')'
                    715: #              .'</div>';
                    716: #      }
1.277     www       717:    return $result;
                    718: }
1.561     damieng   719: 
                    720: 
                    721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       722: #
1.566     damieng   723: # @param {string} $sresid - resource id or map pc
1.565     damieng   724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   725: # @param {integer} $snum - level
                    726: # @param {string} $nval - new value
                    727: # @param {string} $ntype - new type
                    728: # @param {string} $uname - username
                    729: # @param {string} $udom - userdomain
                    730: # @param {string} $csec - section name
                    731: # @param {string} $cgroup - group name
1.186     www       732: sub storeparm {
1.269     raeburn   733:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   734:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       735: }
                    736: 
1.561     damieng   737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    738: 
                    739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    741: #
1.566     damieng   742: # @param {string} $symb - resource symb or map src
1.565     damieng   743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   744: # @param {integer} $snum - level
                    745: # @param {string} $nval - new value
                    746: # @param {string} $ntype - new type
                    747: # @param {string} $uname - username
                    748: # @param {string} $udom - userdomain
                    749: # @param {string} $csec - section name
                    750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    751: # @param {string} $cgroup - group name
1.197     www       752: sub storeparm_by_symb {
1.275     raeburn   753:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       754:     unless ($recflag) {
1.560     damieng   755:         # first time call
                    756:         %recstack=();
                    757:         $recflag=1;
1.226     www       758:     }
1.560     damieng   759:     # store parameter
1.226     www       760:     &storeparm_by_symb_inner
1.473     amueller  761:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   762:     # don't do anything if parameter was reset
1.266     www       763:     unless ($nval) { return; }
1.226     www       764:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   765:     # remember that this was set
1.226     www       766:     $recstack{$parm}=1;
1.560     damieng   767:     # what does this trigger?
1.226     www       768:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   769:         # don't backfire
                    770:         unless ((!$triggered) || ($recstack{$triggered})) {
                    771:             my $action=&rulescache($triggered.'_action');
                    772:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    773:             # set triggered parameter on same level
                    774:             my $newspnam=$prefix.$triggered;
                    775:             my $newvalue='';
                    776:             my $active=1;
                    777:             if ($action=~/^when\_setting/) {
                    778:             # are there restrictions?
                    779:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    780:                     $active=0;
1.565     damieng   781:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   782:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    783:                     }
                    784:                 }
                    785:                 $newvalue=&rulescache($triggered.'_value');
                    786:             } else {
                    787:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    788:                 if ($action=~/^later\_than/) {
                    789:                     $newvalue=$nval+$totalsecs;
                    790:                 } else {
                    791:                     $newvalue=$nval-$totalsecs;
                    792:                 }
                    793:             }
                    794:             if ($active) {
                    795:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    796:                         $uname,$udom,$csec,$recflag,$cgroup);
                    797:             }
                    798:         }
1.226     www       799:     }
                    800:     return '';
                    801: }
                    802: 
1.561     damieng   803: # Adds all given arguments to the course parameter log.
                    804: # @returns {string} - the answer to the lonnet query.
1.293     www       805: sub log_parmset {
1.525     raeburn   806:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       807: }
                    808: 
1.561     damieng   809: # Store a parameter value and type by symb, without using the parameter default actions.
                    810: # Expire related sheets.
                    811: #
1.566     damieng   812: # @param {string} $symb - resource symb or map src
1.561     damieng   813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    814: # @param {integer} $snum - level
                    815: # @param {string} $nval - new value
                    816: # @param {string} $ntype - new type
                    817: # @param {string} $uname - username
                    818: # @param {string} $udom - userdomain
                    819: # @param {string} $csec - section name
                    820: # @param {string} $cgroup - group name
                    821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       822: sub storeparm_by_symb_inner {
1.197     www       823: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   824:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       825: # ---------------------------------------------------------- Construct prefixes
1.186     www       826:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    827:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  828:     $map = &Apache::lonnet::deversion($map);
                    829: 
1.197     www       830:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   831:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       832:     my $mapparm=$map.'___(all).'.$spnam;
                    833: 
1.269     raeburn   834:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    835:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   836:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   837:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    838: 
1.190     albertel  839:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    840:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   841:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  842:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    843: 
1.190     albertel  844:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    845:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   846:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  847:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    848: 
1.186     www       849:     my $storeunder='';
1.578     raeburn   850:     my $possreplace='';
1.556     raeburn   851:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   852:     if (($snum==17) || ($snum==3)) { 
                    853:         $storeunder=$courseleveli;
                    854:         $possreplace=$courselevelm; 
                    855:     } 
                    856:     if (($snum==16) || ($snum==2)) { 
                    857:         $storeunder=$courselevelm;
                    858:         $possreplace=$courseleveli;
                    859:     }
1.556     raeburn   860:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    861:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   862:     if ($snum==11) { 
                    863:         $storeunder=$secleveli;
                    864:         $possreplace=$seclevelm; 
                    865:     }
                    866:     if ($snum==10) { 
                    867:         $storeunder=$seclevelm;
                    868:         $possreplace=$secleveli;
                    869:     }
1.556     raeburn   870:     if ($snum==9) { $storeunder=$seclevelr; }
                    871:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   872:     if ($snum==7) { 
                    873:         $storeunder=$grpleveli;
                    874:         $possreplace=$grplevelm;
                    875:     }
                    876:     if ($snum==6) {
                    877:         $storeunder=$grplevelm;
                    878:         $possreplace=$grpleveli;
                    879:     }
1.556     raeburn   880:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   881: 
1.446     bisitz    882: 
1.186     www       883:     my $delete;
                    884:     if ($nval eq '') { $delete=1;}
                    885:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  886:             $storeunder.'.type' => $ntype);
1.186     www       887:     my $reply='';
1.560     damieng   888:     
1.556     raeburn   889:     if ($snum>4) {
1.186     www       890: # ---------------------------------------------------------------- Store Course
                    891: #
1.560     damieng   892:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    893:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    894:         # Expire sheets
                    895:         &Apache::lonnet::expirespread('','','studentcalc');
                    896:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    897:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   898:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   899:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    900:         } else {
                    901:             &Apache::lonnet::expirespread('','','assesscalc');
                    902:         }
                    903:         # Store parameter
                    904:         if ($delete) {
                    905:             $reply=&Apache::lonnet::del
                    906:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    907:                 &log_parmset(\%storecontent,1);
                    908:         } else {
                    909:             $reply=&Apache::lonnet::cput
                    910:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    911:             &log_parmset(\%storecontent);
1.578     raeburn   912:             if ($possreplace) {
                    913:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    914:                 if (ref($resdata) eq 'HASH') {
                    915:                     if (exists($resdata->{$possreplace})) {
                    916:                         if (&Apache::lonnet::del
                    917:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    918:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    919:                         }
                    920:                     }
                    921:                 }
                    922:             }
1.560     damieng   923:         }
                    924:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       925:     } else {
                    926: # ------------------------------------------------------------------ Store User
                    927: #
1.560     damieng   928:         # Expire sheets
                    929:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    930:         if ($snum==1) {
                    931:             &Apache::lonnet::expirespread
                    932:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   933:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   934:             &Apache::lonnet::expirespread
                    935:             ($uname,$udom,'assesscalc',$map);
                    936:         } else {
                    937:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    938:         }
                    939:         # Store parameter
                    940:         if ($delete) {
                    941:             $reply=&Apache::lonnet::del
                    942:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    943:             &log_parmset(\%storecontent,1,$uname,$udom);
                    944:         } else {
                    945:             $reply=&Apache::lonnet::cput
                    946:             ('resourcedata',\%storecontent,$udom,$uname);
                    947:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   948:             if ($possreplace) {
                    949:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    950:                 if (ref($resdata) eq 'HASH') {
                    951:                     if (exists($resdata->{$possreplace})) {
                    952:                         if (&Apache::lonnet::del
                    953:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    954:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    955:                                           $uname,$udom);
                    956:                         }
                    957:                     }
                    958:                 }
                    959:             }
1.560     damieng   960:         }
                    961:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       962:     }
1.446     bisitz    963: 
1.186     www       964:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   965:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       966:     }
                    967:     return '';
                    968: }
                    969: 
1.9       www       970: 
1.561     damieng   971: # Returns HTML with the value of the given parameter,
                    972: # using a readable format for dates, and
                    973: # a warning if there is a problem with a date.
                    974: # Used by table mode.
                    975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    976: #
                    977: # @param {string} $value - the parameter value
                    978: # @param {string} $type - the parameter type
                    979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       980: sub valout {
1.600     raeburn   981:     my ($value,$type,$editable)=@_;
1.59      matthew   982:     my $result = '';
                    983:     # Values of zero are valid.
                    984:     if (! $value && $value ne '0') {
1.528     bisitz    985:         if ($editable) {
                    986:             $result =
                    987:                 '<img src="/res/adm/pages/editmap.png"'
                    988:                .' alt="'.&mt('Change').'"'
1.539     raeburn   989:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    990:         } else {
                    991:             $result='&nbsp;';
                    992:         }
1.59      matthew   993:     } else {
1.66      www       994:         if ($type eq 'date_interval') {
1.559     raeburn   995:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    996:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    997:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    998:                 $donebuttontext = $1;
                    999:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1000:                 $usesdone = 'done';
                   1001:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1002:                 $donebuttontext = &mt('Done');
                   1003:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1004:             }
1.554     raeburn  1005:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1006:             my @timer;
1.66      www      1007:             $year=$year-70;
                   1008:             $mday--;
                   1009:             if ($year) {
1.413     bisitz   1010: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1011:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1012:             }
                   1013:             if ($mon) {
1.413     bisitz   1014: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1015:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1016:             }
                   1017:             if ($mday) {
1.413     bisitz   1018: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1019:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1020:             }
                   1021:             if ($hour) {
1.413     bisitz   1022: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1023:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1024:             }
                   1025:             if ($min) {
1.413     bisitz   1026: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1027:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1028:             }
                   1029:             if ($sec) {
1.413     bisitz   1030: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1031:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1032:             }
1.413     bisitz   1033: #           $result=~s/\s+$//;
                   1034:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1035:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1036:             }
                   1037:             $result.=join(", ",@timer);
1.559     raeburn  1038:             if ($usesdone eq 'done') {
1.558     raeburn  1039:                 if ($secretkey) {
1.559     raeburn  1040:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1041:                 } else {
1.559     raeburn  1042:                     $result .= ' + "'.$donebuttontext.'"';
                   1043:                 }
1.554     raeburn  1044:             }
1.213     www      1045:         } elsif (&isdateparm($type)) {
1.361     albertel 1046:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1047:                 &date_sanity_info($value);
1.59      matthew  1048:         } else {
                   1049:             $result = $value;
1.517     www      1050:             $result=~s/\,/\, /gs;
1.560     damieng  1051:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1052:         }
                   1053:     }
                   1054:     return $result;
1.9       www      1055: }
                   1056: 
1.59      matthew  1057: 
1.561     damieng  1058: # Returns HTML containing a link on a parameter value, for table mode.
                   1059: # The link uses the javascript function 'pjump'.
                   1060: #
                   1061: # @param {string} $type - parameter type
                   1062: # @param {string} $dis - dialog title for editing the parameter value and type
                   1063: # @param {string} $value - parameter value
                   1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
                   1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1069: sub plink {
1.588     raeburn  1070:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1071:     my $winvalue=$value;
                   1072:     unless ($winvalue) {
1.592     raeburn  1073:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1074:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1075:         } elsif ($type eq 'string_yesno') {
                   1076:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1077:                 $winvalue=$env{'form.recent_string'};
                   1078:             }
1.23      www      1079:         } else {
1.190     albertel 1080:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1081:         }
                   1082:     }
1.229     www      1083:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1084:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1085:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1086:     my $valout = &valout($value,$type,1);
1.429     raeburn  1087:     my $unencmarker = $marker;
1.378     albertel 1088:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1089:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1090:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1091:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1092:     }
1.429     raeburn  1093:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1094:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1095:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1096:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1097:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1098: 
1.5       www      1099: }
                   1100: 
1.561     damieng  1101: # Javascript for table mode.
1.280     albertel 1102: sub page_js {
                   1103: 
1.81      www      1104:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1105:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1106: 
                   1107:     return(<<ENDJS);
                   1108: <script type="text/javascript">
1.454     bisitz   1109: // <![CDATA[
1.44      albertel 1110: 
1.88      matthew  1111:     $pjump_def
1.44      albertel 1112: 
                   1113:     function psub() {
1.591     raeburn  1114:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1115:         if (document.parmform.pres_marker.value!='') {
                   1116:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1117:             var typedef=new Array();
                   1118:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1119:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1120:                 if ((typedef[0]=='date') || 
1.591     raeburn  1121:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1122:                     eval('document.parmform.recent_'+
                   1123:                         document.parmform.pres_type.value+
                   1124:                         '.value=document.parmform.pres_value.value;');
                   1125:                 } else {
                   1126:                     eval('document.parmform.recent_'+typedef[0]+
                   1127:                         '.value=document.parmform.pres_value.value;');
                   1128:                 }
1.44      albertel 1129:             }
                   1130:             document.parmform.submit();
                   1131:         } else {
                   1132:             document.parmform.pres_value.value='';
                   1133:             document.parmform.pres_marker.value='';
                   1134:         }
                   1135:     }
                   1136: 
1.57      albertel 1137:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1138:         var options = "width=" + w + ",height=" + h + ",";
                   1139:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1140:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1141:         var newWin = window.open(url, wdwName, options);
                   1142:         newWin.focus();
                   1143:     }
1.523     raeburn  1144: 
1.454     bisitz   1145: // ]]>
1.523     raeburn  1146: 
1.44      albertel 1147: </script>
1.81      www      1148: $selscript
1.280     albertel 1149: ENDJS
                   1150: 
                   1151: }
1.507     www      1152: 
1.561     damieng  1153: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1154: # for table and overview modes.
1.523     raeburn  1155: sub showhide_js {
                   1156:     return <<"COURSECONTENTSCRIPT";
                   1157: 
                   1158: function showHide_courseContent() {
                   1159:     var parmlevValue=document.getElementById("parmlev").value;
                   1160:     if (parmlevValue == 'general') {
                   1161:         document.getElementById('mapmenu').style.display="none";
                   1162:     } else {
                   1163:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1164:             document.getElementById('mapmenu').style.display ="";
                   1165:         } else {
                   1166:             document.getElementById('mapmenu').style.display="none";
                   1167:         }
                   1168:     }
                   1169:     return;
                   1170: }
                   1171: 
                   1172: COURSECONTENTSCRIPT
                   1173: }
                   1174: 
1.561     damieng  1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1176: sub toggleparmtextbox_js {
                   1177:     return <<"ENDSCRIPT";
                   1178: 
                   1179: if (!document.getElementsByClassName) {
                   1180:     function getElementsByClassName(node, classname) {
                   1181:         var a = [];
                   1182:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1183:         var els = node.getElementsByTagName("*");
                   1184:         for(var i=0,j=els.length; i<j; i++)
                   1185:             if(re.test(els[i].className))a.push(els[i]);
                   1186:         return a;
                   1187:     }
                   1188: }
                   1189: 
                   1190: function showHideLenient() {
                   1191:     var lenients;
                   1192:     var setRegExp = /^set_/;
                   1193:     if (document.getElementsByClassName) {
                   1194:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1195:     } else {
                   1196:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1197:     }
                   1198:     if (lenients != 'undefined') {
                   1199:         for (var i=0; i<lenients.length; i++) {
                   1200:             if (lenients[i].checked) {
                   1201:                 if (lenients[i].value == 'weighted') {
                   1202:                     if (setRegExp.test(lenients[i].name)) {
                   1203:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1204:                         toggleParmTextbox(document.parmform,identifier);
                   1205:                     }
                   1206:                 }
                   1207:             }
                   1208:         }
                   1209:     }
                   1210:     return;
                   1211: }
                   1212: 
                   1213: function toggleParmTextbox(form,key) {
                   1214:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1215:     if (divfortext) {
                   1216:         var caller = form.elements['set_'+key];
                   1217:         if (caller.length) {
                   1218:             for (i=0; i<caller.length; i++) {
                   1219:                 if (caller[i].checked) {
                   1220:                     if (caller[i].value == 'weighted') {
                   1221:                         divfortext.style.display = 'inline';
                   1222:                     } else {
                   1223:                         divfortext.style.display = 'none';
                   1224:                     }
                   1225:                 }
                   1226:             }
                   1227:         }
                   1228:     }
                   1229:     return;
                   1230: }
                   1231: 
                   1232: ENDSCRIPT
                   1233: }
                   1234: 
1.561     damieng  1235: # Javascript function validateParms, for overview mode
1.549     raeburn  1236: sub validateparms_js {
                   1237:     return <<'ENDSCRIPT';
                   1238: 
                   1239: function validateParms() {
                   1240:     var textRegExp = /^settext_/;
                   1241:     var tailLenient = /\.lenient$/;
                   1242:     var patternRelWeight = /^\-?[\d.]+$/;
                   1243:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1244:     var ipRegExp = /^setip/;
1.549     raeburn  1245:     var ipallowRegExp = /^setipallow_/;
                   1246:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1247:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1248:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1249:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1250:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1251:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1252:     var dlKeyRegExp = /^deeplink_key_/;
                   1253:     var dlMenusRegExp = /^deeplink_menus_/;
                   1254:     var dlCollsRegExp = /^deeplink_colls_/;
1.613     raeburn  1255:     var dlTargetRegExp = /^deeplink_target_/;
1.549     raeburn  1256:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1257:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1258:         if (document.parmform.elements.length) {
                   1259:             for (i=0; i<document.parmform.elements.length; i++) {
                   1260:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1261:                 if (textRegExp.test(name)) {
1.549     raeburn  1262:                     var identifier = name.replace(textRegExp,'');
                   1263:                     if (tailLenient.test(identifier)) {
                   1264:                         if (document.parmform.elements['set_'+identifier].length) {
                   1265:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1266:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1267:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1268:                                         var relweight = document.parmform.elements[i].value;
                   1269:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1270:                                         if (!patternRelWeight.test(relweight)) {
                   1271:                                             relweight = '0.0';
                   1272:                                         }
                   1273:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1274:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1275:                                         } else {
                   1276:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1277:                                         }
                   1278:                                     }
                   1279:                                     break;
                   1280:                                 }
                   1281:                             }
                   1282:                         }
                   1283:                     }
1.597     raeburn  1284:                 } else if (ipRegExp.test(name)) {
                   1285:                     if (ipallowRegExp.test(name)) {
                   1286:                         var identifier = name.replace(ipallowRegExp,'');
                   1287:                         var possallow = document.parmform.elements[i].value;
                   1288:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1289:                         if (patternIP.test(possallow)) {
                   1290:                             if (document.parmform.elements['set_'+identifier].value) {
                   1291:                                 possallow = ','+possallow;
                   1292:                             }
                   1293:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1294:                         }
                   1295:                     } else if (ipdenyRegExp.test(name)) {
                   1296:                         var identifier = name.replace(ipdenyRegExp,'');
                   1297:                         var possdeny = document.parmform.elements[i].value;
                   1298:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1299:                         if (patternIP.test(possdeny)) {
                   1300:                             possdeny = '!'+possdeny;
                   1301:                             if (document.parmform.elements['set_'+identifier].value) {
                   1302:                                 possdeny = ','+possdeny;
                   1303:                             }
                   1304:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1305:                         }
                   1306:                     }
                   1307:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1308:                     if (dlListScopeRegExp.test(name)) {
                   1309:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1310:                         var idx = document.parmform.elements[i].selectedIndex;
                   1311:                         if (idx > 0) { 
                   1312:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1313:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1314:                             if (document.parmform.elements['set_'+identifier].value) {
                   1315:                                 possdeeplink = ','+possdeeplink;
                   1316:                             }
                   1317:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1318:                         }
1.601     raeburn  1319:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1320:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1321:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1322:                             var posslinkurl = document.parmform.elements[i].value;
                   1323:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1324:                             if (document.parmform.elements['set_'+identifier].value) {
                   1325:                                 posslinkurl = ','+posslinkurl;
                   1326:                             }
                   1327:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1328:                         }
1.601     raeburn  1329:                     } else if (dlLtidRegExp.test(name)) {
                   1330:                         var identifier = name.replace(dlLtidRegExp,'');
                   1331:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1332:                             var possltid = document.parmform.elements[i].value;
                   1333:                             possltid = possltid.replace(/\D+/g,'');
                   1334:                             if (possltid.length) {
1.597     raeburn  1335:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1336:                                     possltid = ':'+possltid;
1.597     raeburn  1337:                                 }
1.601     raeburn  1338:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1339:                             } else {
                   1340:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1341:                                 alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597     raeburn  1342:                                 return false;  
                   1343:                             }
                   1344:                         }
1.601     raeburn  1345:                     } else if (dlLticRegExp.test(name)) {
                   1346:                         var identifier = name.replace(dlLticRegExp,'');
                   1347:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1348:                             var possltic = document.parmform.elements[i].value;
                   1349:                             possltic = possltic.replace(/\D+/g,'');
                   1350:                             if (possltic.length) {
                   1351:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1352:                                     possltic = ':'+possltic;
                   1353:                                 }
                   1354:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1355:                             } else {
                   1356:                                 document.parmform.elements['set_'+identifier].value = '';
                   1357:                                 alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                   1358:                                 return false;
                   1359:                             }
                   1360:                         }
1.597     raeburn  1361:                     } else if (dlKeyRegExp.test(name)) {
                   1362:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1363:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1364:                             var posskey = document.parmform.elements[i].value;
                   1365:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1366:                             var origlength = posskey.length;
                   1367:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1368:                             var newlength = posskey.length;
                   1369:                             if (newlength > 0) {
                   1370:                                 var change = origlength - newlength;
                   1371:                                 if (change) {
                   1372:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1373:                                 }
                   1374:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1375:                                     posskey = ':'+posskey;
                   1376:                                 }
                   1377:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1378:                             } else {
                   1379:                                 document.parmform.elements['set_'+identifier].value = '';
                   1380:                                 if (newlength < origlength) {
                   1381:                                     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_.!@#$%^&*()+=-");
                   1382:                                 } else {
                   1383:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1384:                                 }
                   1385:                                 return false;
                   1386:                             }
                   1387:                         }
                   1388:                     } else if (dlMenusRegExp.test(name)) {
                   1389:                         if (document.parmform.elements[i].checked) {
                   1390:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1391:                             var posslinkmenu = document.parmform.elements[i].value;
                   1392:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1393:                             if (posslinkmenu == 'std') {
                   1394:                                 posslinkmenu = '0';
                   1395:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1396:                                     posslinkmenu = ','+posslinkmenu;
                   1397:                                 }
                   1398:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1399:                             }
                   1400:                         }
                   1401:                     } else if (dlCollsRegExp.test(name)) {
                   1402:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1403:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1404:                             var posslinkmenu = document.parmform.elements[i].value;
                   1405:                             if (document.parmform.elements['set_'+identifier].value) {
                   1406:                                 posslinkmenu = ','+posslinkmenu;
                   1407:                             }
                   1408:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1409:                         }
1.614     raeburn  1410:                     } else if (dlTargetRegExp.test(name)) {
                   1411:                         var identifier =  name.replace(dlTargetRegExp,'');
1.613     raeburn  1412:                         var idx = document.parmform.elements[i].selectedIndex;
                   1413:                         if (idx > 0) {
                   1414:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1415:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1416:                             if (document.parmform.elements['set_'+identifier].value) {
                   1417:                                 possdeeplink = ','+possdeeplink;
                   1418:                             }
1.614     raeburn  1419:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
1.613     raeburn  1420:                         }
1.549     raeburn  1421:                     }
                   1422:                 }
                   1423:             }
                   1424:         }
                   1425:     }
                   1426:     return true;
                   1427: }
                   1428: 
1.597     raeburn  1429: function isRadioSet(name,expected) {
                   1430:     var menuitems = document.getElementsByName(name);
                   1431:     var radioLength = menuitems.length;
                   1432:     result = false;
                   1433:     if (radioLength  > 1) {
                   1434:         for (var j=0; j<radioLength; j++) {
                   1435:             if (menuitems[j].checked) {
                   1436:                 if (menuitems[j].value == expected) {
                   1437:                     result = true;
                   1438:                     break;
                   1439:                 }
                   1440:             }
                   1441:         }
                   1442:     }
                   1443:     return result;
                   1444: }
                   1445: 
1.549     raeburn  1446: ENDSCRIPT
                   1447: }
                   1448: 
1.561     damieng  1449: # Javascript initialization, for overview mode
1.549     raeburn  1450: sub ipacc_boxes_js  {
                   1451:     my $remove = &mt('Remove');
                   1452:     return <<"END";
                   1453: \$(document).ready(function() {
                   1454:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1455:     var add_button      = \$(".LC_add_ipacc_button");
                   1456:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1457: 
                   1458:     \$(add_button).click(function(e){
                   1459:         e.preventDefault();
                   1460:         var identifier = \$(this).closest("div").attr("id");
                   1461:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1462:         \$(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  1463:     });
                   1464: 
                   1465:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1466:         e.preventDefault(); \$(this).closest("div").remove();
                   1467:     })
                   1468: });
                   1469: 
                   1470: 
                   1471: END
                   1472: }
                   1473: 
1.561     damieng  1474: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1475: sub done_proctor_js {
1.611     raeburn  1476:     my $defaultdone = &mt('Done');
                   1477:     &js_escape(\$defaultdone);
1.558     raeburn  1478:     return <<"END";
                   1479: function toggleSecret(form,radio,key) {
                   1480:     var radios = form[radio+key];
                   1481:     if (radios.length) {
                   1482:         for (var i=0; i<radios.length; i++) {
                   1483:             if (radios[i].checked) {
                   1484:                 if (radios[i].value == '_done_proctor') {
                   1485:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1486:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1487:                     }
                   1488:                 } else {
                   1489:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1490:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1491:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1492:                     }
                   1493:                 }
1.611     raeburn  1494:                 if (document.getElementById('done_'+key+'_buttontext')) {
                   1495:                     if (radios[i].value == '') {
                   1496:                         document.getElementById('done_'+key+'_buttontext').value = '';
                   1497:                     } else {
                   1498:                         if (document.getElementById('done_'+key+'_buttontext').value == '') {
                   1499:                             document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
                   1500:                         }
                   1501:                     }
                   1502:                 }
1.558     raeburn  1503:             }
                   1504:         }
                   1505:     }
                   1506: }
                   1507: END
                   1508: 
                   1509: }
                   1510: 
1.588     raeburn  1511: # Javascript function toggle
                   1512: sub deeplink_js {
                   1513:     return <<"END";
                   1514: function toggleDeepLink(form,item,key) {
                   1515:     var radios = form['deeplink_'+item+'_'+key];
                   1516:     if (radios.length) {
                   1517:         var keybox;
                   1518:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1519:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1520:         }
1.601     raeburn  1521:         var divoptions = new Array();
                   1522:         if (item == 'protect') {
                   1523:             divoptions = ['ltic','ltid'];
1.597     raeburn  1524:         } else {
                   1525:             if (item == 'menus') {
1.601     raeburn  1526:                 divoptions = ['colls'];
1.597     raeburn  1527:             }
                   1528:         }
1.601     raeburn  1529:         var seldivs = new Array();
                   1530:         if ((item == 'protect') || (item == 'menus')) {
                   1531:             for (var i=0; i<divoptions.length; i++) {
                   1532:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1533:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1534:                 } else {
                   1535:                     seldivs[i] = '';
                   1536:                 }
                   1537:             }
1.588     raeburn  1538:         }
                   1539:         for (var i=0; i<radios.length; i++) {
                   1540:             if (radios[i].checked) {
1.601     raeburn  1541:                 if ((item == 'protect') || (item == 'menus')) {
                   1542:                     for (var j=0; j<seldivs.length; j++) {
                   1543:                         if (radios[i].value == divoptions[j]) {
                   1544:                             if (seldivs[j] != '') {
                   1545:                                 seldivs[j].style.display = 'inline-block';
                   1546:                             }
                   1547:                             if (item == 'protect') {
                   1548:                                 keybox.type = 'hidden';
                   1549:                                 keybox.value = '';
                   1550:                             }
                   1551:                         } else {
                   1552:                             if (seldivs[j] != '') {
                   1553:                                 seldivs[j].style.display = 'none';
                   1554:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1555:                             }
                   1556:                         }
1.597     raeburn  1557:                     }
1.601     raeburn  1558:                     if (item == 'protect') {
1.597     raeburn  1559:                         if (radios[i].value == 'key') {
                   1560:                             keybox.type = 'text';
                   1561:                         } else {
                   1562:                             keybox.type = 'hidden';
                   1563:                         }
1.588     raeburn  1564:                     }
                   1565:                 }
                   1566:             }
                   1567:         }
                   1568:     }
                   1569: }
                   1570: END
                   1571: 
                   1572: }
                   1573: 
1.561     damieng  1574: # Prints HTML page start for table mode.
                   1575: # @param {Apache2::RequestRec} $r - the Apache request
                   1576: # @param {string} $psymb - resource symb
                   1577: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1578: sub startpage {
1.531     raeburn  1579:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1580: 
1.515     raeburn  1581:     my %loaditems = (
                   1582:                       'onload'   => "group_or_section('cgroup')",
                   1583:                     );
                   1584:     if (!$psymb) {
1.523     raeburn  1585:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1586:     }
1.280     albertel 1587: 
1.560     damieng  1588:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1589:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1590:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1591:             text=>"Problem Parameters"});
1.414     droeschl 1592:     } else {
1.560     damieng  1593:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1594:             text=>"Table Mode",
                   1595:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1596:     }
1.523     raeburn  1597:     my $js = &page_js().'
                   1598: <script type="text/javascript">
                   1599: // <![CDATA[
                   1600: '.
                   1601:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1602: // ]]>
                   1603: </script>
                   1604: ';
1.446     bisitz   1605:     my $start_page =
1.523     raeburn  1606:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1607:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1608:     my $breadcrumbs =
1.473     amueller 1609:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1610:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1611:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1612:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1613:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1614:     $r->print(<<ENDHEAD);
1.193     albertel 1615: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1616: <input type="hidden" value="" name="pres_value" />
                   1617: <input type="hidden" value="" name="pres_type" />
                   1618: <input type="hidden" value="" name="pres_marker" />
                   1619: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1620: <input type="hidden" value="$escfilter" name="filter" />
                   1621: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1622: ENDHEAD
                   1623: }
                   1624: 
1.209     www      1625: 
1.561     damieng  1626: # Prints a row for table mode (except for the tr start).
                   1627: # Every time a hash reference is passed, a single entry is used, so print_row
                   1628: # could just use these values, but why make it simple when it can be complicated ?
                   1629: #
                   1630: # @param {Apache2::RequestRec} $r - the Apache request
                   1631: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1632: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1633: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1634: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1635: # @param {string} $rid - resource id
                   1636: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1637: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1638: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1639: # @param {string} $defbgone - user level and other levels background color
                   1640: # @param {string} $defbgtwo - section level background color, also used for part number
                   1641: # @param {string} $defbgthree - group level background color
                   1642: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1643: # @param {string} $uname - user name
                   1644: # @param {string} $udom - user domain
                   1645: # @param {string} $csec - section name
                   1646: # @param {string} $cgroup - group name
                   1647: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1648: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1649: # @param {boolean} $readonly - true if no editing allowed.
                   1650: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1651: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1652: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1653: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1654: sub print_row {
1.201     www      1655:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1656:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1657:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1658:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1659:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1660:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1661:     my $numlinks = 0;
1.553     raeburn  1662: 
1.560     damieng  1663:     # get the values for the parameter in cascading order
                   1664:     # empty levels will remain empty
1.44      albertel 1665:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1666:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1667:     # get the type for the parameters
                   1668:     # problem: these may not be set for all levels
1.66      www      1669:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1670:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1671:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1672:     # cascade down manually
1.182     albertel 1673:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1674:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1675:         if ($typeoutpar[$i]) {
1.66      www      1676:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1677:         } else {
1.66      www      1678:             $typeoutpar[$i]=$cascadetype;
                   1679:         }
                   1680:     }
1.57      albertel 1681:     my $parm=$$display{$which};
                   1682: 
1.203     www      1683:     if ($parmlev eq 'full') {
1.419     bisitz   1684:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1685:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1686:     } else {
1.57      albertel 1687:         $parm=~s|\[.*\]\s||g;
                   1688:     }
1.231     www      1689:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1690:     if ($automatic) {
1.560     damieng  1691:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1692:     }
1.427     bisitz   1693:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1694: 
1.44      albertel 1695:     my $thismarker=$which;
                   1696:     $thismarker=~s/^parameter\_//;
                   1697:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1698:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1699:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1700:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1701:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1702:         if ($result eq '') {
                   1703:             $recurse_check = 1;
                   1704:         } elsif (($uname ne '') && ($result > 3)) {
                   1705:             $recurse_check = 1;
                   1706:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1707:             $recurse_check = 1;
                   1708:         } elsif (($csec ne '') && ($result > 11)) {
                   1709:             $recurse_check = 1;
                   1710:         } elsif ($result > 17) {
                   1711:             $recurse_check = 1;
                   1712:         }
                   1713:         if ($recurse_check) {
                   1714:             my $what = $$part{$which}.'.'.$$name{$which};
                   1715:             my $prefix;
                   1716:             if (($uname ne '') && ($udom ne '')) {
                   1717:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1718:                 $prefix = $env{'request.course.id'};
                   1719:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1720:                 if (ref($recursinfo) eq 'ARRAY') {
                   1721:                     $effparm_rec = 1;
                   1722:                     $effparm_level = &mt('user: [_1]',$uname);
                   1723:                 }
                   1724:             }
                   1725:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1726:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1727:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1728:                 if (ref($recursinfo) eq 'ARRAY') {
                   1729:                     $effparm_rec = 1;
                   1730:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1731:                 }
                   1732:             }
                   1733:             if (($csec ne '') && (!$effparm_rec)) {
                   1734:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1735:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1736:                 if (ref($recursinfo) eq 'ARRAY') {
                   1737:                     $effparm_rec = 1;
                   1738:                     $effparm_level = &mt('section: [_1]',$csec);
                   1739:                 }
                   1740:             }
                   1741:             if (!$effparm_rec) {
                   1742:                 $prefix = $env{'request.course.id'};
                   1743:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1744:                 if (ref($recursinfo) eq 'ARRAY') {
                   1745:                     $effparm_rec = 1;
                   1746:                 }
                   1747:             }
                   1748:         }
                   1749:     }
                   1750:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1751:         $effparm_rec = 1;
                   1752:     }
                   1753:     if ((!$effparm_rec) && 
                   1754:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1755:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1756:         $effparm_rec = 1;
                   1757:     }
1.588     raeburn  1758:     if ($parmname eq 'deeplink') {
1.601     raeburn  1759:         my ($domltistr,$crsltistr);
1.588     raeburn  1760:         my %lti =
                   1761:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1762:                                             'linkprot');
1.601     raeburn  1763:         if (keys(%lti)) {
                   1764:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1765:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1766:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1767:                 }
                   1768:             }
1.601     raeburn  1769:             $domltistr =~ s/,$//;
                   1770:             if ($domltistr) {
                   1771:                 $extra = 'ltid_'.$domltistr;
                   1772:             }
1.588     raeburn  1773:         }
1.601     raeburn  1774:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1775:         if (keys(%courselti)) {
                   1776:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1777:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1778:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1779:                 }
                   1780:             }
                   1781:             $crsltistr =~ s/,$//;
                   1782:             if ($crsltistr) {
                   1783:                 if ($extra) {
                   1784:                     $extra .= '&';
                   1785:                 }
                   1786:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1787:             }
                   1788:         }
1.597     raeburn  1789:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1790:             my @colls;
                   1791:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1792:                 my ($num,$value) = split(/\%/,$item);
                   1793:                 if ($num =~ /^\d+$/) {
                   1794:                     push(@colls,$num);
                   1795:                 }
                   1796:             }
                   1797:             if (@colls) {
                   1798:                 if ($extra) {
                   1799:                     $extra .= '&';
                   1800:                 }
                   1801:                 $extra .= 'menus_'.join(',',@colls);
                   1802:             }
                   1803:         }
1.588     raeburn  1804:     }
1.57      albertel 1805:     if ($parmlev eq 'general') {
                   1806:         if ($uname) {
1.588     raeburn  1807:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1808:         } elsif ($cgroup) {
1.588     raeburn  1809:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1810:         } elsif ($csec) {
1.588     raeburn  1811:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1812:         } else {
1.588     raeburn  1813:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1814:         }
                   1815:     } elsif ($parmlev eq 'map') {
                   1816:         if ($uname) {
1.588     raeburn  1817:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1818:         } elsif ($cgroup) {
1.588     raeburn  1819:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1820:         } elsif ($csec) {
1.588     raeburn  1821:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1822:         } else {
1.588     raeburn  1823:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1824:         }
                   1825:     } else {
1.275     raeburn  1826:         if ($uname) {
                   1827:             if (@{$usersgroups} > 1) {
1.582     raeburn  1828:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1829:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1830:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1831:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1832:                     if (defined($controlgrp)) {
                   1833:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1834:                             $eff_groupparm = $grp_parm;
                   1835:                             undef($result);
                   1836:                             undef($effparm_rec);
                   1837:                             if ($grp_is_rec) {
                   1838:                                  $effparm_rec = 1;
                   1839:                             }
1.275     raeburn  1840:                         }
                   1841:                     }
                   1842:                 }
                   1843:             }
                   1844:         }
1.57      albertel 1845: 
1.588     raeburn  1846:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1847:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1848:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1849:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1850:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1851: 
                   1852:         if ($csec) {
1.588     raeburn  1853:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1854:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1855:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1856:         }
1.269     raeburn  1857: 
                   1858:         if ($cgroup) {
1.588     raeburn  1859:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1860:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1861:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1862:         }
1.446     bisitz   1863: 
1.548     raeburn  1864:         if ($uname) {
1.275     raeburn  1865:             if ($othergrp) {
                   1866:                 $r->print($othergrp);
                   1867:             }
1.588     raeburn  1868:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1869:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1870:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1871:         }
1.57      albertel 1872:     } # end of $parmlev if/else
1.582     raeburn  1873:     if (ref($recursinfo) eq 'ARRAY') {
                   1874:         my $rectitle = &mt('recursive');
                   1875:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1876:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1877:                 $rectitle = &mt('set in: [_1]','"'.
                   1878:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1879:                                                               "'$parmname','$$part{$which}'".');">'.
                   1880:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1881:               
                   1882:                 $numlinks ++;
                   1883:             }
                   1884:         }
                   1885:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1886:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1887:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1888:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1889:                   $effparm_level.'</span></td>');
                   1890:     } else {
                   1891:         if ($result) {
1.593     raeburn  1892:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1893:         }
                   1894:         if ($eff_groupparm) {
                   1895:             $effective_parm = $eff_groupparm;
                   1896:         }
                   1897:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1898:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1899:                                 '</span>':'').'</td>');
                   1900:     }
1.203     www      1901:     if ($parmlev eq 'full') {
1.136     albertel 1902:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1903:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1904:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1905:         if (!defined($sessionvaltype)) {
                   1906:             $sessionvaltype=$$defaulttype{$which};
                   1907:         }
1.419     bisitz   1908:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1909:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1910:                   '</font></td>');
1.136     albertel 1911:     }
1.44      albertel 1912:     $r->print('</tr>');
1.57      albertel 1913:     $r->print("\n");
1.582     raeburn  1914:     if (($numlinks) && (ref($reclinks))) {
                   1915:         $$reclinks = $numlinks;
                   1916:     }
1.44      albertel 1917: }
1.59      matthew  1918: 
1.561     damieng  1919: # Prints a cell for table mode.
                   1920: #
                   1921: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1922: # Also, it would make more sense to pass the display for this cell rather
                   1923: # than the full display hash and the key to use.
                   1924: #
                   1925: # @param {Apache2::RequestRec} $r - the Apache request
                   1926: # @param {integer} $which - level
                   1927: # @param {string} $defbg - cell background color
                   1928: # @param {integer} $result - the most specific level that is defined for that parameter
                   1929: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1930: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1931: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1932: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1933: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1934: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1935: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1936: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1937: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1938: sub print_td {
1.578     raeburn  1939:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  1940:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  1941:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   1942:     $ineffect = 0;
                   1943:     $currval = $$outpar[$which];
                   1944:     $currtype = $$typeoutpar[$which];
                   1945:     $currlevel = $which;
                   1946:     if (($result) && ($result == $which)) {
                   1947:         $ineffect = 1;
                   1948:     } 
                   1949:     if ($ismaplevel) {
                   1950:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   1951:             if (($result) && ($result == $which)) {
                   1952:                 $recursive = 1;
                   1953:             }
                   1954:         } elsif ($$outpar[$which+1] ne '') {
                   1955:             $recursive = 1;
                   1956:             $currlevel = $which+1;
                   1957:             $currval = $$outpar[$currlevel];
                   1958:             $currtype = $$typeoutpar[$currlevel];
                   1959:             if (($result) && ($result == $currlevel)) {
                   1960:                 $ineffect = 1;
                   1961:             }
                   1962:         }
                   1963:     }
                   1964:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   1965:               ';" align="center">');
1.437     raeburn  1966:     my $nolink = 0;
1.568     raeburn  1967:     if ($readonly) {
1.552     raeburn  1968:         $nolink = 1;
1.568     raeburn  1969:     } else { 
1.578     raeburn  1970:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  1971:             $nolink = 1;
1.568     raeburn  1972:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1973:             $nolink = 1;
1.568     raeburn  1974:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1975:             if ($noeditgrp) {
                   1976:                 $nolink = 1;
                   1977:             }
                   1978:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  1979:             $nolink = 1;
1.568     raeburn  1980:         } elsif ($mprefix =~ /examcode\&$/) {
                   1981:             unless ($which == 2) {
                   1982:                 $nolink = 1;
                   1983:             }
1.533     raeburn  1984:         }
1.437     raeburn  1985:     }
                   1986:     if ($nolink) {
1.577     raeburn  1987:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  1988:         $r->print(&valout($currval,$currtype));
1.114     www      1989:     } else {
1.578     raeburn  1990:         $r->print(&plink($currtype,
                   1991:                          $$display{$value},$currval,
1.588     raeburn  1992:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   1993:                          $extra));
1.114     www      1994:     }
                   1995:     $r->print('</td>'."\n");
1.57      albertel 1996: }
                   1997: 
1.561     damieng  1998: # Returns HTML and other info for the cell added when a user is selected
                   1999: # and that user is in several groups. This is the cell with the title "Control by other group".
                   2000: #
                   2001: # @param {string} $what - parameter part.'.'.parameter name
                   2002: # @param {string} $rid - resource id
                   2003: # @param {string} $cgroup - group name
                   2004: # @param {string} $defbg - cell background color
                   2005: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2006: # @param {integer} $result - level
                   2007: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  2008: # @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  2009: sub check_other_groups {
                   2010:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  2011:     my $courseid = $env{'request.course.id'};
                   2012:     my $output;
                   2013:     my $symb = &symbcache($rid);
                   2014:     my $symbparm=$symb.'.'.$what;
                   2015:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  2016:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  2017:     my $mapparm=$map.'___(all).'.$what;
                   2018:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  2019:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   2020:                               $recurseparm,$what,$courseopt);
1.275     raeburn  2021:     my $bgcolor = $defbg;
1.582     raeburn  2022:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2023:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2024:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2025:         if ($result > 3) {
1.419     bisitz   2026:             $bgcolor = '#AAFFAA';
1.275     raeburn  2027:         }
1.593     raeburn  2028:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2029:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2030:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2031:             if ($resultlevel eq 'recursive') {
                   2032:                 $resultlevel = 'map/folder';
                   2033:                 $grp_is_rec = 1;
                   2034:             }
                   2035:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2036:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2037:              
1.275     raeburn  2038:         } else {
                   2039:             $output .= '&nbsp;';
                   2040:         }
                   2041:         $output .= '</td>';
                   2042:     } else {
1.419     bisitz   2043:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2044:     }
1.582     raeburn  2045:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2046: }
                   2047: 
1.561     damieng  2048: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2049: # Used by check_other_groups.
1.561     damieng  2050: #
                   2051: # @param {string} $courseid - the course id
                   2052: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2053: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2054: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2055: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2056: # @param {string} $what - parameter part.'.'.parameter name
                   2057: # @param {hash reference} $courseopt - course parameters hash
                   2058: # @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  2059: sub parm_control_group {
1.556     raeburn  2060:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2061:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2062:     my $grpfound = 0;
1.556     raeburn  2063:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2064:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2065:     foreach my $group (@{$usersgroups}) {
                   2066:         if ($grpfound) { last; }
                   2067:         for (my $i=0; $i<@levels; $i++) {
                   2068:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2069:             if (defined($$courseopt{$item})) {
                   2070:                 $coursereply = $$courseopt{$item};
                   2071:                 $resultitem = $item;
                   2072:                 $resultgroup = $group;
                   2073:                 $resultlevel = $levelnames[$i];
                   2074:                 $resulttype = $$courseopt{$item.'.type'};
                   2075:                 $grpfound = 1;
                   2076:                 last;
                   2077:             }
                   2078:         }
                   2079:     }
                   2080:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2081: }
1.201     www      2082: 
1.63      bowersj2 2083: 
                   2084: 
1.562     damieng  2085: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2086: # All the parameters are references and are filled by the sub.
                   2087: #
1.566     damieng  2088: # @param {array reference} $ids - resource and map ids
                   2089: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2090: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2091: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2092: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2093: # @param {hash reference} $allmaps - hash map pc -> map src
                   2094: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2095: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2096: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2097: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2098: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2099: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608     raeburn  2100: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63      bowersj2 2101: sub extractResourceInformation {
                   2102:     my $ids = shift;
                   2103:     my $typep = shift;
                   2104:     my $keyp = shift;
                   2105:     my $allparms = shift;
                   2106:     my $allparts = shift;
                   2107:     my $allmaps = shift;
                   2108:     my $mapp = shift;
                   2109:     my $symbp = shift;
1.82      www      2110:     my $maptitles=shift;
1.196     www      2111:     my $uris=shift;
1.210     www      2112:     my $keyorder=shift;
1.211     www      2113:     my $defkeytype=shift;
1.603     raeburn  2114:     my $pssymb=shift;
1.196     www      2115: 
1.210     www      2116:     my $keyordercnt=100;
1.63      bowersj2 2117: 
1.196     www      2118:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2119:     return unless(ref($navmap));
                   2120:     my @allres;
                   2121:     if ($pssymb ne '') {
                   2122:         my $res = $navmap->getBySymb($pssymb);
                   2123:         if (ref($res)) {
                   2124:             @allres = ($res);
                   2125:         }
                   2126:     }
                   2127:     if (!@allres) { 
                   2128:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2129:     }
1.196     www      2130:     foreach my $resource (@allres) {
1.480     amueller 2131:         my $id=$resource->id();
1.196     www      2132:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2133:         if ($mapid eq '0') { next; }
                   2134:         $$ids[$#$ids+1]=$id;
                   2135:         my $srcf=$resource->src();
                   2136:         $srcf=~/\.(\w+)$/;
                   2137:         $$typep{$id}=$1;
1.584     raeburn  2138:         my $toolsymb;
                   2139:         if ($srcf =~ /ext\.tool$/) {
                   2140:             $toolsymb = $resource->symb();
                   2141:         }
1.480     amueller 2142:         $$keyp{$id}='';
1.196     www      2143:         $$uris{$id}=$srcf;
1.512     foxr     2144: 
1.584     raeburn  2145:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2146:             next if ($key!~/^parameter_/);
1.363     albertel 2147: 
1.209     www      2148: # Hidden parameters
1.584     raeburn  2149:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2150: #
                   2151: # allparms is a hash of parameter names
                   2152: #
1.584     raeburn  2153:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2154:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2155:                 my ($display,$parmdis);
                   2156:                 $display = &standard_parameter_names($name);
                   2157:                 if ($display eq '') {
1.584     raeburn  2158:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2159:                     $parmdis = $display;
                   2160:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2161:                 } else {
                   2162:                     $parmdis = &mt($display);
                   2163:                 }
                   2164:                 $$allparms{$name}=$parmdis;
                   2165:                 if (ref($defkeytype)) {
                   2166:                     $$defkeytype{$name}=
1.584     raeburn  2167:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2168:                 }
                   2169:             }
1.363     albertel 2170: 
1.209     www      2171: #
                   2172: # allparts is a hash of all parts
                   2173: #
1.584     raeburn  2174:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2175:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2176: #
                   2177: # Remember all keys going with this resource
                   2178: #
1.480     amueller 2179:             if ($$keyp{$id}) {
                   2180:                 $$keyp{$id}.=','.$key;
                   2181:             } else {
                   2182:                 $$keyp{$id}=$key;
                   2183:             }   
1.210     www      2184: #
                   2185: # Put in order
1.446     bisitz   2186: #
1.480     amueller 2187:             unless ($$keyorder{$key}) {
                   2188:                 $$keyorder{$key}=$keyordercnt;
                   2189:                 $keyordercnt++;
                   2190:             }
1.473     amueller 2191:         }
                   2192: 
                   2193: 
1.480     amueller 2194:         if (!exists($$mapp{$mapid})) {
                   2195:             $$mapp{$id}=
                   2196:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2197:             $$mapp{$mapid}=$$mapp{$id};
                   2198:             $$allmaps{$mapid}=$$mapp{$id};
                   2199:             if ($mapid eq '1') {
1.532     raeburn  2200:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2201:             } else {
                   2202:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2203:             }
                   2204:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2205:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2206:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2207:                                                      # are commented out in rev. 1.57
1.473     amueller 2208:         } else {
1.480     amueller 2209:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2210:         }
1.480     amueller 2211:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2212:     }
                   2213: }
                   2214: 
1.582     raeburn  2215: sub get_recursive {
                   2216:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2217:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2218:         foreach my $item (@{$recurseup}) {
                   2219:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2220:             if (defined($resdata->{$norecursechk})) {
                   2221:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2222:                     my $type = $resdata->{$norecursechk.'.type'};
                   2223:                     return [$resdata->{$norecursechk},$type,$item];
                   2224:                 } else {
                   2225:                     last;
                   2226:                 }
                   2227:             }
                   2228:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2229:             if (defined($resdata->{$recursechk})) {
                   2230:                 my $type = $resdata->{$recursechk.'.type'};
                   2231:                 return [$resdata->{$recursechk},$type,$item];
                   2232:             }
                   2233:         }
                   2234:     }
                   2235:     return;
                   2236: }
                   2237: 
1.208     www      2238: 
1.562     damieng  2239: # Tells if a parameter type is a date.
                   2240: #
                   2241: # @param {string} type - parameter type
                   2242: # @returns{boolean} - true if it is a date
1.213     www      2243: sub isdateparm {
                   2244:     my $type=shift;
                   2245:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2246: }
                   2247: 
1.589     raeburn  2248: # Determine if parameter type is specialized string type (i.e.,
                   2249: # not just string or string_yesno.  
                   2250: 
                   2251: sub is_specialstring {
                   2252:     my $type=shift;
1.603     raeburn  2253:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2254: }
                   2255: 
1.562     damieng  2256: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2257: #
1.581     raeburn  2258: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2259: sub parmmenu {
1.581     raeburn  2260:     my ($r)=@_;
1.208     www      2261:     $r->print(<<ENDSCRIPT);
                   2262: <script type="text/javascript">
1.454     bisitz   2263: // <![CDATA[
1.208     www      2264:     function checkall(value, checkName) {
1.453     schualex 2265: 
                   2266:         var li = "_li";
                   2267:         var displayOverview = "";
                   2268:         
                   2269:         if (value == false) {
                   2270:             displayOverview = "none"
                   2271:         }
                   2272: 
1.562     damieng  2273:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2274:             ele = document.forms.parmform.elements[i];
                   2275:             if (ele.name == checkName) {
                   2276:                 document.forms.parmform.elements[i].checked=value;
                   2277:             }
                   2278:         }
                   2279:     }
1.210     www      2280: 
                   2281:     function checkthis(thisvalue, checkName) {
1.562     damieng  2282:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2283:             ele = document.forms.parmform.elements[i];
                   2284:             if (ele.name == checkName) {
1.562     damieng  2285:                 if (ele.value == thisvalue) {
                   2286:                     document.forms.parmform.elements[i].checked=true;
                   2287:                 }
1.210     www      2288:             }
                   2289:         }
                   2290:     }
                   2291: 
                   2292:     function checkdates() {
1.562     damieng  2293:         checkthis('duedate','pscat');
                   2294:         checkthis('opendate','pscat');
                   2295:         checkthis('answerdate','pscat');
1.218     www      2296:     }
                   2297: 
                   2298:     function checkdisset() {
1.562     damieng  2299:         checkthis('discussend','pscat');
                   2300:         checkthis('discusshide','pscat');
                   2301:         checkthis('discussvote','pscat');
1.218     www      2302:     }
                   2303: 
                   2304:     function checkcontdates() {
1.562     damieng  2305:         checkthis('contentopen','pscat');
                   2306:         checkthis('contentclose','pscat');
1.218     www      2307:     }
1.446     bisitz   2308: 
1.210     www      2309:     function checkvisi() {
1.562     damieng  2310:         checkthis('hiddenresource','pscat');
                   2311:         checkthis('encrypturl','pscat');
                   2312:         checkthis('problemstatus','pscat');
                   2313:         checkthis('contentopen','pscat');
                   2314:         checkthis('opendate','pscat');
1.210     www      2315:     }
                   2316: 
                   2317:     function checkparts() {
1.562     damieng  2318:         checkthis('hiddenparts','pscat');
                   2319:         checkthis('display','pscat');
                   2320:         checkthis('ordered','pscat');
1.210     www      2321:     }
                   2322: 
                   2323:     function checkstandard() {
                   2324:         checkall(false,'pscat');
1.562     damieng  2325:         checkdates();
                   2326:         checkthis('weight','pscat');
                   2327:         checkthis('maxtries','pscat');
                   2328:         checkthis('type','pscat');
                   2329:         checkthis('problemstatus','pscat');
1.210     www      2330:     }
                   2331: 
1.454     bisitz   2332: // ]]>
1.208     www      2333: </script>
                   2334: ENDSCRIPT
1.453     schualex 2335: 
1.491     bisitz   2336:     $r->print('<hr />');
1.581     raeburn  2337:     &shortCuts($r);
1.491     bisitz   2338:     $r->print('<hr />');
1.453     schualex 2339: }
1.562     damieng  2340: 
                   2341: # Returns parameter categories.
                   2342: #
                   2343: # @returns {hash} - category name -> title in English
1.465     amueller 2344: sub categories {
                   2345:     return ('time_settings' => 'Time Settings',
                   2346:     'grading' => 'Grading',
                   2347:     'tries' => 'Tries',
                   2348:     'problem_appearance' => 'Problem Appearance',
                   2349:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2350:     'hiding' => 'Hiding',
                   2351:     'high_level_randomization' => 'High Level Randomization',
                   2352:     'slots' => 'Slots',
                   2353:     'file_submission' => 'File Submission',
                   2354:     'misc' => 'Miscellaneous' ); 
                   2355: }
                   2356: 
1.562     damieng  2357: # Returns the category for each parameter.
                   2358: #
                   2359: # @returns {hash} - parameter name -> category name
1.465     amueller 2360: sub lookUpTableParameter {
                   2361:  
                   2362:     return ( 
                   2363:         'opendate' => 'time_settings',
                   2364:         'duedate' => 'time_settings',
                   2365:         'answerdate' => 'time_settings',
                   2366:         'interval' => 'time_settings',
                   2367:         'contentopen' => 'time_settings',
                   2368:         'contentclose' => 'time_settings',
                   2369:         'discussend' => 'time_settings',
1.560     damieng  2370:         'printstartdate' => 'time_settings',
                   2371:         'printenddate' => 'time_settings',
1.465     amueller 2372:         'weight' => 'grading',
                   2373:         'handgrade' => 'grading',
                   2374:         'maxtries' => 'tries',
                   2375:         'hinttries' => 'tries',
1.503     raeburn  2376:         'randomizeontries' => 'tries',
1.465     amueller 2377:         'type' => 'problem_appearance',
                   2378:         'problemstatus' => 'problem_appearance',
                   2379:         'display' => 'problem_appearance',
                   2380:         'ordered' => 'problem_appearance',
                   2381:         'numbubbles' => 'problem_appearance',
                   2382:         'tol' => 'behaviour_of_input_fields',
                   2383:         'sig' => 'behaviour_of_input_fields',
                   2384:         'turnoffunit' => 'behaviour_of_input_fields',
                   2385:         'hiddenresource' => 'hiding',
                   2386:         'hiddenparts' => 'hiding',
                   2387:         'discusshide' => 'hiding',
                   2388:         'buttonshide' => 'hiding',
                   2389:         'turnoffeditor' => 'hiding',
                   2390:         'encrypturl' => 'hiding',
1.587     raeburn  2391:         'deeplink' => 'hiding',
1.465     amueller 2392:         'randomorder' => 'high_level_randomization',
                   2393:         'randompick' => 'high_level_randomization',
                   2394:         'available' => 'slots',
                   2395:         'useslots' => 'slots',
                   2396:         'availablestudent' => 'slots',
                   2397:         'uploadedfiletypes' => 'file_submission',
                   2398:         'maxfilesize' => 'file_submission',
                   2399:         'cssfile' => 'misc',
                   2400:         'mapalias' => 'misc',
                   2401:         'acc' => 'misc',
                   2402:         'maxcollaborators' => 'misc',
                   2403:         'scoreformat' => 'misc',
1.514     raeburn  2404:         'lenient' => 'grading',
1.519     raeburn  2405:         'retrypartial' => 'tries',
1.521     raeburn  2406:         'discussvote'  => 'misc',
1.584     raeburn  2407:         'examcode' => 'high_level_randomization',
1.575     raeburn  2408:     );
1.465     amueller 2409: }
                   2410: 
1.562     damieng  2411: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2412: #
                   2413: # @param {string} $name - parameter name
                   2414: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2415: sub whatIsMyCategory {
                   2416:     my $name = shift;
                   2417:     my $catList = shift;
                   2418:     my @list;
                   2419:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2420:     my $cat = $lookUpList{$name};
                   2421:     if (defined($cat)) {
                   2422:         if (!defined($$catList{$cat})){
                   2423:             push @list, ($name);
                   2424:             $$catList{$cat} = \@list;
                   2425:         } else {
                   2426:             push @{${$catList}{$cat}}, ($name);     
                   2427:         }
                   2428:     } else {
                   2429:         if (!defined($$catList{'misc'})){
                   2430:             push @list, ($name);
                   2431:             $$catList{'misc'} = \@list;
                   2432:         } else {
                   2433:             push @{${$catList}{'misc'}}, ($name);     
                   2434:         }
                   2435:     }        
                   2436: }
                   2437: 
1.562     damieng  2438: # Sorts parameter names based on appearance order.
                   2439: #
                   2440: # @param {array reference} name - array reference of parameter names
                   2441: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2442: # @returns {Array} - array of parameter names
1.465     amueller 2443: sub keysindisplayorderCategory {
                   2444:     my ($name,$keyorder)=@_;
                   2445:     return sort {
1.473     amueller 2446:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2447:     } ( @{$name});
                   2448: }
                   2449: 
1.562     damieng  2450: # Returns a hash category name -> order, starting at 1 (integer)
                   2451: #
                   2452: # @returns {hash}
1.467     amueller 2453: sub category_order {
                   2454:     return (
                   2455:         'time_settings' => 1,
                   2456:         'grading' => 2,
                   2457:         'tries' => 3,
                   2458:         'problem_appearance' => 4,
                   2459:         'hiding' => 5,
                   2460:         'behaviour_of_input_fields' => 6,
                   2461:         'high_level_randomization'  => 7,
                   2462:         'slots' => 8,
                   2463:         'file_submission' => 9,
                   2464:         'misc' => 10
                   2465:     );
                   2466: 
                   2467: }
1.453     schualex 2468: 
1.562     damieng  2469: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2470: #
                   2471: # @param {Apache2::RequestRec} $r - the Apache request
                   2472: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2473: # @param {array reference} $pscat - list of selected parameter names
                   2474: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2475: sub parmboxes {
                   2476:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2477:     my %categories = &categories();
1.467     amueller 2478:     my %category_order = &category_order();
1.465     amueller 2479:     my %categoryList = (
                   2480:         'time_settings' => [],
                   2481:         'grading' => [],
                   2482:         'tries' => [],
                   2483:         'problem_appearance' => [],
                   2484:         'behaviour_of_input_fields' => [],
                   2485:         'hiding' => [],
                   2486:         'high_level_randomization' => [],
                   2487:         'slots' => [],
                   2488:         'file_submission' => [],
                   2489:         'misc' => [],
1.489     bisitz   2490:     );
1.510     www      2491: 
1.548     raeburn  2492:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2493:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2494:     }
1.453     schualex 2495:     #part to print the parm-list
1.536     raeburn  2496:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2497:         next if (@{$categoryList{$key}} == 0);
                   2498:         next if ($key eq '');
                   2499:         $r->print('<div class="LC_Box LC_400Box">'
                   2500:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2501:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2502:             next if ($tempkey eq '');
1.536     raeburn  2503:             $r->print('<span class="LC_nobreak">'
                   2504:                      .'<label><input type="checkbox" name="pscat" '
                   2505:                      .'value="'.$tempkey.'" ');
                   2506:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2507:                 $r->print( ' checked="checked"');
                   2508:             }
                   2509:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2510:                                                       : $tempkey)
1.536     raeburn  2511:                      .'</label></span><br />'."\n");
1.465     amueller 2512:         }
1.536     raeburn  2513:         $r->print('</div>');
1.465     amueller 2514:     }
1.536     raeburn  2515:     $r->print("\n");
1.453     schualex 2516: }
1.562     damieng  2517: 
                   2518: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2519: #
1.562     damieng  2520: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2521: sub shortCuts {
1.581     raeburn  2522:     my ($r)=@_;
1.453     schualex 2523: 
1.491     bisitz   2524:     # Parameter Selection
                   2525:     $r->print(
                   2526:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2527:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2528:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2529:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2530:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2531:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2532:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2533:        .&Apache::lonhtmlcommon::end_funclist()
                   2534:     );
                   2535: 
                   2536:     # Add Selection for...
                   2537:     $r->print(
                   2538:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2539:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2540:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2541:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2542:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2543:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2544:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2545:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2546:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2547:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2548:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2549:        .&Apache::lonhtmlcommon::end_funclist()
                   2550:     );
1.208     www      2551: }
                   2552: 
1.562     damieng  2553: # Prints HTML to select parts to view (except for the title).
                   2554: # Used by table and overview modes.
                   2555: #
                   2556: # @param {Apache2::RequestRec} $r - the Apache request
                   2557: # @param {hash reference} $allparts - hash parameter part -> part title
                   2558: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2559: sub partmenu {
1.446     bisitz   2560:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2561:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2562:     if ($selsize > 8) {
                   2563:         $selsize = 8;
                   2564:     }
1.446     bisitz   2565: 
1.523     raeburn  2566:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2567:     $r->print('<option value="all"');
1.562     damieng  2568:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2569:     $r->print('>'.&mt('All Parts').'</option>');
                   2570:     my %temphash=();
                   2571:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2572:     foreach my $tempkey (sort {
1.560     damieng  2573:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2574:             } keys(%{$allparts})) {
                   2575:         unless ($tempkey =~ /\./) {
                   2576:             $r->print('<option value="'.$tempkey.'"');
                   2577:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2578:                 $r->print(' selected="selected"');
                   2579:             }
                   2580:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2581:         }
1.208     www      2582:     }
1.446     bisitz   2583:     $r->print('</select>');
1.209     www      2584: }
                   2585: 
1.562     damieng  2586: # Prints HTML to select a user and/or a group.
                   2587: # Used by table mode.
                   2588: #
                   2589: # @param {Apache2::RequestRec} $r - the Apache request
                   2590: # @param {string} $uname - selected user name
                   2591: # @param {string} $id - selected Student/Employee ID
                   2592: # @param {string} $udom - selected user domain
                   2593: # @param {string} $csec - selected section name
                   2594: # @param {string} $cgroup - selected group name
                   2595: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2596: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2597: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2598: sub usermenu {
1.553     raeburn  2599:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2600:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2601:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2602:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2603: function setCourseadv(form,caller) {
                   2604:     if (caller.value == 'st') {
                   2605:         form.courseadv.value = 'none';
                   2606:     } else {
                   2607:         form.courseadv.value = '';
                   2608:     }
                   2609:     return;
                   2610: }
                   2611: ENDJS
1.412     bisitz   2612: 
1.596     raeburn  2613:     my (%chkroles,$stuonly,$courseadv);
                   2614:     if ($env{'form.userroles'} eq 'any') {
                   2615:         $chkroles{'any'} = ' checked="checked"';
                   2616:     } else {
                   2617:         $chkroles{'st'} = ' checked="checked"';
                   2618:         $courseadv = 'none';
                   2619:     }
                   2620:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2621:     if ($crstype eq 'Community') {
                   2622:         $stuonly = &mt('member only');
                   2623:     } else {
                   2624:         $stuonly = &mt('student only');
                   2625:     }
                   2626:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2627:                   &mt("User's role").':&nbsp;'.
                   2628:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2629:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2630:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2631:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2632:     my $sections='';
1.300     albertel 2633:     my %sectionhash = &Apache::loncommon::get_sections();
                   2634: 
1.269     raeburn  2635:     my $groups;
1.553     raeburn  2636:     my %grouphash;
                   2637:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2638:         %grouphash = &Apache::longroup::coursegroups();
                   2639:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2640:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2641:     }
1.299     albertel 2642: 
1.412     bisitz   2643:     my $g_s_header='';
                   2644:     my $g_s_footer='';
1.446     bisitz   2645: 
1.552     raeburn  2646:     my $currsec = $env{'request.course.sec'};
                   2647:     if ($currsec) {
                   2648:         $sections=&mt('Section:').' '.$currsec;
                   2649:         if (%grouphash) {
                   2650:             $sections .= ';'.('&nbsp;' x2);
                   2651:         }
                   2652:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2653:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2654:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2655:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2656:         }
                   2657:         $sections .= '>';
1.548     raeburn  2658:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2659:         $sections.='<option value="'.$section.'" '.
                   2660:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2661:                                                               '</option>';
1.209     www      2662:         }
                   2663:         $sections.='</select>';
1.269     raeburn  2664:     }
1.412     bisitz   2665: 
1.552     raeburn  2666:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2667:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2668:         $sections .= qq|
                   2669: <script type="text/javascript">
1.454     bisitz   2670: // <![CDATA[
1.269     raeburn  2671: function group_or_section(caller) {
                   2672:    if (caller == "cgroup") {
                   2673:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2674:            document.parmform.csec.selectedIndex = 0;
                   2675:        }
                   2676:    } else {
                   2677:        if (document.parmform.csec.selectedIndex != 0) {
                   2678:            document.parmform.cgroup.selectedIndex = 0;
                   2679:        }
                   2680:    }
                   2681: }
1.454     bisitz   2682: // ]]>
1.269     raeburn  2683: </script>
                   2684: |;
1.554     raeburn  2685:     } else {
1.269     raeburn  2686:         $sections .= qq|
                   2687: <script type="text/javascript">
1.454     bisitz   2688: // <![CDATA[
1.269     raeburn  2689: function group_or_section(caller) {
                   2690:     return;
                   2691: }
1.454     bisitz   2692: // ]]>
1.269     raeburn  2693: </script>
                   2694: |;
1.446     bisitz   2695:     }
1.299     albertel 2696: 
                   2697:     if (%grouphash) {
1.597     raeburn  2698:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2699:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2700:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2701:         }
                   2702:         $groups .= '>';
1.548     raeburn  2703:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2704:             $groups.='<option value="'.$grp.'" ';
                   2705:             if ($grp eq $cgroup) {
                   2706:                 unless ((defined($uname)) && ($grp eq '')) {
                   2707:                     $groups .=  'selected="selected" ';
                   2708:                 }
                   2709:             } elsif (!defined($cgroup)) {
                   2710:                 if (@{$usersgroups} == 1) {
                   2711:                     if ($grp eq $$usersgroups[0]) {
                   2712:                         $groups .=  'selected="selected" ';
                   2713:                     }
                   2714:                 }
                   2715:             }
                   2716:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2717:         }
                   2718:         $groups.='</select>';
                   2719:     }
1.412     bisitz   2720: 
1.445     neumanie 2721:     if (%sectionhash || %grouphash) {
1.446     bisitz   2722:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2723:         $r->print($sections.$groups);
1.448     bisitz   2724:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2725:     } else {
                   2726:         $r->print($sections); 
1.445     neumanie 2727:     }
1.446     bisitz   2728: 
                   2729:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2730:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2731:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2732:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2733:                  ,$chooseopt));
1.209     www      2734: }
                   2735: 
1.562     damieng  2736: # Prints HTML to select parameters from a list of all parameters.
                   2737: # Uses parmmenu and parmboxes.
                   2738: # Used by table and overview modes.
1.468     amueller 2739: #
1.562     damieng  2740: # @param {Apache2::RequestRec} $r - the Apache request
                   2741: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2742: # @param {array reference} $pscat - list of selected parameter names
                   2743: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2744: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2745: sub displaymenu {
1.581     raeburn  2746:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2747: 
1.445     neumanie 2748:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2749:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2750: 
1.581     raeburn  2751:     &parmmenu($r);
1.536     raeburn  2752:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2753:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2754:     $r->print(&Apache::loncommon::end_scrollbox());
                   2755: 
                   2756:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2757:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2758:  
1.209     www      2759: }
                   2760: 
1.562     damieng  2761: # Prints HTML to select a map.
                   2762: # Used by table mode and overview mode.
                   2763: #
                   2764: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2765: # @param {hash reference} $allmaps - hash map pc -> map src
                   2766: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2767: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2768: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610     raeburn  2769: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445     neumanie 2770: sub mapmenu {
1.610     raeburn  2771:     my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468     amueller 2772:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2773:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2774:     my $tree=[];
                   2775:     my $treeinfo={};
                   2776:     if (defined($navmap)) {
1.499     raeburn  2777:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2778:         my $curRes;
                   2779:         my $depth = 0;
1.468     amueller 2780:         my %parent = ();
                   2781:         my $startcount = 5;
                   2782:         my $lastcontainer = $startcount;
                   2783: # preparing what is to show ...
1.461     neumanie 2784:         while ($curRes = $it->next()) {
                   2785:             if ($curRes == $it->BEGIN_MAP()) {
                   2786:                 $depth++;
1.468     amueller 2787:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2788:             }
                   2789:             if ($curRes == $it->END_MAP()) {
                   2790:                 $depth--;
1.468     amueller 2791:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2792:             }
                   2793:             if (ref($curRes)) {
1.468     amueller 2794:                 my $symb = $curRes->symb();
                   2795:                 my $ressymb = $symb;
1.461     neumanie 2796:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2797:                     my $type = 'sequence';
                   2798:                     if ($curRes->is_page()) {
                   2799:                         $type = 'page';
                   2800:                     }
                   2801:                     my $id= $curRes->id();
1.468     amueller 2802:                     my $srcf = $curRes->src();
                   2803:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2804:                     if(!exists($treeinfo->{$id})) {
                   2805:                         push(@$tree,$id);
1.473     amueller 2806:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2807:                         $treeinfo->{$id} = {
1.461     neumanie 2808:                                     depth => $depth,
                   2809:                                     type  => $type,
1.468     amueller 2810:                                     name  => $resource_name,
                   2811:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2812:                                     };
1.462     neumanie 2813:                     }
1.461     neumanie 2814:                 }
                   2815:             }
                   2816:         }
1.462     neumanie 2817:     }
1.473     amueller 2818: # Show it ...    
1.610     raeburn  2819:     my $rowattr = ' id="mapmenu"';
                   2820:     if ($parmlev eq 'general') {
                   2821:         $rowattr .= ' style="display:none"';
                   2822:     }
                   2823:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461     neumanie 2824:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2825:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2826:         my $whitespace =
                   2827:             '<img src="'
                   2828:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2829:            .'" alt="" />';
                   2830: 
1.498     bisitz   2831:         # Info about selectable folders/maps
                   2832:         $r->print(
                   2833:             '<div class="LC_info">'
1.508     www      2834:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2835:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2836:            .'</div>'
                   2837:         );
                   2838: 
1.536     raeburn  2839:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2840:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2841: 
1.498     bisitz   2842:         # Display row: "All Maps or Folders"
                   2843:         $r->print(
1.523     raeburn  2844:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2845:            .'<td>'
                   2846:            .'<label>'
                   2847:            .'<input type="radio" name="pschp"'
1.497     bisitz   2848:         );
                   2849:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2850:         $r->print(
                   2851:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2852:            .&mt('All Maps or Folders')
                   2853:            .'</label>'
                   2854:            .'<hr /></td>'
                   2855:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2856:         );
1.497     bisitz   2857: 
1.532     raeburn  2858:         # Display row: "Main Content"
1.468     amueller 2859:         if (exists($$allmaps{1})) {
1.498     bisitz   2860:             $r->print(
                   2861:                 &Apache::loncommon::start_data_table_row()
                   2862:                .'<td>'
                   2863:                .'<label>'
                   2864:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2865:             );
1.497     bisitz   2866:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2867:             $r->print(
                   2868:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2869:                .$$maptitles{1}
                   2870:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2871:                .'</label>'
                   2872:                .'</td>'
                   2873:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2874:             );
                   2875:         }
1.497     bisitz   2876: 
                   2877:         # Display rows for all course maps and folders
1.468     amueller 2878:         foreach my $id (@{$tree}) {
                   2879:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2880:             # Indentation
1.468     amueller 2881:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2882:             my $indent;
                   2883:             for (my $i = 0; $i < $depth; $i++) {
                   2884:                 $indent.= $whitespace;
                   2885:             }
1.461     neumanie 2886:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2887:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2888:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2889:             }
1.468     amueller 2890:             my $symb_name = $$symbp{$id};
                   2891:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2892:             $symb_name = $tail;
1.498     bisitz   2893:             $r->print(
                   2894:                 &Apache::loncommon::start_data_table_row()
                   2895:                .'<td>'
                   2896:                .'<label>'
1.463     bisitz   2897:             );
1.498     bisitz   2898:             # Only offer radio button for folders/maps which can be parameterized
                   2899:             if ($allmaps_inverted{$symb_name}) {
                   2900:                 $r->print(
                   2901:                     '<input type ="radio" name="pschp"'
                   2902:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2903:                 );
                   2904:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2905:                 $r->print('/>');
                   2906:             } else {
                   2907:                 $r->print($whitespace);
1.461     neumanie 2908:             }
1.498     bisitz   2909:             $r->print(
                   2910:                 $indent.$icon.'&nbsp;'
                   2911:                .$treeinfo->{$id}->{name}
                   2912:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2913:                .'</label>'
                   2914:                .'</td>'
                   2915:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2916:             );
1.461     neumanie 2917:         }
1.497     bisitz   2918: 
1.523     raeburn  2919:         $r->print(&Apache::loncommon::end_data_table().
                   2920:                   '<br style="line-height:2px;" />'.
                   2921:                   &Apache::loncommon::end_scrollbox());
1.209     www      2922:     }
                   2923: }
                   2924: 
1.563     damieng  2925: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2926: # Used by table and overview modes.
                   2927: #
                   2928: # @param {Apache2::RequestRec} $r - the Apache request
                   2929: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2930: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2931: sub levelmenu {
1.446     bisitz   2932:     my ($r,$alllevs,$parmlev)=@_;
                   2933: 
1.548     raeburn  2934:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2935:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2936:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2937:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2938:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2939:         if ($parmlev eq $$alllevs{$lev}) {
                   2940:             $r->print(' selected="selected"');
                   2941:         }
                   2942:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2943:     }
1.446     bisitz   2944:     $r->print("</select>");
1.208     www      2945: }
                   2946: 
1.211     www      2947: 
1.563     damieng  2948: # Returns HTML to select a section (with a select HTML element).
                   2949: # Used by overview mode.
                   2950: #
                   2951: # @param {array reference} $selectedsections - list of selected section ids
                   2952: # @returns {string}
1.211     www      2953: sub sectionmenu {
1.553     raeburn  2954:     my ($selectedsections)=@_;
1.300     albertel 2955:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2956:     return '' if (!%sectionhash);
1.300     albertel 2957: 
1.552     raeburn  2958:     my (@possibles,$disabled);
                   2959:     if ($env{'request.course.sec'} ne '') {
                   2960:         @possibles = ($env{'request.course.sec'});
                   2961:         $selectedsections = [$env{'request.course.sec'}];
                   2962:         $disabled = ' disabled="disabled"';
                   2963:     } else {
                   2964:         @possibles = ('all',sort(keys(%sectionhash)));
                   2965:     }
1.553     raeburn  2966:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2967:     foreach my $s (@possibles) {
1.553     raeburn  2968:         $output .= '    <option value="'.$s.'"';
                   2969:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2970:             $output .= ' selected="selected"';
1.473     amueller 2971:         }
1.553     raeburn  2972:         $output .= '>'."$s</option>\n";
1.300     albertel 2973:     }
1.553     raeburn  2974:     $output .= "</select>\n";
                   2975:     return $output;
1.269     raeburn  2976: }
                   2977: 
1.563     damieng  2978: # Returns HTML to select a group (with a select HTML element).
                   2979: # Used by overview mode.
                   2980: #
                   2981: # @param {array reference} $selectedgroups - list of selected group names
                   2982: # @returns {string}
1.269     raeburn  2983: sub groupmenu {
1.553     raeburn  2984:     my ($selectedgroups)=@_;
                   2985:     my %grouphash;
                   2986:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2987:         %grouphash = &Apache::longroup::coursegroups();
                   2988:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2989:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2990:     }
                   2991:     return '' if (!%grouphash);
1.299     albertel 2992: 
1.553     raeburn  2993:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2994:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2995:         $output .= '    <option value="'.$group.'"';
                   2996:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2997:             $output .=  ' selected="selected"';
1.473     amueller 2998:         }
1.553     raeburn  2999:         $output .= '>'."$group</option>\n";
1.211     www      3000:     }
1.553     raeburn  3001:     $output .= "</select>\n";
                   3002:     return $output;
1.211     www      3003: }
                   3004: 
1.563     damieng  3005: # Returns an array with the given parameter split by comma.
                   3006: # Used by assessparms (table mode).
                   3007: #
                   3008: # @param {string} $keyp - the string to split
                   3009: # @returns {Array<string>}
1.210     www      3010: sub keysplit {
                   3011:     my $keyp=shift;
                   3012:     return (split(/\,/,$keyp));
                   3013: }
                   3014: 
1.563     damieng  3015: # Returns the keys in $name, sorted using $keyorder.
                   3016: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   3017: # Used by assessparms (table mode) for resource level.
                   3018: #
                   3019: # @param {hash reference} $name - parameter key -> parameter name
                   3020: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3021: # @returns {Array<string>}
1.210     www      3022: sub keysinorder {
                   3023:     my ($name,$keyorder)=@_;
                   3024:     return sort {
1.560     damieng  3025:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  3026:     } (keys(%{$name}));
1.210     www      3027: }
                   3028: 
1.563     damieng  3029: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3030: # Used by assessparms (table mode) for map and general levels.
                   3031: #
                   3032: # @param {hash reference} $name - parameter key -> parameter name
                   3033: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3034: # @returns {Array<string>}
1.236     albertel 3035: sub keysinorder_bytype {
                   3036:     my ($name,$keyorder)=@_;
                   3037:     return sort {
1.563     damieng  3038:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3039:         my $tb=(split('_',$b))[-1];
                   3040:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3041:             return ($a cmp $b);
                   3042:         }
                   3043:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3044:     } (keys(%{$name}));
1.236     albertel 3045: }
                   3046: 
1.563     damieng  3047: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3048: # Used by defaultsetter (parameter settings default actions).
                   3049: #
                   3050: # @param {hash reference} $name - hash parameter name -> parameter title
                   3051: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3052: # @returns {Array<string>}
1.211     www      3053: sub keysindisplayorder {
                   3054:     my ($name,$keyorder)=@_;
                   3055:     return sort {
1.560     damieng  3056:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3057:     } (keys(%{$name}));
1.211     www      3058: }
                   3059: 
1.563     damieng  3060: # Prints HTML with a choice to sort results by realm or student first.
                   3061: # Used by overview mode.
                   3062: #
                   3063: # @param {Apache2::RequestRec} $r - the Apache request
                   3064: # @param {string} $sortorder - realmstudent|studentrealm
1.608     raeburn  3065: # @param {string} $context - newoverview|overview
1.214     www      3066: sub sortmenu {
1.608     raeburn  3067:     my ($r,$sortorder,$context)=@_;
                   3068:     my %text;
                   3069:     if ($context eq 'newoverview') {
                   3070:         %text = &Apache::lonlocal::texthash (
                   3071:                    realmstudent => 'Sort by location in course first, then student (group/section)',
                   3072:                    studentrealm => 'Sort by student (group/section) first, then location in course',
                   3073:         );
                   3074:     } else {
                   3075:         %text = &Apache::lonlocal::texthash (
                   3076:                    realmstudent => 'Sort by realm first, then student (group/section)',
                   3077:                    studentrealm => 'Sort by student (group/section) first, then realm',
                   3078:         );
1.214     www      3079:     }
1.608     raeburn  3080:     my %sortchecked = (
                   3081:        realmstudent => ' checked="checked"',
                   3082:        studentrealm => '',
                   3083:     );
1.214     www      3084:     if ($sortorder eq 'studentrealm') {
1.608     raeburn  3085:         $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
                   3086:         $sortchecked{'realmstudent'} = '';
                   3087:     }
                   3088:     foreach my $sorttype ('realmstudent','studentrealm') {
                   3089:         $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                   3090:                   $text{$sorttype}.'</label>');
1.214     www      3091:     }
                   3092: }
                   3093: 
1.563     damieng  3094: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3095: #
                   3096: # @returns {hash}
1.211     www      3097: sub standardkeyorder {
                   3098:     return ('parameter_0_opendate' => 1,
1.473     amueller 3099:         'parameter_0_duedate' => 2,
                   3100:         'parameter_0_answerdate' => 3,
                   3101:         'parameter_0_interval' => 4,
                   3102:         'parameter_0_weight' => 5,
                   3103:         'parameter_0_maxtries' => 6,
                   3104:         'parameter_0_hinttries' => 7,
                   3105:         'parameter_0_contentopen' => 8,
                   3106:         'parameter_0_contentclose' => 9,
                   3107:         'parameter_0_type' => 10,
                   3108:         'parameter_0_problemstatus' => 11,
                   3109:         'parameter_0_hiddenresource' => 12,
                   3110:         'parameter_0_hiddenparts' => 13,
                   3111:         'parameter_0_display' => 14,
                   3112:         'parameter_0_ordered' => 15,
                   3113:         'parameter_0_tol' => 16,
                   3114:         'parameter_0_sig' => 17,
                   3115:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3116:         'parameter_0_discussend' => 19,
                   3117:         'parameter_0_discusshide' => 20,
                   3118:         'parameter_0_discussvote' => 21,
1.560     damieng  3119:         'parameter_0_printstartdate'  =>  22,
                   3120:         'parameter_0_printenddate' =>  23);
1.211     www      3121: }
                   3122: 
1.59      matthew  3123: 
1.560     damieng  3124: # Table mode UI.
1.563     damieng  3125: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3126: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3127: #
                   3128: # Parameters used from the request:
                   3129: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3130: # cgroup - selected group
                   3131: # command - 'set': direct access to table mode for a resource
                   3132: # csec - selected section
                   3133: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3134: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3135: # id - student/employee ID
                   3136: # parmlev - selected level (full|map|general)
                   3137: # part - selected part (unused ?)
                   3138: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3139: # pres_type - &&&-separated parameter types
                   3140: # pres_value - &&&-separated parameter values
                   3141: # prevvisit - '1' if the user has submitted the form before
                   3142: # pscat (multiple values) - selected parameter names
1.566     damieng  3143: # pschp - selected map pc, or 'all'
1.563     damieng  3144: # psprt (multiple values) - list of selected parameter parts
                   3145: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3146: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3147: # symb - resource symb (when a single resource is selected)
                   3148: # udom - selected user domain
                   3149: # uname - selected user name
                   3150: # url - used only with command 'set', the resource url
                   3151: #
                   3152: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3153: # @param $parm_permission - ref to hash of permissions
                   3154: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3155: sub assessparms {
1.1       www      3156: 
1.568     raeburn  3157:     my ($r,$parm_permission) = @_;
1.201     www      3158: 
1.512     foxr     3159: 
                   3160: # -------------------------------------------------------- Variable declaration
1.566     damieng  3161:     my @ids=(); # resource and map ids
                   3162:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3163:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3164:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3165:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3166:     my %uris=(); # hash resource/map id -> resource src
                   3167:     my %maptitles=(); # hash map pc or src -> map title
                   3168:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3169:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3170:     my %alllevs=(); # hash English level title -> value
                   3171: 
                   3172:     my $uname; # selected user name
                   3173:     my $udom; # selected user domain
                   3174:     my $uhome; # server with the user's files, or 'no_host'
                   3175:     my $csec; # selected section name
                   3176:     my $cgroup; # selected group name
                   3177:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3178:     my $numreclinks = 0;
1.446     bisitz   3179: 
1.190     albertel 3180:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3181: 
1.57      albertel 3182:     $alllevs{'Resource Level'}='full';
1.215     www      3183:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3184:     $alllevs{'Course Level'}='general';
                   3185: 
1.563     damieng  3186:     my %allparms; # hash parameter name -> parameter title
                   3187:     my %allparts; # hash parameter part -> part title
1.512     foxr     3188: # ------------------------------------------------------------------------------
                   3189: 
1.210     www      3190: #
                   3191: # Order in which these parameters will be displayed
                   3192: #
1.211     www      3193:     my %keyorder=&standardkeyorder();
                   3194: 
1.512     foxr     3195: #    @ids=();
                   3196: #    %symbp=();       # These seem defined above already.
                   3197: #    %typep=();
1.43      albertel 3198: 
                   3199:     my $message='';
                   3200: 
1.190     albertel 3201:     $csec=$env{'form.csec'};
1.552     raeburn  3202:     if ($env{'request.course.sec'} ne '') {
                   3203:         $csec = $env{'request.course.sec'};    
                   3204:     }
                   3205: 
1.553     raeburn  3206: # Check group privs.
1.269     raeburn  3207:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3208:     my $noeditgrp; 
                   3209:     if ($cgroup ne '') {
                   3210:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3211:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3212:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3213:                 $noeditgrp = 1;
                   3214:             }
                   3215:         }
                   3216:     }
1.188     www      3217: 
1.190     albertel 3218:     if      ($udom=$env{'form.udom'}) {
                   3219:     } elsif ($udom=$env{'request.role.domain'}) {
                   3220:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3221:     } else {
1.473     amueller 3222:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3223:     }
1.468     amueller 3224:     
1.43      albertel 3225: 
1.134     albertel 3226:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3227:     my $pschp=$env{'form.pschp'};
1.506     www      3228: 
                   3229: 
1.134     albertel 3230:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3231:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3232:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3233: 
1.43      albertel 3234:     my $pssymb='';
1.57      albertel 3235:     my $parmlev='';
1.446     bisitz   3236: 
1.190     albertel 3237:     unless ($env{'form.parmlev'}) {
1.57      albertel 3238:         $parmlev = 'map';
                   3239:     } else {
1.190     albertel 3240:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3241:     }
1.26      www      3242: 
1.29      www      3243: # ----------------------------------------------- Was this started from grades?
                   3244: 
1.560     damieng  3245:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3246:             (!$env{'form.dis'})) {
1.473     amueller 3247:         my $url=$env{'form.url'};
                   3248:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3249:         $pssymb=&Apache::lonnet::symbread($url);
                   3250:         if (!@pscat) { @pscat=('all'); }
                   3251:         $pschp='';
1.57      albertel 3252:         $parmlev = 'full';
1.190     albertel 3253:     } elsif ($env{'form.symb'}) {
1.473     amueller 3254:         $pssymb=$env{'form.symb'};
                   3255:         if (!@pscat) { @pscat=('all'); }
                   3256:         $pschp='';
1.57      albertel 3257:         $parmlev = 'full';
1.43      albertel 3258:     } else {
1.473     amueller 3259:         $env{'form.url'}='';
1.43      albertel 3260:     }
                   3261: 
1.190     albertel 3262:     my $id=$env{'form.id'};
1.43      albertel 3263:     if (($id) && ($udom)) {
1.555     raeburn  3264:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3265:         if ($uname) {
                   3266:             $id='';
                   3267:         } else {
                   3268:             $message=
1.540     bisitz   3269:                 '<p class="LC_warning">'.
                   3270:                 &mt('Unknown ID [_1] at domain [_2]',
                   3271:                     "'".$id."'","'".$udom."'").
                   3272:                 '</p>';
1.473     amueller 3273:         }
1.43      albertel 3274:     } else {
1.473     amueller 3275:         $uname=$env{'form.uname'};
1.43      albertel 3276:     }
                   3277:     unless ($udom) { $uname=''; }
                   3278:     $uhome='';
                   3279:     if ($uname) {
1.473     amueller 3280:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3281:         if ($uhome eq 'no_host') {
1.473     amueller 3282:             $message=
1.540     bisitz   3283:                 '<p class="LC_warning">'.
                   3284:                 &mt('Unknown user [_1] at domain [_2]',
                   3285:                     "'".$uname."'","'".$udom."'").
                   3286:                 '</p>';
1.473     amueller 3287:             $uname='';
1.12      www      3288:         } else {
1.473     amueller 3289:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3290:                           $env{'request.course.id'});
                   3291:             if ($csec eq '-1') {
1.596     raeburn  3292:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3293:                 if ($env{'form.userroles'} eq 'any') {
                   3294:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3295:                         $csec = $env{'request.course.sec'};
                   3296:                         $message = '<span class="LC_info">';
                   3297:                         if ($crstype eq 'Community') {
                   3298:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3299:                                             $uname,$udom);
                   3300:                         } else {
                   3301:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3302:                                             $uname,$udom);
                   3303:                         }
                   3304:                         $message .= '</span>';
                   3305:                     } else {
                   3306:                         my @possroles = ('in','ep','ta','cr');
                   3307:                         if ($crstype eq 'Community') {
                   3308:                             unshift(@possroles,'co');
                   3309:                         } else {
                   3310:                             unshift(@possroles,'cc');
                   3311:                         }
                   3312:                         my %not_student_roles =
                   3313:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3314:                                                           \@possroles,[$udom],1,1);
                   3315:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3316:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3317:                         my %sections_by_role;
                   3318:                         foreach my $role (keys(%not_student_roles)) {
                   3319:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3320:                                 my ($rolename,$sec) = ($1,$2);
                   3321:                                 if ($rolename =~ m{^cr/}) {
                   3322:                                     $rolename = 'cr';
                   3323:                                 }
                   3324:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3325:                             }
                   3326:                         }
                   3327:                         my $numroles = scalar(keys(%sections_by_role));
                   3328:                         if ($numroles) {
                   3329:                             foreach my $role (@possroles) {
                   3330:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3331:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3332:                                     $csec = $secs[0];
                   3333:                                     last;
                   3334:                                 }
                   3335:                             }
                   3336:                         }
                   3337:                         if ($csec eq '-1') {
                   3338:                             $message = '<span class="LC_warning">';
                   3339:                             if ($crstype eq 'Community') {
                   3340:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3341:                                                 $uname,$udom);
                   3342:                             } else {
                   3343:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3344:                                                 $uname,$udom);
                   3345:                             }
                   3346:                             $message .= '</span>';
                   3347:                             $uname='';
                   3348:                             if ($env{'request.course.sec'} ne '') {
                   3349:                                 $csec=$env{'request.course.sec'};
                   3350:                             } else {
                   3351:                                 $csec=$env{'form.csec'};
                   3352:                             }
                   3353:                             $cgroup=$env{'form.cgroup'};
                   3354:                         } else {
                   3355:                             $message = '<span class="LC_info">';
                   3356:                             if ($crstype eq 'Community') {
                   3357:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3358:                                          $uname,$udom);
                   3359:                             } else {
                   3360:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3361:                                                 $uname,$udom);
                   3362:                             }
                   3363:                             $message .= '</span>';
                   3364:                         }
                   3365:                     }
1.594     raeburn  3366:                 } else {
1.596     raeburn  3367:                     $message = '<span class="LC_warning">';
                   3368:                     if ($crstype eq 'Community') {
                   3369:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3370:                                          $uname,$udom);
                   3371:                     } else {
                   3372:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3373:                                          $uname,$udom);
                   3374:                     }
                   3375:                     $message .= '</span>';
                   3376:                     $uname='';
                   3377:                     if ($env{'request.course.sec'} ne '') {
                   3378:                         $csec=$env{'request.course.sec'};
                   3379:                     } else {
                   3380:                         $csec=$env{'form.csec'};
                   3381:                     }
                   3382:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3383:                 }
                   3384:             } elsif ($env{'request.course.sec'} ne '') {
                   3385:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3386:                     $message='<span class="LC_warning">'.
1.594     raeburn  3387:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3388:                                   $uname,$udom,$env{'request.course.sec'}).
                   3389:                               '</span>';
                   3390:                     $uname='';
                   3391:                     $csec=$env{'request.course.sec'};
                   3392:                 }
1.269     raeburn  3393:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3394:             }
                   3395:             if ($uname ne '') {
1.473     amueller 3396:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3397:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3398:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3399:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3400:                             .$name{'lastname'}.' '.$name{'generation'}
                   3401:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3402:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3403:                                    $udom,$uname,$env{'request.course.id'});
                   3404:                 if (@usersgroups > 0) {
                   3405:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3406:                         $cgroup = $usersgroups[0];
                   3407:                     }
                   3408:                 } else {
                   3409:                     $cgroup = '';
1.297     raeburn  3410:                 }
1.269     raeburn  3411:             }
1.12      www      3412:         }
1.43      albertel 3413:     }
1.2       www      3414: 
1.43      albertel 3415:     unless ($csec) { $csec=''; }
1.269     raeburn  3416:     unless ($cgroup) { $cgroup=''; }
1.12      www      3417: 
1.14      www      3418: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3419:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3420:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3421:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3422: 
1.582     raeburn  3423:     %allmaps_inverted = reverse(%allmaps);
                   3424: 
1.57      albertel 3425:     $mapp{'0.0'} = '';
                   3426:     $symbp{'0.0'} = '';
1.99      albertel 3427: 
1.14      www      3428: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3429:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3430:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3431:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3432:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3433:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3434:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3435:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3436:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3437:         my $totalstored = 0;
1.605     raeburn  3438:         my $totalskippeduser = 0;
1.546     raeburn  3439:         my $now = time;
1.473     amueller 3440:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3441:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3442:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3443:                 next if ($csec ne $env{'request.course.sec'});
                   3444:             }
1.556     raeburn  3445:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3446:                 next if ($noeditgrp);
1.605     raeburn  3447:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3448:                 if ($uname eq '') {
                   3449:                     $totalskippeduser ++;
                   3450:                     next;
                   3451:                 }
1.557     raeburn  3452:             }
                   3453:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3454:                 $namematch = 'maplevelrecurse';
                   3455:             }
1.556     raeburn  3456:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3457:                 my (@ok_slots,@fail_slots,@del_slots);
                   3458:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3459:                 my ($level,@all) =
                   3460:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3461:                                      $csec,$cgroup,$courseopt);
                   3462:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3463:                     next if ($slot_name eq '');
                   3464:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3465:                         push(@ok_slots,$slot_name);
                   3466: 
                   3467:                     } else {
                   3468:                         push(@fail_slots,$slot_name);
                   3469:                     }
                   3470:                 }
                   3471:                 if (@ok_slots) {
                   3472:                     $values[$i] = join(':',@ok_slots);
                   3473:                 } else {
                   3474:                     $values[$i] = '';
                   3475:                 }
                   3476:                 if ($all[$level] ne '') {
                   3477:                     my @existing = split(/:/,$all[$level]);
                   3478:                     foreach my $slot_name (@existing) {
                   3479:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3480:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3481:                                 push(@del_slots,$slot_name);
                   3482:                             }
                   3483:                         }
                   3484:                     }
                   3485:                 }
1.554     raeburn  3486:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3487:                 $name = $1;
1.533     raeburn  3488:                 my $val = $values[$i];
1.549     raeburn  3489:                 my $valmatch = '';
1.533     raeburn  3490:                 if ($name eq 'examcode') {
1.544     raeburn  3491:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3492:                         $val = 'valid';
                   3493:                     }
1.546     raeburn  3494:                 } elsif ($name eq 'printstartdate') {
                   3495:                     if ($val =~ /^\d+$/) {
                   3496:                         if ($val > $now) {
                   3497:                             $val = 'future';
                   3498:                         }
                   3499:                     } 
                   3500:                 } elsif ($name eq 'printenddate') {
                   3501:                     if ($val =~ /^\d+$/) {
                   3502:                         if ($val < $now) {
                   3503:                             $val = 'past';
                   3504:                         }
                   3505:                     }
1.549     raeburn  3506:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3507:                     my $stringtype = &get_stringtype($name);
                   3508:                     my $stringmatch = &standard_string_matches($stringtype);
                   3509:                     if (ref($stringmatch) eq 'ARRAY') {
                   3510:                         foreach my $item (@{$stringmatch}) {
                   3511:                             if (ref($item) eq 'ARRAY') {
                   3512:                                 my ($regexpname,$pattern) = @{$item};
                   3513:                                 if ($pattern ne '') {
                   3514:                                     if ($val =~ /$pattern/) {
                   3515:                                         $valmatch = $regexpname;
                   3516:                                         $val = '';
                   3517:                                         last;
                   3518:                                     }
                   3519:                                 }
                   3520:                             }
                   3521:                         }
                   3522:                     }
1.554     raeburn  3523:                 } elsif ($name eq 'interval') {
                   3524:                     my $intervaltype = &get_intervaltype($name);
                   3525:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3526:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3527:                         foreach my $item (@{$intervalmatch}) {
                   3528:                             if (ref($item) eq 'ARRAY') {
                   3529:                                 my ($regexpname,$pattern) = @{$item};
                   3530:                                 if ($pattern ne '') {
                   3531:                                     if ($val =~ /$pattern/) {
                   3532:                                         $valmatch = $regexpname;
                   3533:                                         $val = '';
                   3534:                                         last;
                   3535:                                     }
                   3536:                                 }
                   3537:                             }
                   3538:                         }
                   3539:                     }
1.533     raeburn  3540:                 }
1.504     raeburn  3541:                 $needsrelease =
1.557     raeburn  3542:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3543:                 if ($needsrelease) {
1.505     raeburn  3544:                     unless ($got_chostname) {
1.514     raeburn  3545:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3546:                         $got_chostname = 1;
1.546     raeburn  3547:                     } 
1.557     raeburn  3548:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3549:                                                           $needsrelease,
                   3550:                                                           $cmajor,$cminor);
1.500     raeburn  3551:                 }
1.437     raeburn  3552:             }
1.504     raeburn  3553:             if ($needsnewer) {
1.557     raeburn  3554:                 undef($namematch);
                   3555:             } else {
                   3556:                 my $currneeded;
                   3557:                 if ($needsrelease) {
                   3558:                     $currneeded = $needsrelease;
                   3559:                 }
                   3560:                 if ($namematch) {
                   3561:                     $needsrelease =
                   3562:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3563:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3564:                         unless ($got_chostname) {
                   3565:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3566:                             $got_chostname = 1;
                   3567:                         }
                   3568:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3569:                                                               $needsrelease,
                   3570:                                                               $cmajor,$cminor);
                   3571:                     } else {
                   3572:                         undef($namematch);
                   3573:                     }
                   3574:                 }
                   3575:             }
                   3576:             if ($needsnewer) {
                   3577:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3578:                                                 $cminor,$needsrelease);
                   3579:             } else {
                   3580:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3581:                                      $values[$i],
                   3582:                                      $types[$i],
                   3583:                                      $uname,$udom,$csec,$cgroup);
                   3584:                 $totalstored ++;
                   3585:             }
1.473     amueller 3586:         }
1.68      www      3587: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3588:         if ($totalstored) {
                   3589:             $message.='<p class="LC_warning">'
1.605     raeburn  3590:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3591:                      .'<br />'
1.504     raeburn  3592:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3593:                      .&Apache::loncommon::help_open_topic('Caching')
                   3594:                      .'</p>';
1.605     raeburn  3595:         } else {
                   3596:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3597:         }
                   3598:         if ($totalskippeduser) {
                   3599:             $message .= '<p class="LC_warning">';
                   3600:             if ($uhome eq 'no_host') {
                   3601:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3602:                                 $totalskippeduser);
                   3603:             } elsif ($env{'form.userroles'} eq 'any') {
                   3604:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3605:                                 $totalskippeduser);
                   3606:             } else {
                   3607:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3608:                                 $totalskippeduser);
                   3609:             }
                   3610:             $message .= '</p>';
1.504     raeburn  3611:         }
1.68      www      3612:     }
1.584     raeburn  3613: 
1.57      albertel 3614: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3615:     if ($pscat[0] eq "all") {
                   3616:         @pscat = (keys(%allparms));
                   3617:     }
                   3618:     if (!@pscat) {
                   3619:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3620:     };
                   3621:     if ($psprt[0] eq "all" || !@psprt) {
                   3622:         @psprt = (keys(%allparts));
                   3623:     }
1.2       www      3624: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3625: 
1.531     raeburn  3626:     my $crstype = &Apache::loncommon::course_type();
                   3627:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3628: 
1.548     raeburn  3629:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3630:             'date_interval','int','float','string','string_lenient',
                   3631:             'string_examcode','string_deeplink','string_discussvote',
                   3632:             'string_useslots','string_problemstatus','string_ip',
                   3633:             'string_questiontype') {
1.473     amueller 3634:         $r->print('<input type="hidden" value="'.
1.563     damieng  3635:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3636:             '" name="recent_'.$item.'" />');
1.44      albertel 3637:     }
1.446     bisitz   3638: 
1.459     bisitz   3639:     # ----- Start Parameter Selection
                   3640: 
1.606     raeburn  3641:     # Hide parm selection and possibly table?
                   3642:     my ($tablejs,$tabledivsty);
                   3643:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
                   3644:         ($env{'form.dis'}) && ($pssymb eq '')) {
                   3645:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
                   3646:         $tabledivsty = ' style="display:none"';
                   3647:     }
1.459     bisitz   3648:     $r->print(<<ENDPARMSELSCRIPT);
                   3649: <script type="text/javascript">
                   3650: // <![CDATA[
                   3651: function parmsel_show() {
1.562     damieng  3652:     document.getElementById('parmsel').style.display = "";
                   3653:     document.getElementById('parmsellink').style.display = "none";
1.606     raeburn  3654:     $tablejs
1.459     bisitz   3655: }
                   3656: // ]]>
                   3657: </script>
                   3658: ENDPARMSELSCRIPT
1.474     amueller 3659:     
1.445     neumanie 3660:     if (!$pssymb) {
1.563     damieng  3661:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3662:         my $parmselhiddenstyle=' style="display:none"';
                   3663:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3664:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3665:         } else  {
                   3666:            $r->print('<div id="parmsel">');
                   3667:         }
                   3668: 
1.491     bisitz   3669:         # Step 1
1.523     raeburn  3670:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3671:         $r->print('
1.474     amueller 3672: <script type="text/javascript">
1.523     raeburn  3673: // <![CDATA['.
                   3674:                  &showhide_js().'
1.474     amueller 3675: // ]]>
                   3676: </script>
1.523     raeburn  3677: ');
                   3678:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3679:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3680:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.610     raeburn  3681:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491     bisitz   3682:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3683:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3684:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3685:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3686:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3687: 
                   3688:         # Step 2
1.523     raeburn  3689:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3690:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3691: 
                   3692:         # Step 3
1.523     raeburn  3693:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3694:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3695:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3696:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3697:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3698: 
                   3699:         # Update Display Button
1.486     www      3700:         $r->print('<p>'
                   3701:              .'<input type="submit" name="dis"'
1.511     www      3702:              .' value="'.&mt('Update Display').'" />'
1.486     www      3703:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3704:              .'</p>');
                   3705:         $r->print('</div>');
1.491     bisitz   3706: 
1.486     www      3707:         # Offer link to display parameter selection again
                   3708:         $r->print('<p id="parmsellink"');
                   3709:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3710:            $r->print($parmselhiddenstyle);
                   3711:         }
                   3712:         $r->print('>'
                   3713:              .'<a href="javascript:parmsel_show()">'
                   3714:              .&mt('Change Parameter Selection')
                   3715:              .'</a>'
                   3716:              .'</p>');
1.44      albertel 3717:     } else {
1.478     amueller 3718:         # parameter screen for a single resource. 
1.486     www      3719:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3720:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3721:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3722:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3723:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3724:                   '<br />');
                   3725:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3726:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3727:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3728:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3729:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3730:         $r->print('<p>'
1.459     bisitz   3731:              .'<input type="submit" name="dis"'
1.511     www      3732:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3733:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3734:              .'</p>');
1.459     bisitz   3735:     }
1.478     amueller 3736:     
1.486     www      3737:     # ----- End Parameter Selection
1.57      albertel 3738: 
1.459     bisitz   3739:     # Display Messages
                   3740:     $r->print('<div>'.$message.'</div>');
1.210     www      3741: 
1.57      albertel 3742: 
                   3743:     my @temp_pscat;
                   3744:     map {
                   3745:         my $cat = $_;
                   3746:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3747:     } @pscat;
                   3748: 
                   3749:     @pscat = @temp_pscat;
                   3750: 
1.548     raeburn  3751: 
1.209     www      3752:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3753: # ----------------------------------------------------------------- Start Table
1.57      albertel 3754:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3755:         my $csuname=$env{'user.name'};
                   3756:         my $csudom=$env{'user.domain'};
1.568     raeburn  3757:         my $readonly = 1;
                   3758:         if ($parm_permission->{'edit'}) {
                   3759:             undef($readonly); 
                   3760:         }
1.606     raeburn  3761:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3762: 
1.203     www      3763:         if ($parmlev eq 'full') {
1.506     www      3764: #
                   3765: # This produces the cascading table output of parameters
                   3766: #
1.578     raeburn  3767:             my $coursespan=$csec?8:5;
                   3768:             my $userspan=3;
1.560     damieng  3769:             if ($cgroup ne '') {
1.578     raeburn  3770:                 $coursespan += 3;
1.560     damieng  3771:             }
1.473     amueller 3772: 
1.560     damieng  3773:             $r->print(&Apache::loncommon::start_data_table());
                   3774:             #
                   3775:             # This produces the headers
                   3776:             #
                   3777:             $r->print('<tr><td colspan="5"></td>');
                   3778:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3779:             if ($uname) {
1.473     amueller 3780:                 if (@usersgroups > 1) {
1.560     damieng  3781:                     $userspan ++;
                   3782:                 }
                   3783:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3784:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3785:             }
                   3786:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3787:                 'pie'    => "Parameter in Effect",
                   3788:                 'csv'    => "Current Session Value",
1.472     amueller 3789:                 'rl'     => "Resource Level",
1.473     amueller 3790:                 'ic'     => 'in Course',
                   3791:                 'aut'    => "Assessment URL and Title",
                   3792:                 'type'   => 'Type',
                   3793:                 'emof'   => "Enclosing Map or Folder",
                   3794:                 'part'   => 'Part',
1.472     amueller 3795:                 'pn'     => 'Parameter Name',
1.473     amueller 3796:                 'def'    => 'default',
                   3797:                 'femof'  => 'from Enclosing Map or Folder',
                   3798:                 'gen'    => 'general',
                   3799:                 'foremf' => 'for Enclosing Map or Folder',
                   3800:                 'fr'     => 'for Resource'
                   3801:             );
1.560     damieng  3802:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3803: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3804: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3805: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3806: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3807: 
1.10      www      3808: ENDTABLETWO
1.560     damieng  3809:             if ($csec) {
1.578     raeburn  3810:                 $r->print('<th colspan="3">'.
1.560     damieng  3811:                 &mt("in Section")." $csec</th>");
                   3812:             }
                   3813:             if ($cgroup) {
1.578     raeburn  3814:                 $r->print('<th colspan="3">'.
1.472     amueller 3815:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3816:             }
                   3817:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3818: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3819: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3820: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3821: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3822: ENDTABLEHEADFOUR
1.57      albertel 3823: 
1.560     damieng  3824:             if ($csec) {
1.578     raeburn  3825:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3826:             }
1.473     amueller 3827: 
1.560     damieng  3828:             if ($cgroup) {
1.578     raeburn  3829:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3830:             }
                   3831: 
                   3832:             if ($uname) {
                   3833:                 if (@usersgroups > 1) {
                   3834:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3835:                 }
1.578     raeburn  3836:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3837:             }
                   3838: 
                   3839:             $r->print('</tr>');
1.506     www      3840: #
                   3841: # Done with the headers
                   3842: # 
1.560     damieng  3843:             my $defbgone='';
                   3844:             my $defbgtwo='';
                   3845:             my $defbgthree = '';
1.57      albertel 3846: 
1.560     damieng  3847:             foreach my $rid (@ids) {
1.57      albertel 3848: 
                   3849:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3850:                 if ((!$pssymb &&
1.560     damieng  3851:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3852:                         ||
                   3853:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3854: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3855:                     if ($defbgone eq '#E0E099') {
                   3856:                         $defbgone='#E0E0DD';
1.57      albertel 3857:                     } else {
1.419     bisitz   3858:                         $defbgone='#E0E099';
1.57      albertel 3859:                     }
1.419     bisitz   3860:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3861:                         $defbgtwo='#FFFFDD';
1.57      albertel 3862:                     } else {
1.473     amueller 3863:                         $defbgtwo='#FFFF99';
1.57      albertel 3864:                     }
1.419     bisitz   3865:                     if ($defbgthree eq '#FFBB99') {
                   3866:                         $defbgthree='#FFBBDD';
1.269     raeburn  3867:                     } else {
1.419     bisitz   3868:                         $defbgthree='#FFBB99';
1.269     raeburn  3869:                     }
                   3870: 
1.57      albertel 3871:                     my $thistitle='';
                   3872:                     my %name=   ();
                   3873:                     undef %name;
                   3874:                     my %part=   ();
                   3875:                     my %display=();
                   3876:                     my %type=   ();
                   3877:                     my %default=();
1.196     www      3878:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3879:                     my $toolsymb;
                   3880:                     if ($uri =~ /ext\.tool$/) {
                   3881:                         $toolsymb = $symbp{$rid};
                   3882:                     }
1.57      albertel 3883: 
1.506     www      3884:                     my $filter=$env{'form.filter'};
1.548     raeburn  3885:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3886:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3887:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3888:     # We may only want certain parameters listed
                   3889:                             if ($filter) {
                   3890:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3891:                             }
                   3892:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3893:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3894: 
1.584     raeburn  3895:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3896:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3897:                                 my $identifier;
                   3898:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3899:                                     $identifier = $1;
                   3900:                                 }
                   3901:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3902:                             } else {
                   3903:                                 $display{$tempkeyp} = $parmdis;
                   3904:                             }
                   3905:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3906:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3907:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3908:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3909:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3910:                         }
                   3911:                     }
1.548     raeburn  3912:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3913:                     if ($totalparms>0) {
1.560     damieng  3914:                         my $firstrow=1;
1.473     amueller 3915:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3916:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3917:                         my @recurseup;
                   3918:                         if (ref($navmap) && $mapp{$rid}) {
                   3919:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3920:                         }
1.419     bisitz   3921:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3922:                              ' rowspan='.$totalparms.
1.419     bisitz   3923:                              '><tt><font size="-1">'.
1.57      albertel 3924:                              join(' / ',split(/\//,$uri)).
                   3925:                              '</font></tt><p><b>'.
1.154     albertel 3926:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3927:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3928:                           &escape($symbp{$rid}).
1.336     albertel 3929:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3930:                              " target=\"_self\">$title");
1.57      albertel 3931: 
                   3932:                         if ($thistitle) {
1.473     amueller 3933:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3934:                         }
                   3935:                         $r->print('</a></b></td>');
1.419     bisitz   3936:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3937:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3938:                                       '</td>');
                   3939: 
1.419     bisitz   3940:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3941:                                       ' rowspan='.$totalparms.
1.238     www      3942:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3943:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3944:                             unless ($firstrow) {
                   3945:                                 $r->print('<tr>');
                   3946:                             } else {
                   3947:                                 undef $firstrow;
                   3948:                             }
1.548     raeburn  3949:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3950:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3951:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  3952:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   3953:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   3954:                                        \$numreclinks);
1.57      albertel 3955:                         }
                   3956:                     }
                   3957:                 }
                   3958:             } # end foreach ids
1.43      albertel 3959: # -------------------------------------------------- End entry for one resource
1.517     www      3960:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3961:         } # end of  full
1.57      albertel 3962: #--------------------------------------------------- Entry for parm level map
                   3963:         if ($parmlev eq 'map') {
1.419     bisitz   3964:             my $defbgone = '#E0E099';
                   3965:             my $defbgtwo = '#FFFF99';
                   3966:             my $defbgthree = '#FFBB99';
1.57      albertel 3967: 
                   3968:             my %maplist;
                   3969: 
                   3970:             if ($pschp eq 'all') {
1.446     bisitz   3971:                 %maplist = %allmaps;
1.57      albertel 3972:             } else {
                   3973:                 %maplist = ($pschp => $mapp{$pschp});
                   3974:             }
                   3975: 
                   3976: #-------------------------------------------- for each map, gather information
                   3977:             my $mapid;
1.607     raeburn  3978:             foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60      albertel 3979:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3980: 
                   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 = ();
                   3988:                 my $map = 0;
                   3989: 
1.473     amueller 3990: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3991: 
1.548     raeburn  3992:                 foreach my $id (@ids) {
                   3993:                     ($map)=($id =~ /([\d]*?)\./);
                   3994:                     my $rid = $id;
1.446     bisitz   3995: 
1.57      albertel 3996: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3997: 
1.560     damieng  3998:                     if ($map eq $mapid) {
1.473     amueller 3999:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4000:                         my $toolsymb;
                   4001:                         if ($uri =~ /ext\.tool$/) {
                   4002:                             $toolsymb = $symbp{$rid};
                   4003:                         }
1.582     raeburn  4004: 
1.57      albertel 4005: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   4006: 
                   4007: #--------------------------------------------------------------------
                   4008: # @catmarker contains list of all possible parameters including part #s
                   4009: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4010: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4011: # When storing information, store as part 0
                   4012: # When requesting information, request from full part
                   4013: #-------------------------------------------------------------------
1.548     raeburn  4014:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4015:                             my $tempkeyp = $fullkeyp;
                   4016:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 4017: 
1.548     raeburn  4018:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4019:                                 $part{$tempkeyp}="0";
1.584     raeburn  4020:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4021:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4022:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   4023:                                     my $identifier;
                   4024:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4025:                                         $identifier = $1;
                   4026:                                     }
                   4027:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4028:                                 } else {
                   4029:                                     $display{$tempkeyp} = $parmdis;
                   4030:                                 }
                   4031:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4032:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4033:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4034:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4035:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 4036:                               }
                   4037:                         } # end loop through keys
1.560     damieng  4038:                     }
1.57      albertel 4039:                 } # end loop through ids
1.446     bisitz   4040: 
1.57      albertel 4041: #---------------------------------------------------- print header information
1.133     www      4042:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4043:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4044:                 my $tmp="";
1.57      albertel 4045:                 if ($uname) {
1.473     amueller 4046:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4047:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4048:                         &mt('in')." \n";
1.57      albertel 4049:                 } else {
1.401     bisitz   4050:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4051:                 }
1.269     raeburn  4052:                 if ($cgroup) {
1.401     bisitz   4053:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4054:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4055:                     $csec = '';
                   4056:                 } elsif ($csec) {
1.401     bisitz   4057:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4058:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4059:                 }
1.401     bisitz   4060:                 $r->print('<div align="center"><h4>'
                   4061:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4062:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4063:                              ,$tmp
                   4064:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4065:                              )
                   4066:                          ."<br /></h4>\n"
1.422     bisitz   4067:                 );
1.57      albertel 4068: #---------------------------------------------------------------- print table
1.419     bisitz   4069:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4070:                          .&Apache::loncommon::start_data_table_header_row()
                   4071:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4072:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4073:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4074:                          .&Apache::loncommon::end_data_table_header_row()
                   4075:                 );
1.57      albertel 4076: 
1.582     raeburn  4077:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4078:                 my @recurseup;
                   4079:                 if (ref($navmap)) {
                   4080:                      my $mapres = $navmap->getByMapPc($mapid);
                   4081:                      if (ref($mapres)) {
                   4082:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4083:                      }
                   4084:                 }
                   4085: 
                   4086: 
1.548     raeburn  4087:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4088:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4089:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4090:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4091:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4092:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4093:                            \$numreclinks);
1.57      albertel 4094:                 }
1.422     bisitz   4095:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4096:                          .'</div>'
                   4097:                 );
1.57      albertel 4098:             } # end each map
                   4099:         } # end of $parmlev eq map
                   4100: #--------------------------------- Entry for parm level general (Course level)
                   4101:         if ($parmlev eq 'general') {
1.473     amueller 4102:             my $defbgone = '#E0E099';
1.419     bisitz   4103:             my $defbgtwo = '#FFFF99';
                   4104:             my $defbgthree = '#FFBB99';
1.57      albertel 4105: 
                   4106: #-------------------------------------------- for each map, gather information
                   4107:             my $mapid="0.0";
                   4108: #-----------------------  loop through ids and get all parameter types for map
                   4109: #-----------------------------------------          and associated information
                   4110:             my %name = ();
                   4111:             my %part = ();
                   4112:             my %display = ();
                   4113:             my %type = ();
                   4114:             my %default = ();
1.446     bisitz   4115: 
1.548     raeburn  4116:             foreach $id (@ids) {
                   4117:                 my $rid = $id;
1.446     bisitz   4118: 
1.196     www      4119:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4120:                 my $toolsymb;
                   4121:                 if ($uri =~ /ext\.tool$/) {
                   4122:                     $toolsymb = $symbp{$rid};
                   4123:                 }
1.57      albertel 4124: 
                   4125: #--------------------------------------------------------------------
                   4126: # @catmarker contains list of all possible parameters including part #s
                   4127: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4128: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4129: # When storing information, store as part 0
                   4130: # When requesting information, request from full part
                   4131: #-------------------------------------------------------------------
1.548     raeburn  4132:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4133:                     my $tempkeyp = $fullkeyp;
                   4134:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4135:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4136:                         $part{$tempkeyp}="0";
1.584     raeburn  4137:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4138:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4139:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4140:                             my $identifier;
                   4141:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4142:                                 $identifier = $1;
                   4143:                             }
                   4144:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4145:                         } else {
                   4146:                             $display{$tempkeyp} = $parmdis;
                   4147:                         }
                   4148:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4149:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4150:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4151:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4152:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4153:                     }
1.57      albertel 4154:                 } # end loop through keys
                   4155:             } # end loop through ids
1.446     bisitz   4156: 
1.57      albertel 4157: #---------------------------------------------------- print header information
1.473     amueller 4158:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4159:             $r->print(<<ENDMAPONE);
1.419     bisitz   4160: <center>
                   4161: <h4>$setdef
1.135     albertel 4162: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4163: ENDMAPONE
                   4164:             if ($uname) {
1.473     amueller 4165:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4166:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4167:             } else {
1.135     albertel 4168:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4169:             }
1.446     bisitz   4170: 
1.135     albertel 4171:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4172:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4173:             $r->print("</h4>\n");
1.57      albertel 4174: #---------------------------------------------------------------- print table
1.419     bisitz   4175:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4176:                      .&Apache::loncommon::start_data_table_header_row()
                   4177:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4178:                      .'<th>'.&mt('Default Value').'</th>'
                   4179:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4180:                      .&Apache::loncommon::end_data_table_header_row()
                   4181:             );
1.57      albertel 4182: 
1.548     raeburn  4183:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4184:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4185:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4186:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4187:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4188:                            $readonly);
1.57      albertel 4189:             }
1.419     bisitz   4190:             $r->print(&Apache::loncommon::end_data_table()
                   4191:                      .'</p>'
                   4192:                      .'</center>'
                   4193:             );
1.57      albertel 4194:         } # end of $parmlev eq general
1.606     raeburn  4195:         $r->print('</div>');
1.43      albertel 4196:     }
1.507     www      4197:     $r->print('</form>');
1.582     raeburn  4198:     if ($numreclinks) {
                   4199:         $r->print(<<"END");
                   4200: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4201: <input type="hidden" name="pschp" />
                   4202: <input type="hidden" name="pscat" />
                   4203: <input type="hidden" name="psprt" />
                   4204: <input type="hidden" name="hideparmsel" value="hidden" />
                   4205: </form>
                   4206: <script type="text/javascript">
                   4207: function pjumprec(rid,name,part) {
                   4208:     document.forms.recurseform.pschp.value = rid;
                   4209:     document.forms.recurseform.pscat.value = name;
                   4210:     document.forms.recurseform.psprt.value = part;
                   4211:     document.forms.recurseform.submit();
                   4212:     return false;
                   4213: }
                   4214: </script>
                   4215: END
                   4216:     }
1.507     www      4217:     &endSettingsScreen($r);
                   4218:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4219: } # end sub assessparms
1.30      www      4220: 
1.560     damieng  4221: 
                   4222: 
1.120     www      4223: ##################################################
1.560     damieng  4224: # OVERVIEW MODE
1.207     www      4225: ##################################################
1.124     www      4226: 
1.563     damieng  4227: my $tableopen; # boolean, true if HTML table is already opened
                   4228: 
                   4229: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4230: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4231: # @returns {string}
1.124     www      4232: sub tablestart {
1.576     raeburn  4233:     my ($readonly,$is_map) = @_;
1.124     www      4234:     if ($tableopen) {
1.552     raeburn  4235:         return '';
1.124     www      4236:     } else {
1.552     raeburn  4237:         $tableopen=1;
                   4238:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4239:         if ($readonly) {
                   4240:             $output .= '<th>'.&mt('Current value').'</th>';
                   4241:         } else {
1.576     raeburn  4242:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4243:                        '<th>'.&mt('Set to ...').'</th>';
                   4244:             if ($is_map) {
                   4245:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4246:             }
1.552     raeburn  4247:         }
                   4248:         $output .= '</tr>';
                   4249:         return $output;
1.124     www      4250:     }
                   4251: }
                   4252: 
1.563     damieng  4253: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4254: # @returns {string}
1.124     www      4255: sub tableend {
                   4256:     if ($tableopen) {
1.560     damieng  4257:         $tableopen=0;
                   4258:         return &Apache::loncommon::end_data_table();
1.124     www      4259:     } else {
1.560     damieng  4260:         return'';
1.124     www      4261:     }
                   4262: }
                   4263: 
1.563     damieng  4264: # Reads course and user information.
                   4265: # 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).
                   4266: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4267: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4268: # @param {string} $crs - course number
                   4269: # @param {string} $dom - course domain
                   4270: # @returns {hash reference|Array}
1.207     www      4271: sub readdata {
                   4272:     my ($crs,$dom)=@_;
                   4273: # Read coursedata
                   4274:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4275: # Read userdata
                   4276: 
                   4277:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4278:     foreach my $user (keys(%$classlist)) {
                   4279:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4280:             my ($tuname,$tudom)=($1,$2);
                   4281:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4282:             foreach my $userkey (keys(%{$useropt})) {
                   4283:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4284:                     my $newkey=$userkey;
1.548     raeburn  4285:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4286:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4287:                 }
                   4288:             }
1.473     amueller 4289:         }
                   4290:     }
1.552     raeburn  4291:     if (wantarray) {
                   4292:         return ($resourcedata,$classlist);
                   4293:     } else {
                   4294:         return $resourcedata;
                   4295:     }
1.207     www      4296: }
                   4297: 
                   4298: 
1.563     damieng  4299: # Stores parameter data, using form parameters directly.
                   4300: #
                   4301: # 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  4302: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4303: # del_* - remove a parameter
                   4304: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4305: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4306: # key_* - date values
                   4307: # days_* - for date intervals
                   4308: # hours_* - for date intervals
                   4309: # minutes_* - for date intervals
                   4310: # seconds_* - for date intervals
                   4311: # done_* - for date intervals
                   4312: # typeof_* - parameter type
                   4313: # 
                   4314: # @param {Apache2::RequestRec} $r - the Apache request
                   4315: # @param {string} $crs - course number
                   4316: # @param {string} $dom - course domain
1.208     www      4317: sub storedata {
                   4318:     my ($r,$crs,$dom)=@_;
1.207     www      4319: # Set userlevel immediately
                   4320: # Do an intermediate store of course level
                   4321:     my $olddata=&readdata($crs,$dom);
1.124     www      4322:     my %newdata=();
                   4323:     undef %newdata;
                   4324:     my @deldata=();
1.576     raeburn  4325:     my @delrec=();
                   4326:     my @delnonrec=();
1.124     www      4327:     undef @deldata;
1.504     raeburn  4328:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4329:     my $now = time;
1.560     damieng  4330:     foreach my $key (keys(%env)) {
                   4331:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4332:             my $cmd=$1;
                   4333:             my $thiskey=$2;
1.576     raeburn  4334:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4335:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4336:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4337:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4338:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4339:                     $altkey = $thiskey;
                   4340:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4341:                     if ($env{'form.rec_'.$thiskey}) {
                   4342:                         $recursive = 1;
                   4343:                     }
                   4344:                 }
                   4345:             }
1.560     damieng  4346:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4347:             if ($tuname) {
1.576     raeburn  4348:                 $tkey=$thiskey;
1.560     damieng  4349:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4350:                 if ($altkey) {
                   4351:                     $tkeynonrec = $tkey; 
                   4352:                     $tkeyrec = $altkey;
                   4353:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4354:                 }
1.560     damieng  4355:             }
                   4356:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4357:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4358:                 if ($cmd eq 'set') {
                   4359:                     $data=$env{$key};
                   4360:                     $valmatch = '';
                   4361:                     $valchk = $data;
                   4362:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4363:                     $text = &mt('Saved modified parameter for');
                   4364:                     if ($typeof eq 'string_questiontype') {
                   4365:                         $name = 'type';
1.588     raeburn  4366:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4367:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4368:                         my $stringmatch = &standard_string_matches($typeof);
                   4369:                         if (ref($stringmatch) eq 'ARRAY') {
                   4370:                             foreach my $item (@{$stringmatch}) {
                   4371:                                 if (ref($item) eq 'ARRAY') {
                   4372:                                     my ($regexpname,$pattern) = @{$item};
                   4373:                                     if ($pattern ne '') {
                   4374:                                         if ($data =~ /$pattern/) {
                   4375:                                             $valmatch = $regexpname;
                   4376:                                             $valchk = '';
                   4377:                                             last;
                   4378:                                         }
1.560     damieng  4379:                                     }
1.549     raeburn  4380:                                 }
                   4381:                             }
                   4382:                         }
1.563     damieng  4383:                     } elsif ($typeof eq 'string_discussvote') {
                   4384:                         $name = 'discussvote';
                   4385:                     } elsif ($typeof eq 'string_examcode') {
                   4386:                         $name = 'examcode';
                   4387:                         if (&Apache::lonnet::validCODE($data)) {
                   4388:                             $valchk = 'valid';
                   4389:                         }
                   4390:                     } elsif ($typeof eq 'string_yesno') {
                   4391:                         if ($thiskey =~ /\.retrypartial$/) {
                   4392:                             $name = 'retrypartial';
                   4393:                         }
1.549     raeburn  4394:                     }
1.563     damieng  4395:                 } elsif ($cmd eq 'datepointer') {
                   4396:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4397:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4398:                     $text = &mt('Saved modified date for');
                   4399:                     if ($typeof eq 'date_start') {
                   4400:                         if ($thiskey =~ /\.printstartdate$/) {
                   4401:                             $name = 'printstartdate';
                   4402:                             if (($data) && ($data > $now)) {
                   4403:                                 $valchk = 'future';
                   4404:                             }
1.560     damieng  4405:                         }
1.563     damieng  4406:                     } elsif ($typeof eq 'date_end') {
                   4407:                         if ($thiskey =~ /\.printenddate$/) {
                   4408:                             $name = 'printenddate';
                   4409:                             if (($data) && ($data < $now)) {
                   4410:                                 $valchk = 'past';
                   4411:                             }
1.560     damieng  4412:                         }
1.504     raeburn  4413:                     }
1.563     damieng  4414:                 } elsif ($cmd eq 'dateinterval') {
                   4415:                     $data=&get_date_interval_from_form($thiskey);
                   4416:                     if ($thiskey =~ /\.interval$/) {
                   4417:                         $name = 'interval';
                   4418:                         my $intervaltype = &get_intervaltype($name);
                   4419:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4420:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4421:                             foreach my $item (@{$intervalmatch}) {
                   4422:                                 if (ref($item) eq 'ARRAY') {
                   4423:                                     my ($regexpname,$pattern) = @{$item};
                   4424:                                     if ($pattern ne '') {
                   4425:                                         if ($data =~ /$pattern/) {
                   4426:                                             $valmatch = $regexpname;
                   4427:                                             $valchk = '';
                   4428:                                             last;
                   4429:                                         }
1.560     damieng  4430:                                     }
1.554     raeburn  4431:                                 }
                   4432:                             }
                   4433:                         }
                   4434:                     }
1.563     damieng  4435:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4436:                     $text = &mt('Saved modified date for');
1.554     raeburn  4437:                 }
1.576     raeburn  4438:                 if ($recursive) {
1.563     damieng  4439:                     $namematch = 'maplevelrecurse';
1.560     damieng  4440:                 }
1.563     damieng  4441:                 if (($name ne '') || ($namematch ne '')) {
                   4442:                     my ($needsrelease,$needsnewer);
                   4443:                     if ($name ne '') {
                   4444:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4445:                         if ($needsrelease) {
                   4446:                             unless ($got_chostname) {
1.563     damieng  4447:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4448:                                 $got_chostname = 1;
                   4449:                             }
1.563     damieng  4450:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4451:                                                                 $needsrelease,
                   4452:                                                                 $cmajor,$cminor);
                   4453:                         }
                   4454:                     }
                   4455:                     if ($namematch ne '') {
                   4456:                         if ($needsnewer) {
                   4457:                             undef($namematch);
1.560     damieng  4458:                         } else {
1.563     damieng  4459:                             my $currneeded;
                   4460:                             if ($needsrelease) {
                   4461:                                 $currneeded = $needsrelease;
                   4462:                             }
                   4463:                             $needsrelease =
                   4464:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4465:                             if (($needsrelease) &&
                   4466:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4467:                                 unless ($got_chostname) {
                   4468:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4469:                                     $got_chostname = 1;
                   4470:                                 }
                   4471:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4472:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4473:                             } else {
                   4474:                                 undef($namematch);
                   4475:                             }
1.560     damieng  4476:                         }
1.557     raeburn  4477:                     }
1.563     damieng  4478:                     if ($needsnewer) {
                   4479:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4480:                                                             $chostname,$cmajor,
                   4481:                                                             $cminor,$needsrelease));
                   4482:                         next;
                   4483:                     }
1.504     raeburn  4484:                 }
1.576     raeburn  4485:                 my ($reconlychg,$haschange,$storekey);
                   4486:                 if ($tuname) {
                   4487:                     my $ustorekey;
                   4488:                     if ($altkey) {
                   4489:                         if ($recursive) {
                   4490:                             if (exists($$olddata{$thiskey})) {
                   4491:                                 if ($$olddata{$thiskey} eq $data) {
                   4492:                                     $reconlychg = 1;
                   4493:                                 }
                   4494:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4495:                             }
                   4496:                             if (exists($$olddata{$altkey})) {
                   4497:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4498:                                     $haschange = 1;
                   4499:                                 }
                   4500:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4501:                                 $haschange = 1;
                   4502:                             }
                   4503:                             $ustorekey = $tkeyrec;
                   4504:                         } else {
                   4505:                             if (exists($$olddata{$altkey})) {
                   4506:                                 if ($$olddata{$altkey} eq $data) {
                   4507:                                     $reconlychg = 1;
                   4508:                                 }
                   4509:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4510:                             }
                   4511:                             if (exists($$olddata{$thiskey})) {
                   4512:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4513:                                     $haschange = 1;
                   4514:                                 }
                   4515:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4516:                                 $haschange = 1;
                   4517:                             }
                   4518:                             $ustorekey = $tkeynonrec;
                   4519:                         }
                   4520:                     } else {
                   4521:                         if (exists($$olddata{$tkey})) {
                   4522:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4523:                                 $haschange = 1;
                   4524:                             }
                   4525:                             $ustorekey = $tkey;
                   4526:                         }
                   4527:                     }
                   4528:                     if ($haschange || $reconlychg)  {
                   4529:                         unless ($env{'form.del_'.$thiskey}) {
                   4530:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4531:                                                                      $ustorekey.'.type' => $typeof},
                   4532:                                                                      $tudom,$tuname) eq 'ok') {
                   4533:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4534:                                 $r->print('<br />'.$text.' '.
                   4535:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4536:                             } else {
                   4537:                                 $r->print('<div class="LC_error">'.
                   4538:                                           &mt('Error saving parameters').'</div>');
                   4539:                             }
                   4540:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4541:                         }
                   4542:                     }
                   4543:                 } else {
                   4544:                     if ($altkey) {
                   4545:                         if ($recursive) {
                   4546:                             if (exists($$olddata{$thiskey})) {
                   4547:                                 if ($$olddata{$thiskey} eq $data) {
                   4548:                                     $reconlychg = 1;
                   4549:                                 }
                   4550:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4551:                             }
                   4552:                             if (exists($$olddata{$altkey})) {
                   4553:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4554:                                     $haschange = 1;
                   4555:                                 }
                   4556:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4557:                                 $haschange = 1;
                   4558:                             }
                   4559:                             $storekey = $altkey;
1.563     damieng  4560:                         } else {
1.576     raeburn  4561:                             if (exists($$olddata{$altkey})) {
                   4562:                                 if ($$olddata{$altkey} eq $data) {
                   4563:                                     $reconlychg = 1;
                   4564:                                 }
                   4565:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4566:                             } 
                   4567:                             if (exists($$olddata{$thiskey})) {
                   4568:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4569:                                     $haschange = 1;
                   4570:                                 }
                   4571:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4572:                                 $haschange = 1;
                   4573:                             }
                   4574:                             $storekey = $thiskey;
1.563     damieng  4575:                         }
1.560     damieng  4576:                     } else {
1.576     raeburn  4577:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4578:                             $haschange = 1;
                   4579:                             $storekey = $thiskey;
                   4580:                         }
                   4581:                     }
                   4582:                 }
                   4583:                 if ($reconlychg || $haschange) {
                   4584:                     unless ($env{'form.del_'.$thiskey}) {
                   4585:                         $newdata{$storekey}=$data;
                   4586:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4587:                     }
                   4588:                 }
                   4589:             } elsif ($cmd eq 'del') {
                   4590:                 if ($tuname) {
1.576     raeburn  4591:                     my $error;
                   4592:                     if ($altkey) {  
                   4593:                         if (exists($$olddata{$altkey})) {
                   4594:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4595:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4596:                                 if ($recursive) {
                   4597:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4598:                                 }
                   4599:                             } elsif ($recursive) {
                   4600:                                 $error = 1;
                   4601:                             }
                   4602:                         }
                   4603:                         if (exists($$olddata{$thiskey})) {
                   4604:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4605:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4606:                                 unless ($recursive) {
                   4607:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4608:                                 }
                   4609:                             } elsif (!$recursive) {
                   4610:                                 $error = 1;
                   4611:                             }
                   4612:                         }
1.560     damieng  4613:                     } else {
1.576     raeburn  4614:                         if (exists($$olddata{$thiskey})) {
                   4615:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4616:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4617:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4618:                             } else {
                   4619:                                 $error = 1;
                   4620:                             }
                   4621:                         }
                   4622:                     }
                   4623:                     if ($error) { 
1.560     damieng  4624:                         $r->print('<div class="LC_error">'.
                   4625:                             &mt('Error deleting parameters').'</div>');
                   4626:                     }
                   4627:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4628:                 } else {
1.576     raeburn  4629:                     if ($altkey) {
                   4630:                         if (exists($$olddata{$altkey})) {
                   4631:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4632:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4633:                             }
                   4634:                         }
                   4635:                         if (exists($$olddata{$thiskey})) {
                   4636:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4637:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4638:                             }
                   4639:                         }
                   4640:                     } elsif (exists($$olddata{$thiskey})) {
                   4641:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4642:                     }
1.560     damieng  4643:                 }
1.473     amueller 4644:             }
                   4645:         }
                   4646:     }
1.207     www      4647: # Store all course level
1.144     www      4648:     my $delentries=$#deldata+1;
1.576     raeburn  4649:     my @alldels;
                   4650:     if (@delrec) {
                   4651:         push(@alldels,@delrec);
                   4652:     }
                   4653:     if (@delnonrec) {
                   4654:         push(@alldels,@delnonrec);
                   4655:     }
                   4656:     if (@deldata) {
                   4657:         push(@alldels,@deldata);
                   4658:     }
1.548     raeburn  4659:     my @newdatakeys=keys(%newdata);
1.144     www      4660:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4661:     my ($delresult,$devalidate);
                   4662:     if (@alldels) {
                   4663:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4664:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4665:             &log_parmset(\%loghash,1);
1.576     raeburn  4666:             if ($delentries) {
                   4667:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4668:             }
                   4669:         } elsif ($delentries) {
1.560     damieng  4670:             $r->print('<div class="LC_error">'.
                   4671:                 &mt('Error deleting parameters').'</div>');
                   4672:         }
1.576     raeburn  4673:         $devalidate = 1; 
1.144     www      4674:     }
                   4675:     if ($putentries) {
1.560     damieng  4676:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4677:                     &log_parmset(\%newdata,0);
                   4678:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4679:         } else {
                   4680:             $r->print('<div class="LC_error">'.
                   4681:                 &mt('Error saving parameters').'</div>');
                   4682:         }
1.576     raeburn  4683:         $devalidate = 1; 
                   4684:     }
                   4685:     if ($devalidate) {
1.560     damieng  4686:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4687:     }
1.208     www      4688: }
1.207     www      4689: 
1.563     damieng  4690: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4691: #
                   4692: # @param {string} $key - the key
                   4693: # @returns {Array}
1.208     www      4694: sub extractuser {
                   4695:     my $key=shift;
1.350     albertel 4696:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4697: }
1.206     www      4698: 
1.563     damieng  4699: # Parses a parameter key and returns the components.
                   4700: #
                   4701: # @param {string} $key - 
                   4702: # @param {hash reference} $listdata - 
                   4703: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4704: sub parse_listdata_key {
                   4705:     my ($key,$listdata) = @_;
                   4706:     # split into student/section affected, and
                   4707:     # the realm (folder/resource part and parameter
1.446     bisitz   4708:     my ($student,$realm) =
1.473     amueller 4709:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4710:     # if course wide student would be undefined
                   4711:     if (!defined($student)) {
1.560     damieng  4712:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4713:     }
                   4714:     # strip off the .type if it's not the Question type parameter
                   4715:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4716:         $realm=~s/\.type//;
1.381     albertel 4717:     }
                   4718:     # split into resource+part and parameter name
1.388     albertel 4719:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4720:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4721:     return ($student,$res,$part,$parm);
                   4722: }
                   4723: 
1.563     damieng  4724: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4725: #
                   4726: # @param {Apache2::RequestRec} $r - the Apache request
                   4727: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4728: # @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
                   4729: # @param {string} $sortorder - realmstudent|studentrealm
                   4730: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4731: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4732: # @param {boolean} $readonly - true if editing not allowed
1.608     raeburn  4733: # @param {string} $parmlev - full|map
                   4734: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
                   4735: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4736: # @returns{integer} - number of $listdata parameters processed
1.208     www      4737: sub listdata {
1.608     raeburn  4738:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552     raeburn  4739:     
1.207     www      4740: # Start list output
1.206     www      4741: 
1.122     www      4742:     my $oldsection='';
                   4743:     my $oldrealm='';
                   4744:     my $oldpart='';
1.123     www      4745:     my $pointer=0;
1.124     www      4746:     $tableopen=0;
1.145     www      4747:     my $foundkeys=0;
1.248     albertel 4748:     my %keyorder=&standardkeyorder();
1.594     raeburn  4749:     my $readonlyall = $readonly;
1.381     albertel 4750: 
1.552     raeburn  4751:     my ($secidx,%grouphash);
                   4752:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4753:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4754:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4755:             %grouphash = &Apache::longroup::coursegroups();
                   4756:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4757:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4758:         }
1.552     raeburn  4759:     }
                   4760: 
1.576     raeburn  4761:     foreach my $key (sort {
1.560     damieng  4762:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4763:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608     raeburn  4764:         my ($aid,$bid);
                   4765:         if ($caller eq 'newoverview') {
                   4766:             if (ref($hash_for_realm) eq 'HASH') {
                   4767:                 if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4768:                     my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4769:                     my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4770:                     $aid = $hash_for_realm->{$aurl};
                   4771:                     $bid = $hash_for_realm->{$burl};
                   4772:                 } elsif ($parmlev eq 'full') {
                   4773:                     $aid = $hash_for_realm->{$ares};
                   4774:                     $bid = $hash_for_realm->{$bres};
                   4775:                 }
                   4776:             }
                   4777:         }
1.381     albertel 4778: 
1.560     damieng  4779:         # get the numerical order for the param
                   4780:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4781:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4782: 
1.560     damieng  4783:         my $result=0;
1.381     albertel 4784: 
1.560     damieng  4785:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4786:             if ($ares     ne $bres    ) {
1.608     raeburn  4787:                 if ($caller eq 'newoverview') {
                   4788:                     if (ref($hash_for_realm) eq 'HASH') {
                   4789:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4790:                             $result = ($aid <=> $bid);
                   4791:                         } elsif ($parmlev eq 'full') {
                   4792:                             $result = ($aid <=> $bid);
                   4793:                         } else {
                   4794:                             $result = ($ares cmp $bres);
                   4795:                         }
                   4796:                     } else {
                   4797:                         $result = ($ares cmp $bres);
                   4798:                     }
                   4799:                 } else {
                   4800:                     $result = ($ares cmp $bres);
                   4801:                 }
1.446     bisitz   4802:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4803:                 $result = ($astudent cmp $bstudent);
                   4804:             } elsif ($apart    ne $bpart   ) {
                   4805:                 $result = ($apart    cmp $bpart);
                   4806:             }
                   4807:         } else {
                   4808:             if      ($astudent ne $bstudent) {
                   4809:                 $result = ($astudent cmp $bstudent);
                   4810:             } elsif ($ares     ne $bres    ) {
1.608     raeburn  4811:                 if ($caller eq 'newoverview') {
                   4812:                     if (ref($hash_for_realm) eq 'HASH') {
                   4813:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4814:                             $result = ($aid <=> $bid);
                   4815:                         } elsif ($parmlev eq 'full') {
                   4816:                             $result = ($aid <=> $bid);
                   4817:                         } else {
                   4818:                             $result = ($ares cmp $bres);
                   4819:                         }
                   4820:                     } else {
                   4821:                         $result = ($ares cmp $bres);
                   4822:                     }
                   4823:                 } else {
                   4824:                     $result = ($ares cmp $bres);
                   4825:                 }
1.560     damieng  4826:             } elsif ($apart    ne $bpart   ) {
                   4827:                 $result = ($apart    cmp $bpart);
                   4828:             }
1.473     amueller 4829:         }
1.446     bisitz   4830: 
1.560     damieng  4831:         if (!$result) {
1.381     albertel 4832:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4833:                 $result = ($aparm <=> $bparm);
1.381     albertel 4834:             } elsif (defined($aparm)) {
1.560     damieng  4835:                 $result = -1;
1.381     albertel 4836:             } elsif (defined($bparm)) {
1.560     damieng  4837:                 $result = 1;
                   4838:             }
1.473     amueller 4839:         }
1.381     albertel 4840: 
1.560     damieng  4841:         $result;
                   4842:         
1.576     raeburn  4843:     } keys(%{$listdata})) { # foreach my $key
                   4844:         my $thiskey = $key;
1.560     damieng  4845:         if ($$listdata{$thiskey.'.type'}) {
                   4846:             my $thistype=$$listdata{$thiskey.'.type'};
                   4847:             if ($$resourcedata{$thiskey.'.type'}) {
                   4848:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4849:             }
                   4850:             my ($middle,$part,$name)=
1.572     damieng  4851:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4852:             my $section=&mt('All Students');
1.594     raeburn  4853:             $readonly = $readonlyall;
1.599     raeburn  4854:             my $userscope;
1.576     raeburn  4855:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4856:             if ($middle=~/^\[(.*)\]/) {
                   4857:                 my $issection=$1;
                   4858:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4859:                     my ($stuname,$studom) = ($1,$2);
                   4860:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4861:                         if (ref($classlist) eq 'HASH') {
                   4862:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4863:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4864:                             }
                   4865:                         }
                   4866:                     }
                   4867:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4868:                     $userscope = 1;
1.560     damieng  4869:                 } else {
                   4870:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4871:                         if (exists($grouphash{$issection})) {
                   4872:                             $section=&mt('Group').': '.$issection;
                   4873:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4874:                             $section = &mt('Section').': '.$issection;
                   4875:                         } else {
                   4876:                             next; 
1.552     raeburn  4877:                         }
1.560     damieng  4878:                     } else {
                   4879:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4880:                     }
                   4881:                 }
1.560     damieng  4882:                 $middle=~s/^\[(.*)\]//;
                   4883:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4884:                 $readonly = 1;
                   4885:             }
                   4886:             $middle=~s/\.+$//;
                   4887:             $middle=~s/^\.+//;
                   4888:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4889:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4890:             if ($caller eq 'overview') {
                   4891:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4892:                     $mapurl = $1;
                   4893:                     $maplevel = $2;
                   4894:                     $is_map = 1;
                   4895:                 }
                   4896:             } elsif ($caller eq 'newoverview') {
                   4897:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4898:                     $mapurl = $1;
                   4899:                     $maplevel = $2;
                   4900:                     $is_map = 1;
                   4901:                 }
                   4902:             }
                   4903:             if ($is_map) {
1.560     damieng  4904:                 my $leveltitle = &mt('Folder/Map');
1.615   ! raeburn  4905:                 my $title = &Apache::lonnet::gettitle($mapurl);
1.608     raeburn  4906:                 if (ref($hash_for_realm) eq 'HASH') {
                   4907:                     if ($hash_for_realm->{$mapurl} eq '1') {
                   4908:                         $title = &mt('Main Content');
                   4909:                     }
                   4910:                 }
1.576     raeburn  4911:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4912:                     if ($caller eq 'newoverview') {
                   4913:                         my $altkey = $thiskey;
                   4914:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4915:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4916:                             $is_recursive = 1;
                   4917:                             if ($$resourcedata{$altkey.'.type'}) {
                   4918:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4919:                             }
                   4920:                             $showval = $$resourcedata{$altkey};
                   4921:                         }
                   4922:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4923:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4924:                         $is_recursive = 1;
                   4925:                     }
1.560     damieng  4926:                 }
1.608     raeburn  4927:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560     damieng  4928:             } elsif ($middle) {
                   4929:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609     raeburn  4930:                 next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560     damieng  4931:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4932:                     ': '.&Apache::lonnet::gettitle($middle).
                   4933:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4934:                     $id.')</span></span>';
                   4935:             }
                   4936:             if ($sortorder eq 'realmstudent') {
                   4937:                 if ($realm ne $oldrealm) {
                   4938:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4939:                     $oldrealm=$realm;
                   4940:                     $oldsection='';
                   4941:                 }
                   4942:                 if ($section ne $oldsection) {
                   4943:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4944:                     $oldsection=$section;
                   4945:                     $oldpart='';
                   4946:                 }
1.552     raeburn  4947:             } else {
1.560     damieng  4948:                 if ($section ne $oldsection) {
                   4949:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4950:                     $oldsection=$section;
                   4951:                     $oldrealm='';
                   4952:                 }
                   4953:                 if ($realm ne $oldrealm) {
                   4954:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4955:                     $oldrealm=$realm;
                   4956:                     $oldpart='';
1.552     raeburn  4957:                 }
                   4958:             }
1.560     damieng  4959:             if ($part ne $oldpart) {
                   4960:                 $r->print(&tableend().
                   4961:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4962:                 $oldpart=$part;
1.556     raeburn  4963:             }
1.560     damieng  4964:     #
                   4965:     # Ready to print
                   4966:     #
1.470     raeburn  4967:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  4968:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  4969:                 &Apache::loncommon::start_data_table_row().
                   4970:                 '<td><b>'.&mt($parmitem).
                   4971:                 '</b></td>');
                   4972:             unless ($readonly) {
1.599     raeburn  4973:                 my $disabled;
                   4974:                 if (($name eq 'availablestudent') &&
                   4975:                     (($showval eq '') || ($userscope))) {
                   4976:                     $disabled = ' disabled="disabled"';
                   4977:                 }
1.560     damieng  4978:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  4979:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  4980:             }
                   4981:             $r->print('<td>');
                   4982:             $foundkeys++;
                   4983:             if (&isdateparm($thistype)) {
                   4984:                 my $jskey='key_'.$pointer;
                   4985:                 my $state;
                   4986:                 $pointer++;
                   4987:                 if ($readonly) {
                   4988:                     $state = 'disabled';
                   4989:                 }
                   4990:                 $r->print(
                   4991:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4992:                                                         $jskey,
1.576     raeburn  4993:                                                         $showval,
1.560     damieng  4994:                                                         '',1,$state));
                   4995:                 unless  ($readonly) {
                   4996:                     $r->print(
                   4997:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  4998:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  4999:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  5000:     &date_sanity_info($showval)
1.560     damieng  5001:                     );
                   5002:                 }
                   5003:             } elsif ($thistype eq 'date_interval') {
                   5004:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  5005:                           $showval,$readonly));
1.560     damieng  5006:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  5007:                 if ($name eq 'availablestudent') {
                   5008:                     $readonly = 1;
                   5009:                 }
1.560     damieng  5010:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  5011:                           $showval,$name,$readonly));
1.560     damieng  5012:             } else {
1.576     raeburn  5013:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  5014:             }
1.560     damieng  5015:             unless ($readonly) {
                   5016:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   5017:                         $thistype.'" />');
1.552     raeburn  5018:             }
1.576     raeburn  5019:             $r->print('</td>');
                   5020:             if ($is_map) {
                   5021:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   5022:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   5023:                 } else {
                   5024:                     my ($disabled,$recon,$recoff);
                   5025:                     if ($readonly) {
                   5026:                         $disabled = ' disabled="disabled"';
                   5027:                     }
                   5028:                     if ($is_recursive) {
                   5029:                         $recon = ' checked="checked"';
                   5030:                     } else {
                   5031:                         $recoff = ' checked="checked"';
                   5032:                     }
                   5033:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   5034:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   5035:                 }
                   5036:             }
                   5037:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 5038:         }
1.121     www      5039:     }
1.208     www      5040:     return $foundkeys;
                   5041: }
                   5042: 
1.563     damieng  5043: # Returns a string representing the interval, directly using form data matching the given key.
                   5044: # The returned string may also include information related to proctored exams.
                   5045: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   5046: #
                   5047: # @param {string} $key - suffix for form fields related to the interval
                   5048: # @returns {string}
1.385     albertel 5049: sub get_date_interval_from_form {
                   5050:     my ($key) = @_;
                   5051:     my $seconds = 0;
1.611     raeburn  5052:     my $numnotnull = 0;
1.385     albertel 5053:     foreach my $which (['days', 86400],
1.473     amueller 5054:                ['hours', 3600],
                   5055:                ['minutes', 60],
                   5056:                ['seconds',  1]) {
1.560     damieng  5057:         my ($name, $factor) = @{ $which };
                   5058:         if (defined($env{'form.'.$name.'_'.$key})) {
1.611     raeburn  5059:             unless ($env{'form.'.$name.'_'.$key} eq '') {
                   5060:                 $numnotnull ++;
                   5061:                 $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   5062:             }
1.560     damieng  5063:         }
1.473     amueller 5064:     }
1.560     damieng  5065:     if (($key =~ /\.interval$/) &&
                   5066:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  5067:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   5068:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   5069:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   5070:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   5071:                 $seconds .= '_proctor';
                   5072:             }
                   5073:         } else {
                   5074:             $seconds .= $env{'form.done_'.$key}; 
                   5075:         }
                   5076:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  5077:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  5078:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   5079:         }
1.554     raeburn  5080:     }
1.611     raeburn  5081:     return if (!$numnotnull);
1.385     albertel 5082:     return $seconds;
                   5083: }
                   5084: 
                   5085: 
1.563     damieng  5086: # Returns HTML to enter a text value for a parameter.
                   5087: #
                   5088: # @param {string} $thiskey - parameter key
                   5089: # @param {string} $showval - the current value
                   5090: # @param {boolean} $readonly - true if the field should not be made editable
                   5091: # @returns {string}
1.383     albertel 5092: sub default_selector {
1.552     raeburn  5093:     my ($thiskey, $showval, $readonly) = @_;
                   5094:     my $disabled;
                   5095:     if ($readonly) {
                   5096:         $disabled = ' disabled="disabled"';
                   5097:     }
                   5098:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 5099: }
                   5100: 
1.563     damieng  5101: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5102: #
                   5103: # @param {string} $thiskey - parameter key
                   5104: # @param {string} $showval - the current value
                   5105: # @param {boolean} $readonly - true if the fields should not be made editable
                   5106: # @returns {string}
1.549     raeburn  5107: sub string_ip_selector {
1.552     raeburn  5108:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5109:     my %access = (
                   5110:                    allow => [],
                   5111:                    deny  => [],
                   5112:                  );
                   5113:     if ($showval ne '') {
                   5114:         my @current;
                   5115:         if ($showval =~ /,/) {
                   5116:             @current = split(/,/,$showval);
                   5117:         } else {
                   5118:             @current = ($showval);
                   5119:         }
                   5120:         foreach my $item (@current) {
                   5121:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5122:                 push(@{$access{'deny'}},$1);
                   5123:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5124:                 push(@{$access{'allow'}},$item);
                   5125:             }
                   5126:         }
                   5127:     }
                   5128:     if (!@{$access{'allow'}}) {
                   5129:         @{$access{'allow'}} = ('');
                   5130:     }
                   5131:     if (!@{$access{'deny'}}) {
                   5132:         @{$access{'deny'}} = ('');
                   5133:     }
1.552     raeburn  5134:     my ($disabled,$addmore);
1.567     raeburn  5135:     if ($readonly) {
1.552     raeburn  5136:         $disabled=' disabled="disabled"';
                   5137:     } else {
                   5138:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5139:     }
1.549     raeburn  5140:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5141: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5142:     foreach my $acctype ('allow','deny') {
                   5143:         $output .= '
                   5144: <td valign="top">
                   5145: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5146:   <div class="LC_string_ipacc_inner">'."\n";
                   5147:         my $num = 0;
                   5148:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5149:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5150:             if ($num > 0) {
                   5151:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5152:             }
                   5153:             $output .= '</div>'."\n";
                   5154:             $num ++;
                   5155:         }
                   5156:         $output .= '
1.552     raeburn  5157:   </div>'.$addmore.'
1.549     raeburn  5158: </div>
                   5159: </td>';
                   5160:    }
                   5161:    $output .= '
                   5162: </tr>
                   5163: </table>'."\n";
                   5164:     return $output;
                   5165: }
                   5166: 
1.588     raeburn  5167: sub string_deeplink_selector {
                   5168:     my ($thiskey, $showval, $readonly) = @_;
1.597     raeburn  5169:     my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601     raeburn  5170:         %selectnull,%domlti,%crslti,@possmenus);
1.613     raeburn  5171:     @components = ('state','others','listing','scope','protect','menus','target');
1.588     raeburn  5172:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5173:                   state   => 'Access status',
                   5174:                   others  => 'Hide other resources',
1.588     raeburn  5175:                   listing => 'In Contents and/or Gradebook',
                   5176:                   scope   => 'Access scope for link',
1.601     raeburn  5177:                   protect => 'Link protection',
1.597     raeburn  5178:                   menus   => 'Menu Items Displayed',
1.613     raeburn  5179:                   target  => 'Embedded?',
1.588     raeburn  5180:               );
                   5181:     %options = (
1.601     raeburn  5182:                    state   => ['only','off','both'],
                   5183:                    others  => ['hide','unhide'],
1.588     raeburn  5184:                    listing => ['full','absent','grades','details','datestatus'],
                   5185:                    scope   => ['res','map','rec'],
1.601     raeburn  5186:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5187:                    menus   => ['std','colls'],
1.613     raeburn  5188:                    target  => ['_self','_top'],
1.588     raeburn  5189:                );
                   5190:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5191:                     only       => 'deep only',
                   5192:                     off        => 'deeplink off',
                   5193:                     both       => 'regular + deep',
                   5194:                     hide       => 'Hidden',
                   5195:                     unhide     => 'Unhidden',
1.588     raeburn  5196:                     full       => 'Listed (linked) in both',
                   5197:                     absent     => 'Not listed',
                   5198:                     grades     => 'Listed in grades only',
                   5199:                     details    => 'Listed (unlinked) in both',
                   5200:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5201:                     res        => 'resource only',
                   5202:                     map        => 'enclosing map/folder',
                   5203:                     rec        => 'recursive map/folder',
1.601     raeburn  5204:                     none       => 'not in use',
                   5205:                     key        => 'key access',
                   5206:                     ltic       => 'LTI access (course)',
                   5207:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5208:                     std        => 'Standard (all menus)',
                   5209:                     colls      => 'Numbered collection',
1.614     raeburn  5210:                     _self      => 'Embedded',
1.613     raeburn  5211:                     _top       => 'Not embedded',
1.597     raeburn  5212:                   );
                   5213:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5214:                     ltic => 'Select Launcher',
                   5215:                     ltid => 'Select Launcher', 
1.597     raeburn  5216:                     colls => 'Select',
1.588     raeburn  5217:                   );
                   5218:     if ($showval =~ /,/) {
1.597     raeburn  5219:         %values=();
1.588     raeburn  5220:         @current = split(/,/,$showval);
1.601     raeburn  5221:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5222:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5223:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5224:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5225:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5226:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613     raeburn  5227:         ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.588     raeburn  5228:     } else {
1.601     raeburn  5229:         $defaults{'state'} = 'off',
                   5230:         $defaults{'others'} = 'unhide',
1.588     raeburn  5231:         $defaults{'listing'} = 'full';
                   5232:         $defaults{'scope'} = 'res';
1.601     raeburn  5233:         $defaults{'protect'} = 'none';
1.597     raeburn  5234:         $defaults{'menus'} = '0';
1.613     raeburn  5235:         $defaults{'target'} = '_top';
1.588     raeburn  5236:     }
                   5237:     my $disabled;
                   5238:     if ($readonly) {
                   5239:         $disabled=' disabled="disabled"';
                   5240:     }
1.601     raeburn  5241:     my %courselti =
                   5242:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5243:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5244:     foreach my $item (keys(%courselti)) {
                   5245:         if (ref($courselti{$item}) eq 'HASH') {
                   5246:             $crslti{$item} = $courselti{$item}{'name'};
                   5247:         }
                   5248:     }
                   5249:     my %lti =
1.588     raeburn  5250:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5251:                                         'linkprot');
1.588     raeburn  5252:     foreach my $item (keys(%lti)) {
1.604     raeburn  5253:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5254:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5255:         }
                   5256:     }
1.597     raeburn  5257:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5258:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5259:             my ($num,$value) = split(/\%/,$item);
                   5260:             if ($num =~ /^\d+$/) {
                   5261:                 push(@possmenus,$num);
                   5262:             }
                   5263:         }
                   5264:     }
                   5265: 
1.588     raeburn  5266:     my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597     raeburn  5267:     foreach my $item (@components) {
1.588     raeburn  5268:         $output .= '<th>'.$titles{$item}.'</th>';
                   5269:     }
                   5270:     $output .= '</tr><tr>';
                   5271:     foreach my $item (@components) {
                   5272:         $output .= '<td>';
1.601     raeburn  5273:         if (($item eq 'protect') || ($item eq 'menus')) {
1.588     raeburn  5274:             my $selected = $values{$item};
                   5275:             foreach my $option (@{$options{$item}}) {
1.601     raeburn  5276:                 if ($item eq 'protect') { 
                   5277:                     if ($option eq 'ltid') {
                   5278:                         next unless (keys(%domlti));
                   5279:                     } elsif ($option eq 'ltic') {
                   5280:                         next unless (keys(%crslti));
                   5281:                     }
1.597     raeburn  5282:                 } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5283:                     next unless (@possmenus);
1.588     raeburn  5284:                 }
                   5285:                 my $checked;
1.597     raeburn  5286:                 if ($item eq 'menus') {
                   5287:                     if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5288:                         (grep(/^\Q$selected\E$/,@possmenus))) {
                   5289:                         if ($option eq 'colls') {
                   5290:                             $checked = ' checked="checked"';
                   5291:                         }
                   5292:                     } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
                   5293:                         $checked = ' checked="checked"';
                   5294:                     }
                   5295:                 } elsif ($selected =~ /^\Q$option\E/) {
1.588     raeburn  5296:                     $checked = ' checked="checked"';
                   5297:                 }
                   5298:                 my $onclick;
                   5299:                 unless ($readonly) {
                   5300:                     my $esc_key = &js_escape($thiskey);
                   5301:                     $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5302:                 }
                   5303:                 $output .= '<span class="LC_nobreak"><label>'.
                   5304:                            '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5305:                            $optiontext{$option}.'</label>';
1.601     raeburn  5306:                 if (($item eq 'protect') && ($option eq 'key')) {
1.588     raeburn  5307:                     my $visibility="hidden";
                   5308:                     my $currkey;
                   5309:                     if ($checked) {
                   5310:                         $visibility = "text";
                   5311:                         $currkey = (split(/\:/,$values{$item}))[1];
                   5312:                     }
                   5313:                     $output .= '&nbsp;'.
1.597     raeburn  5314:                         '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601     raeburn  5315:                 } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588     raeburn  5316:                     my $display="none";
1.597     raeburn  5317:                     my ($current,$blankcheck,@possibles);
1.588     raeburn  5318:                     if ($checked) {
                   5319:                         $display = 'inline-block';
1.601     raeburn  5320:                         if (($option eq 'ltic') || ($option eq 'ltid'))  {
1.597     raeburn  5321:                             $current = (split(/\:/,$selected))[1];
                   5322:                         } else {
                   5323:                             $current = $selected;
                   5324:                         }
1.588     raeburn  5325:                     } else {
                   5326:                         $blankcheck = ' selected="selected"';
                   5327:                     }
1.601     raeburn  5328:                     if ($option eq 'ltid') {
                   5329:                         @possibles = keys(%domlti);
                   5330:                     } elsif ($option eq 'ltic') {
                   5331:                         @possibles = keys(%crslti); 
1.597     raeburn  5332:                     } else {
                   5333:                         @possibles = @possmenus;
                   5334:                     }
1.588     raeburn  5335:                     $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5336:                                ' style="display: '.$display.'">&nbsp;<select name="'.
1.597     raeburn  5337:                                'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5338:                     if (@possibles > 1) {
                   5339:                         $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5340:                                    '</option>'."\n";
                   5341:                     }
                   5342:                     foreach my $poss (sort { $a <=> $b } @possibles) {
1.588     raeburn  5343:                         my $selected;
1.597     raeburn  5344:                         if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588     raeburn  5345:                             $selected = ' selected="selected"';
                   5346:                         }
1.597     raeburn  5347:                         my $shown = $poss;
1.601     raeburn  5348:                         if ($option eq 'ltid') {
                   5349:                             $shown = $domlti{$poss};
                   5350:                         } elsif ($option eq 'ltic') {
                   5351:                             $shown = $crslti{$poss};
1.597     raeburn  5352:                         }
                   5353:                         $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588     raeburn  5354:                     }
                   5355:                     $output .= '</select></div>';
                   5356:                 }
                   5357:                 $output .= '</span> ';
                   5358:             }
                   5359:         } else {
                   5360:             my $selected = $values{$item};
                   5361:             my $defsel;
                   5362:             if ($selected eq '') {
                   5363:                 $defsel = ' selected="selected"';
                   5364:             }
                   5365:             $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5366:                        '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5367:             foreach my $option (@{$options{$item}}) {
                   5368:                 $output .= '<option value="'.$option.'"';
                   5369:                 if ($option eq $selected) {
                   5370:                     $output .= ' selected="selected"';
                   5371:                 }
                   5372:                 $output .= '>'.$optiontext{$option}.'</option>';
                   5373:             }
                   5374:             $output .= '</select>';
                   5375:         }
                   5376:         $output .= '</td>';
                   5377:     }
                   5378:     $output .= '</tr></table>'."\n";
                   5379:     return $output;
                   5380: }
                   5381: 
1.560     damieng  5382: 
                   5383: { # block using some constants related to parameter types (overview mode)
                   5384: 
1.446     bisitz   5385: my %strings =
1.383     albertel 5386:     (
                   5387:      'string_yesno'
                   5388:              => [[ 'yes', 'Yes' ],
1.560     damieng  5389:                  [ 'no', 'No' ]],
1.383     albertel 5390:      'string_problemstatus'
                   5391:              => [[ 'yes', 'Yes' ],
1.473     amueller 5392:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5393:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5394:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5395:      'string_questiontype'
                   5396:              => [[ 'problem', 'Standard Problem'],
                   5397:                  [ 'survey', 'Survey'],
                   5398:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5399:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5400:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5401:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5402:                  [ 'practice', 'Practice'],
                   5403:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5404:      'string_lenient'
                   5405:              => [['yes', 'Yes' ],
                   5406:                  [ 'no', 'No' ],
1.549     raeburn  5407:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5408:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5409:      'string_discussvote'
                   5410:              => [['yes','Yes'],
                   5411:                  ['notended','Yes, unless discussion ended'],
                   5412:                  ['no','No']],
1.549     raeburn  5413:      'string_ip'
                   5414:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5415:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5416:      'string_deeplink'
1.613     raeburn  5417:              => [['on','Set choices for link protection, resource listing, access scope, shown menu items, and embedding']],
1.587     raeburn  5418:     );
                   5419:    
1.383     albertel 5420: 
1.549     raeburn  5421: my %stringmatches = (
                   5422:          'string_lenient'
                   5423:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5424:          'string_ip'
                   5425:               => [['_allowfrom_','[^\!]+'],
                   5426:                   ['_denyfrom_','\!']],
1.588     raeburn  5427:          'string_deeplink'
1.613     raeburn  5428:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top)$']],
1.549     raeburn  5429:     );
                   5430: 
                   5431: my %stringtypes = (
                   5432:                     type         => 'string_questiontype',
                   5433:                     lenient      => 'string_lenient',
                   5434:                     retrypartial => 'string_yesno',
                   5435:                     discussvote  => 'string_discussvote',
                   5436:                     examcode     => 'string_examcode',
                   5437:                     acc          => 'string_ip',
1.587     raeburn  5438:                     deeplink     => 'string_deeplink',
1.549     raeburn  5439:                   );
                   5440: 
1.563     damieng  5441: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5442: # Used by courseprefs.
                   5443: #
                   5444: # @param {string} $string_type - a parameter type for strings
                   5445: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5446: sub standard_string_options {
                   5447:     my ($string_type) = @_;
                   5448:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5449:         return $strings{$string_type};
                   5450:     }
                   5451:     return;
                   5452: }
1.383     albertel 5453: 
1.563     damieng  5454: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5455: #
                   5456: # @param {string} $string_type - a parameter type for strings
                   5457: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5458: sub standard_string_matches {
                   5459:     my ($string_type) = @_;
                   5460:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5461:         return $stringmatches{$string_type};
                   5462:     }
                   5463:     return;
                   5464: }
                   5465: 
1.563     damieng  5466: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5467: #
                   5468: # @param {string} $name - parameter name
                   5469: # @returns {string}
1.549     raeburn  5470: sub get_stringtype {
                   5471:     my ($name) = @_;
                   5472:     if (exists($stringtypes{$name})) {
                   5473:         return $stringtypes{$name};
                   5474:     }
                   5475:     return;
                   5476: }
                   5477: 
1.563     damieng  5478: # Returns HTML to edit a string parameter.
                   5479: #
                   5480: # @param {string} $thistype - parameter type
                   5481: # @param {string} $thiskey - parameter key
                   5482: # @param {string} $showval - parameter current value
                   5483: # @param {string} $name - parameter name
                   5484: # @param {boolean} $readonly - true if the values should not be made editable
                   5485: # @returns {string}
1.383     albertel 5486: sub string_selector {
1.552     raeburn  5487:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5488: 
1.383     albertel 5489:     if (!exists($strings{$thistype})) {
1.552     raeburn  5490:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5491:     }
                   5492: 
1.504     raeburn  5493:     my %skiptype;
1.514     raeburn  5494:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5495:             ($thistype eq 'string_lenient') ||
                   5496:             ($thistype eq 'string_discussvote') ||
                   5497:             ($thistype eq 'string_ip') ||
1.588     raeburn  5498:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5499:             ($name eq 'retrypartial')) {
1.504     raeburn  5500:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5501:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5502:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5503:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5504:             my $parmmatch;
                   5505:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5506:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5507:                     if (ref($item) eq 'ARRAY') {
                   5508:                         if ($parmval eq $item->[0]) {
                   5509:                             $parmmatch = $parmval;
                   5510:                             $parmval = '';
                   5511:                             last;
                   5512:                         }
                   5513:                     }
                   5514:                 }
                   5515:             }
                   5516:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5517:             if ($needsrelease) {
                   5518:                 unless ($got_chostname) {
1.514     raeburn  5519:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5520:                     $got_chostname = 1;
                   5521:                 }
1.557     raeburn  5522:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5523:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5524:                 if ($needsnewer) {
1.549     raeburn  5525:                     if ($parmmatch ne '') {
                   5526:                         $skiptype{$parmmatch} = 1;
                   5527:                     } elsif ($parmval ne '') {
                   5528:                         $skiptype{$parmval} = 1;
                   5529:                     }
1.504     raeburn  5530:                 }
                   5531:             }
                   5532:         }
                   5533:     }
1.549     raeburn  5534: 
                   5535:     if ($thistype eq 'string_ip') {
1.552     raeburn  5536:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5537:     } elsif ($thistype eq 'string_deeplink') {
                   5538:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5539:     }
1.504     raeburn  5540: 
1.552     raeburn  5541:     my ($result,$disabled);
                   5542: 
                   5543:     if ($readonly) {
                   5544:         $disabled = ' disabled="disabled"';
                   5545:     }
1.504     raeburn  5546:     my $numinrow = 3;
                   5547:     if ($thistype eq 'string_problemstatus') {
                   5548:         $numinrow = 2;
                   5549:     } elsif ($thistype eq 'string_questiontype') {
                   5550:         if (keys(%skiptype) > 0) {
                   5551:              $numinrow = 4;
                   5552:         }
                   5553:     }
                   5554:     my $rem;
                   5555:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5556:         my $i=0;
                   5557:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5558:             next unless (ref($possibilities) eq 'ARRAY');
                   5559:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5560:             next if ($skiptype{$name});
1.504     raeburn  5561:             $rem = $i%($numinrow);
                   5562:             if ($rem == 0) {
                   5563:                 if ($i > 0) {
                   5564:                     $result .= '</tr>';
                   5565:                 }
                   5566:                 $result .= '<tr>';
                   5567:             }
1.549     raeburn  5568:             my $colspan;
                   5569:             if ($i == @{ $strings{$thistype} }-1) {
                   5570:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5571:                 if ($rem) {
                   5572:                     my $colsleft = $numinrow - $rem;
                   5573:                     if ($colsleft) {
                   5574:                         $colspan = $colsleft+1;
                   5575:                         $colspan = ' colspan="'.$colspan.'"';
                   5576:                     }
                   5577:                 }
                   5578:             }
                   5579:             my ($add,$onchange,$css_class);
                   5580:             if ($thistype eq 'string_lenient') {
                   5581:                 if ($name eq 'weighted') {
                   5582:                     my $display;
                   5583:                     my %relatives = &Apache::lonlocal::texthash(
                   5584:                                         corrchkd     => 'Correct (checked)',
                   5585:                                         corrunchkd   => 'Correct (unchecked)',
                   5586:                                         incorrchkd   => 'Incorrect (checked)',
                   5587:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5588:                     );
                   5589:                     my %textval = (
                   5590:                                     corrchkd     => '1.0',
                   5591:                                     corrunchkd   => '1.0',
                   5592:                                     incorrchkd   => '0.0',
                   5593:                                     incorrunchkd => '0.0',
                   5594:                     );
                   5595:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5596:                         $textval{'corrchkd'} = $1;
                   5597:                         $textval{'corrunchkd'} = $2;
                   5598:                         $textval{'incorrchkd'} = $3;
                   5599:                         $textval{'incorrunchkd'} = $4;
                   5600:                         $display = 'inline';
                   5601:                         $showval = $name;
                   5602:                     } else {
                   5603:                         $display = 'none';
                   5604:                     }
                   5605:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5606:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5607:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5608:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5609:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5610:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5611:                                 '</td></tr>';
                   5612:                     }
                   5613:                     $add .= '</table></div>'."\n";
                   5614:                 }
                   5615:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5616:                 $css_class = ' class="LC_lenient_radio"';
                   5617:             }
                   5618:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5619:                        '<span class="LC_nobreak"><label>'.
                   5620:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5621:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5622:             if ($showval eq $name) {
                   5623:                 $result .= ' checked="checked"';
                   5624:             }
1.549     raeburn  5625:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5626:             $i++;
                   5627:         }
                   5628:         $result .= '</tr>';
1.473     amueller 5629:     }
1.504     raeburn  5630:     if ($result) {
                   5631:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5632:     }
                   5633:     return $result;
                   5634: }
                   5635: 
1.554     raeburn  5636: my %intervals =
                   5637:     (
                   5638:      'date_interval'
                   5639:              => [[ 'done', 'Yes' ],
1.558     raeburn  5640:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5641:                  [ '', 'No' ]],
                   5642:     );
                   5643: 
                   5644: my %intervalmatches = (
                   5645:          'date_interval'
1.559     raeburn  5646:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5647:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5648:     );
                   5649: 
                   5650: my %intervaltypes = (
                   5651:                       interval => 'date_interval',
                   5652:     );
                   5653: 
1.563     damieng  5654: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5655: #
                   5656: # @param {string} $interval_type - a parameter type for intervals
                   5657: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5658: sub standard_interval_matches {
                   5659:     my ($interval_type) = @_;
                   5660:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5661:         return $intervalmatches{$interval_type};
                   5662:     }
                   5663:     return;
                   5664: }
                   5665: 
1.563     damieng  5666: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5667: #
                   5668: # @param {string} $name - parameter name
                   5669: # @returns {string}
1.554     raeburn  5670: sub get_intervaltype {
                   5671:     my ($name) = @_;
                   5672:     if (exists($intervaltypes{$name})) {
                   5673:         return $intervaltypes{$name};
                   5674:     }
                   5675:     return;
                   5676: }
                   5677: 
1.563     damieng  5678: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5679: # Used by courseprefs.
                   5680: #
                   5681: # @param {string} $interval_type - a parameter type for intervals
                   5682: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5683: sub standard_interval_options {
                   5684:     my ($interval_type) = @_;
                   5685:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5686:         return $intervals{$interval_type};
                   5687:     }
                   5688:     return;
                   5689: }
                   5690: 
1.563     damieng  5691: # Returns HTML to edit a date interval parameter.
                   5692: #
                   5693: # @param {string} $thiskey - parameter key
                   5694: # @param {string} $name - parameter name
                   5695: # @param {string} $showval - parameter current value
                   5696: # @param {boolean} $readonly - true if the values should not be made editable
                   5697: # @returns {string}
1.554     raeburn  5698: sub date_interval_selector {
                   5699:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5700:     my ($result,%skipval);
                   5701:     if ($name eq 'interval') {
                   5702:         my $intervaltype = &get_intervaltype($name);
                   5703:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5704:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5705:             next unless (ref($possibilities) eq 'ARRAY');
                   5706:             my ($parmval, $description) = @{ $possibilities };
                   5707:             my $parmmatch;
                   5708:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5709:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5710:                     if (ref($item) eq 'ARRAY') {
                   5711:                         if ($parmval eq $item->[0]) {
                   5712:                             $parmmatch = $parmval;
                   5713:                             $parmval = '';
                   5714:                             last;
                   5715:                         }
                   5716:                     }
                   5717:                 }
                   5718:             }
                   5719:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5720:             if ($needsrelease) {
                   5721:                 unless ($got_chostname) {
                   5722:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5723:                     $got_chostname = 1;
                   5724:                 }
1.557     raeburn  5725:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5726:                                                        $needsrelease,$cmajor,$cminor);
                   5727:                 if ($needsnewer) {
                   5728:                     if ($parmmatch ne '') {
                   5729:                         $skipval{$parmmatch} = 1;
                   5730:                     } elsif ($parmval ne '') {
                   5731:                         $skipval{$parmval} = 1;
                   5732:                     }
                   5733:                 }
                   5734:             }
                   5735:         }
                   5736:     }
                   5737: 
                   5738:     my $currval = $showval;
                   5739:     foreach my $which (['days', 86400, 31],
                   5740:                ['hours', 3600, 23],
                   5741:                ['minutes', 60, 59],
                   5742:                ['seconds',  1, 59]) {
1.560     damieng  5743:         my ($name, $factor, $max) = @{ $which };
                   5744:         my $amount = int($showval/$factor);
                   5745:         $showval  %= $factor;
                   5746:         my %select = ((map {$_ => $_} (0..$max)),
                   5747:                 'select_form_order' => [0..$max]);
1.611     raeburn  5748:         if ($currval eq '') {
                   5749:             unshift(@{$select{'select_form_order'}},'');
                   5750:             $select{''} = '';
                   5751:             $amount = '';
                   5752:         }
1.560     damieng  5753:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5754:                             \%select,'',$readonly);
                   5755:         $result .= ' '.&mt($name);
1.554     raeburn  5756:     }
                   5757:     if ($name eq 'interval') {
                   5758:         unless ($skipval{'done'}) {
                   5759:             my $checkedon = '';
1.611     raeburn  5760:             my $checkedoff = '';
1.558     raeburn  5761:             my $checkedproc = '';
                   5762:             my $currproctorkey = '';
                   5763:             my $currprocdisplay = 'hidden';
1.559     raeburn  5764:             my $currdonetext = &mt('Done');
                   5765:             if ($currval =~ /^(?:\d+)_done$/) {
                   5766:                 $checkedon = ' checked="checked"';
                   5767:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5768:                 $currdonetext = $1;
1.554     raeburn  5769:                 $checkedon = ' checked="checked"';
1.558     raeburn  5770:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5771:                 $currproctorkey = $1;
                   5772:                 $checkedproc = ' checked="checked"';
                   5773:                 $currprocdisplay = 'text';
1.559     raeburn  5774:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5775:                 $currdonetext = $1;
                   5776:                 $currproctorkey = $2;
                   5777:                 $checkedproc = ' checked="checked"';
                   5778:                 $currprocdisplay = 'text';
1.611     raeburn  5779:             } elsif ($currval ne '') {
                   5780:                 $checkedoff = ' checked="checked"';
                   5781:             } else {
                   5782:                 $currdonetext = '';
1.554     raeburn  5783:             }
1.558     raeburn  5784:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5785:             my $disabled;
                   5786:             if ($readonly) {
                   5787:                 $disabled = ' disabled="disabled"';
                   5788:             }
1.558     raeburn  5789:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5790:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5791:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5792:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5793:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5794:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5795:                        &mt('Yes, with proctor key').'</label>'.
                   5796:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5797:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5798:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611     raeburn  5799:                        '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
                   5800:                        &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5801:         }
                   5802:     }
                   5803:     unless ($readonly) {
                   5804:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5805:     }
                   5806:     return $result;
                   5807: }
                   5808: 
1.563     damieng  5809: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5810: #
                   5811: # @param {string} $name - parameter name
                   5812: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5813: # @param {string} $value - parameter value
                   5814: # @param {string} $chostname - course server name
                   5815: # @param {integer} $cmajor - major version number
                   5816: # @param {integer} $cminor - minor version number
                   5817: # @param {string} $needsrelease - release version needed (major.minor)
                   5818: # @returns {string}
1.549     raeburn  5819: sub oldversion_warning {
1.557     raeburn  5820:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5821:     my $standard_name = &standard_parameter_names($name);
                   5822:     if ($namematch) {
                   5823:         my $level = &standard_parameter_levels($namematch);
                   5824:         my $msg = '';
                   5825:         if ($level) {
                   5826:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5827:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5828:         } else {
                   5829:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5830:                       $standard_name,'<b>','</b>');
                   5831:         }
                   5832:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5833:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5834:                    $cmajor.'.'.$cminor,$chostname,
                   5835:                    $needsrelease).
                   5836:                    '</p>';
                   5837:     }
1.549     raeburn  5838:     my $desc;
                   5839:     my $stringtype = &get_stringtype($name);
                   5840:     if ($stringtype ne '') {
                   5841:         if ($name eq 'examcode') {
                   5842:             $desc = $value;
                   5843:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5844:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5845:                 next unless (ref($possibilities) eq 'ARRAY');
                   5846:                 my ($parmval, $description) = @{ $possibilities };
                   5847:                 my $parmmatch;
                   5848:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5849:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5850:                         if (ref($item) eq 'ARRAY') {
                   5851:                             my ($regexpname,$pattern) = @{$item};
                   5852:                             if ($parmval eq $regexpname) {
                   5853:                                 if ($value =~ /$pattern/) {
                   5854:                                     $desc = $description; 
                   5855:                                     $parmmatch = 1;
                   5856:                                     last;
                   5857:                                 }
                   5858:                             }
                   5859:                         }
                   5860:                     }
                   5861:                     last if ($parmmatch);
                   5862:                 } elsif ($parmval eq $value) {
                   5863:                     $desc = $description;
                   5864:                     last;
                   5865:                 }
                   5866:             }
                   5867:         }
                   5868:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5869:         my $now = time;
                   5870:         if ($value =~ /^\d+$/) {
                   5871:             if ($name eq 'printstartdate') {
                   5872:                 if ($value > $now) {
                   5873:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5874:                 }
                   5875:             } elsif ($name eq 'printenddate') {
                   5876:                 if ($value < $now) {
                   5877:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5878:                 }
                   5879:             }
                   5880:         }
                   5881:     }
                   5882:     return '<p class="LC_warning">'.
1.557     raeburn  5883:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5884:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5885:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5886:        $cmajor.'.'.$cminor,$chostname,
                   5887:        $needsrelease).
                   5888:        '</p>';
1.549     raeburn  5889: }
                   5890: 
1.560     damieng  5891: } # end of block using some constants related to parameter types
                   5892: 
1.549     raeburn  5893: 
1.563     damieng  5894: 
                   5895: # Shifts all start and end dates in the current course by $shift.
1.389     www      5896: #
1.563     damieng  5897: # @param {integer} $shift - time to shift, in seconds
                   5898: # @returns {string} - error name or 'ok'
1.389     www      5899: sub dateshift {
1.594     raeburn  5900:     my ($shift,$numchanges)=@_;
1.389     www      5901:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5902:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  5903:     my $sec = $env{'request.course.sec'};
1.595     raeburn  5904:     my $secgrpregex;
                   5905:     if ($sec ne '') {
                   5906:         my @groups;
                   5907:         if ($env{'request.course.groups'} ne '') {
                   5908:             @groups = split(/:/,$env{'request.course.groups'});
                   5909:         }
                   5910:         if (@groups) {
                   5911:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   5912:         } else {
                   5913:             $secgrpregex = $sec;
                   5914:         }
                   5915:     }
1.389     www      5916:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   5917: # ugly retro fix for broken version of types
1.548     raeburn  5918:     foreach my $key (keys(%data)) {
1.389     www      5919:         if ($key=~/\wtype$/) {
                   5920:             my $newkey=$key;
                   5921:             $newkey=~s/type$/\.type/;
                   5922:             $data{$newkey}=$data{$key};
                   5923:             delete $data{$key};
                   5924:         }
                   5925:     }
1.391     www      5926:     my %storecontent=();
1.389     www      5927: # go through all parameters and look for dates
1.548     raeburn  5928:     foreach my $key (keys(%data)) {
1.389     www      5929:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  5930:           if ($sec ne '') {
1.595     raeburn  5931:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  5932:           }
1.389     www      5933:           my $newdate=$data{$key}+$shift;
1.594     raeburn  5934:           $$numchanges ++;
1.391     www      5935:           $storecontent{$key}=$newdate;
1.389     www      5936:        }
                   5937:     }
1.391     www      5938:     my $reply=&Apache::lonnet::cput
                   5939:                 ('resourcedata',\%storecontent,$dom,$crs);
                   5940:     if ($reply eq 'ok') {
                   5941:        &log_parmset(\%storecontent);
                   5942:     }
                   5943:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   5944:     return $reply;
1.389     www      5945: }
                   5946: 
1.563     damieng  5947: # Overview mode UI to edit course parameters.
                   5948: #
                   5949: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5950: sub newoverview {
1.568     raeburn  5951:     my ($r,$parm_permission) = @_;
1.280     albertel 5952: 
1.208     www      5953:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5954:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5955:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5956:     my $readonly = 1;
                   5957:     if ($parm_permission->{'edit'}) {
                   5958:         undef($readonly);
                   5959:     }
1.414     droeschl 5960:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5961:         text=>"Overview Mode"});
1.523     raeburn  5962: 
                   5963:     my %loaditems = (
1.549     raeburn  5964:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  5965:                     );
                   5966:     my $js = '
                   5967: <script type="text/javascript">
                   5968: // <![CDATA[
                   5969: '.
                   5970:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   5971:             &showhide_js()."\n".
1.549     raeburn  5972:             &toggleparmtextbox_js()."\n".
                   5973:             &validateparms_js()."\n".
                   5974:             &ipacc_boxes_js()."\n".
1.558     raeburn  5975:             &done_proctor_js()."\n".
1.588     raeburn  5976:             &deeplink_js()."\n".
1.523     raeburn  5977: '// ]]>
                   5978: </script>
                   5979: ';
1.549     raeburn  5980: 
1.523     raeburn  5981:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   5982:                                                     {'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.208     www      5986:     $r->print(<<ENDOVER);
1.549     raeburn  5987: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      5988: ENDOVER
1.211     www      5989:     my @ids=();
                   5990:     my %typep=();
                   5991:     my %keyp=();
                   5992:     my %allparms=();
                   5993:     my %allparts=();
                   5994:     my %allmaps=();
                   5995:     my %mapp=();
                   5996:     my %symbp=();
                   5997:     my %maptitles=();
                   5998:     my %uris=();
                   5999:     my %keyorder=&standardkeyorder();
                   6000:     my %defkeytype=();
                   6001: 
                   6002:     my %alllevs=();
                   6003:     $alllevs{'Resource Level'}='full';
1.215     www      6004:     $alllevs{'Map/Folder Level'}='map';
1.211     www      6005:     $alllevs{'Course Level'}='general';
                   6006: 
                   6007:     my $csec=$env{'form.csec'};
1.269     raeburn  6008:     my $cgroup=$env{'form.cgroup'};
1.211     www      6009: 
                   6010:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   6011:     my $pschp=$env{'form.pschp'};
1.506     www      6012: 
1.211     www      6013:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      6014:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      6015: 
1.446     bisitz   6016:     my @selected_sections =
1.473     amueller 6017:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      6018:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 6019:     foreach my $sec (@selected_sections) {
                   6020:         if ($sec eq 'all') {
1.211     www      6021:             @selected_sections = ('all');
                   6022:         }
                   6023:     }
1.552     raeburn  6024:     if ($env{'request.course.sec'} ne '') {
                   6025:         @selected_sections = ($env{'request.course.sec'});
                   6026:     }
1.269     raeburn  6027:     my @selected_groups =
                   6028:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      6029: 
                   6030:     my $pssymb='';
                   6031:     my $parmlev='';
1.446     bisitz   6032: 
1.211     www      6033:     unless ($env{'form.parmlev'}) {
                   6034:         $parmlev = 'map';
                   6035:     } else {
                   6036:         $parmlev = $env{'form.parmlev'};
                   6037:     }
                   6038: 
1.446     bisitz   6039:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6040:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  6041:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      6042: 
1.374     albertel 6043:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 6044:         @psprt = keys(%allparts);
1.374     albertel 6045:     }
1.211     www      6046: # Menu to select levels, etc
                   6047: 
1.456     bisitz   6048:     $r->print('<div class="LC_Box">');
1.445     neumanie 6049:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   6050:     $r->print('<div>');
1.523     raeburn  6051:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      6052:     &levelmenu($r,\%alllevs,$parmlev);
1.610     raeburn  6053:     $r->print(&Apache::lonhtmlcommon::row_closure());
                   6054:     &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447     bisitz   6055:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6056:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6057:     $r->print('</div></div>');
1.446     bisitz   6058: 
1.456     bisitz   6059:     $r->print('<div class="LC_Box">');
1.452     bisitz   6060:     $r->print('<div>');
1.581     raeburn  6061:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 6062:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   6063:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  6064:     my $sectionselector = &sectionmenu(\@selected_sections);
                   6065:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 6066:     $r->print('<table>'.
1.553     raeburn  6067:               '<tr><th>'.&mt('Parts').'</th>');
                   6068:     if ($sectionselector) {
                   6069:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   6070:     }
                   6071:     if ($groupselector) {
                   6072:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   6073:     }
                   6074:     $r->print('</tr><tr><td>');
1.211     www      6075:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  6076:     $r->print('</td>');
                   6077:     if ($sectionselector) { 
                   6078:         $r->print('<td>'.$sectionselector.'</td>');
                   6079:     }
                   6080:     if ($groupselector) {
                   6081:         $r->print('<td>'.$groupselector.'</td>');
                   6082:     }
                   6083:     $r->print('</tr></table>');
1.447     bisitz   6084:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6085:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6086:     $r->print('</div></div>');
                   6087: 
1.456     bisitz   6088:     $r->print('<div class="LC_Box">');
1.452     bisitz   6089:     $r->print('<div>');
1.214     www      6090:     my $sortorder=$env{'form.sortorder'};
                   6091:     unless ($sortorder) { $sortorder='realmstudent'; }
1.612     raeburn  6092:     &sortmenu($r,$sortorder,'newoverview');
1.445     neumanie 6093:     $r->print('</div></div>');
1.446     bisitz   6094: 
1.214     www      6095:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   6096: 
1.211     www      6097: # Build the list data hash from the specified parms
                   6098: 
                   6099:     my $listdata;
                   6100:     %{$listdata}=();
                   6101: 
                   6102:     foreach my $cat (@pscat) {
1.269     raeburn  6103:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   6104:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      6105:     }
                   6106: 
1.212     www      6107:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      6108: 
1.481     amueller 6109:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6110: 
                   6111: # Read modified data
                   6112: 
1.481     amueller 6113:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6114: 
                   6115: # List data
                   6116: 
1.608     raeburn  6117:         my $hash_for_realm;
                   6118:         if (($parmlev eq 'map') && (keys(%allmaps))) {
                   6119:             %{$hash_for_realm} = reverse(%allmaps);
                   6120:         } elsif (($parmlev eq 'full') && (keys(%symbp))) {
                   6121:             for (my $i=0; $i<@ids; $i++) {
                   6122:                 $hash_for_realm->{$symbp{$ids[$i]}} = $i;
                   6123:             }
                   6124:         }
                   6125:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568     raeburn  6126:     }
                   6127:     $r->print(&tableend());
                   6128:     unless ($readonly) {
                   6129:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6130:     }
1.568     raeburn  6131:     $r->print('</form>');
1.507     www      6132:     &endSettingsScreen($r);
                   6133:     $r->print(&Apache::loncommon::end_page());
1.208     www      6134: }
                   6135: 
1.563     damieng  6136: # Fills $listdata with parameter information.
                   6137: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6138: # The non-type value is always 1.
                   6139: #
                   6140: # @param {string} $cat - parameter name
1.566     damieng  6141: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6142: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6143: # @param {hash reference} $listdata - the parameter data that will be modified
                   6144: # @param {array reference} $psprt - selected parts
                   6145: # @param {array reference} $selections - selected sections
                   6146: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6147: # @param {hash reference} $allmaps - hash map pc -> map src
                   6148: # @param {array reference} $ids - resource and map ids
                   6149: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6150: sub secgroup_lister {
                   6151:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6152:     foreach my $item (@{$selections}) {
                   6153:         foreach my $part (@{$psprt}) {
                   6154:             my $rootparmkey=$env{'request.course.id'};
                   6155:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6156:                 $rootparmkey.='.['.$item.']';
                   6157:             }
                   6158:             if ($parmlev eq 'general') {
                   6159: # course-level parameter
                   6160:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6161:                 $$listdata{$newparmkey}=1;
                   6162:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6163:             } elsif ($parmlev eq 'map') {
                   6164: # map-level parameter
1.548     raeburn  6165:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6166:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6167:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6168:                     $$listdata{$newparmkey}=1;
                   6169:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6170:                 }
                   6171:             } else {
                   6172: # resource-level parameter
                   6173:                 foreach my $rid (@{$ids}) {
                   6174:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6175:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6176:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6177:                     $$listdata{$newparmkey}=1;
                   6178:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6179:                 }
                   6180:             }
                   6181:         }
                   6182:     }
                   6183: }
                   6184: 
1.563     damieng  6185: # UI to edit parameter settings starting with a list of all existing parameters.
                   6186: # (called by setoverview action)
                   6187: #
                   6188: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6189: sub overview {
1.568     raeburn  6190:     my ($r,$parm_permission) = @_;
1.208     www      6191:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6192:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6193:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6194:     my $readonly = 1;
                   6195:     if ($parm_permission->{'edit'}) {
                   6196:         undef($readonly);
                   6197:     }
1.549     raeburn  6198:     my $js = '<script type="text/javascript">'."\n".
                   6199:              '// <![CDATA['."\n".
                   6200:              &toggleparmtextbox_js()."\n".
                   6201:              &validateparms_js()."\n".
                   6202:              &ipacc_boxes_js()."\n".
1.558     raeburn  6203:              &done_proctor_js()."\n".
1.588     raeburn  6204:              &deeplink_js()."\n".
1.549     raeburn  6205:              '// ]]>'."\n".
                   6206:              '</script>'."\n";
1.414     droeschl 6207:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6208:     text=>"Overview Mode"});
1.549     raeburn  6209:     my %loaditems = (
                   6210:                       'onload'   => "showHideLenient();",
                   6211:                     );
                   6212: 
                   6213:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6214:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6215:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6216:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6217:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6218: 
1.208     www      6219: # Store modified
                   6220: 
1.568     raeburn  6221:     unless ($readonly) {
                   6222:         &storedata($r,$crs,$dom);
                   6223:     }
1.208     www      6224: 
                   6225: # Read modified data
                   6226: 
1.552     raeburn  6227:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6228: 
1.214     www      6229: 
                   6230:     my $sortorder=$env{'form.sortorder'};
                   6231:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6232:     &sortmenu($r,$sortorder,'overview');
1.214     www      6233: 
1.568     raeburn  6234:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6235: 
                   6236:     if ($readonly) {
                   6237:         $r->print('<p>'.$submitbutton.'</p>');
                   6238:     }
                   6239: 
1.208     www      6240: # List data
                   6241: 
1.568     raeburn  6242:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6243:     $r->print(&tableend().'<p>');
                   6244:     if ($foundkeys) {
                   6245:         unless ($readonly) {
                   6246:             $r->print('<p>'.$submitbutton.'</p>');
                   6247:         }
                   6248:     } else {
                   6249:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6250:     }
                   6251:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6252: }
1.121     www      6253: 
1.560     damieng  6254: # Unused sub.
1.563     damieng  6255: #
                   6256: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6257: sub clean_parameters {
                   6258:     my ($r) = @_;
                   6259:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6260:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6261: 
1.414     droeschl 6262:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6263:         text=>"Clean Parameters"});
1.333     albertel 6264:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6265:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6266:     $r->print(<<ENDOVER);
                   6267: $start_page
                   6268: $breadcrumbs
                   6269: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6270: ENDOVER
                   6271: # Store modified
                   6272: 
                   6273:     &storedata($r,$crs,$dom);
                   6274: 
                   6275: # Read modified data
                   6276: 
                   6277:     my $resourcedata=&readdata($crs,$dom);
                   6278: 
                   6279: # List data
                   6280: 
                   6281:     $r->print('<h3>'.
1.473     amueller 6282:           &mt('These parameters refer to resources that do not exist.').
                   6283:           '</h3>'.
                   6284:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6285:           '<br />');
1.333     albertel 6286:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6287:           '<tr>'.
                   6288:           '<th>'.&mt('Delete').'</th>'.
                   6289:           '<th>'.&mt('Parameter').'</th>'.
                   6290:           '</tr>');
1.333     albertel 6291:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6292:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6293:             && $thiskey=~/\.type$/);
                   6294:         my %data = &parse_key($thiskey);
                   6295:         if (1) { #exists($data{'realm_exists'})
                   6296:             #&& !$data{'realm_exists'}) {
                   6297:             $r->print(&Apache::loncommon::start_data_table_row().
                   6298:                 '<tr>'.
                   6299:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6300: 
                   6301:             $r->print('<td>');
                   6302:             my $display_value = $resourcedata->{$thiskey};
                   6303:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6304:             $display_value =
                   6305:                 &Apache::lonlocal::locallocaltime($display_value);
                   6306:             }
1.470     raeburn  6307:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6308:             $parmitem = &mt($parmitem);
1.560     damieng  6309:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6310:                 $parmitem,$resourcedata->{$thiskey}));
                   6311:             $r->print('<br />');
                   6312:             if ($data{'scope_type'} eq 'all') {
                   6313:                 $r->print(&mt('All users'));
                   6314:             } elsif ($data{'scope_type'} eq 'user') {
                   6315:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6316:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6317:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6318:             }
                   6319:             $r->print('<br />');
                   6320:             if ($data{'realm_type'} eq 'all') {
                   6321:                 $r->print(&mt('All Resources'));
                   6322:             } elsif ($data{'realm_type'} eq 'folder') {
                   6323:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6324:             } elsif ($data{'realm_type'} eq 'symb') {
                   6325:             my ($map,$resid,$url) =
                   6326:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6327:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6328:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6329:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6330:             }
                   6331:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6332:             $r->print('</td></tr>');
                   6333: 
1.473     amueller 6334:         }
1.333     albertel 6335:     }
                   6336:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6337:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6338:           '</p></form>');
                   6339:     &endSettingsScreen($r);
                   6340:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6341: }
                   6342: 
1.563     damieng  6343: # UI to shift all dates (called by dateshift1 action).
                   6344: # Used by overview mode.
                   6345: #
                   6346: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6347: sub date_shift_one {
                   6348:     my ($r) = @_;
                   6349:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6350:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6351:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6352:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6353:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6354:         text=>"Shifting Dates"});
1.594     raeburn  6355:     my $submit_text = &mt('Shift all dates accordingly');
                   6356:     if ($sec ne '') {
1.595     raeburn  6357:         my @groups;
                   6358:         if ($env{'request.course.groups'} ne '') {
                   6359:             @groups = split(/:/,$env{'request.course.groups'});
                   6360:         }
                   6361:         if (@groups) {
                   6362:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6363:         } else {
                   6364:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6365:         }
1.594     raeburn  6366:     }
1.390     www      6367:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6368:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6369:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6370:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6371:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6372:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6373:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6374:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6375:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6376:                                                         'timeshifted',
                   6377:                                                         $env{'form.timebase'},,
                   6378:                                                         '').
                   6379:               '</td></tr></table>'.
                   6380:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6381:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6382:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6383:     &endSettingsScreen($r);
1.390     www      6384:     $r->print(&Apache::loncommon::end_page());
                   6385: }
                   6386: 
1.563     damieng  6387: # UI to shift all dates (second form).
                   6388: #
                   6389: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6390: sub date_shift_two {
                   6391:     my ($r) = @_;
                   6392:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6393:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6394:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6395:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6396:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6397:         text=>"Shifting Dates"});
1.390     www      6398:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6399:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6400:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6401:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6402:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6403:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6404:     if ($sec ne '') {
1.595     raeburn  6405:         my @groups;
                   6406:         if ($env{'request.course.groups'} ne '') {
                   6407:             @groups = split(/:/,$env{'request.course.groups'});
                   6408:         }
                   6409:         if (@groups) {
                   6410:             $r->print('<p>'.
                   6411:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6412:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6413:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6414:                       '</p>');
                   6415:         } else {
                   6416:             $r->print('<p>'.
                   6417:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6418:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6419:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6420:                       '</p>');
                   6421:         }
1.594     raeburn  6422:     } else {
                   6423:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6424:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6425:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6426:                   '</p>');
                   6427:     }
1.390     www      6428:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6429:     my $numchanges = 0;
                   6430:     my $result = &dateshift($delta,\$numchanges);
                   6431:     if ($result eq 'ok') {
                   6432:         $r->print(
                   6433:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6434:                                                     $numchanges)));
                   6435:     } elsif ($result eq 'con_delayed') {
                   6436:         $r->print(
                   6437:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6438:                                                         $numchanges)));
                   6439:     } else {
                   6440:         $r->print(
                   6441:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6442:     }
1.543     bisitz   6443:     $r->print(
                   6444:         '<br /><br />'.
                   6445:         &Apache::lonhtmlcommon::actionbox(
                   6446:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6447:     &endSettingsScreen($r);
1.390     www      6448:     $r->print(&Apache::loncommon::end_page());
                   6449: }
                   6450: 
1.563     damieng  6451: # Returns the different components of a resourcedata key.
                   6452: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6453: #       realm_exists, parameter_part, parameter_name.
                   6454: # Was used by clean_parameters (which is unused).
                   6455: #
                   6456: # @param {string} $key - the parameter key
                   6457: # @returns {hash}
1.333     albertel 6458: sub parse_key {
                   6459:     my ($key) = @_;
                   6460:     my %data;
                   6461:     my ($middle,$part,$name)=
1.572     damieng  6462:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6463:     $data{'scope_type'} = 'all';
                   6464:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6465:         $data{'scope'} = $1;
                   6466:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6467:             $data{'scope_type'} = 'user';
                   6468:             $data{'scope'} = [$1,$2];
                   6469:         } else {
1.581     raeburn  6470:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6471:         }
                   6472:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6473:     }
                   6474:     $middle=~s/\.+$//;
                   6475:     $middle=~s/^\.+//;
                   6476:     $data{'realm_type'}='all';
                   6477:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6478:         $data{'realm'} = $1;
                   6479:         $data{'realm_type'} = 'folder';
                   6480:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6481:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6482:     } elsif ($middle) {
1.560     damieng  6483:         $data{'realm'} = $middle;
                   6484:         $data{'realm_type'} = 'symb';
                   6485:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6486:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6487:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6488:     }
1.446     bisitz   6489: 
1.333     albertel 6490:     $data{'parameter_part'} = $part;
                   6491:     $data{'parameter_name'} = $name;
                   6492: 
                   6493:     return %data;
                   6494: }
                   6495: 
1.239     raeburn  6496: 
1.563     damieng  6497: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6498: sub header {
1.507     www      6499:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6500: }
1.193     albertel 6501: 
                   6502: 
                   6503: 
1.560     damieng  6504: ##################################################
                   6505: # MAIN MENU
                   6506: ##################################################
                   6507: 
1.563     damieng  6508: # Content and problem settings main menu.
                   6509: #
                   6510: # @param {Apache2::RequestRec} $r - the Apache request
                   6511: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6512: sub print_main_menu {
                   6513:     my ($r,$parm_permission)=@_;
                   6514:     #
1.414     droeschl 6515:     $r->print(&header());
1.507     www      6516:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6517:     my $crstype = &Apache::loncommon::course_type();
                   6518:     my $lc_crstype = lc($crstype);
                   6519: 
                   6520:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6521:     $r->print(<<ENDMAINFORMHEAD);
                   6522: <form method="post" enctype="multipart/form-data"
                   6523:       action="/adm/parmset" name="studentform">
                   6524: ENDMAINFORMHEAD
                   6525: #
1.195     albertel 6526:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6527:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6528:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6529:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6530:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6531:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6532:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6533:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6534:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6535:                                         '/'.$env{'request.course.sec'});
                   6536:     }
1.568     raeburn  6537:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6538:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6539:                                         '/'.$env{'request.course.sec'});
                   6540:     }
                   6541:     my (%linktext,%linktitle,%url);
                   6542:     if ($parm_permission->{'edit'}) {
                   6543:         %linktext = (
                   6544:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6545:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6546:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6547:                     );
                   6548:         %linktitle = (
                   6549:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6550:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6551:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6552:                      );
                   6553:     } else {
                   6554:         %linktext = (
                   6555:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6556:                      settable        => 'View Resource Parameters - Table Mode',
                   6557:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6558:                    );
                   6559:         %linktitle = (
                   6560:                      newoverview     => 'Display resource parameters in overview mode.',
                   6561:                      settable        => 'Display resource parameters in table mode.',
                   6562:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6563:                      );
                   6564:     }
                   6565:     if ($mgr) {
                   6566:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6567:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6568:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6569:     } elsif ($vgr) {
                   6570:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6571:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6572:         $url{'resettimes'} = '/adm/accesstimes';
                   6573:     }
1.193     albertel 6574:     my @menu =
1.507     www      6575:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6576:         items => [
                   6577:           { linktext => 'Portfolio Metadata',
                   6578:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6579:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6580:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6581:             icon =>'contact-new.png'   ,
                   6582:             },
1.568     raeburn  6583:           { linktext => $linktext{'resettimes'},
                   6584:             url => $url{'resettimes'},
                   6585:             permission => ($vgr || $mgr),
                   6586:             linktitle => $linktitle{'resettimes'},
                   6587:             icon => 'start-here.png',
1.473     amueller 6588:             },
1.520     raeburn  6589:           { linktext => 'Blocking Communication/Resource Access',
                   6590:             url => '/adm/setblock',
1.568     raeburn  6591:             permission => ($vcb || $dcm),
1.520     raeburn  6592:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6593:             icon => 'comblock.png',
                   6594:             },
1.473     amueller 6595:           { linktext => 'Set Parameter Setting Default Actions',
                   6596:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6597:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6598:             linktitle =>'Set default actions for parameters.'  ,
                   6599:             icon => 'folder-new.png'  ,
                   6600:             }]},
                   6601:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6602:         items => [
                   6603:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6604:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6605:             permission => $parm_permission->{'helper'},
1.473     amueller 6606:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6607:             icon => 'dialog-information.png'  ,
                   6608:             #help => 'Parameter_Helper',
                   6609:             },
1.568     raeburn  6610:           { linktext => $linktext{'newoverview'},
1.473     amueller 6611:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6612:             permission => $parm_permission->{'newoverview'},
                   6613:             linktitle => $linktitle{'newoverview'},
                   6614:             icon => 'edit-find.png',
1.473     amueller 6615:             #help => 'Parameter_Overview',
                   6616:             },
1.568     raeburn  6617:           { linktext => $linktext{'settable'},
1.473     amueller 6618:             url => '/adm/parmset?action=settable',
1.568     raeburn  6619:             permission => $parm_permission->{'settable'},
                   6620:             linktitle => $linktitle{'settable'},
                   6621:             icon => 'edit-copy.png',
1.473     amueller 6622:             #help => 'Table_Mode',
                   6623:             }]},
1.417     droeschl 6624:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6625:          items => [
1.570     raeburn  6626:           { linktext => $linktext{'setoverview'},
1.473     amueller 6627:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6628:             permission => $parm_permission->{'setoverview'},
                   6629:             linktitle => $linktitle{'setoverview'},
                   6630:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6631:             #help => 'Parameter_Overview',
                   6632:             },
                   6633:           { linktext => 'Change Log',
                   6634:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6635:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6636:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6637:             icon => 'document-properties.png',
1.473     amueller 6638:             }]}
1.193     albertel 6639:           );
1.414     droeschl 6640:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6641:     $r->print('</form>');
1.507     www      6642:     &endSettingsScreen($r);
1.539     raeburn  6643:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6644:     return;
                   6645: }
1.414     droeschl 6646: 
1.416     jms      6647: 
                   6648: 
1.560     damieng  6649: ##################################################
                   6650: # PORTFOLIO METADATA
                   6651: ##################################################
                   6652: 
1.563     damieng  6653: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6654: # It looks like field titles are not localized.
                   6655: #
                   6656: # @param {Apache2::RequestRec} $r - the Apache request
                   6657: # @param {string} $field_name - metadata field name
                   6658: # @param {string} $field_text - metadata field title, in English unless manually added
                   6659: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6660: sub output_row {
1.347     banghart 6661:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6662:     my $output;
1.263     banghart 6663:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6664:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6665:     if (!defined($options)) {
1.254     banghart 6666:         $options = 'active,stuadd';
1.261     banghart 6667:         $values = '';
1.252     banghart 6668:     }
1.337     banghart 6669:     if (!($options =~ /deleted/)) {
                   6670:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6671:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6672:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6673: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6674:         if ($added_flag) {
                   6675:             push @options,['deleted', 'Delete Metadata Field'];
                   6676:         }
1.351     banghart 6677:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6678:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6679:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6680:         foreach my $opt (@options) {
1.560     damieng  6681:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6682:             $output .= &Apache::loncommon::continue_data_table_row();
                   6683:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6684:                     <input type="checkbox" name="'.
                   6685:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6686:                     &mt($opt->[1]).'</label></td>';
                   6687:             $output .= &Apache::loncommon::end_data_table_row();
                   6688:         }
1.351     banghart 6689:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6690:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6691:         $output .= &Apache::loncommon::end_data_table_row();
                   6692:         my $multiple_checked;
                   6693:         my $single_checked;
                   6694:         if ($options =~ m/onlyone/) {
1.422     bisitz   6695:             $multiple_checked = '';
1.423     bisitz   6696:             $single_checked = ' checked="checked"';
1.351     banghart 6697:         } else {
1.423     bisitz   6698:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6699:             $single_checked = '';
1.351     banghart 6700:         }
1.560     damieng  6701:         $output .= &Apache::loncommon::continue_data_table_row();
                   6702:         $output .= '<td>'.('&nbsp;' x 10).'
                   6703:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6704:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6705:         $output .= &Apache::loncommon::end_data_table_row();
                   6706:         $output .= &Apache::loncommon::continue_data_table_row();
                   6707:         $output .= '<td>'.('&nbsp;' x 10).'
                   6708:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6709:                     '.&mt('Student may select only one choice from list').'</td>';
                   6710:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6711:     }
                   6712:     return ($output);
                   6713: }
1.416     jms      6714: 
                   6715: 
1.560     damieng  6716: # UI to order portfolio metadata fields.
1.563     damieng  6717: # Currently useless because addmetafield does not work.
                   6718: #
                   6719: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6720: sub order_meta_fields {
                   6721:     my ($r)=@_;
                   6722:     my $idx = 1;
                   6723:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6724:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6725:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6726:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6727:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6728:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6729:         text=>"Add Metadata Field"});
1.560     damieng  6730:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6731:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6732:         text=>"Restrict Metadata"},
                   6733:         {text=>"Order Metadata"});
1.345     banghart 6734:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6735:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6736:     if ($env{'form.storeorder'}) {
                   6737:         my $newpos = $env{'form.newpos'} - 1;
                   6738:         my $currentpos = $env{'form.currentpos'} - 1;
                   6739:         my @neworder = ();
1.548     raeburn  6740:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6741:         my $i;
1.341     banghart 6742:         if ($newpos > $currentpos) {
1.340     banghart 6743:         # moving stuff up
                   6744:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6745:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6746:             }
                   6747:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6748:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6749:             }
                   6750:             $neworder[$newpos]=$oldorder[$currentpos];
                   6751:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6752:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6753:             }
                   6754:         } else {
                   6755:         # moving stuff down
1.473     amueller 6756:             for ($i=0;$i<$newpos;$i++) {
                   6757:                 $neworder[$i]=$oldorder[$i];
                   6758:             }
                   6759:             $neworder[$newpos]=$oldorder[$currentpos];
                   6760:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6761:                 $neworder[$i]=$oldorder[$i-1];
                   6762:             }
                   6763:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6764:                 $neworder[$i]=$oldorder[$i];
                   6765:             }
1.340     banghart 6766:         }
1.560     damieng  6767:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6768:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6769:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6770:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6771:     }
1.357     raeburn  6772:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6773:     my $ordered_fields;
1.548     raeburn  6774:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6775:     if (!@fields_in_order) {
                   6776:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6777:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6778:             push @fields_in_order, $key;
1.341     banghart 6779:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6780:         }
1.341     banghart 6781:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6782:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6783:     }
1.340     banghart 6784:     $r->print('<table>');
                   6785:     my $num_fields = scalar(@fields_in_order);
                   6786:     foreach my $key (@fields_in_order) {
                   6787:         $r->print('<tr><td>');
                   6788:         $r->print('<form method="post" action="">');
1.537     bisitz   6789:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6790:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6791:             if ($i eq $idx) {
                   6792:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6793:             } else {
                   6794:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6795:             }
                   6796:         }
                   6797:         $r->print('</select></td><td>');
                   6798:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6799:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6800:         $r->print('</form>');
                   6801:         $r->print($$fields{$key}.'</td></tr>');
                   6802:         $idx ++;
                   6803:     }
                   6804:     $r->print('</table>');
1.507     www      6805:     &endSettingsScreen($r);
1.340     banghart 6806:     return 'ok';
                   6807: }
1.416     jms      6808: 
                   6809: 
1.563     damieng  6810: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6811: # @returns {string}
1.359     banghart 6812: sub continue {
                   6813:     my $output;
                   6814:     $output .= '<form action="" method="post">';
                   6815:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6816:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6817:     return ($output);
                   6818: }
1.416     jms      6819: 
                   6820: 
1.563     damieng  6821: # UI to add a metadata field.
                   6822: # Currenly does not work because of an HTML error (the field is not visible).
                   6823: #
                   6824: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6825: sub addmetafield {
                   6826:     my ($r)=@_;
1.414     droeschl 6827:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6828:         text=>"Add Metadata Field"});
1.334     banghart 6829:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6830:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6831:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6832:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6833:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6834:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6835:     if (exists($env{'form.undelete'})) {
1.358     banghart 6836:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6837:         foreach my $meta_field(@meta_fields) {
                   6838:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6839:             $options =~ s/deleted//;
                   6840:             $options =~ s/,,/,/;
                   6841:             my $put_result = &Apache::lonnet::put('environment',
                   6842:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6843: 
1.586     raeburn  6844:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6845:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6846:                           '</strong>',$put_result).
                   6847:                       '<br />');
1.339     banghart 6848:         }
1.359     banghart 6849:         $r->print(&continue());
1.339     banghart 6850:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6851:         my $meta_field = $env{'form.fieldname'};
                   6852:         my $display_field = $env{'form.fieldname'};
                   6853:         $meta_field =~ s/\W/_/g;
1.338     banghart 6854:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6855:         my $put_result = &Apache::lonnet::put('environment',
                   6856:                             {'metadata.'.$meta_field.'.values'=>"",
                   6857:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6858:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6859:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6860:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6861:                   '<br />');
1.359     banghart 6862:         $r->print(&continue());
1.335     banghart 6863:     } else {
1.357     raeburn  6864:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6865:         if ($fields) {
1.586     raeburn  6866:             $r->print(&mt('You may undelete previously deleted fields.').
                   6867:                       '<br />'.
                   6868:                       &mt('Check those you wish to undelete and click Undelete.').
                   6869:                       '<br />');
1.339     banghart 6870:             $r->print('<form method="post" action="">');
                   6871:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6872:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6873:             }
1.586     raeburn  6874:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6875:             $r->print('</form>');
                   6876:         }
1.586     raeburn  6877:         $r->print('<hr />'.
                   6878:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6879:                       '<strong>','</strong>').
1.581     raeburn  6880:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6881:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6882:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6883:         $r->print('</form>');
1.334     banghart 6884:     }
1.507     www      6885:     &endSettingsScreen($r);
1.334     banghart 6886: }
1.416     jms      6887: 
                   6888: 
                   6889: 
1.560     damieng  6890: # Display or save portfolio metadata.
1.563     damieng  6891: #
                   6892: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6893: sub setrestrictmeta {
1.240     banghart 6894:     my ($r)=@_;
1.242     banghart 6895:     my $next_meta;
1.244     banghart 6896:     my $output;
1.245     banghart 6897:     my $item_num;
1.246     banghart 6898:     my $put_result;
1.414     droeschl 6899:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6900:         text=>"Restrict Metadata"});
1.280     albertel 6901:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6902:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6903:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6904:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6905:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6906:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 6907:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 6908:     my $save_field = '';
1.586     raeburn  6909:     my %lt = &Apache::lonlocal::texthash(
                   6910:                                            addm => 'Add Metadata Field',
                   6911:                                            ordm => 'Order Metadata Fields',
                   6912:                                            save => 'Save',
                   6913:                                         );
1.259     banghart 6914:     if ($env{'form.restrictmeta'}) {
1.254     banghart 6915:         foreach my $field (sort(keys(%env))) {
1.252     banghart 6916:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 6917:                 my $options;
1.252     banghart 6918:                 my $meta_field = $1;
                   6919:                 my $meta_key = $2;
1.253     banghart 6920:                 if ($save_field ne $meta_field) {
1.252     banghart 6921:                     $save_field = $meta_field;
1.473     amueller 6922:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   6923:                         $options.='stuadd,';
                   6924:                     }
                   6925:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   6926:                         $options.='choices,';
                   6927:                     }
                   6928:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   6929:                         $options.='onlyone,';
                   6930:                     }
                   6931:                     if ($env{'form.'.$meta_field.'_active'}) {
                   6932:                         $options.='active,';
                   6933:                     }
                   6934:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   6935:                         $options.='deleted,';
                   6936:                     }
1.259     banghart 6937:                     my $name = $save_field;
1.560     damieng  6938:                     $put_result = &Apache::lonnet::put('environment',
                   6939:                         {'metadata.'.$meta_field.'.options'=>$options,
                   6940:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   6941:                         },$dom,$crs);
1.252     banghart 6942:                 }
                   6943:             }
                   6944:         }
                   6945:     }
1.296     albertel 6946:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 6947:                        {'freshen_cache' => 1});
1.335     banghart 6948:     # Get the default metadata fields
1.258     albertel 6949:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 6950:     # Now get possible added metadata fields
1.357     raeburn  6951:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 6952:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 6953:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 6954:         if ($field ne 'courserestricted') {
1.586     raeburn  6955:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  6956:         }
1.255     banghart 6957:     }
1.351     banghart 6958:     my $buttons = (<<ENDButtons);
1.586     raeburn  6959:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 6960:         </form><br />
                   6961:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  6962:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 6963:         </form>
                   6964:         <br />
                   6965:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  6966:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 6967: ENDButtons
1.337     banghart 6968:     my $added_flag = 1;
1.335     banghart 6969:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  6970:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 6971:     }
1.347     banghart 6972:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   6973:     $r->print(<<ENDenv);
1.259     banghart 6974:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 6975:         $output
1.351     banghart 6976:         $buttons
1.340     banghart 6977:         </form>
1.244     banghart 6978: ENDenv
1.507     www      6979:     &endSettingsScreen($r);
1.280     albertel 6980:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 6981:     return 'ok';
                   6982: }
1.416     jms      6983: 
                   6984: 
1.563     damieng  6985: # Returns metadata fields that have been manually added.
                   6986: #
                   6987: # @param {string} $cid - course id
                   6988: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 6989: sub get_added_meta_fieldnames {
1.357     raeburn  6990:     my ($cid) = @_;
1.335     banghart 6991:     my %fields;
                   6992:     foreach my $key(%env) {
1.357     raeburn  6993:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 6994:             my $field_name = $1;
                   6995:             my ($display_field_name) = $env{$key};
                   6996:             $fields{$field_name} = $display_field_name;
                   6997:         }
                   6998:     }
                   6999:     return \%fields;
                   7000: }
1.416     jms      7001: 
                   7002: 
1.563     damieng  7003: # Returns metadata fields that have been manually added and deleted.
                   7004: #
                   7005: # @param {string} $cid - course id
                   7006: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 7007: sub get_deleted_meta_fieldnames {
1.357     raeburn  7008:     my ($cid) = @_;
1.339     banghart 7009:     my %fields;
                   7010:     foreach my $key(%env) {
1.357     raeburn  7011:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 7012:             my $field_name = $1;
                   7013:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   7014:                 my ($display_field_name) = $env{$key};
                   7015:                 $fields{$field_name} = $display_field_name;
                   7016:             }
                   7017:         }
                   7018:     }
                   7019:     return \%fields;
                   7020: }
1.560     damieng  7021: 
                   7022: 
                   7023: ##################################################
                   7024: # PARAMETER SETTINGS DEFAULT ACTIONS
                   7025: ##################################################
                   7026: 
                   7027: # UI to change parameter setting default actions
1.563     damieng  7028: #
                   7029: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      7030: sub defaultsetter {
1.280     albertel 7031:     my ($r) = @_;
                   7032: 
1.414     droeschl 7033:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 7034:         text=>"Set Defaults"});
1.531     raeburn  7035:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7036:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   7037:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   7038:     my $start_page =
1.531     raeburn  7039:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 7040:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      7041:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  7042:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      7043:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 7044: 
1.221     www      7045:     my @ids=();
                   7046:     my %typep=();
                   7047:     my %keyp=();
                   7048:     my %allparms=();
                   7049:     my %allparts=();
                   7050:     my %allmaps=();
                   7051:     my %mapp=();
                   7052:     my %symbp=();
                   7053:     my %maptitles=();
                   7054:     my %uris=();
                   7055:     my %keyorder=&standardkeyorder();
                   7056:     my %defkeytype=();
                   7057: 
1.446     bisitz   7058:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 7059:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   7060:                 \%keyorder,\%defkeytype);
1.224     www      7061:     if ($env{'form.storerules'}) {
1.560     damieng  7062:         my %newrules=();
                   7063:         my @delrules=();
                   7064:         my %triggers=();
                   7065:         foreach my $key (keys(%env)) {
1.225     albertel 7066:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  7067:                 my $tempkey=$1;
                   7068:                 my $action=$env{$key};
1.226     www      7069:                 if ($action) {
1.560     damieng  7070:                     $newrules{$tempkey.'_action'}=$action;
                   7071:                     if ($action ne 'default') {
                   7072:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   7073:                         $triggers{$whichparm}.=$tempkey.':';
                   7074:                     }
                   7075:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   7076:                     if (&isdateparm($defkeytype{$tempkey})) {
                   7077:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   7078:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   7079:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   7080:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   7081:                     } else {
                   7082:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   7083:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   7084:                     }
                   7085:                 } else {
                   7086:                     push(@delrules,$tempkey.'_action');
                   7087:                     push(@delrules,$tempkey.'_type');
                   7088:                     push(@delrules,$tempkey.'_hours');
                   7089:                     push(@delrules,$tempkey.'_min');
                   7090:                     push(@delrules,$tempkey.'_sec');
                   7091:                     push(@delrules,$tempkey.'_value');
                   7092:                 }
1.473     amueller 7093:             }
                   7094:         }
1.560     damieng  7095:         foreach my $key (keys(%allparms)) {
                   7096:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 7097:         }
1.560     damieng  7098:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   7099:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   7100:         &resetrulescache();
1.224     www      7101:     }
1.227     www      7102:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 7103:                        'hours' => 'Hours',
                   7104:                        'min' => 'Minutes',
                   7105:                        'sec' => 'Seconds',
                   7106:                        'yes' => 'Yes',
                   7107:                        'no' => 'No');
1.222     www      7108:     my @standardoptions=('','default');
                   7109:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   7110:     my @dateoptions=('','default');
                   7111:     my @datedisplay=('',&mt('Default value when manually setting'));
                   7112:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7113:         unless ($tempkey) { next; }
                   7114:         push @standardoptions,'when_setting_'.$tempkey;
                   7115:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   7116:         if (&isdateparm($defkeytype{$tempkey})) {
                   7117:             push @dateoptions,'later_than_'.$tempkey;
                   7118:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7119:             push @dateoptions,'earlier_than_'.$tempkey;
                   7120:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7121:         }
1.222     www      7122:     }
1.563     damieng  7123:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7124:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7125:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7126:           &Apache::loncommon::start_data_table_header_row().
                   7127:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7128:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7129:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7130:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7131:         unless ($tempkey) { next; }
                   7132:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7133:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7134:         my $action=&rulescache($tempkey.'_action');
                   7135:         $r->print('<select name="'.$tempkey.'_action">');
                   7136:         if (&isdateparm($defkeytype{$tempkey})) {
                   7137:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7138:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7139:             $r->print("\n<option value='$dateoptions[$i]'".
                   7140:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7141:                 ">$datedisplay[$i]</option>");
                   7142:             }
                   7143:         } else {
                   7144:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7145:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7146:             $r->print("\n<option value='$standardoptions[$i]'".
                   7147:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7148:                 ">$standarddisplay[$i]</option>");
                   7149:             }
1.473     amueller 7150:         }
1.560     damieng  7151:         $r->print('</select>');
                   7152:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7153:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7154:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7155:         }
1.560     damieng  7156:         $r->print("\n</td><td>\n");
1.222     www      7157: 
1.221     www      7158:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7159:             my $days=&rulescache($tempkey.'_days');
                   7160:             my $hours=&rulescache($tempkey.'_hours');
                   7161:             my $min=&rulescache($tempkey.'_min');
                   7162:             my $sec=&rulescache($tempkey.'_sec');
                   7163:             $r->print(<<ENDINPUTDATE);
                   7164:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7165:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7166:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7167:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7168: ENDINPUTDATE
1.560     damieng  7169:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7170:                 my $yeschecked='';
                   7171:                 my $nochecked='';
                   7172:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7173:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7174: 
                   7175:             $r->print(<<ENDYESNO);
                   7176:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7177:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7178: ENDYESNO
1.221     www      7179:         } else {
1.560     damieng  7180:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7181:         }
1.318     albertel 7182:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7183:     }
1.318     albertel 7184:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7185:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7186:           &mt('Save').'" /></form>'."\n");
                   7187:     &endSettingsScreen($r);
                   7188:     $r->print(&Apache::loncommon::end_page());
1.220     www      7189:     return;
                   7190: }
1.193     albertel 7191: 
1.560     damieng  7192: ##################################################
                   7193: # PARAMETER CHANGES LOG
                   7194: ##################################################
                   7195: 
1.563     damieng  7196: # Returns some info for a parameter log entry.
                   7197: # Returned entries:
                   7198: # $realm - HTML title for the parameter level and resource
                   7199: # $section - parameter section
                   7200: # $name - parameter name
                   7201: # $part - parameter part
                   7202: # $what - $part.'.'.$name
                   7203: # $middle - resource symb ?
                   7204: # $uname - user name (same as given)
                   7205: # $udom - user domain (same as given)
                   7206: # $issection - section or group name
                   7207: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7208: #
                   7209: # @param {string} $key - parameter log key
                   7210: # @param {string} $uname - user name
                   7211: # @param {string} $udom - user domain
                   7212: # @param {boolean} $typeflag - .type log entry
                   7213: # @returns {Array}
1.290     www      7214: sub components {
1.581     raeburn  7215:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7216: 
                   7217:     if ($typeflag) {
1.560     damieng  7218:         $key=~s/\.type$//;
1.290     www      7219:     }
1.330     albertel 7220: 
                   7221:     my ($middle,$part,$name)=
1.572     damieng  7222:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7223:     my $issection;
1.330     albertel 7224: 
1.290     www      7225:     my $section=&mt('All Students');
                   7226:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7227:         $issection=$1;
                   7228:         $section=&mt('Group/Section').': '.$issection;
                   7229:         $middle=~s/^\[(.*)\]//;
1.290     www      7230:     }
                   7231:     $middle=~s/\.+$//;
                   7232:     $middle=~s/^\.+//;
1.291     www      7233:     if ($uname) {
1.560     damieng  7234:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7235:         $issection='';
1.291     www      7236:     }
1.316     albertel 7237:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7238:     my $realmdescription=&mt('all resources');
1.556     raeburn  7239:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7240:         my $mapurl = $1;
                   7241:         my $maplevel = $2;
                   7242:         my $leveltitle = &mt('Folder/Map');
                   7243:         if ($maplevel eq 'rec') {
                   7244:             $leveltitle = &mt('Recursive');
                   7245:         }
1.560     damieng  7246:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7247:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7248:             $mapurl.')</span></span>';
                   7249:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7250:     } elsif ($middle) {
                   7251:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7252:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7253:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7254:             ' in '.$map.' id: '.$id.')</span></span>';
                   7255:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7256:     }
1.291     www      7257:     my $what=$part.'.'.$name;
1.330     albertel 7258:     return ($realm,$section,$name,$part,
1.473     amueller 7259:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7260: }
1.293     www      7261: 
1.563     damieng  7262: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7263: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7264: 
1.563     damieng  7265: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7266: sub load_parameter_names {
1.583     raeburn  7267:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7268:     while (my $configline=<$config>) {
1.560     damieng  7269:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7270:         chomp($configline);
                   7271:         my ($short,$plain)=split(/:/,$configline);
                   7272:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7273:         if ($type eq 'display') {
                   7274:             $standard_parms{$name} = $plain;
1.469     raeburn  7275:         } elsif ($type eq 'type') {
1.560     damieng  7276:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7277:         }
1.328     albertel 7278:     }
                   7279:     close($config);
                   7280:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7281:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7282:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7283: }
                   7284: 
1.563     damieng  7285: # Returns a parameter title for standard parameters, the name for others.
                   7286: #
                   7287: # @param {string} $name - parameter name
                   7288: # @returns {string}
1.292     www      7289: sub standard_parameter_names {
                   7290:     my ($name)=@_;
1.328     albertel 7291:     if (!%standard_parms) {
1.560     damieng  7292:         &load_parameter_names();
1.328     albertel 7293:     }
1.292     www      7294:     if ($standard_parms{$name}) {
1.560     damieng  7295:         return $standard_parms{$name};
1.446     bisitz   7296:     } else {
1.560     damieng  7297:         return $name;
1.292     www      7298:     }
                   7299: }
1.290     www      7300: 
1.563     damieng  7301: # Returns a parameter type for standard parameters, undef for others.
                   7302: #
                   7303: # @param {string} $name - parameter name
                   7304: # @returns {string}
1.469     raeburn  7305: sub standard_parameter_types {
                   7306:     my ($name)=@_;
                   7307:     if (!%standard_parms_types) {
                   7308:         &load_parameter_names();
                   7309:     }
                   7310:     if ($standard_parms_types{$name}) {
                   7311:         return $standard_parms_types{$name};
                   7312:     }
                   7313:     return;
                   7314: }
1.309     www      7315: 
1.563     damieng  7316: # Returns a parameter level title (not localized) from the parameter level name.
                   7317: #
                   7318: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7319: # @returns {string}
1.557     raeburn  7320: sub standard_parameter_levels {
                   7321:     my ($name)=@_;
                   7322:     my %levels = (
                   7323:                     'resourcelevel'   => 'a single resource',
                   7324:                     'maplevel'        => 'the enclosing map/folder', 
                   7325:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7326:                     'courselevel'     => 'the general (course) level',
                   7327:                  );
                   7328:     if ($levels{$name}) {
                   7329:         return $levels{$name};
                   7330:     }
                   7331:     return;
                   7332: }
                   7333: 
1.560     damieng  7334: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7335: #
                   7336: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7337: sub parm_change_log {
1.568     raeburn  7338:     my ($r,$parm_permission)=@_;
1.531     raeburn  7339:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7340:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7341:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7342:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7343:     text=>"Parameter Change Log"});
1.522     raeburn  7344:     my $js = '<script type="text/javascript">'."\n".
                   7345:              '// <![CDATA['."\n".
                   7346:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7347:              '// ]]>'."\n".
                   7348:              '</script>'."\n";
                   7349:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7350:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7351:     &startSettingsScreen($r,'parmset',$crstype);
                   7352:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7353: 
1.301     www      7354:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7355: 
1.522     raeburn  7356:     $r->print('<div class="LC_left_float">'.
                   7357:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7358:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7359:                      method="post" name="parameterlog">');
1.446     bisitz   7360: 
1.311     albertel 7361:     my %saveable_parameters = ('show' => 'scalar',);
                   7362:     &Apache::loncommon::store_course_settings('parameter_log',
                   7363:                                               \%saveable_parameters);
                   7364:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7365:                                                 \%saveable_parameters);
1.522     raeburn  7366:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7367:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7368:               '</form></fieldset></div><br clear="all" />');
1.301     www      7369: 
1.568     raeburn  7370:     my $readonly = 1;
                   7371:     if ($parm_permission->{'edit'}) {
                   7372:         undef($readonly);
                   7373:     }
1.531     raeburn  7374:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7375:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7376:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7377:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7378:     unless ($readonly) {
                   7379:         $r->print('<th>'.&mt('Announce').'</th>');
                   7380:     }
                   7381:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7382:     my $shown=0;
1.349     www      7383:     my $folder='';
                   7384:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7385:         my $last='';
                   7386:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7387:                 &GDBM_READER(),0640)) {
                   7388:             $last=$hash{'last_known'};
                   7389:             untie(%hash);
                   7390:         }
                   7391:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7392:     }
1.595     raeburn  7393:     my $numgroups = 0;
                   7394:     my @groups;
                   7395:     if ($env{'request.course.groups'} ne '') {
                   7396:         @groups = split(/:/,$env{'request.course.groups'});
                   7397:         $numgroups = scalar(@groups);
                   7398:     }
1.560     damieng  7399:     foreach my $id (sort {
                   7400:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7401:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7402:                 }
                   7403:                 my $aid = (split('00000',$a))[-1];
                   7404:                 my $bid = (split('00000',$b))[-1];
                   7405:                 return $bid<=>$aid;
1.473     amueller 7406:             } (keys(%parmlog))) {
1.294     www      7407:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7408:         my $count = 0;
                   7409:         my $time =
                   7410:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7411:         my $plainname =
                   7412:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7413:                         $parmlog{$id}{'exe_udom'});
                   7414:         my $about_me_link =
                   7415:             &Apache::loncommon::aboutmewrapper($plainname,
                   7416:                             $parmlog{$id}{'exe_uname'},
                   7417:                             $parmlog{$id}{'exe_udom'});
                   7418:         my $send_msg_link='';
1.568     raeburn  7419:         if ((!$readonly) && 
                   7420:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7421:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7422:             $send_msg_link ='<br />'.
                   7423:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7424:                             $parmlog{$id}{'exe_uname'},
                   7425:                             $parmlog{$id}{'exe_udom'});
                   7426:         }
                   7427:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7428:         my $makenewrow=0;
                   7429:         my %istype=();
                   7430:         my $output;
                   7431:         foreach my $changed (reverse(sort(@changes))) {
                   7432:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7433:             my $typeflag = ($changed =~/\.type$/ &&
                   7434:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7435:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7436:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7437:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7438:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7439:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7440:                 if ($uname ne '') {
                   7441:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7442:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7443:                 }
                   7444:             }
                   7445:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7446:                 if ($folder) {
                   7447:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7448:                 }
                   7449:             }
                   7450:             if ($typeflag) {
                   7451:                 $istype{$parmname}=$value;
                   7452:                 if (!$env{'form.includetypes'}) { next; }
                   7453:             }
                   7454:             $count++;
                   7455:             if ($makenewrow) {
                   7456:                 $output .= $row_start;
                   7457:             } else {
                   7458:                 $makenewrow=1;
                   7459:             }
1.470     raeburn  7460:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7461:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7462:                 &mt($parmitem).'</td><td>'.
                   7463:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7464:             my $stillactive=0;
                   7465:             if ($parmlog{$id}{'delflag'}) {
                   7466:                 $output .= &mt('Deleted');
                   7467:             } else {
                   7468:                 if ($typeflag) {
1.470     raeburn  7469:                     my $parmitem = &standard_parameter_names($value); 
                   7470:                     $parmitem = &mt($parmitem);
1.560     damieng  7471:                     $output .= &mt('Type: [_1]',$parmitem);
                   7472:                 } else {
1.584     raeburn  7473:                     my $toolsymb;
                   7474:                     if ($middle =~ /ext\.tool$/) {
                   7475:                         $toolsymb = $middle;
                   7476:                     }
1.560     damieng  7477:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7478:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7479:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7480:                     my $showvalue = $value;
                   7481:                     if ($istype{$parmname} eq '') {
                   7482:                         my $type = &standard_parameter_types($parmname);
                   7483:                         if ($type ne '') {
                   7484:                             if (&isdateparm($type)) {
                   7485:                                 $showvalue =
                   7486:                                     &Apache::lonlocal::locallocaltime($value);
                   7487:                             }
                   7488:                         }
                   7489:                     } else {
1.560     damieng  7490:                         if (&isdateparm($istype{$parmname})) {
                   7491:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7492:                         }
1.469     raeburn  7493:                     }
                   7494:                     $output .= $showvalue;
1.560     damieng  7495:                     if ($value ne $all[$level]) {
                   7496:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7497:                     } else {
                   7498:                         $stillactive=1;
                   7499:                     }
                   7500:                 }
1.473     amueller 7501:             }
1.568     raeburn  7502:             $output .= '</td>';
                   7503: 
                   7504:             unless ($readonly) { 
                   7505:                 $output .= '<td>';
                   7506:                 if ($stillactive) {
                   7507:                     my $parmitem = &standard_parameter_names($parmname);
                   7508:                     $parmitem = &mt($parmitem);
                   7509:                     my $title=&mt('Changed [_1]',$parmitem);
                   7510:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7511:                         $parmitem,$realmdescription,
                   7512:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7513:                     if (($uname) && ($udom)) {
                   7514:                         $output .=
                   7515:                         &Apache::loncommon::messagewrapper('Notify User',
                   7516:                                                            $uname,$udom,$title,
                   7517:                                                            $description);
                   7518:                     } else {
                   7519:                         $output .=
                   7520:                             &Apache::lonrss::course_blog_link($id,$title,
                   7521:                                                               $description);
                   7522:                     }
1.560     damieng  7523:                 }
1.568     raeburn  7524:                 $output .= '</td>';
1.560     damieng  7525:             }
1.568     raeburn  7526:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7527:         }
1.560     damieng  7528:         if ($env{'form.displayfilter'} eq 'containing') {
                   7529:             my $wholeentry=$about_me_link.':'.
                   7530:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7531:             $output;
                   7532:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7533:         }
1.349     www      7534:         if ($count) {
1.560     damieng  7535:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7536:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7537:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7538:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7539:             $send_msg_link.'</td>'.$output);
                   7540:             $shown++;
                   7541:         }
                   7542:         if (!($env{'form.show'} eq &mt('all')
                   7543:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7544:     }
1.301     www      7545:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7546:     &endSettingsScreen($r);
1.284     www      7547:     $r->print(&Apache::loncommon::end_page());
                   7548: }
                   7549: 
1.560     damieng  7550: ##################################################
                   7551: # MISC !
                   7552: ##################################################
                   7553: 
1.563     damieng  7554: # Stores slot information.
1.560     damieng  7555: # Used by table UI
1.563     damieng  7556: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7557: #
                   7558: # @param {string} $slot_name - slot name
                   7559: # @param {string} $cdom - course domain
                   7560: # @param {string} $cnum - course number
                   7561: # @param {string} $symb - resource symb
                   7562: # @param {string} $uname - user name
                   7563: # @param {string} $udom - user domain
                   7564: # @returns {string} - 'ok' or error name
1.437     raeburn  7565: sub update_slots {
                   7566:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7567:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7568:     if (!keys(%slot)) {
                   7569:         return 'error: slot does not exist';
                   7570:     }
                   7571:     my $max=$slot{'maxspace'};
                   7572:     if (!defined($max)) { $max=99999; }
                   7573: 
                   7574:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7575:                                        "^$slot_name\0");
                   7576:     my ($tmp)=%consumed;
                   7577:     if ($tmp=~/^error: 2 / ) {
                   7578:         return 'error: unable to determine current slot status';
                   7579:     }
                   7580:     my $last=0;
                   7581:     foreach my $key (keys(%consumed)) {
                   7582:         my $num=(split('\0',$key))[1];
                   7583:         if ($num > $last) { $last=$num; }
                   7584:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7585:             return 'ok';
                   7586:         }
                   7587:     }
                   7588: 
                   7589:     if (scalar(keys(%consumed)) >= $max) {
                   7590:         return 'error: no space left in slot';
                   7591:     }
                   7592:     my $wanted=$last+1;
                   7593: 
                   7594:     my %reservation=('name'      => $uname.':'.$udom,
                   7595:                      'timestamp' => time,
                   7596:                      'symb'      => $symb);
                   7597: 
                   7598:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7599:                                         {"$slot_name\0$wanted" =>
                   7600:                                              \%reservation},
                   7601:                                         $cdom, $cnum);
1.438     raeburn  7602:     if ($success eq 'ok') {
                   7603:         my %storehash = (
                   7604:                           symb    => $symb,
                   7605:                           slot    => $slot_name,
                   7606:                           action  => 'reserve',
                   7607:                           context => 'parameter',
                   7608:                         );
1.526     raeburn  7609:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7610:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7611: 
1.526     raeburn  7612:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7613:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7614:     }
1.437     raeburn  7615:     return $success;
                   7616: }
                   7617: 
1.563     damieng  7618: # Deletes a slot reservation.
1.560     damieng  7619: # Used by table UI
1.563     damieng  7620: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7621: #
                   7622: # @param {string} $slot_name - slot name
                   7623: # @param {string} $cdom - course domain
                   7624: # @param {string} $cnum - course number
                   7625: # @param {string} $uname - user name
                   7626: # @param {string} $udom - user domain
                   7627: # @param {string} $symb - resource symb
                   7628: # @returns {string} - 'ok' or error name
1.437     raeburn  7629: sub delete_slots {
                   7630:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7631:     my $delresult;
                   7632:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7633:                                          $cnum, "^$slot_name\0");
                   7634:     if (&Apache::lonnet::error(%consumed)) {
                   7635:         return 'error: unable to determine current slot status';
                   7636:     }
                   7637:     my ($tmp)=%consumed;
                   7638:     if ($tmp=~/^error: 2 /) {
                   7639:         return 'error: unable to determine current slot status';
                   7640:     }
                   7641:     foreach my $key (keys(%consumed)) {
                   7642:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7643:             my $num=(split('\0',$key))[1];
                   7644:             my $entry = $slot_name.'\0'.$num;
                   7645:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7646:                                               $cdom,$cnum);
                   7647:             if ($delresult eq 'ok') {
                   7648:                 my %storehash = (
                   7649:                                   symb    => $symb,
                   7650:                                   slot    => $slot_name,
                   7651:                                   action  => 'release',
                   7652:                                   context => 'parameter',
                   7653:                                 );
1.526     raeburn  7654:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7655:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7656:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7657:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7658:             }
                   7659:         }
                   7660:     }
                   7661:     return $delresult;
                   7662: }
                   7663: 
1.563     damieng  7664: # Returns true if there is a current course.
1.560     damieng  7665: # Used by handler
1.563     damieng  7666: #
                   7667: # @returns {boolean}
1.355     albertel 7668: sub check_for_course_info {
                   7669:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7670:     return 1 if ($navmap);
                   7671:     return 0;
                   7672: }
                   7673: 
1.563     damieng  7674: # Returns the current course host and host LON-CAPA version.
                   7675: #
                   7676: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7677: sub parameter_release_vars { 
1.504     raeburn  7678:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7679:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7680:    my $chostname = &Apache::lonnet::hostname($chome);
                   7681:    my ($cmajor,$cminor) = 
                   7682:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7683:    return ($chostname,$cmajor,$cminor);
                   7684: }
                   7685: 
1.563     damieng  7686: # Checks if the course host version can handle a parameter required version,
                   7687: # and if it does, stores the release needed for the course.
                   7688: #
                   7689: # @param {string} $name - parameter name
                   7690: # @param {string} $value - parameter value
                   7691: # @param {string} $valmatch - name of the test used for checking the value
                   7692: # @param {string} $namematch - name of the test used for checking the name
                   7693: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7694: # @param {integer} $cmajor - course major version number
                   7695: # @param {integer} $cminor - course minor version number
                   7696: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7697: sub parameter_releasecheck {
1.557     raeburn  7698:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7699:     my $needsnewer;
                   7700:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7701:     if (($cmajor < $needsmajor) || 
                   7702:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7703:         $needsnewer = 1;
1.557     raeburn  7704:     } elsif ($name) {
                   7705:         if ($valmatch) {
                   7706:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7707:         } elsif ($value) { 
                   7708:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7709:         }
                   7710:     } elsif ($namematch) {
                   7711:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7712:     }
                   7713:     return $needsnewer;
                   7714: }
                   7715: 
1.568     raeburn  7716: sub get_permission {
                   7717:     my %permission;
                   7718:     my $allowed = 0;
                   7719:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7720:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7721:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7722:                   $env{'request.course.sec'}))) {
                   7723:         %permission= (
                   7724:                        'edit'               => 1,
                   7725:                        'set'                => 1,
                   7726:                        'setoverview'        => 1,
                   7727:                        'addmetadata'        => 1,
                   7728:                        'ordermetadata'      => 1,
                   7729:                        'setrestrictmeta'    => 1,
                   7730:                        'newoverview'        => 1,
                   7731:                        'setdefaults'        => 1,
                   7732:                        'settable'           => 1,
                   7733:                        'parameterchangelog' => 1,
                   7734:                        'cleanparameters'    => 1,
                   7735:                        'dateshift1'         => 1,
                   7736:                        'dateshift2'         => 1,
                   7737:                        'helper'             => 1,
                   7738:          );
                   7739:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7740:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7741:                   $env{'request.course.sec'}))) {
                   7742:         %permission = (
                   7743:                        'set'                => 1,
                   7744:                        'settable'           => 1,
                   7745:                        'newoverview'        => 1,
                   7746:                        'setoverview'        => 1,
                   7747:                        'parameterchangelog' => 1,
                   7748:                       );
                   7749:     }
                   7750:     foreach my $perm (values(%permission)) {
                   7751:         if ($perm) { $allowed=1; last; }
                   7752:     }
                   7753:     return (\%permission,$allowed);
                   7754: }
                   7755: 
1.560     damieng  7756: ##################################################
                   7757: # HANDLER
                   7758: ##################################################
                   7759: 
                   7760: # Main handler for lonparmset.
                   7761: # Sub called based on request parameters action and command:
                   7762: # no command or action: print_main_menu
                   7763: # command 'set': assessparms (direct access to table mode for a resource)
                   7764: #                (this can also be accessed simply with the symb parameter)
                   7765: # action 'setoverview': overview (display all existing parameter settings)
                   7766: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7767: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7768: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7769: # action 'newoverview': newoverview (overview mode)
                   7770: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7771: # action 'settable': assessparms (table mode)
                   7772: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7773: #                              blog postings, user notification changes)
                   7774: # action 'cleanparameters': clean_parameters (unused)
                   7775: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7776: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7777: sub handler {
1.43      albertel 7778:     my $r=shift;
1.30      www      7779: 
1.376     albertel 7780:     &reset_caches();
                   7781: 
1.414     droeschl 7782:     &Apache::loncommon::content_type($r,'text/html');
                   7783:     $r->send_http_header;
                   7784:     return OK if $r->header_only;
                   7785: 
1.193     albertel 7786:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7787:                         ['action','state',
1.205     www      7788:                                              'pres_marker',
                   7789:                                              'pres_value',
1.206     www      7790:                                              'pres_type',
1.506     www      7791:                                              'filter','part',
1.390     www      7792:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7793: 
1.83      bowersj2 7794: 
1.193     albertel 7795:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7796:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7797:                         text=>"Content and Problem Settings",
1.473     amueller 7798:                         faq=>10,
                   7799:                         bug=>'Instructor Interface',
1.442     droeschl 7800:                                             help =>
                   7801:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7802: 
1.30      www      7803: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7804:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7805:     my $exists = &check_for_course_info();
                   7806: 
1.568     raeburn  7807:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7808:         #
                   7809:         # Main switch on form.action and form.state, as appropriate
                   7810:         #
                   7811:         # Check first if coming from someone else headed directly for
                   7812:         #  the table mode
1.568     raeburn  7813:         if (($parm_permission->{'set'}) && 
                   7814:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7815:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7816:             &assessparms($r,$parm_permission);
1.193     albertel 7817:         } elsif (! exists($env{'form.action'})) {
                   7818:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7819:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7820:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7821:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7822:             &overview($r,$parm_permission);
1.560     damieng  7823:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7824:             &addmetafield($r);
                   7825:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7826:             &order_meta_fields($r);
1.414     droeschl 7827:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7828:             &setrestrictmeta($r);
1.414     droeschl 7829:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7830:             &newoverview($r,$parm_permission);
1.414     droeschl 7831:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7832:             &defaultsetter($r);
                   7833:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7834:             &assessparms($r,$parm_permission);
1.414     droeschl 7835:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7836:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7837:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7838:             &clean_parameters($r);
1.414     droeschl 7839:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7840:             &date_shift_one($r);
1.414     droeschl 7841:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7842:             &date_shift_two($r);
1.446     bisitz   7843:         }
1.43      albertel 7844:     } else {
1.1       www      7845: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7846:         if ($exists) {
                   7847:             $env{'user.error.msg'}=
                   7848:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7849:         } else {
                   7850:             $env{'user.error.msg'}=
                   7851:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7852:         }
                   7853:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7854:     }
1.376     albertel 7855:     &reset_caches();
                   7856: 
1.43      albertel 7857:     return OK;
1.1       www      7858: }
                   7859: 
                   7860: 1;
                   7861: __END__
                   7862: 
                   7863: 

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