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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.610   ! raeburn     4: # $Id: lonparmset.pm,v 1.609 2022/04/30 03:11:05 raeburn Exp $
1.40      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.59      matthew    28: ###################################################################
                     29: ###################################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: lonparmset - Handler to set parameters for assessments and course
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
1.579     raeburn    39: lonparmset provides an interface to setting content parameters in a 
                     40: course.
1.560     damieng    41: 
                     42: It contains all the code for the "Content and Problem Settings" UI, except
                     43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
                     44: and lonblockingmenu.pm.
1.59      matthew    45: 
                     46: =head1 DESCRIPTION
                     47: 
                     48: This module sets coursewide and assessment parameters.
                     49: 
                     50: =head1 INTERNAL SUBROUTINES
                     51: 
1.416     jms        52: =over
1.59      matthew    53: 
1.416     jms        54: =item parmval()
1.59      matthew    55: 
                     56: Figure out a cascading parameter.
                     57: 
1.71      albertel   58: Inputs:  $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162     albertel   59:          $id   - a bighash Id number
1.71      albertel   60:          $def  - the resource's default value   'stupid emacs
                     61: 
1.556     raeburn    62: Returns:  A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71      albertel   63: 
1.556     raeburn    64: 18 - General Course
                     65: 17 - Map or Folder level in course (recursive) 
                     66: 16 - Map or Folder level in course (non-recursive)
                     67: 15 - resource default
                     68: 14 - map default
                     69: 13 - resource level in course
                     70: 12 - General for section
                     71: 11 - Map or Folder level for section (recursive)
                     72: 10 - Map or Folder level for section (non-recursive)
                     73: 9 - resource level in section
                     74: 8 - General for group
                     75: 7 - Map or Folder level for group (recursive)
                     76: 6 - Map or Folder level for group (non-recursive)
                     77: 5 - resource level in group
                     78: 4 - General for specific student
                     79: 3 - Map or Folder level for specific student (recursive)
                     80: 2 - Map or Folder level for specific student (non-recursive)
1.71      albertel   81: 1 - resource level for specific student
1.2       www        82: 
1.416     jms        83: =item parmval_by_symb()
                     84: 
                     85: =item reset_caches()
                     86: 
                     87: =item cacheparmhash() 
                     88: 
                     89: =item parmhash()
                     90: 
                     91: =item symbcache()
                     92: 
                     93: =item preset_defaults()
                     94: 
                     95: =item date_sanity_info()
                     96: 
                     97: =item storeparm()
                     98: 
                     99: Store a parameter by symb
                    100: 
                    101:     Takes
                    102:     - symb
                    103:     - name of parameter
                    104:     - level
                    105:     - new value
                    106:     - new type
                    107:     - username
                    108:     - userdomain
                    109: 
                    110: =item log_parmset()
                    111: 
                    112: =item storeparm_by_symb_inner()
                    113: 
                    114: =item valout()
                    115: 
                    116: Format a value for output.
                    117: 
                    118: Inputs:  $value, $type, $editable
                    119: 
                    120: Returns: $value, formatted for output.  If $type indicates it is a date,
                    121: localtime($value) is returned.
                    122: $editable will return an icon to click on
                    123: 
                    124: =item plink()
                    125: 
                    126: Produces a link anchor.
                    127: 
                    128: Inputs: $type,$dis,$value,$marker,$return,$call
                    129: 
                    130: Returns: scalar with html code for a link which will envoke the 
                    131: javascript function 'pjump'.
                    132: 
                    133: =item page_js()
                    134: 
                    135: =item startpage()
                    136: 
                    137: =item print_row()
                    138: 
                    139: =item print_td()
                    140: 
1.580     raeburn   141: =item check_other_groups()
1.416     jms       142: 
                    143: =item parm_control_group()
                    144: 
                    145: =item extractResourceInformation() : 
                    146: 
1.512     foxr      147:  extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416     jms       148: 
1.542     raeburn   149: Input: See list below
                    150: 
                    151: =over 4
1.416     jms       152: 
1.512     foxr      153: =item * B<env{'user.name'}> : Current username
1.416     jms       154: 
1.512     foxr      155: =item * B<env{'user.domain'}> : Domain of current user.
1.416     jms       156: 
1.542     raeburn   157: =item * B<env{"request.course.fn"}> : Course
                    158: 
                    159: =back
1.416     jms       160: 
1.512     foxr      161: Outputs: See list below:
1.416     jms       162: 
1.542     raeburn   163: =over 4
                    164: 
1.512     foxr      165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416     jms       166: 
1.512     foxr      167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416     jms       168: 
1.512     foxr      169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416     jms       170: 
1.512     foxr      171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416     jms       172: 
1.512     foxr      173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
                    174: 
                    175: =item * B<allmaps> (out) : hash, ???
1.416     jms       176: 
                    177: =item * B<mapp> : ??
                    178: 
                    179: =item * B<symbp> : hash, id->full sym?
                    180: 
1.512     foxr      181: =item * B<maptitles>
                    182: 
                    183: =item * B<uris>
1.416     jms       184: 
1.512     foxr      185: =item * B<keyorder>
                    186: 
                    187: =item * B<defkeytype>
1.416     jms       188: 
1.542     raeburn   189: =back
                    190: 
1.416     jms       191: =item isdateparm()
                    192: 
                    193: =item parmmenu()
                    194: 
                    195: =item partmenu()
                    196: 
                    197: =item usermenu()
                    198: 
                    199: =item displaymenu()
                    200: 
                    201: =item mapmenu()
                    202: 
                    203: =item levelmenu()
                    204: 
                    205: =item sectionmenu()
                    206: 
                    207: =item keysplit()
                    208: 
                    209: =item keysinorder()
                    210: 
                    211: =item keysinorder_bytype()
                    212: 
                    213: =item keysindisplayorder()
                    214: 
                    215: =item standardkeyorder()
                    216: 
                    217: =item assessparms() : 
                    218: 
                    219: Show assessment data and parameters.  This is a large routine that should
                    220: be simplified and shortened... someday.
                    221: 
1.513     foxr      222: Inputs: $r - the Apache request object.
                    223:   
1.416     jms       224: Returns: nothing
                    225: 
                    226: Variables used (guessed by Jeremy):
                    227: 
1.542     raeburn   228: =over
                    229: 
1.416     jms       230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
                    231: 
                    232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
                    233: 
                    234: =item * B<@catmarker> contains list of all possible parameters including part #s
                    235: 
                    236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
                    237: 
                    238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
                    239:         When storing information, store as part 0
                    240:         When requesting information, request from full part
                    241: 
1.542     raeburn   242: =back
                    243: 
1.416     jms       244: =item tablestart()
                    245: 
                    246: =item tableend()
                    247: 
                    248: =item extractuser()
                    249: 
                    250: =item parse_listdata_key()
                    251: 
                    252: =item listdata()
                    253: 
                    254: =item date_interval_selector()
                    255: 
                    256: =item get_date_interval_from_form()
                    257: 
                    258: =item default_selector()
                    259: 
                    260: =item string_selector()
                    261: 
                    262: =item dateshift()
                    263: 
                    264: =item newoverview()
                    265: 
                    266: =item secgroup_lister()
                    267: 
                    268: =item overview()
                    269: 
                    270: =item clean_parameters()
                    271: 
                    272: =item date_shift_one()
                    273: 
                    274: =item date_shift_two()
                    275: 
                    276: =item parse_key()
                    277: 
                    278: =item header()
                    279: 
                    280: Output html header for page
                    281: 
                    282: =item print_main_menu()
                    283: 
                    284: =item output_row()
                    285: 
                    286: Set portfolio metadata
                    287: 
                    288: =item order_meta_fields()
                    289: 
                    290: =item addmetafield()
                    291: 
                    292: =item setrestrictmeta()
                    293: 
                    294: =item get_added_meta_fieldnames()
                    295: 
                    296: =item get_deleted_meta_fieldnames()
                    297: 
                    298: =item defaultsetter()
                    299: 
                    300: =item components()
                    301: 
                    302: =item load_parameter_names()
                    303: 
                    304: =item parm_change_log()
                    305: 
                    306: =item handler() : 
                    307: 
1.450     raeburn   308: Main handler.  Calls &assessparms subroutine.
1.416     jms       309: 
                    310: =back
                    311: 
1.59      matthew   312: =cut
                    313: 
1.416     jms       314: ###################################################################
                    315: ###################################################################
                    316: 
                    317: package Apache::lonparmset;
                    318: 
                    319: use strict;
                    320: use Apache::lonnet;
                    321: use Apache::Constants qw(:common :http REDIRECT);
                    322: use Apache::lonhtmlcommon();
                    323: use Apache::loncommon;
                    324: use GDBM_File;
                    325: use Apache::lonhomework;
                    326: use Apache::lonxml;
                    327: use Apache::lonlocal;
                    328: use Apache::lonnavmaps;
                    329: use Apache::longroup;
                    330: use Apache::lonrss;
1.506     www       331: use HTML::Entities;
1.416     jms       332: use LONCAPA qw(:DEFAULT :match);
                    333: 
                    334: 
1.560     damieng   335: ##################################################
                    336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    337: ##################################################
                    338: 
                    339: # Page header
1.561     damieng   340: #
                    341: # @param {Apache2::RequestRec} $r - Apache request object
                    342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    343: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       344: sub startSettingsScreen {
1.531     raeburn   345:     my ($r,$mode,$crstype)=@_;
1.507     www       346: 
1.531     raeburn   347:     my $tabtext = &mt('Course Settings');
                    348:     if ($crstype eq 'Community') {
                    349:         $tabtext = &mt('Community Settings');
                    350:     } 
1.507     www       351:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    352:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   353:                                           $tabtext.
1.507     www       354:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    355: 
1.523     raeburn   356:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       357:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    358:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   359:     $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507     www       360: }
                    361: 
1.560     damieng   362: # Page footer
1.507     www       363: sub endSettingsScreen {
                    364:    my ($r)=@_;
                    365:    $r->print('</div></div></div>');
                    366: }
                    367: 
                    368: 
                    369: 
1.560     damieng   370: ##################################################
1.563     damieng   371: # (mostly) TABLE MODE
1.560     damieng   372: # (parmval is also used for the log of parameter changes)
                    373: ##################################################
                    374: 
1.566     damieng   375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   376: #
                    377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   378: # @param {string} $id - resource id or map pc
1.561     damieng   379: # @param {string} $def - the resource's default value for this parameter
                    380: # @param {string} $uname - user name
                    381: # @param {string} $udom - user domain
                    382: # @param {string} $csec - section name
                    383: # @param {string} $cgroup - group name
                    384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    385: # @returns {Array}
1.2       www       386: sub parmval {
1.275     raeburn   387:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    388:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    389:                                                            $cgroup,$courseopt);
1.201     www       390: }
                    391: 
1.561     damieng   392: # Returns an array containing
                    393: # - the most specific level that is defined for that parameter (integer)
                    394: # - an array with the level as index and the parameter value as value (when defined)
                    395: #   (level 1 is the most specific and will have precedence)
                    396: #
                    397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   398: # @param {string} $symb - resource symb or map src
1.561     damieng   399: # @param {string} $def - the resource's default value for this parameter
                    400: # @param {string} $uname - user name
                    401: # @param {string} $udom - user domain
                    402: # @param {string} $csec - section name
                    403: # @param {string} $cgroup - group name
                    404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    405: # @returns {Array}
1.201     www       406: sub parmval_by_symb {
1.275     raeburn   407:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       408: 
1.352     albertel  409:     my $useropt;
                    410:     if ($uname ne '' && $udom ne '') {
1.561     damieng   411:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  412:     }
1.200     www       413: 
1.8       www       414:     my $result='';
1.44      albertel  415:     my @outpar=();
1.2       www       416: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    417:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  418:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   419:     
                    420:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    421:     # any change should be reflected there.
                    422:     
1.201     www       423:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   424:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       425:     my $mapparm=$map.'___(all).'.$what;
1.10      www       426: 
1.269     raeburn   427:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    428:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   429:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   430:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    431: 
1.190     albertel  432:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    433:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   434:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  435:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    436: 
                    437:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    438:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   439:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  440:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       441: 
1.11      www       442: 
1.182     albertel  443: # --------------------------------------------------------- first, check course
1.11      www       444: 
1.561     damieng   445: # 18 - General Course
1.200     www       446:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   447:         $outpar[18]=$$courseopt{$courselevel};
                    448:         $result=18;
                    449:     }
                    450: 
1.561     damieng   451: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   452:     if (defined($$courseopt{$courseleveli})) {
                    453:         $outpar[17]=$$courseopt{$courseleveli};
                    454:         $result=17;
1.43      albertel  455:     }
1.11      www       456: 
1.561     damieng   457: # 16 - Map or Folder level in course (non-recursive)
1.200     www       458:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   459:         $outpar[16]=$$courseopt{$courselevelm};
                    460:         $result=16;
1.43      albertel  461:     }
1.11      www       462: 
1.182     albertel  463: # ------------------------------------------------------- second, check default
                    464: 
1.561     damieng   465: # 15 - resource default
1.556     raeburn   466:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  467: 
                    468: # ------------------------------------------------------ third, check map parms
                    469: 
1.556     raeburn   470:     
1.561     damieng   471: # 14 - map default
1.376     albertel  472:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   473:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  474: 
1.561     damieng   475: # 13 - resource level in course
1.200     www       476:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   477:         $outpar[13]=$$courseopt{$courselevelr};
                    478:         $result=13;
1.43      albertel  479:     }
1.11      www       480: 
1.182     albertel  481: # ------------------------------------------------------ fourth, back to course
1.352     albertel  482:     if ($csec ne '') {
1.561     damieng   483: # 12 - General for section
1.200     www       484:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   485:             $outpar[12]=$$courseopt{$seclevel};
                    486:             $result=12;
                    487:         }
1.561     damieng   488: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   489:         if (defined($$courseopt{$secleveli})) {
                    490:             $outpar[11]=$$courseopt{$secleveli};
                    491:             $result=11;
                    492:         }
1.561     damieng   493: # 10 - Map or Folder level for section (non-recursive)
1.200     www       494:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   495:             $outpar[10]=$$courseopt{$seclevelm};
                    496:             $result=10;
                    497:         }
1.561     damieng   498: # 9 - resource level in section
1.200     www       499:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   500:             $outpar[9]=$$courseopt{$seclevelr};
                    501:             $result=9;
                    502:         }
1.43      albertel  503:     }
1.275     raeburn   504: # ------------------------------------------------------ fifth, check course group
1.352     albertel  505:     if ($cgroup ne '') {
1.561     damieng   506: # 8 - General for group
1.269     raeburn   507:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   508:             $outpar[8]=$$courseopt{$grplevel};
                    509:             $result=8;
                    510:         }
1.561     damieng   511: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   512:         if (defined($$courseopt{$grpleveli})) {
                    513:             $outpar[7]=$$courseopt{$grpleveli};
                    514:             $result=7;
1.269     raeburn   515:         }
1.561     damieng   516: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   517:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   518:             $outpar[6]=$$courseopt{$grplevelm};
                    519:             $result=6;
1.269     raeburn   520:         }
1.561     damieng   521: # 5 - resource level in group
1.269     raeburn   522:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   523:             $outpar[5]=$$courseopt{$grplevelr};
                    524:             $result=5;
1.269     raeburn   525:         }
                    526:     }
1.11      www       527: 
1.556     raeburn   528: # ---------------------------------------------------------- sixth, check user
1.11      www       529: 
1.352     albertel  530:     if ($uname ne '') {
1.561     damieng   531: # 4 - General for specific student
                    532:         if (defined($$useropt{$courselevel})) {
                    533:             $outpar[4]=$$useropt{$courselevel};
                    534:             $result=4;
                    535:         }
1.556     raeburn   536: 
1.561     damieng   537: # 3 - Map or Folder level for specific student (recursive)
                    538:         if (defined($$useropt{$courseleveli})) {
                    539:             $outpar[3]=$$useropt{$courseleveli};
                    540:             $result=3;
                    541:         }
1.473     amueller  542: 
1.561     damieng   543: # 2 - Map or Folder level for specific student (non-recursive)
                    544:         if (defined($$useropt{$courselevelm})) {
                    545:             $outpar[2]=$$useropt{$courselevelm};
                    546:             $result=2;
                    547:         }
1.473     amueller  548: 
1.561     damieng   549: # 1 - resource level for specific student
                    550:         if (defined($$useropt{$courselevelr})) {
                    551:             $outpar[1]=$$useropt{$courselevelr};
                    552:             $result=1;
                    553:         }
1.43      albertel  554:     }
1.44      albertel  555:     return ($result,@outpar);
1.2       www       556: }
                    557: 
1.198     www       558: 
                    559: 
1.376     albertel  560: # --- Caches local to lonparmset
                    561: 
1.446     bisitz    562: 
1.561     damieng   563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  564: sub reset_caches {
                    565:     &resetparmhash();
                    566:     &resetsymbcache();
                    567:     &resetrulescache();
1.203     www       568: }
                    569: 
1.561     damieng   570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  572: {
1.561     damieng   573:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    574:     my %parmhash; # the parameter cache
                    575:     # reset map parameter hash
1.376     albertel  576:     sub resetparmhash {
1.560     damieng   577:         undef($parmhashid);
                    578:         undef(%parmhash);
1.376     albertel  579:     }
1.446     bisitz    580: 
1.561     damieng   581:     # dump the _parms.db database into %parmhash
1.376     albertel  582:     sub cacheparmhash {
1.560     damieng   583:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    584:         my %parmhashfile;
                    585:         if (tie(%parmhashfile,'GDBM_File',
                    586:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    587:             %parmhash=%parmhashfile;
                    588:             untie(%parmhashfile);
                    589:             $parmhashid=$env{'request.course.fn'};
                    590:         }
1.201     www       591:     }
1.446     bisitz    592: 
1.561     damieng   593:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  594:     sub parmhash {
1.560     damieng   595:         my ($id) = @_;
                    596:         &cacheparmhash();
                    597:         return $parmhash{$id};
1.376     albertel  598:     }
1.560     damieng   599: }
1.376     albertel  600: 
1.566     damieng   601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    602: {
1.561     damieng   603:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    604:     my %symbs; # hash id->symb
                    605:     # reset the id->symb cache
1.376     albertel  606:     sub resetsymbcache {
1.560     damieng   607:         undef($symbsid);
                    608:         undef(%symbs);
1.376     albertel  609:     }
1.446     bisitz    610: 
1.566     damieng   611:     # returns the resource symb or map src corresponding to a resource id or map pc
                    612:     # (using lonnavmaps and a cache)
1.376     albertel  613:     sub symbcache {
1.560     damieng   614:         my $id=shift;
                    615:         if ($symbsid ne $env{'request.course.id'}) {
                    616:             undef(%symbs);
                    617:         }
                    618:         if (!$symbs{$id}) {
                    619:             my $navmap = Apache::lonnavmaps::navmap->new();
                    620:             if ($id=~/\./) {
                    621:                 my $resource=$navmap->getById($id);
                    622:                 $symbs{$id}=$resource->symb();
                    623:             } else {
                    624:                 my $resource=$navmap->getByMapPc($id);
                    625:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    626:             }
                    627:             $symbsid=$env{'request.course.id'};
1.473     amueller  628:         }
1.560     damieng   629:         return $symbs{$id};
1.473     amueller  630:     }
1.560     damieng   631: }
1.201     www       632: 
1.561     damieng   633: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    634: {
1.561     damieng   635:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    636:     my %rules; # parameter default actions hash
1.376     albertel  637:     sub resetrulescache {
1.560     damieng   638:         undef($rulesid);
                    639:         undef(%rules);
1.376     albertel  640:     }
1.446     bisitz    641: 
1.561     damieng   642:     # returns the value for a given key in the parameter default action hash
1.376     albertel  643:     sub rulescache {
1.560     damieng   644:         my $id=shift;
                    645:         if ($rulesid ne $env{'request.course.id'}
                    646:             && !defined($rules{$id})) {
                    647:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    648:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    649:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    650:             $rulesid=$env{'request.course.id'};
                    651:         }
                    652:         return $rules{$id};
1.221     www       653:     }
                    654: }
                    655: 
1.416     jms       656: 
1.561     damieng   657: # Returns the values of the parameter type default action
                    658: # "default value when manually setting".
                    659: # If none is defined, ('','','','','') is returned.
                    660: #
                    661: # @param {string} $type - parameter type
                    662: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       663: sub preset_defaults {
                    664:     my $type=shift;
                    665:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   666:         # yes, there is something
                    667:         return (&rulescache($type.'_hours'),
                    668:             &rulescache($type.'_min'),
                    669:             &rulescache($type.'_sec'),
                    670:             &rulescache($type.'_value'));
1.229     www       671:     } else {
1.560     damieng   672:         # nothing there or something else
                    673:         return ('','','','','');
1.229     www       674:     }
                    675: }
                    676: 
1.416     jms       677: 
1.561     damieng   678: # Checks that a date is after enrollment start date and before
                    679: # enrollment end date.
                    680: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    681: # This is used by both overview and table modes.
                    682: #
                    683: # @param {integer} $checkdate - the date to check.
                    684: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       685: sub date_sanity_info {
                    686:    my $checkdate=shift;
                    687:    unless ($checkdate) { return ''; }
                    688:    my $result='';
                    689:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    690:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    691:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    692:          $result.='<div class="LC_warning">'
                    693:                  .&mt('After course enrollment end!')
                    694:                  .'</div>';
1.277     www       695:       }
                    696:    }
                    697:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    698:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    699:          $result.='<div class="LC_warning">'
                    700:                  .&mt('Before course enrollment start!')
                    701:                  .'</div>';
1.277     www       702:       }
                    703:    }
1.413     bisitz    704: # Preparation for additional warnings about dates in the past/future.
                    705: # An improved, more context sensitive version is recommended,
                    706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    707: #   if ($checkdate<time) {
                    708: #      $result.='<div class="LC_info">'
                    709: #              .'('.&mt('in the past').')'
                    710: #              .'</div>';
                    711: #      }
                    712: #   if ($checkdate>time) {
                    713: #      $result.='<div class="LC_info">'
                    714: #              .'('.&mt('in the future').')'
                    715: #              .'</div>';
                    716: #      }
1.277     www       717:    return $result;
                    718: }
1.561     damieng   719: 
                    720: 
                    721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       722: #
1.566     damieng   723: # @param {string} $sresid - resource id or map pc
1.565     damieng   724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   725: # @param {integer} $snum - level
                    726: # @param {string} $nval - new value
                    727: # @param {string} $ntype - new type
                    728: # @param {string} $uname - username
                    729: # @param {string} $udom - userdomain
                    730: # @param {string} $csec - section name
                    731: # @param {string} $cgroup - group name
1.186     www       732: sub storeparm {
1.269     raeburn   733:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   734:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       735: }
                    736: 
1.561     damieng   737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    738: 
                    739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    741: #
1.566     damieng   742: # @param {string} $symb - resource symb or map src
1.565     damieng   743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   744: # @param {integer} $snum - level
                    745: # @param {string} $nval - new value
                    746: # @param {string} $ntype - new type
                    747: # @param {string} $uname - username
                    748: # @param {string} $udom - userdomain
                    749: # @param {string} $csec - section name
                    750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    751: # @param {string} $cgroup - group name
1.197     www       752: sub storeparm_by_symb {
1.275     raeburn   753:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       754:     unless ($recflag) {
1.560     damieng   755:         # first time call
                    756:         %recstack=();
                    757:         $recflag=1;
1.226     www       758:     }
1.560     damieng   759:     # store parameter
1.226     www       760:     &storeparm_by_symb_inner
1.473     amueller  761:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   762:     # don't do anything if parameter was reset
1.266     www       763:     unless ($nval) { return; }
1.226     www       764:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   765:     # remember that this was set
1.226     www       766:     $recstack{$parm}=1;
1.560     damieng   767:     # what does this trigger?
1.226     www       768:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   769:         # don't backfire
                    770:         unless ((!$triggered) || ($recstack{$triggered})) {
                    771:             my $action=&rulescache($triggered.'_action');
                    772:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    773:             # set triggered parameter on same level
                    774:             my $newspnam=$prefix.$triggered;
                    775:             my $newvalue='';
                    776:             my $active=1;
                    777:             if ($action=~/^when\_setting/) {
                    778:             # are there restrictions?
                    779:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    780:                     $active=0;
1.565     damieng   781:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   782:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    783:                     }
                    784:                 }
                    785:                 $newvalue=&rulescache($triggered.'_value');
                    786:             } else {
                    787:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    788:                 if ($action=~/^later\_than/) {
                    789:                     $newvalue=$nval+$totalsecs;
                    790:                 } else {
                    791:                     $newvalue=$nval-$totalsecs;
                    792:                 }
                    793:             }
                    794:             if ($active) {
                    795:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    796:                         $uname,$udom,$csec,$recflag,$cgroup);
                    797:             }
                    798:         }
1.226     www       799:     }
                    800:     return '';
                    801: }
                    802: 
1.561     damieng   803: # Adds all given arguments to the course parameter log.
                    804: # @returns {string} - the answer to the lonnet query.
1.293     www       805: sub log_parmset {
1.525     raeburn   806:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       807: }
                    808: 
1.561     damieng   809: # Store a parameter value and type by symb, without using the parameter default actions.
                    810: # Expire related sheets.
                    811: #
1.566     damieng   812: # @param {string} $symb - resource symb or map src
1.561     damieng   813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    814: # @param {integer} $snum - level
                    815: # @param {string} $nval - new value
                    816: # @param {string} $ntype - new type
                    817: # @param {string} $uname - username
                    818: # @param {string} $udom - userdomain
                    819: # @param {string} $csec - section name
                    820: # @param {string} $cgroup - group name
                    821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       822: sub storeparm_by_symb_inner {
1.197     www       823: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   824:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       825: # ---------------------------------------------------------- Construct prefixes
1.186     www       826:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    827:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  828:     $map = &Apache::lonnet::deversion($map);
                    829: 
1.197     www       830:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   831:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       832:     my $mapparm=$map.'___(all).'.$spnam;
                    833: 
1.269     raeburn   834:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    835:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   836:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   837:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    838: 
1.190     albertel  839:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    840:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   841:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  842:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    843: 
1.190     albertel  844:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    845:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   846:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  847:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    848: 
1.186     www       849:     my $storeunder='';
1.578     raeburn   850:     my $possreplace='';
1.556     raeburn   851:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   852:     if (($snum==17) || ($snum==3)) { 
                    853:         $storeunder=$courseleveli;
                    854:         $possreplace=$courselevelm; 
                    855:     } 
                    856:     if (($snum==16) || ($snum==2)) { 
                    857:         $storeunder=$courselevelm;
                    858:         $possreplace=$courseleveli;
                    859:     }
1.556     raeburn   860:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    861:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   862:     if ($snum==11) { 
                    863:         $storeunder=$secleveli;
                    864:         $possreplace=$seclevelm; 
                    865:     }
                    866:     if ($snum==10) { 
                    867:         $storeunder=$seclevelm;
                    868:         $possreplace=$secleveli;
                    869:     }
1.556     raeburn   870:     if ($snum==9) { $storeunder=$seclevelr; }
                    871:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   872:     if ($snum==7) { 
                    873:         $storeunder=$grpleveli;
                    874:         $possreplace=$grplevelm;
                    875:     }
                    876:     if ($snum==6) {
                    877:         $storeunder=$grplevelm;
                    878:         $possreplace=$grpleveli;
                    879:     }
1.556     raeburn   880:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   881: 
1.446     bisitz    882: 
1.186     www       883:     my $delete;
                    884:     if ($nval eq '') { $delete=1;}
                    885:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  886:             $storeunder.'.type' => $ntype);
1.186     www       887:     my $reply='';
1.560     damieng   888:     
1.556     raeburn   889:     if ($snum>4) {
1.186     www       890: # ---------------------------------------------------------------- Store Course
                    891: #
1.560     damieng   892:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    893:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    894:         # Expire sheets
                    895:         &Apache::lonnet::expirespread('','','studentcalc');
                    896:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    897:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   898:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   899:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    900:         } else {
                    901:             &Apache::lonnet::expirespread('','','assesscalc');
                    902:         }
                    903:         # Store parameter
                    904:         if ($delete) {
                    905:             $reply=&Apache::lonnet::del
                    906:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    907:                 &log_parmset(\%storecontent,1);
                    908:         } else {
                    909:             $reply=&Apache::lonnet::cput
                    910:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    911:             &log_parmset(\%storecontent);
1.578     raeburn   912:             if ($possreplace) {
                    913:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    914:                 if (ref($resdata) eq 'HASH') {
                    915:                     if (exists($resdata->{$possreplace})) {
                    916:                         if (&Apache::lonnet::del
                    917:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    918:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    919:                         }
                    920:                     }
                    921:                 }
                    922:             }
1.560     damieng   923:         }
                    924:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       925:     } else {
                    926: # ------------------------------------------------------------------ Store User
                    927: #
1.560     damieng   928:         # Expire sheets
                    929:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    930:         if ($snum==1) {
                    931:             &Apache::lonnet::expirespread
                    932:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   933:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   934:             &Apache::lonnet::expirespread
                    935:             ($uname,$udom,'assesscalc',$map);
                    936:         } else {
                    937:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    938:         }
                    939:         # Store parameter
                    940:         if ($delete) {
                    941:             $reply=&Apache::lonnet::del
                    942:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    943:             &log_parmset(\%storecontent,1,$uname,$udom);
                    944:         } else {
                    945:             $reply=&Apache::lonnet::cput
                    946:             ('resourcedata',\%storecontent,$udom,$uname);
                    947:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   948:             if ($possreplace) {
                    949:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    950:                 if (ref($resdata) eq 'HASH') {
                    951:                     if (exists($resdata->{$possreplace})) {
                    952:                         if (&Apache::lonnet::del
                    953:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    954:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    955:                                           $uname,$udom);
                    956:                         }
                    957:                     }
                    958:                 }
                    959:             }
1.560     damieng   960:         }
                    961:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       962:     }
1.446     bisitz    963: 
1.186     www       964:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   965:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       966:     }
                    967:     return '';
                    968: }
                    969: 
1.9       www       970: 
1.561     damieng   971: # Returns HTML with the value of the given parameter,
                    972: # using a readable format for dates, and
                    973: # a warning if there is a problem with a date.
                    974: # Used by table mode.
                    975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    976: #
                    977: # @param {string} $value - the parameter value
                    978: # @param {string} $type - the parameter type
                    979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       980: sub valout {
1.600     raeburn   981:     my ($value,$type,$editable)=@_;
1.59      matthew   982:     my $result = '';
                    983:     # Values of zero are valid.
                    984:     if (! $value && $value ne '0') {
1.528     bisitz    985:         if ($editable) {
                    986:             $result =
                    987:                 '<img src="/res/adm/pages/editmap.png"'
                    988:                .' alt="'.&mt('Change').'"'
1.539     raeburn   989:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    990:         } else {
                    991:             $result='&nbsp;';
                    992:         }
1.59      matthew   993:     } else {
1.66      www       994:         if ($type eq 'date_interval') {
1.559     raeburn   995:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    996:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    997:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    998:                 $donebuttontext = $1;
                    999:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1000:                 $usesdone = 'done';
                   1001:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1002:                 $donebuttontext = &mt('Done');
                   1003:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1004:             }
1.554     raeburn  1005:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1006:             my @timer;
1.66      www      1007:             $year=$year-70;
                   1008:             $mday--;
                   1009:             if ($year) {
1.413     bisitz   1010: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1011:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1012:             }
                   1013:             if ($mon) {
1.413     bisitz   1014: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1015:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1016:             }
                   1017:             if ($mday) {
1.413     bisitz   1018: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1019:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1020:             }
                   1021:             if ($hour) {
1.413     bisitz   1022: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1023:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1024:             }
                   1025:             if ($min) {
1.413     bisitz   1026: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1027:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1028:             }
                   1029:             if ($sec) {
1.413     bisitz   1030: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1031:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1032:             }
1.413     bisitz   1033: #           $result=~s/\s+$//;
                   1034:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1035:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1036:             }
                   1037:             $result.=join(", ",@timer);
1.559     raeburn  1038:             if ($usesdone eq 'done') {
1.558     raeburn  1039:                 if ($secretkey) {
1.559     raeburn  1040:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1041:                 } else {
1.559     raeburn  1042:                     $result .= ' + "'.$donebuttontext.'"';
                   1043:                 }
1.554     raeburn  1044:             }
1.213     www      1045:         } elsif (&isdateparm($type)) {
1.361     albertel 1046:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1047:                 &date_sanity_info($value);
1.59      matthew  1048:         } else {
                   1049:             $result = $value;
1.517     www      1050:             $result=~s/\,/\, /gs;
1.560     damieng  1051:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1052:         }
                   1053:     }
                   1054:     return $result;
1.9       www      1055: }
                   1056: 
1.59      matthew  1057: 
1.561     damieng  1058: # Returns HTML containing a link on a parameter value, for table mode.
                   1059: # The link uses the javascript function 'pjump'.
                   1060: #
                   1061: # @param {string} $type - parameter type
                   1062: # @param {string} $dis - dialog title for editing the parameter value and type
                   1063: # @param {string} $value - parameter value
                   1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
                   1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1069: sub plink {
1.588     raeburn  1070:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1071:     my $winvalue=$value;
                   1072:     unless ($winvalue) {
1.592     raeburn  1073:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1074:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1075:         } elsif ($type eq 'string_yesno') {
                   1076:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1077:                 $winvalue=$env{'form.recent_string'};
                   1078:             }
1.23      www      1079:         } else {
1.190     albertel 1080:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1081:         }
                   1082:     }
1.229     www      1083:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1084:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1085:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1086:     my $valout = &valout($value,$type,1);
1.429     raeburn  1087:     my $unencmarker = $marker;
1.378     albertel 1088:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1089:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1090:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1091:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1092:     }
1.429     raeburn  1093:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1094:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1095:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1096:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1097:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1098: 
1.5       www      1099: }
                   1100: 
1.561     damieng  1101: # Javascript for table mode.
1.280     albertel 1102: sub page_js {
                   1103: 
1.81      www      1104:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1105:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1106: 
                   1107:     return(<<ENDJS);
                   1108: <script type="text/javascript">
1.454     bisitz   1109: // <![CDATA[
1.44      albertel 1110: 
1.88      matthew  1111:     $pjump_def
1.44      albertel 1112: 
                   1113:     function psub() {
1.591     raeburn  1114:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1115:         if (document.parmform.pres_marker.value!='') {
                   1116:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1117:             var typedef=new Array();
                   1118:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1119:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1120:                 if ((typedef[0]=='date') || 
1.591     raeburn  1121:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1122:                     eval('document.parmform.recent_'+
                   1123:                         document.parmform.pres_type.value+
                   1124:                         '.value=document.parmform.pres_value.value;');
                   1125:                 } else {
                   1126:                     eval('document.parmform.recent_'+typedef[0]+
                   1127:                         '.value=document.parmform.pres_value.value;');
                   1128:                 }
1.44      albertel 1129:             }
                   1130:             document.parmform.submit();
                   1131:         } else {
                   1132:             document.parmform.pres_value.value='';
                   1133:             document.parmform.pres_marker.value='';
                   1134:         }
                   1135:     }
                   1136: 
1.57      albertel 1137:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1138:         var options = "width=" + w + ",height=" + h + ",";
                   1139:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1140:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1141:         var newWin = window.open(url, wdwName, options);
                   1142:         newWin.focus();
                   1143:     }
1.523     raeburn  1144: 
1.454     bisitz   1145: // ]]>
1.523     raeburn  1146: 
1.44      albertel 1147: </script>
1.81      www      1148: $selscript
1.280     albertel 1149: ENDJS
                   1150: 
                   1151: }
1.507     www      1152: 
1.561     damieng  1153: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1154: # for table and overview modes.
1.523     raeburn  1155: sub showhide_js {
                   1156:     return <<"COURSECONTENTSCRIPT";
                   1157: 
                   1158: function showHide_courseContent() {
                   1159:     var parmlevValue=document.getElementById("parmlev").value;
                   1160:     if (parmlevValue == 'general') {
                   1161:         document.getElementById('mapmenu').style.display="none";
                   1162:     } else {
                   1163:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1164:             document.getElementById('mapmenu').style.display ="";
                   1165:         } else {
                   1166:             document.getElementById('mapmenu').style.display="none";
                   1167:         }
                   1168:     }
                   1169:     return;
                   1170: }
                   1171: 
                   1172: COURSECONTENTSCRIPT
                   1173: }
                   1174: 
1.561     damieng  1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1176: sub toggleparmtextbox_js {
                   1177:     return <<"ENDSCRIPT";
                   1178: 
                   1179: if (!document.getElementsByClassName) {
                   1180:     function getElementsByClassName(node, classname) {
                   1181:         var a = [];
                   1182:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1183:         var els = node.getElementsByTagName("*");
                   1184:         for(var i=0,j=els.length; i<j; i++)
                   1185:             if(re.test(els[i].className))a.push(els[i]);
                   1186:         return a;
                   1187:     }
                   1188: }
                   1189: 
                   1190: function showHideLenient() {
                   1191:     var lenients;
                   1192:     var setRegExp = /^set_/;
                   1193:     if (document.getElementsByClassName) {
                   1194:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1195:     } else {
                   1196:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1197:     }
                   1198:     if (lenients != 'undefined') {
                   1199:         for (var i=0; i<lenients.length; i++) {
                   1200:             if (lenients[i].checked) {
                   1201:                 if (lenients[i].value == 'weighted') {
                   1202:                     if (setRegExp.test(lenients[i].name)) {
                   1203:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1204:                         toggleParmTextbox(document.parmform,identifier);
                   1205:                     }
                   1206:                 }
                   1207:             }
                   1208:         }
                   1209:     }
                   1210:     return;
                   1211: }
                   1212: 
                   1213: function toggleParmTextbox(form,key) {
                   1214:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1215:     if (divfortext) {
                   1216:         var caller = form.elements['set_'+key];
                   1217:         if (caller.length) {
                   1218:             for (i=0; i<caller.length; i++) {
                   1219:                 if (caller[i].checked) {
                   1220:                     if (caller[i].value == 'weighted') {
                   1221:                         divfortext.style.display = 'inline';
                   1222:                     } else {
                   1223:                         divfortext.style.display = 'none';
                   1224:                     }
                   1225:                 }
                   1226:             }
                   1227:         }
                   1228:     }
                   1229:     return;
                   1230: }
                   1231: 
                   1232: ENDSCRIPT
                   1233: }
                   1234: 
1.561     damieng  1235: # Javascript function validateParms, for overview mode
1.549     raeburn  1236: sub validateparms_js {
                   1237:     return <<'ENDSCRIPT';
                   1238: 
                   1239: function validateParms() {
                   1240:     var textRegExp = /^settext_/;
                   1241:     var tailLenient = /\.lenient$/;
                   1242:     var patternRelWeight = /^\-?[\d.]+$/;
                   1243:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1244:     var ipRegExp = /^setip/;
1.549     raeburn  1245:     var ipallowRegExp = /^setipallow_/;
                   1246:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1247:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1248:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1249:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1250:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1251:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1252:     var dlKeyRegExp = /^deeplink_key_/;
                   1253:     var dlMenusRegExp = /^deeplink_menus_/;
                   1254:     var dlCollsRegExp = /^deeplink_colls_/;
1.549     raeburn  1255:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1256:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1257:         if (document.parmform.elements.length) {
                   1258:             for (i=0; i<document.parmform.elements.length; i++) {
                   1259:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1260:                 if (textRegExp.test(name)) {
1.549     raeburn  1261:                     var identifier = name.replace(textRegExp,'');
                   1262:                     if (tailLenient.test(identifier)) {
                   1263:                         if (document.parmform.elements['set_'+identifier].length) {
                   1264:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1265:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1266:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1267:                                         var relweight = document.parmform.elements[i].value;
                   1268:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1269:                                         if (!patternRelWeight.test(relweight)) {
                   1270:                                             relweight = '0.0';
                   1271:                                         }
                   1272:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1273:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1274:                                         } else {
                   1275:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1276:                                         }
                   1277:                                     }
                   1278:                                     break;
                   1279:                                 }
                   1280:                             }
                   1281:                         }
                   1282:                     }
1.597     raeburn  1283:                 } else if (ipRegExp.test(name)) {
                   1284:                     if (ipallowRegExp.test(name)) {
                   1285:                         var identifier = name.replace(ipallowRegExp,'');
                   1286:                         var possallow = document.parmform.elements[i].value;
                   1287:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1288:                         if (patternIP.test(possallow)) {
                   1289:                             if (document.parmform.elements['set_'+identifier].value) {
                   1290:                                 possallow = ','+possallow;
                   1291:                             }
                   1292:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1293:                         }
                   1294:                     } else if (ipdenyRegExp.test(name)) {
                   1295:                         var identifier = name.replace(ipdenyRegExp,'');
                   1296:                         var possdeny = document.parmform.elements[i].value;
                   1297:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1298:                         if (patternIP.test(possdeny)) {
                   1299:                             possdeny = '!'+possdeny;
                   1300:                             if (document.parmform.elements['set_'+identifier].value) {
                   1301:                                 possdeny = ','+possdeny;
                   1302:                             }
                   1303:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1304:                         }
                   1305:                     }
                   1306:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1307:                     if (dlListScopeRegExp.test(name)) {
                   1308:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1309:                         var idx = document.parmform.elements[i].selectedIndex;
                   1310:                         if (idx > 0) { 
                   1311:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1312:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1313:                             if (document.parmform.elements['set_'+identifier].value) {
                   1314:                                 possdeeplink = ','+possdeeplink;
                   1315:                             }
                   1316:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1317:                         }
1.601     raeburn  1318:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1319:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1320:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1321:                             var posslinkurl = document.parmform.elements[i].value;
                   1322:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1323:                             if (document.parmform.elements['set_'+identifier].value) {
                   1324:                                 posslinkurl = ','+posslinkurl;
                   1325:                             }
                   1326:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1327:                         }
1.601     raeburn  1328:                     } else if (dlLtidRegExp.test(name)) {
                   1329:                         var identifier = name.replace(dlLtidRegExp,'');
                   1330:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1331:                             var possltid = document.parmform.elements[i].value;
                   1332:                             possltid = possltid.replace(/\D+/g,'');
                   1333:                             if (possltid.length) {
1.597     raeburn  1334:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1335:                                     possltid = ':'+possltid;
1.597     raeburn  1336:                                 }
1.601     raeburn  1337:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1338:                             } else {
                   1339:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1340:                                 alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597     raeburn  1341:                                 return false;  
                   1342:                             }
                   1343:                         }
1.601     raeburn  1344:                     } else if (dlLticRegExp.test(name)) {
                   1345:                         var identifier = name.replace(dlLticRegExp,'');
                   1346:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1347:                             var possltic = document.parmform.elements[i].value;
                   1348:                             possltic = possltic.replace(/\D+/g,'');
                   1349:                             if (possltic.length) {
                   1350:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1351:                                     possltic = ':'+possltic;
                   1352:                                 }
                   1353:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1354:                             } else {
                   1355:                                 document.parmform.elements['set_'+identifier].value = '';
                   1356:                                 alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                   1357:                                 return false;
                   1358:                             }
                   1359:                         }
1.597     raeburn  1360:                     } else if (dlKeyRegExp.test(name)) {
                   1361:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1362:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1363:                             var posskey = document.parmform.elements[i].value;
                   1364:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1365:                             var origlength = posskey.length;
                   1366:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1367:                             var newlength = posskey.length;
                   1368:                             if (newlength > 0) {
                   1369:                                 var change = origlength - newlength;
                   1370:                                 if (change) {
                   1371:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1372:                                 }
                   1373:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1374:                                     posskey = ':'+posskey;
                   1375:                                 }
                   1376:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1377:                             } else {
                   1378:                                 document.parmform.elements['set_'+identifier].value = '';
                   1379:                                 if (newlength < origlength) {
                   1380:                                     alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
                   1381:                                 } else {
                   1382:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1383:                                 }
                   1384:                                 return false;
                   1385:                             }
                   1386:                         }
                   1387:                     } else if (dlMenusRegExp.test(name)) {
                   1388:                         if (document.parmform.elements[i].checked) {
                   1389:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1390:                             var posslinkmenu = document.parmform.elements[i].value;
                   1391:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1392:                             if (posslinkmenu == 'std') {
                   1393:                                 posslinkmenu = '0';
                   1394:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1395:                                     posslinkmenu = ','+posslinkmenu;
                   1396:                                 }
                   1397:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1398:                             }
                   1399:                         }
                   1400:                     } else if (dlCollsRegExp.test(name)) {
                   1401:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1402:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1403:                             var posslinkmenu = document.parmform.elements[i].value;
                   1404:                             if (document.parmform.elements['set_'+identifier].value) {
                   1405:                                 posslinkmenu = ','+posslinkmenu;
                   1406:                             }
                   1407:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1408:                         }
1.549     raeburn  1409:                     }
                   1410:                 }
                   1411:             }
                   1412:         }
                   1413:     }
                   1414:     return true;
                   1415: }
                   1416: 
1.597     raeburn  1417: function isRadioSet(name,expected) {
                   1418:     var menuitems = document.getElementsByName(name);
                   1419:     var radioLength = menuitems.length;
                   1420:     result = false;
                   1421:     if (radioLength  > 1) {
                   1422:         for (var j=0; j<radioLength; j++) {
                   1423:             if (menuitems[j].checked) {
                   1424:                 if (menuitems[j].value == expected) {
                   1425:                     result = true;
                   1426:                     break;
                   1427:                 }
                   1428:             }
                   1429:         }
                   1430:     }
                   1431:     return result;
                   1432: }
                   1433: 
1.549     raeburn  1434: ENDSCRIPT
                   1435: }
                   1436: 
1.561     damieng  1437: # Javascript initialization, for overview mode
1.549     raeburn  1438: sub ipacc_boxes_js  {
                   1439:     my $remove = &mt('Remove');
                   1440:     return <<"END";
                   1441: \$(document).ready(function() {
                   1442:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1443:     var add_button      = \$(".LC_add_ipacc_button");
                   1444:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1445: 
                   1446:     \$(add_button).click(function(e){
                   1447:         e.preventDefault();
                   1448:         var identifier = \$(this).closest("div").attr("id");
                   1449:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1450:         \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');
1.549     raeburn  1451:     });
                   1452: 
                   1453:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1454:         e.preventDefault(); \$(this).closest("div").remove();
                   1455:     })
                   1456: });
                   1457: 
                   1458: 
                   1459: END
                   1460: }
                   1461: 
1.561     damieng  1462: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1463: sub done_proctor_js {
                   1464:     return <<"END";
                   1465: function toggleSecret(form,radio,key) {
                   1466:     var radios = form[radio+key];
                   1467:     if (radios.length) {
                   1468:         for (var i=0; i<radios.length; i++) {
                   1469:             if (radios[i].checked) {
                   1470:                 if (radios[i].value == '_done_proctor') {
                   1471:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1472:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1473:                     }
                   1474:                 } else {
                   1475:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1476:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1477:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1478:                     }
                   1479:                 }
                   1480:             }
                   1481:         }
                   1482:     }
                   1483: }
                   1484: END
                   1485: 
                   1486: }
                   1487: 
1.588     raeburn  1488: # Javascript function toggle
                   1489: sub deeplink_js {
                   1490:     return <<"END";
                   1491: function toggleDeepLink(form,item,key) {
                   1492:     var radios = form['deeplink_'+item+'_'+key];
                   1493:     if (radios.length) {
                   1494:         var keybox;
                   1495:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1496:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1497:         }
1.601     raeburn  1498:         var divoptions = new Array();
                   1499:         if (item == 'protect') {
                   1500:             divoptions = ['ltic','ltid'];
1.597     raeburn  1501:         } else {
                   1502:             if (item == 'menus') {
1.601     raeburn  1503:                 divoptions = ['colls'];
1.597     raeburn  1504:             }
                   1505:         }
1.601     raeburn  1506:         var seldivs = new Array();
                   1507:         if ((item == 'protect') || (item == 'menus')) {
                   1508:             for (var i=0; i<divoptions.length; i++) {
                   1509:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1510:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1511:                 } else {
                   1512:                     seldivs[i] = '';
                   1513:                 }
                   1514:             }
1.588     raeburn  1515:         }
                   1516:         for (var i=0; i<radios.length; i++) {
                   1517:             if (radios[i].checked) {
1.601     raeburn  1518:                 if ((item == 'protect') || (item == 'menus')) {
                   1519:                     for (var j=0; j<seldivs.length; j++) {
                   1520:                         if (radios[i].value == divoptions[j]) {
                   1521:                             if (seldivs[j] != '') {
                   1522:                                 seldivs[j].style.display = 'inline-block';
                   1523:                             }
                   1524:                             if (item == 'protect') {
                   1525:                                 keybox.type = 'hidden';
                   1526:                                 keybox.value = '';
                   1527:                             }
                   1528:                         } else {
                   1529:                             if (seldivs[j] != '') {
                   1530:                                 seldivs[j].style.display = 'none';
                   1531:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1532:                             }
                   1533:                         }
1.597     raeburn  1534:                     }
1.601     raeburn  1535:                     if (item == 'protect') {
1.597     raeburn  1536:                         if (radios[i].value == 'key') {
                   1537:                             keybox.type = 'text';
                   1538:                         } else {
                   1539:                             keybox.type = 'hidden';
                   1540:                         }
1.588     raeburn  1541:                     }
                   1542:                 }
                   1543:             }
                   1544:         }
                   1545:     }
                   1546: }
                   1547: END
                   1548: 
                   1549: }
                   1550: 
1.561     damieng  1551: # Prints HTML page start for table mode.
                   1552: # @param {Apache2::RequestRec} $r - the Apache request
                   1553: # @param {string} $psymb - resource symb
                   1554: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1555: sub startpage {
1.531     raeburn  1556:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1557: 
1.515     raeburn  1558:     my %loaditems = (
                   1559:                       'onload'   => "group_or_section('cgroup')",
                   1560:                     );
                   1561:     if (!$psymb) {
1.523     raeburn  1562:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1563:     }
1.280     albertel 1564: 
1.560     damieng  1565:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1566:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1567:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1568:             text=>"Problem Parameters"});
1.414     droeschl 1569:     } else {
1.560     damieng  1570:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1571:             text=>"Table Mode",
                   1572:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1573:     }
1.523     raeburn  1574:     my $js = &page_js().'
                   1575: <script type="text/javascript">
                   1576: // <![CDATA[
                   1577: '.
                   1578:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1579: // ]]>
                   1580: </script>
                   1581: ';
1.446     bisitz   1582:     my $start_page =
1.523     raeburn  1583:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1584:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1585:     my $breadcrumbs =
1.473     amueller 1586:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1587:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1588:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1589:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1590:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1591:     $r->print(<<ENDHEAD);
1.193     albertel 1592: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1593: <input type="hidden" value="" name="pres_value" />
                   1594: <input type="hidden" value="" name="pres_type" />
                   1595: <input type="hidden" value="" name="pres_marker" />
                   1596: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1597: <input type="hidden" value="$escfilter" name="filter" />
                   1598: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1599: ENDHEAD
                   1600: }
                   1601: 
1.209     www      1602: 
1.561     damieng  1603: # Prints a row for table mode (except for the tr start).
                   1604: # Every time a hash reference is passed, a single entry is used, so print_row
                   1605: # could just use these values, but why make it simple when it can be complicated ?
                   1606: #
                   1607: # @param {Apache2::RequestRec} $r - the Apache request
                   1608: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1609: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1610: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1611: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1612: # @param {string} $rid - resource id
                   1613: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1614: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1615: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1616: # @param {string} $defbgone - user level and other levels background color
                   1617: # @param {string} $defbgtwo - section level background color, also used for part number
                   1618: # @param {string} $defbgthree - group level background color
                   1619: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1620: # @param {string} $uname - user name
                   1621: # @param {string} $udom - user domain
                   1622: # @param {string} $csec - section name
                   1623: # @param {string} $cgroup - group name
                   1624: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1625: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1626: # @param {boolean} $readonly - true if no editing allowed.
                   1627: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1628: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1629: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1630: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1631: sub print_row {
1.201     www      1632:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1633:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1634:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1635:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1636:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1637:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1638:     my $numlinks = 0;
1.553     raeburn  1639: 
1.560     damieng  1640:     # get the values for the parameter in cascading order
                   1641:     # empty levels will remain empty
1.44      albertel 1642:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1643:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1644:     # get the type for the parameters
                   1645:     # problem: these may not be set for all levels
1.66      www      1646:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1647:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1648:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1649:     # cascade down manually
1.182     albertel 1650:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1651:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1652:         if ($typeoutpar[$i]) {
1.66      www      1653:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1654:         } else {
1.66      www      1655:             $typeoutpar[$i]=$cascadetype;
                   1656:         }
                   1657:     }
1.57      albertel 1658:     my $parm=$$display{$which};
                   1659: 
1.203     www      1660:     if ($parmlev eq 'full') {
1.419     bisitz   1661:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1662:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1663:     } else {
1.57      albertel 1664:         $parm=~s|\[.*\]\s||g;
                   1665:     }
1.231     www      1666:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1667:     if ($automatic) {
1.560     damieng  1668:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1669:     }
1.427     bisitz   1670:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1671: 
1.44      albertel 1672:     my $thismarker=$which;
                   1673:     $thismarker=~s/^parameter\_//;
                   1674:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1675:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1676:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1677:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1678:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1679:         if ($result eq '') {
                   1680:             $recurse_check = 1;
                   1681:         } elsif (($uname ne '') && ($result > 3)) {
                   1682:             $recurse_check = 1;
                   1683:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1684:             $recurse_check = 1;
                   1685:         } elsif (($csec ne '') && ($result > 11)) {
                   1686:             $recurse_check = 1;
                   1687:         } elsif ($result > 17) {
                   1688:             $recurse_check = 1;
                   1689:         }
                   1690:         if ($recurse_check) {
                   1691:             my $what = $$part{$which}.'.'.$$name{$which};
                   1692:             my $prefix;
                   1693:             if (($uname ne '') && ($udom ne '')) {
                   1694:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1695:                 $prefix = $env{'request.course.id'};
                   1696:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1697:                 if (ref($recursinfo) eq 'ARRAY') {
                   1698:                     $effparm_rec = 1;
                   1699:                     $effparm_level = &mt('user: [_1]',$uname);
                   1700:                 }
                   1701:             }
                   1702:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1703:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1704:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1705:                 if (ref($recursinfo) eq 'ARRAY') {
                   1706:                     $effparm_rec = 1;
                   1707:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1708:                 }
                   1709:             }
                   1710:             if (($csec ne '') && (!$effparm_rec)) {
                   1711:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1712:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1713:                 if (ref($recursinfo) eq 'ARRAY') {
                   1714:                     $effparm_rec = 1;
                   1715:                     $effparm_level = &mt('section: [_1]',$csec);
                   1716:                 }
                   1717:             }
                   1718:             if (!$effparm_rec) {
                   1719:                 $prefix = $env{'request.course.id'};
                   1720:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1721:                 if (ref($recursinfo) eq 'ARRAY') {
                   1722:                     $effparm_rec = 1;
                   1723:                 }
                   1724:             }
                   1725:         }
                   1726:     }
                   1727:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1728:         $effparm_rec = 1;
                   1729:     }
                   1730:     if ((!$effparm_rec) && 
                   1731:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1732:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1733:         $effparm_rec = 1;
                   1734:     }
1.588     raeburn  1735:     if ($parmname eq 'deeplink') {
1.601     raeburn  1736:         my ($domltistr,$crsltistr);
1.588     raeburn  1737:         my %lti =
                   1738:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1739:                                             'linkprot');
1.601     raeburn  1740:         if (keys(%lti)) {
                   1741:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1742:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1743:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1744:                 }
                   1745:             }
1.601     raeburn  1746:             $domltistr =~ s/,$//;
                   1747:             if ($domltistr) {
                   1748:                 $extra = 'ltid_'.$domltistr;
                   1749:             }
1.588     raeburn  1750:         }
1.601     raeburn  1751:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1752:         if (keys(%courselti)) {
                   1753:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1754:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1755:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1756:                 }
                   1757:             }
                   1758:             $crsltistr =~ s/,$//;
                   1759:             if ($crsltistr) {
                   1760:                 if ($extra) {
                   1761:                     $extra .= '&';
                   1762:                 }
                   1763:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1764:             }
                   1765:         }
1.597     raeburn  1766:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1767:             my @colls;
                   1768:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1769:                 my ($num,$value) = split(/\%/,$item);
                   1770:                 if ($num =~ /^\d+$/) {
                   1771:                     push(@colls,$num);
                   1772:                 }
                   1773:             }
                   1774:             if (@colls) {
                   1775:                 if ($extra) {
                   1776:                     $extra .= '&';
                   1777:                 }
                   1778:                 $extra .= 'menus_'.join(',',@colls);
                   1779:             }
                   1780:         }
1.588     raeburn  1781:     }
1.57      albertel 1782:     if ($parmlev eq 'general') {
                   1783:         if ($uname) {
1.588     raeburn  1784:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1785:         } elsif ($cgroup) {
1.588     raeburn  1786:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1787:         } elsif ($csec) {
1.588     raeburn  1788:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1789:         } else {
1.588     raeburn  1790:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1791:         }
                   1792:     } elsif ($parmlev eq 'map') {
                   1793:         if ($uname) {
1.588     raeburn  1794:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1795:         } elsif ($cgroup) {
1.588     raeburn  1796:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1797:         } elsif ($csec) {
1.588     raeburn  1798:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1799:         } else {
1.588     raeburn  1800:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1801:         }
                   1802:     } else {
1.275     raeburn  1803:         if ($uname) {
                   1804:             if (@{$usersgroups} > 1) {
1.582     raeburn  1805:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1806:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1807:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1808:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1809:                     if (defined($controlgrp)) {
                   1810:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1811:                             $eff_groupparm = $grp_parm;
                   1812:                             undef($result);
                   1813:                             undef($effparm_rec);
                   1814:                             if ($grp_is_rec) {
                   1815:                                  $effparm_rec = 1;
                   1816:                             }
1.275     raeburn  1817:                         }
                   1818:                     }
                   1819:                 }
                   1820:             }
                   1821:         }
1.57      albertel 1822: 
1.588     raeburn  1823:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1824:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1825:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1826:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1827:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1828: 
                   1829:         if ($csec) {
1.588     raeburn  1830:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1831:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1832:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1833:         }
1.269     raeburn  1834: 
                   1835:         if ($cgroup) {
1.588     raeburn  1836:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1837:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1838:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1839:         }
1.446     bisitz   1840: 
1.548     raeburn  1841:         if ($uname) {
1.275     raeburn  1842:             if ($othergrp) {
                   1843:                 $r->print($othergrp);
                   1844:             }
1.588     raeburn  1845:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1846:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1847:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1848:         }
1.57      albertel 1849:     } # end of $parmlev if/else
1.582     raeburn  1850:     if (ref($recursinfo) eq 'ARRAY') {
                   1851:         my $rectitle = &mt('recursive');
                   1852:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1853:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1854:                 $rectitle = &mt('set in: [_1]','"'.
                   1855:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1856:                                                               "'$parmname','$$part{$which}'".');">'.
                   1857:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1858:               
                   1859:                 $numlinks ++;
                   1860:             }
                   1861:         }
                   1862:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1863:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1864:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1865:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1866:                   $effparm_level.'</span></td>');
                   1867:     } else {
                   1868:         if ($result) {
1.593     raeburn  1869:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1870:         }
                   1871:         if ($eff_groupparm) {
                   1872:             $effective_parm = $eff_groupparm;
                   1873:         }
                   1874:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1875:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1876:                                 '</span>':'').'</td>');
                   1877:     }
1.203     www      1878:     if ($parmlev eq 'full') {
1.136     albertel 1879:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1880:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1881:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1882:         if (!defined($sessionvaltype)) {
                   1883:             $sessionvaltype=$$defaulttype{$which};
                   1884:         }
1.419     bisitz   1885:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1886:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1887:                   '</font></td>');
1.136     albertel 1888:     }
1.44      albertel 1889:     $r->print('</tr>');
1.57      albertel 1890:     $r->print("\n");
1.582     raeburn  1891:     if (($numlinks) && (ref($reclinks))) {
                   1892:         $$reclinks = $numlinks;
                   1893:     }
1.44      albertel 1894: }
1.59      matthew  1895: 
1.561     damieng  1896: # Prints a cell for table mode.
                   1897: #
                   1898: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1899: # Also, it would make more sense to pass the display for this cell rather
                   1900: # than the full display hash and the key to use.
                   1901: #
                   1902: # @param {Apache2::RequestRec} $r - the Apache request
                   1903: # @param {integer} $which - level
                   1904: # @param {string} $defbg - cell background color
                   1905: # @param {integer} $result - the most specific level that is defined for that parameter
                   1906: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1907: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1908: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1909: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1910: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1911: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1912: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1913: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1914: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1915: sub print_td {
1.578     raeburn  1916:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  1917:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  1918:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   1919:     $ineffect = 0;
                   1920:     $currval = $$outpar[$which];
                   1921:     $currtype = $$typeoutpar[$which];
                   1922:     $currlevel = $which;
                   1923:     if (($result) && ($result == $which)) {
                   1924:         $ineffect = 1;
                   1925:     } 
                   1926:     if ($ismaplevel) {
                   1927:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   1928:             if (($result) && ($result == $which)) {
                   1929:                 $recursive = 1;
                   1930:             }
                   1931:         } elsif ($$outpar[$which+1] ne '') {
                   1932:             $recursive = 1;
                   1933:             $currlevel = $which+1;
                   1934:             $currval = $$outpar[$currlevel];
                   1935:             $currtype = $$typeoutpar[$currlevel];
                   1936:             if (($result) && ($result == $currlevel)) {
                   1937:                 $ineffect = 1;
                   1938:             }
                   1939:         }
                   1940:     }
                   1941:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   1942:               ';" align="center">');
1.437     raeburn  1943:     my $nolink = 0;
1.568     raeburn  1944:     if ($readonly) {
1.552     raeburn  1945:         $nolink = 1;
1.568     raeburn  1946:     } else { 
1.578     raeburn  1947:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  1948:             $nolink = 1;
1.568     raeburn  1949:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1950:             $nolink = 1;
1.568     raeburn  1951:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1952:             if ($noeditgrp) {
                   1953:                 $nolink = 1;
                   1954:             }
                   1955:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  1956:             $nolink = 1;
1.568     raeburn  1957:         } elsif ($mprefix =~ /examcode\&$/) {
                   1958:             unless ($which == 2) {
                   1959:                 $nolink = 1;
                   1960:             }
1.533     raeburn  1961:         }
1.437     raeburn  1962:     }
                   1963:     if ($nolink) {
1.577     raeburn  1964:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  1965:         $r->print(&valout($currval,$currtype));
1.114     www      1966:     } else {
1.578     raeburn  1967:         $r->print(&plink($currtype,
                   1968:                          $$display{$value},$currval,
1.588     raeburn  1969:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   1970:                          $extra));
1.114     www      1971:     }
                   1972:     $r->print('</td>'."\n");
1.57      albertel 1973: }
                   1974: 
1.561     damieng  1975: # Returns HTML and other info for the cell added when a user is selected
                   1976: # and that user is in several groups. This is the cell with the title "Control by other group".
                   1977: #
                   1978: # @param {string} $what - parameter part.'.'.parameter name
                   1979: # @param {string} $rid - resource id
                   1980: # @param {string} $cgroup - group name
                   1981: # @param {string} $defbg - cell background color
                   1982: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1983: # @param {integer} $result - level
                   1984: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  1985: # @returns {Array} - array (parameter value for the other group, HTML for the cell, HTML with the value, name of the other group, true if recursive)
1.580     raeburn  1986: sub check_other_groups {
                   1987:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  1988:     my $courseid = $env{'request.course.id'};
                   1989:     my $output;
                   1990:     my $symb = &symbcache($rid);
                   1991:     my $symbparm=$symb.'.'.$what;
                   1992:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  1993:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  1994:     my $mapparm=$map.'___(all).'.$what;
                   1995:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  1996:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   1997:                               $recurseparm,$what,$courseopt);
1.275     raeburn  1998:     my $bgcolor = $defbg;
1.582     raeburn  1999:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2000:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2001:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2002:         if ($result > 3) {
1.419     bisitz   2003:             $bgcolor = '#AAFFAA';
1.275     raeburn  2004:         }
1.593     raeburn  2005:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2006:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2007:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2008:             if ($resultlevel eq 'recursive') {
                   2009:                 $resultlevel = 'map/folder';
                   2010:                 $grp_is_rec = 1;
                   2011:             }
                   2012:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2013:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2014:              
1.275     raeburn  2015:         } else {
                   2016:             $output .= '&nbsp;';
                   2017:         }
                   2018:         $output .= '</td>';
                   2019:     } else {
1.419     bisitz   2020:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2021:     }
1.582     raeburn  2022:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2023: }
                   2024: 
1.561     damieng  2025: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2026: # Used by check_other_groups.
1.561     damieng  2027: #
                   2028: # @param {string} $courseid - the course id
                   2029: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2030: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2031: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2032: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2033: # @param {string} $what - parameter part.'.'.parameter name
                   2034: # @param {hash reference} $courseopt - course parameters hash
                   2035: # @returns {Array} - (parameter value for the group, course parameter hash key for the parameter, name of the group, level name, parameter type)
1.275     raeburn  2036: sub parm_control_group {
1.556     raeburn  2037:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2038:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2039:     my $grpfound = 0;
1.556     raeburn  2040:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2041:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2042:     foreach my $group (@{$usersgroups}) {
                   2043:         if ($grpfound) { last; }
                   2044:         for (my $i=0; $i<@levels; $i++) {
                   2045:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2046:             if (defined($$courseopt{$item})) {
                   2047:                 $coursereply = $$courseopt{$item};
                   2048:                 $resultitem = $item;
                   2049:                 $resultgroup = $group;
                   2050:                 $resultlevel = $levelnames[$i];
                   2051:                 $resulttype = $$courseopt{$item.'.type'};
                   2052:                 $grpfound = 1;
                   2053:                 last;
                   2054:             }
                   2055:         }
                   2056:     }
                   2057:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2058: }
1.201     www      2059: 
1.63      bowersj2 2060: 
                   2061: 
1.562     damieng  2062: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2063: # All the parameters are references and are filled by the sub.
                   2064: #
1.566     damieng  2065: # @param {array reference} $ids - resource and map ids
                   2066: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2067: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2068: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2069: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2070: # @param {hash reference} $allmaps - hash map pc -> map src
                   2071: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2072: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2073: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2074: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2075: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2076: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608     raeburn  2077: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63      bowersj2 2078: sub extractResourceInformation {
                   2079:     my $ids = shift;
                   2080:     my $typep = shift;
                   2081:     my $keyp = shift;
                   2082:     my $allparms = shift;
                   2083:     my $allparts = shift;
                   2084:     my $allmaps = shift;
                   2085:     my $mapp = shift;
                   2086:     my $symbp = shift;
1.82      www      2087:     my $maptitles=shift;
1.196     www      2088:     my $uris=shift;
1.210     www      2089:     my $keyorder=shift;
1.211     www      2090:     my $defkeytype=shift;
1.603     raeburn  2091:     my $pssymb=shift;
1.196     www      2092: 
1.210     www      2093:     my $keyordercnt=100;
1.63      bowersj2 2094: 
1.196     www      2095:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2096:     return unless(ref($navmap));
                   2097:     my @allres;
                   2098:     if ($pssymb ne '') {
                   2099:         my $res = $navmap->getBySymb($pssymb);
                   2100:         if (ref($res)) {
                   2101:             @allres = ($res);
                   2102:         }
                   2103:     }
                   2104:     if (!@allres) { 
                   2105:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2106:     }
1.196     www      2107:     foreach my $resource (@allres) {
1.480     amueller 2108:         my $id=$resource->id();
1.196     www      2109:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2110:         if ($mapid eq '0') { next; }
                   2111:         $$ids[$#$ids+1]=$id;
                   2112:         my $srcf=$resource->src();
                   2113:         $srcf=~/\.(\w+)$/;
                   2114:         $$typep{$id}=$1;
1.584     raeburn  2115:         my $toolsymb;
                   2116:         if ($srcf =~ /ext\.tool$/) {
                   2117:             $toolsymb = $resource->symb();
                   2118:         }
1.480     amueller 2119:         $$keyp{$id}='';
1.196     www      2120:         $$uris{$id}=$srcf;
1.512     foxr     2121: 
1.584     raeburn  2122:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2123:             next if ($key!~/^parameter_/);
1.363     albertel 2124: 
1.209     www      2125: # Hidden parameters
1.584     raeburn  2126:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2127: #
                   2128: # allparms is a hash of parameter names
                   2129: #
1.584     raeburn  2130:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2131:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2132:                 my ($display,$parmdis);
                   2133:                 $display = &standard_parameter_names($name);
                   2134:                 if ($display eq '') {
1.584     raeburn  2135:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2136:                     $parmdis = $display;
                   2137:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2138:                 } else {
                   2139:                     $parmdis = &mt($display);
                   2140:                 }
                   2141:                 $$allparms{$name}=$parmdis;
                   2142:                 if (ref($defkeytype)) {
                   2143:                     $$defkeytype{$name}=
1.584     raeburn  2144:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2145:                 }
                   2146:             }
1.363     albertel 2147: 
1.209     www      2148: #
                   2149: # allparts is a hash of all parts
                   2150: #
1.584     raeburn  2151:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2152:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2153: #
                   2154: # Remember all keys going with this resource
                   2155: #
1.480     amueller 2156:             if ($$keyp{$id}) {
                   2157:                 $$keyp{$id}.=','.$key;
                   2158:             } else {
                   2159:                 $$keyp{$id}=$key;
                   2160:             }   
1.210     www      2161: #
                   2162: # Put in order
1.446     bisitz   2163: #
1.480     amueller 2164:             unless ($$keyorder{$key}) {
                   2165:                 $$keyorder{$key}=$keyordercnt;
                   2166:                 $keyordercnt++;
                   2167:             }
1.473     amueller 2168:         }
                   2169: 
                   2170: 
1.480     amueller 2171:         if (!exists($$mapp{$mapid})) {
                   2172:             $$mapp{$id}=
                   2173:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2174:             $$mapp{$mapid}=$$mapp{$id};
                   2175:             $$allmaps{$mapid}=$$mapp{$id};
                   2176:             if ($mapid eq '1') {
1.532     raeburn  2177:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2178:             } else {
                   2179:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2180:             }
                   2181:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2182:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2183:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2184:                                                      # are commented out in rev. 1.57
1.473     amueller 2185:         } else {
1.480     amueller 2186:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2187:         }
1.480     amueller 2188:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2189:     }
                   2190: }
                   2191: 
1.582     raeburn  2192: sub get_recursive {
                   2193:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2194:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2195:         foreach my $item (@{$recurseup}) {
                   2196:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2197:             if (defined($resdata->{$norecursechk})) {
                   2198:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2199:                     my $type = $resdata->{$norecursechk.'.type'};
                   2200:                     return [$resdata->{$norecursechk},$type,$item];
                   2201:                 } else {
                   2202:                     last;
                   2203:                 }
                   2204:             }
                   2205:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2206:             if (defined($resdata->{$recursechk})) {
                   2207:                 my $type = $resdata->{$recursechk.'.type'};
                   2208:                 return [$resdata->{$recursechk},$type,$item];
                   2209:             }
                   2210:         }
                   2211:     }
                   2212:     return;
                   2213: }
                   2214: 
1.208     www      2215: 
1.562     damieng  2216: # Tells if a parameter type is a date.
                   2217: #
                   2218: # @param {string} type - parameter type
                   2219: # @returns{boolean} - true if it is a date
1.213     www      2220: sub isdateparm {
                   2221:     my $type=shift;
                   2222:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2223: }
                   2224: 
1.589     raeburn  2225: # Determine if parameter type is specialized string type (i.e.,
                   2226: # not just string or string_yesno.  
                   2227: 
                   2228: sub is_specialstring {
                   2229:     my $type=shift;
1.603     raeburn  2230:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2231: }
                   2232: 
1.562     damieng  2233: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2234: #
1.581     raeburn  2235: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2236: sub parmmenu {
1.581     raeburn  2237:     my ($r)=@_;
1.208     www      2238:     $r->print(<<ENDSCRIPT);
                   2239: <script type="text/javascript">
1.454     bisitz   2240: // <![CDATA[
1.208     www      2241:     function checkall(value, checkName) {
1.453     schualex 2242: 
                   2243:         var li = "_li";
                   2244:         var displayOverview = "";
                   2245:         
                   2246:         if (value == false) {
                   2247:             displayOverview = "none"
                   2248:         }
                   2249: 
1.562     damieng  2250:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2251:             ele = document.forms.parmform.elements[i];
                   2252:             if (ele.name == checkName) {
                   2253:                 document.forms.parmform.elements[i].checked=value;
                   2254:             }
                   2255:         }
                   2256:     }
1.210     www      2257: 
                   2258:     function checkthis(thisvalue, checkName) {
1.562     damieng  2259:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2260:             ele = document.forms.parmform.elements[i];
                   2261:             if (ele.name == checkName) {
1.562     damieng  2262:                 if (ele.value == thisvalue) {
                   2263:                     document.forms.parmform.elements[i].checked=true;
                   2264:                 }
1.210     www      2265:             }
                   2266:         }
                   2267:     }
                   2268: 
                   2269:     function checkdates() {
1.562     damieng  2270:         checkthis('duedate','pscat');
                   2271:         checkthis('opendate','pscat');
                   2272:         checkthis('answerdate','pscat');
1.218     www      2273:     }
                   2274: 
                   2275:     function checkdisset() {
1.562     damieng  2276:         checkthis('discussend','pscat');
                   2277:         checkthis('discusshide','pscat');
                   2278:         checkthis('discussvote','pscat');
1.218     www      2279:     }
                   2280: 
                   2281:     function checkcontdates() {
1.562     damieng  2282:         checkthis('contentopen','pscat');
                   2283:         checkthis('contentclose','pscat');
1.218     www      2284:     }
1.446     bisitz   2285: 
1.210     www      2286:     function checkvisi() {
1.562     damieng  2287:         checkthis('hiddenresource','pscat');
                   2288:         checkthis('encrypturl','pscat');
                   2289:         checkthis('problemstatus','pscat');
                   2290:         checkthis('contentopen','pscat');
                   2291:         checkthis('opendate','pscat');
1.210     www      2292:     }
                   2293: 
                   2294:     function checkparts() {
1.562     damieng  2295:         checkthis('hiddenparts','pscat');
                   2296:         checkthis('display','pscat');
                   2297:         checkthis('ordered','pscat');
1.210     www      2298:     }
                   2299: 
                   2300:     function checkstandard() {
                   2301:         checkall(false,'pscat');
1.562     damieng  2302:         checkdates();
                   2303:         checkthis('weight','pscat');
                   2304:         checkthis('maxtries','pscat');
                   2305:         checkthis('type','pscat');
                   2306:         checkthis('problemstatus','pscat');
1.210     www      2307:     }
                   2308: 
1.454     bisitz   2309: // ]]>
1.208     www      2310: </script>
                   2311: ENDSCRIPT
1.453     schualex 2312: 
1.491     bisitz   2313:     $r->print('<hr />');
1.581     raeburn  2314:     &shortCuts($r);
1.491     bisitz   2315:     $r->print('<hr />');
1.453     schualex 2316: }
1.562     damieng  2317: 
                   2318: # Returns parameter categories.
                   2319: #
                   2320: # @returns {hash} - category name -> title in English
1.465     amueller 2321: sub categories {
                   2322:     return ('time_settings' => 'Time Settings',
                   2323:     'grading' => 'Grading',
                   2324:     'tries' => 'Tries',
                   2325:     'problem_appearance' => 'Problem Appearance',
                   2326:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2327:     'hiding' => 'Hiding',
                   2328:     'high_level_randomization' => 'High Level Randomization',
                   2329:     'slots' => 'Slots',
                   2330:     'file_submission' => 'File Submission',
                   2331:     'misc' => 'Miscellaneous' ); 
                   2332: }
                   2333: 
1.562     damieng  2334: # Returns the category for each parameter.
                   2335: #
                   2336: # @returns {hash} - parameter name -> category name
1.465     amueller 2337: sub lookUpTableParameter {
                   2338:  
                   2339:     return ( 
                   2340:         'opendate' => 'time_settings',
                   2341:         'duedate' => 'time_settings',
                   2342:         'answerdate' => 'time_settings',
                   2343:         'interval' => 'time_settings',
                   2344:         'contentopen' => 'time_settings',
                   2345:         'contentclose' => 'time_settings',
                   2346:         'discussend' => 'time_settings',
1.560     damieng  2347:         'printstartdate' => 'time_settings',
                   2348:         'printenddate' => 'time_settings',
1.465     amueller 2349:         'weight' => 'grading',
                   2350:         'handgrade' => 'grading',
                   2351:         'maxtries' => 'tries',
                   2352:         'hinttries' => 'tries',
1.503     raeburn  2353:         'randomizeontries' => 'tries',
1.465     amueller 2354:         'type' => 'problem_appearance',
                   2355:         'problemstatus' => 'problem_appearance',
                   2356:         'display' => 'problem_appearance',
                   2357:         'ordered' => 'problem_appearance',
                   2358:         'numbubbles' => 'problem_appearance',
                   2359:         'tol' => 'behaviour_of_input_fields',
                   2360:         'sig' => 'behaviour_of_input_fields',
                   2361:         'turnoffunit' => 'behaviour_of_input_fields',
                   2362:         'hiddenresource' => 'hiding',
                   2363:         'hiddenparts' => 'hiding',
                   2364:         'discusshide' => 'hiding',
                   2365:         'buttonshide' => 'hiding',
                   2366:         'turnoffeditor' => 'hiding',
                   2367:         'encrypturl' => 'hiding',
1.587     raeburn  2368:         'deeplink' => 'hiding',
1.465     amueller 2369:         'randomorder' => 'high_level_randomization',
                   2370:         'randompick' => 'high_level_randomization',
                   2371:         'available' => 'slots',
                   2372:         'useslots' => 'slots',
                   2373:         'availablestudent' => 'slots',
                   2374:         'uploadedfiletypes' => 'file_submission',
                   2375:         'maxfilesize' => 'file_submission',
                   2376:         'cssfile' => 'misc',
                   2377:         'mapalias' => 'misc',
                   2378:         'acc' => 'misc',
                   2379:         'maxcollaborators' => 'misc',
                   2380:         'scoreformat' => 'misc',
1.514     raeburn  2381:         'lenient' => 'grading',
1.519     raeburn  2382:         'retrypartial' => 'tries',
1.521     raeburn  2383:         'discussvote'  => 'misc',
1.584     raeburn  2384:         'examcode' => 'high_level_randomization',
1.575     raeburn  2385:     );
1.465     amueller 2386: }
                   2387: 
1.562     damieng  2388: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2389: #
                   2390: # @param {string} $name - parameter name
                   2391: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2392: sub whatIsMyCategory {
                   2393:     my $name = shift;
                   2394:     my $catList = shift;
                   2395:     my @list;
                   2396:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2397:     my $cat = $lookUpList{$name};
                   2398:     if (defined($cat)) {
                   2399:         if (!defined($$catList{$cat})){
                   2400:             push @list, ($name);
                   2401:             $$catList{$cat} = \@list;
                   2402:         } else {
                   2403:             push @{${$catList}{$cat}}, ($name);     
                   2404:         }
                   2405:     } else {
                   2406:         if (!defined($$catList{'misc'})){
                   2407:             push @list, ($name);
                   2408:             $$catList{'misc'} = \@list;
                   2409:         } else {
                   2410:             push @{${$catList}{'misc'}}, ($name);     
                   2411:         }
                   2412:     }        
                   2413: }
                   2414: 
1.562     damieng  2415: # Sorts parameter names based on appearance order.
                   2416: #
                   2417: # @param {array reference} name - array reference of parameter names
                   2418: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2419: # @returns {Array} - array of parameter names
1.465     amueller 2420: sub keysindisplayorderCategory {
                   2421:     my ($name,$keyorder)=@_;
                   2422:     return sort {
1.473     amueller 2423:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2424:     } ( @{$name});
                   2425: }
                   2426: 
1.562     damieng  2427: # Returns a hash category name -> order, starting at 1 (integer)
                   2428: #
                   2429: # @returns {hash}
1.467     amueller 2430: sub category_order {
                   2431:     return (
                   2432:         'time_settings' => 1,
                   2433:         'grading' => 2,
                   2434:         'tries' => 3,
                   2435:         'problem_appearance' => 4,
                   2436:         'hiding' => 5,
                   2437:         'behaviour_of_input_fields' => 6,
                   2438:         'high_level_randomization'  => 7,
                   2439:         'slots' => 8,
                   2440:         'file_submission' => 9,
                   2441:         'misc' => 10
                   2442:     );
                   2443: 
                   2444: }
1.453     schualex 2445: 
1.562     damieng  2446: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2447: #
                   2448: # @param {Apache2::RequestRec} $r - the Apache request
                   2449: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2450: # @param {array reference} $pscat - list of selected parameter names
                   2451: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2452: sub parmboxes {
                   2453:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2454:     my %categories = &categories();
1.467     amueller 2455:     my %category_order = &category_order();
1.465     amueller 2456:     my %categoryList = (
                   2457:         'time_settings' => [],
                   2458:         'grading' => [],
                   2459:         'tries' => [],
                   2460:         'problem_appearance' => [],
                   2461:         'behaviour_of_input_fields' => [],
                   2462:         'hiding' => [],
                   2463:         'high_level_randomization' => [],
                   2464:         'slots' => [],
                   2465:         'file_submission' => [],
                   2466:         'misc' => [],
1.489     bisitz   2467:     );
1.510     www      2468: 
1.548     raeburn  2469:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2470:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2471:     }
1.453     schualex 2472:     #part to print the parm-list
1.536     raeburn  2473:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2474:         next if (@{$categoryList{$key}} == 0);
                   2475:         next if ($key eq '');
                   2476:         $r->print('<div class="LC_Box LC_400Box">'
                   2477:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2478:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2479:             next if ($tempkey eq '');
1.536     raeburn  2480:             $r->print('<span class="LC_nobreak">'
                   2481:                      .'<label><input type="checkbox" name="pscat" '
                   2482:                      .'value="'.$tempkey.'" ');
                   2483:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2484:                 $r->print( ' checked="checked"');
                   2485:             }
                   2486:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2487:                                                       : $tempkey)
1.536     raeburn  2488:                      .'</label></span><br />'."\n");
1.465     amueller 2489:         }
1.536     raeburn  2490:         $r->print('</div>');
1.465     amueller 2491:     }
1.536     raeburn  2492:     $r->print("\n");
1.453     schualex 2493: }
1.562     damieng  2494: 
                   2495: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2496: #
1.562     damieng  2497: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2498: sub shortCuts {
1.581     raeburn  2499:     my ($r)=@_;
1.453     schualex 2500: 
1.491     bisitz   2501:     # Parameter Selection
                   2502:     $r->print(
                   2503:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2504:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2505:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2506:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2507:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2508:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2509:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2510:        .&Apache::lonhtmlcommon::end_funclist()
                   2511:     );
                   2512: 
                   2513:     # Add Selection for...
                   2514:     $r->print(
                   2515:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2516:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2517:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2518:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2519:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2520:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2521:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2522:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2523:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2524:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2525:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2526:        .&Apache::lonhtmlcommon::end_funclist()
                   2527:     );
1.208     www      2528: }
                   2529: 
1.562     damieng  2530: # Prints HTML to select parts to view (except for the title).
                   2531: # Used by table and overview modes.
                   2532: #
                   2533: # @param {Apache2::RequestRec} $r - the Apache request
                   2534: # @param {hash reference} $allparts - hash parameter part -> part title
                   2535: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2536: sub partmenu {
1.446     bisitz   2537:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2538:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2539:     if ($selsize > 8) {
                   2540:         $selsize = 8;
                   2541:     }
1.446     bisitz   2542: 
1.523     raeburn  2543:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2544:     $r->print('<option value="all"');
1.562     damieng  2545:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2546:     $r->print('>'.&mt('All Parts').'</option>');
                   2547:     my %temphash=();
                   2548:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2549:     foreach my $tempkey (sort {
1.560     damieng  2550:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2551:             } keys(%{$allparts})) {
                   2552:         unless ($tempkey =~ /\./) {
                   2553:             $r->print('<option value="'.$tempkey.'"');
                   2554:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2555:                 $r->print(' selected="selected"');
                   2556:             }
                   2557:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2558:         }
1.208     www      2559:     }
1.446     bisitz   2560:     $r->print('</select>');
1.209     www      2561: }
                   2562: 
1.562     damieng  2563: # Prints HTML to select a user and/or a group.
                   2564: # Used by table mode.
                   2565: #
                   2566: # @param {Apache2::RequestRec} $r - the Apache request
                   2567: # @param {string} $uname - selected user name
                   2568: # @param {string} $id - selected Student/Employee ID
                   2569: # @param {string} $udom - selected user domain
                   2570: # @param {string} $csec - selected section name
                   2571: # @param {string} $cgroup - selected group name
                   2572: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2573: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2574: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2575: sub usermenu {
1.553     raeburn  2576:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2577:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2578:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2579:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2580: function setCourseadv(form,caller) {
                   2581:     if (caller.value == 'st') {
                   2582:         form.courseadv.value = 'none';
                   2583:     } else {
                   2584:         form.courseadv.value = '';
                   2585:     }
                   2586:     return;
                   2587: }
                   2588: ENDJS
1.412     bisitz   2589: 
1.596     raeburn  2590:     my (%chkroles,$stuonly,$courseadv);
                   2591:     if ($env{'form.userroles'} eq 'any') {
                   2592:         $chkroles{'any'} = ' checked="checked"';
                   2593:     } else {
                   2594:         $chkroles{'st'} = ' checked="checked"';
                   2595:         $courseadv = 'none';
                   2596:     }
                   2597:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2598:     if ($crstype eq 'Community') {
                   2599:         $stuonly = &mt('member only');
                   2600:     } else {
                   2601:         $stuonly = &mt('student only');
                   2602:     }
                   2603:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2604:                   &mt("User's role").':&nbsp;'.
                   2605:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2606:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2607:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2608:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2609:     my $sections='';
1.300     albertel 2610:     my %sectionhash = &Apache::loncommon::get_sections();
                   2611: 
1.269     raeburn  2612:     my $groups;
1.553     raeburn  2613:     my %grouphash;
                   2614:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2615:         %grouphash = &Apache::longroup::coursegroups();
                   2616:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2617:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2618:     }
1.299     albertel 2619: 
1.412     bisitz   2620:     my $g_s_header='';
                   2621:     my $g_s_footer='';
1.446     bisitz   2622: 
1.552     raeburn  2623:     my $currsec = $env{'request.course.sec'};
                   2624:     if ($currsec) {
                   2625:         $sections=&mt('Section:').' '.$currsec;
                   2626:         if (%grouphash) {
                   2627:             $sections .= ';'.('&nbsp;' x2);
                   2628:         }
                   2629:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2630:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2631:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2632:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2633:         }
                   2634:         $sections .= '>';
1.548     raeburn  2635:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2636:         $sections.='<option value="'.$section.'" '.
                   2637:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2638:                                                               '</option>';
1.209     www      2639:         }
                   2640:         $sections.='</select>';
1.269     raeburn  2641:     }
1.412     bisitz   2642: 
1.552     raeburn  2643:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2644:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2645:         $sections .= qq|
                   2646: <script type="text/javascript">
1.454     bisitz   2647: // <![CDATA[
1.269     raeburn  2648: function group_or_section(caller) {
                   2649:    if (caller == "cgroup") {
                   2650:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2651:            document.parmform.csec.selectedIndex = 0;
                   2652:        }
                   2653:    } else {
                   2654:        if (document.parmform.csec.selectedIndex != 0) {
                   2655:            document.parmform.cgroup.selectedIndex = 0;
                   2656:        }
                   2657:    }
                   2658: }
1.454     bisitz   2659: // ]]>
1.269     raeburn  2660: </script>
                   2661: |;
1.554     raeburn  2662:     } else {
1.269     raeburn  2663:         $sections .= qq|
                   2664: <script type="text/javascript">
1.454     bisitz   2665: // <![CDATA[
1.269     raeburn  2666: function group_or_section(caller) {
                   2667:     return;
                   2668: }
1.454     bisitz   2669: // ]]>
1.269     raeburn  2670: </script>
                   2671: |;
1.446     bisitz   2672:     }
1.299     albertel 2673: 
                   2674:     if (%grouphash) {
1.597     raeburn  2675:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2676:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2677:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2678:         }
                   2679:         $groups .= '>';
1.548     raeburn  2680:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2681:             $groups.='<option value="'.$grp.'" ';
                   2682:             if ($grp eq $cgroup) {
                   2683:                 unless ((defined($uname)) && ($grp eq '')) {
                   2684:                     $groups .=  'selected="selected" ';
                   2685:                 }
                   2686:             } elsif (!defined($cgroup)) {
                   2687:                 if (@{$usersgroups} == 1) {
                   2688:                     if ($grp eq $$usersgroups[0]) {
                   2689:                         $groups .=  'selected="selected" ';
                   2690:                     }
                   2691:                 }
                   2692:             }
                   2693:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2694:         }
                   2695:         $groups.='</select>';
                   2696:     }
1.412     bisitz   2697: 
1.445     neumanie 2698:     if (%sectionhash || %grouphash) {
1.446     bisitz   2699:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2700:         $r->print($sections.$groups);
1.448     bisitz   2701:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2702:     } else {
                   2703:         $r->print($sections); 
1.445     neumanie 2704:     }
1.446     bisitz   2705: 
                   2706:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2707:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2708:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2709:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2710:                  ,$chooseopt));
1.209     www      2711: }
                   2712: 
1.562     damieng  2713: # Prints HTML to select parameters from a list of all parameters.
                   2714: # Uses parmmenu and parmboxes.
                   2715: # Used by table and overview modes.
1.468     amueller 2716: #
1.562     damieng  2717: # @param {Apache2::RequestRec} $r - the Apache request
                   2718: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2719: # @param {array reference} $pscat - list of selected parameter names
                   2720: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2721: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2722: sub displaymenu {
1.581     raeburn  2723:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2724: 
1.445     neumanie 2725:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2726:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2727: 
1.581     raeburn  2728:     &parmmenu($r);
1.536     raeburn  2729:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2730:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2731:     $r->print(&Apache::loncommon::end_scrollbox());
                   2732: 
                   2733:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2734:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2735:  
1.209     www      2736: }
                   2737: 
1.562     damieng  2738: # Prints HTML to select a map.
                   2739: # Used by table mode and overview mode.
                   2740: #
                   2741: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2742: # @param {hash reference} $allmaps - hash map pc -> map src
                   2743: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2744: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2745: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610   ! raeburn  2746: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445     neumanie 2747: sub mapmenu {
1.610   ! raeburn  2748:     my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468     amueller 2749:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2750:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2751:     my $tree=[];
                   2752:     my $treeinfo={};
                   2753:     if (defined($navmap)) {
1.499     raeburn  2754:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2755:         my $curRes;
                   2756:         my $depth = 0;
1.468     amueller 2757:         my %parent = ();
                   2758:         my $startcount = 5;
                   2759:         my $lastcontainer = $startcount;
                   2760: # preparing what is to show ...
1.461     neumanie 2761:         while ($curRes = $it->next()) {
                   2762:             if ($curRes == $it->BEGIN_MAP()) {
                   2763:                 $depth++;
1.468     amueller 2764:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2765:             }
                   2766:             if ($curRes == $it->END_MAP()) {
                   2767:                 $depth--;
1.468     amueller 2768:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2769:             }
                   2770:             if (ref($curRes)) {
1.468     amueller 2771:                 my $symb = $curRes->symb();
                   2772:                 my $ressymb = $symb;
1.461     neumanie 2773:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2774:                     my $type = 'sequence';
                   2775:                     if ($curRes->is_page()) {
                   2776:                         $type = 'page';
                   2777:                     }
                   2778:                     my $id= $curRes->id();
1.468     amueller 2779:                     my $srcf = $curRes->src();
                   2780:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2781:                     if(!exists($treeinfo->{$id})) {
                   2782:                         push(@$tree,$id);
1.473     amueller 2783:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2784:                         $treeinfo->{$id} = {
1.461     neumanie 2785:                                     depth => $depth,
                   2786:                                     type  => $type,
1.468     amueller 2787:                                     name  => $resource_name,
                   2788:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2789:                                     };
1.462     neumanie 2790:                     }
1.461     neumanie 2791:                 }
                   2792:             }
                   2793:         }
1.462     neumanie 2794:     }
1.473     amueller 2795: # Show it ...    
1.610   ! raeburn  2796:     my $rowattr = ' id="mapmenu"';
        !          2797:     if ($parmlev eq 'general') {
        !          2798:         $rowattr .= ' style="display:none"';
        !          2799:     }
        !          2800:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461     neumanie 2801:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2802:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2803:         my $whitespace =
                   2804:             '<img src="'
                   2805:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2806:            .'" alt="" />';
                   2807: 
1.498     bisitz   2808:         # Info about selectable folders/maps
                   2809:         $r->print(
                   2810:             '<div class="LC_info">'
1.508     www      2811:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2812:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2813:            .'</div>'
                   2814:         );
                   2815: 
1.536     raeburn  2816:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2817:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2818: 
1.498     bisitz   2819:         # Display row: "All Maps or Folders"
                   2820:         $r->print(
1.523     raeburn  2821:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2822:            .'<td>'
                   2823:            .'<label>'
                   2824:            .'<input type="radio" name="pschp"'
1.497     bisitz   2825:         );
                   2826:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2827:         $r->print(
                   2828:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2829:            .&mt('All Maps or Folders')
                   2830:            .'</label>'
                   2831:            .'<hr /></td>'
                   2832:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2833:         );
1.497     bisitz   2834: 
1.532     raeburn  2835:         # Display row: "Main Content"
1.468     amueller 2836:         if (exists($$allmaps{1})) {
1.498     bisitz   2837:             $r->print(
                   2838:                 &Apache::loncommon::start_data_table_row()
                   2839:                .'<td>'
                   2840:                .'<label>'
                   2841:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2842:             );
1.497     bisitz   2843:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2844:             $r->print(
                   2845:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2846:                .$$maptitles{1}
                   2847:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2848:                .'</label>'
                   2849:                .'</td>'
                   2850:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2851:             );
                   2852:         }
1.497     bisitz   2853: 
                   2854:         # Display rows for all course maps and folders
1.468     amueller 2855:         foreach my $id (@{$tree}) {
                   2856:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2857:             # Indentation
1.468     amueller 2858:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2859:             my $indent;
                   2860:             for (my $i = 0; $i < $depth; $i++) {
                   2861:                 $indent.= $whitespace;
                   2862:             }
1.461     neumanie 2863:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2864:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2865:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2866:             }
1.468     amueller 2867:             my $symb_name = $$symbp{$id};
                   2868:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2869:             $symb_name = $tail;
1.498     bisitz   2870:             $r->print(
                   2871:                 &Apache::loncommon::start_data_table_row()
                   2872:                .'<td>'
                   2873:                .'<label>'
1.463     bisitz   2874:             );
1.498     bisitz   2875:             # Only offer radio button for folders/maps which can be parameterized
                   2876:             if ($allmaps_inverted{$symb_name}) {
                   2877:                 $r->print(
                   2878:                     '<input type ="radio" name="pschp"'
                   2879:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2880:                 );
                   2881:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2882:                 $r->print('/>');
                   2883:             } else {
                   2884:                 $r->print($whitespace);
1.461     neumanie 2885:             }
1.498     bisitz   2886:             $r->print(
                   2887:                 $indent.$icon.'&nbsp;'
                   2888:                .$treeinfo->{$id}->{name}
                   2889:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2890:                .'</label>'
                   2891:                .'</td>'
                   2892:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2893:             );
1.461     neumanie 2894:         }
1.497     bisitz   2895: 
1.523     raeburn  2896:         $r->print(&Apache::loncommon::end_data_table().
                   2897:                   '<br style="line-height:2px;" />'.
                   2898:                   &Apache::loncommon::end_scrollbox());
1.209     www      2899:     }
                   2900: }
                   2901: 
1.563     damieng  2902: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2903: # Used by table and overview modes.
                   2904: #
                   2905: # @param {Apache2::RequestRec} $r - the Apache request
                   2906: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2907: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2908: sub levelmenu {
1.446     bisitz   2909:     my ($r,$alllevs,$parmlev)=@_;
                   2910: 
1.548     raeburn  2911:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2912:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2913:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2914:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2915:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2916:         if ($parmlev eq $$alllevs{$lev}) {
                   2917:             $r->print(' selected="selected"');
                   2918:         }
                   2919:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2920:     }
1.446     bisitz   2921:     $r->print("</select>");
1.208     www      2922: }
                   2923: 
1.211     www      2924: 
1.563     damieng  2925: # Returns HTML to select a section (with a select HTML element).
                   2926: # Used by overview mode.
                   2927: #
                   2928: # @param {array reference} $selectedsections - list of selected section ids
                   2929: # @returns {string}
1.211     www      2930: sub sectionmenu {
1.553     raeburn  2931:     my ($selectedsections)=@_;
1.300     albertel 2932:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2933:     return '' if (!%sectionhash);
1.300     albertel 2934: 
1.552     raeburn  2935:     my (@possibles,$disabled);
                   2936:     if ($env{'request.course.sec'} ne '') {
                   2937:         @possibles = ($env{'request.course.sec'});
                   2938:         $selectedsections = [$env{'request.course.sec'}];
                   2939:         $disabled = ' disabled="disabled"';
                   2940:     } else {
                   2941:         @possibles = ('all',sort(keys(%sectionhash)));
                   2942:     }
1.553     raeburn  2943:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2944:     foreach my $s (@possibles) {
1.553     raeburn  2945:         $output .= '    <option value="'.$s.'"';
                   2946:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2947:             $output .= ' selected="selected"';
1.473     amueller 2948:         }
1.553     raeburn  2949:         $output .= '>'."$s</option>\n";
1.300     albertel 2950:     }
1.553     raeburn  2951:     $output .= "</select>\n";
                   2952:     return $output;
1.269     raeburn  2953: }
                   2954: 
1.563     damieng  2955: # Returns HTML to select a group (with a select HTML element).
                   2956: # Used by overview mode.
                   2957: #
                   2958: # @param {array reference} $selectedgroups - list of selected group names
                   2959: # @returns {string}
1.269     raeburn  2960: sub groupmenu {
1.553     raeburn  2961:     my ($selectedgroups)=@_;
                   2962:     my %grouphash;
                   2963:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2964:         %grouphash = &Apache::longroup::coursegroups();
                   2965:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2966:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2967:     }
                   2968:     return '' if (!%grouphash);
1.299     albertel 2969: 
1.553     raeburn  2970:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2971:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2972:         $output .= '    <option value="'.$group.'"';
                   2973:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2974:             $output .=  ' selected="selected"';
1.473     amueller 2975:         }
1.553     raeburn  2976:         $output .= '>'."$group</option>\n";
1.211     www      2977:     }
1.553     raeburn  2978:     $output .= "</select>\n";
                   2979:     return $output;
1.211     www      2980: }
                   2981: 
1.563     damieng  2982: # Returns an array with the given parameter split by comma.
                   2983: # Used by assessparms (table mode).
                   2984: #
                   2985: # @param {string} $keyp - the string to split
                   2986: # @returns {Array<string>}
1.210     www      2987: sub keysplit {
                   2988:     my $keyp=shift;
                   2989:     return (split(/\,/,$keyp));
                   2990: }
                   2991: 
1.563     damieng  2992: # Returns the keys in $name, sorted using $keyorder.
                   2993: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   2994: # Used by assessparms (table mode) for resource level.
                   2995: #
                   2996: # @param {hash reference} $name - parameter key -> parameter name
                   2997: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2998: # @returns {Array<string>}
1.210     www      2999: sub keysinorder {
                   3000:     my ($name,$keyorder)=@_;
                   3001:     return sort {
1.560     damieng  3002:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  3003:     } (keys(%{$name}));
1.210     www      3004: }
                   3005: 
1.563     damieng  3006: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3007: # Used by assessparms (table mode) for map and general levels.
                   3008: #
                   3009: # @param {hash reference} $name - parameter key -> parameter name
                   3010: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3011: # @returns {Array<string>}
1.236     albertel 3012: sub keysinorder_bytype {
                   3013:     my ($name,$keyorder)=@_;
                   3014:     return sort {
1.563     damieng  3015:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3016:         my $tb=(split('_',$b))[-1];
                   3017:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3018:             return ($a cmp $b);
                   3019:         }
                   3020:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3021:     } (keys(%{$name}));
1.236     albertel 3022: }
                   3023: 
1.563     damieng  3024: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3025: # Used by defaultsetter (parameter settings default actions).
                   3026: #
                   3027: # @param {hash reference} $name - hash parameter name -> parameter title
                   3028: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3029: # @returns {Array<string>}
1.211     www      3030: sub keysindisplayorder {
                   3031:     my ($name,$keyorder)=@_;
                   3032:     return sort {
1.560     damieng  3033:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3034:     } (keys(%{$name}));
1.211     www      3035: }
                   3036: 
1.563     damieng  3037: # Prints HTML with a choice to sort results by realm or student first.
                   3038: # Used by overview mode.
                   3039: #
                   3040: # @param {Apache2::RequestRec} $r - the Apache request
                   3041: # @param {string} $sortorder - realmstudent|studentrealm
1.608     raeburn  3042: # @param {string} $context - newoverview|overview
1.214     www      3043: sub sortmenu {
1.608     raeburn  3044:     my ($r,$sortorder,$context)=@_;
                   3045:     my %text;
                   3046:     if ($context eq 'newoverview') {
                   3047:         %text = &Apache::lonlocal::texthash (
                   3048:                    realmstudent => 'Sort by location in course first, then student (group/section)',
                   3049:                    studentrealm => 'Sort by student (group/section) first, then location in course',
                   3050:         );
                   3051:     } else {
                   3052:         %text = &Apache::lonlocal::texthash (
                   3053:                    realmstudent => 'Sort by realm first, then student (group/section)',
                   3054:                    studentrealm => 'Sort by student (group/section) first, then realm',
                   3055:         );
1.214     www      3056:     }
1.608     raeburn  3057:     my %sortchecked = (
                   3058:        realmstudent => ' checked="checked"',
                   3059:        studentrealm => '',
                   3060:     );
1.214     www      3061:     if ($sortorder eq 'studentrealm') {
1.608     raeburn  3062:         $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
                   3063:         $sortchecked{'realmstudent'} = '';
                   3064:     }
                   3065:     foreach my $sorttype ('realmstudent','studentrealm') {
                   3066:         $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                   3067:                   $text{$sorttype}.'</label>');
1.214     www      3068:     }
                   3069: }
                   3070: 
1.563     damieng  3071: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3072: #
                   3073: # @returns {hash}
1.211     www      3074: sub standardkeyorder {
                   3075:     return ('parameter_0_opendate' => 1,
1.473     amueller 3076:         'parameter_0_duedate' => 2,
                   3077:         'parameter_0_answerdate' => 3,
                   3078:         'parameter_0_interval' => 4,
                   3079:         'parameter_0_weight' => 5,
                   3080:         'parameter_0_maxtries' => 6,
                   3081:         'parameter_0_hinttries' => 7,
                   3082:         'parameter_0_contentopen' => 8,
                   3083:         'parameter_0_contentclose' => 9,
                   3084:         'parameter_0_type' => 10,
                   3085:         'parameter_0_problemstatus' => 11,
                   3086:         'parameter_0_hiddenresource' => 12,
                   3087:         'parameter_0_hiddenparts' => 13,
                   3088:         'parameter_0_display' => 14,
                   3089:         'parameter_0_ordered' => 15,
                   3090:         'parameter_0_tol' => 16,
                   3091:         'parameter_0_sig' => 17,
                   3092:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3093:         'parameter_0_discussend' => 19,
                   3094:         'parameter_0_discusshide' => 20,
                   3095:         'parameter_0_discussvote' => 21,
1.560     damieng  3096:         'parameter_0_printstartdate'  =>  22,
                   3097:         'parameter_0_printenddate' =>  23);
1.211     www      3098: }
                   3099: 
1.59      matthew  3100: 
1.560     damieng  3101: # Table mode UI.
1.563     damieng  3102: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3103: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3104: #
                   3105: # Parameters used from the request:
                   3106: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3107: # cgroup - selected group
                   3108: # command - 'set': direct access to table mode for a resource
                   3109: # csec - selected section
                   3110: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3111: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3112: # id - student/employee ID
                   3113: # parmlev - selected level (full|map|general)
                   3114: # part - selected part (unused ?)
                   3115: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3116: # pres_type - &&&-separated parameter types
                   3117: # pres_value - &&&-separated parameter values
                   3118: # prevvisit - '1' if the user has submitted the form before
                   3119: # pscat (multiple values) - selected parameter names
1.566     damieng  3120: # pschp - selected map pc, or 'all'
1.563     damieng  3121: # psprt (multiple values) - list of selected parameter parts
                   3122: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3123: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3124: # symb - resource symb (when a single resource is selected)
                   3125: # udom - selected user domain
                   3126: # uname - selected user name
                   3127: # url - used only with command 'set', the resource url
                   3128: #
                   3129: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3130: # @param $parm_permission - ref to hash of permissions
                   3131: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3132: sub assessparms {
1.1       www      3133: 
1.568     raeburn  3134:     my ($r,$parm_permission) = @_;
1.201     www      3135: 
1.512     foxr     3136: 
                   3137: # -------------------------------------------------------- Variable declaration
1.566     damieng  3138:     my @ids=(); # resource and map ids
                   3139:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3140:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3141:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3142:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3143:     my %uris=(); # hash resource/map id -> resource src
                   3144:     my %maptitles=(); # hash map pc or src -> map title
                   3145:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3146:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3147:     my %alllevs=(); # hash English level title -> value
                   3148: 
                   3149:     my $uname; # selected user name
                   3150:     my $udom; # selected user domain
                   3151:     my $uhome; # server with the user's files, or 'no_host'
                   3152:     my $csec; # selected section name
                   3153:     my $cgroup; # selected group name
                   3154:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3155:     my $numreclinks = 0;
1.446     bisitz   3156: 
1.190     albertel 3157:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3158: 
1.57      albertel 3159:     $alllevs{'Resource Level'}='full';
1.215     www      3160:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3161:     $alllevs{'Course Level'}='general';
                   3162: 
1.563     damieng  3163:     my %allparms; # hash parameter name -> parameter title
                   3164:     my %allparts; # hash parameter part -> part title
1.512     foxr     3165: # ------------------------------------------------------------------------------
                   3166: 
1.210     www      3167: #
                   3168: # Order in which these parameters will be displayed
                   3169: #
1.211     www      3170:     my %keyorder=&standardkeyorder();
                   3171: 
1.512     foxr     3172: #    @ids=();
                   3173: #    %symbp=();       # These seem defined above already.
                   3174: #    %typep=();
1.43      albertel 3175: 
                   3176:     my $message='';
                   3177: 
1.190     albertel 3178:     $csec=$env{'form.csec'};
1.552     raeburn  3179:     if ($env{'request.course.sec'} ne '') {
                   3180:         $csec = $env{'request.course.sec'};    
                   3181:     }
                   3182: 
1.553     raeburn  3183: # Check group privs.
1.269     raeburn  3184:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3185:     my $noeditgrp; 
                   3186:     if ($cgroup ne '') {
                   3187:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3188:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3189:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3190:                 $noeditgrp = 1;
                   3191:             }
                   3192:         }
                   3193:     }
1.188     www      3194: 
1.190     albertel 3195:     if      ($udom=$env{'form.udom'}) {
                   3196:     } elsif ($udom=$env{'request.role.domain'}) {
                   3197:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3198:     } else {
1.473     amueller 3199:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3200:     }
1.468     amueller 3201:     
1.43      albertel 3202: 
1.134     albertel 3203:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3204:     my $pschp=$env{'form.pschp'};
1.506     www      3205: 
                   3206: 
1.134     albertel 3207:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3208:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3209:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3210: 
1.43      albertel 3211:     my $pssymb='';
1.57      albertel 3212:     my $parmlev='';
1.446     bisitz   3213: 
1.190     albertel 3214:     unless ($env{'form.parmlev'}) {
1.57      albertel 3215:         $parmlev = 'map';
                   3216:     } else {
1.190     albertel 3217:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3218:     }
1.26      www      3219: 
1.29      www      3220: # ----------------------------------------------- Was this started from grades?
                   3221: 
1.560     damieng  3222:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3223:             (!$env{'form.dis'})) {
1.473     amueller 3224:         my $url=$env{'form.url'};
                   3225:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3226:         $pssymb=&Apache::lonnet::symbread($url);
                   3227:         if (!@pscat) { @pscat=('all'); }
                   3228:         $pschp='';
1.57      albertel 3229:         $parmlev = 'full';
1.190     albertel 3230:     } elsif ($env{'form.symb'}) {
1.473     amueller 3231:         $pssymb=$env{'form.symb'};
                   3232:         if (!@pscat) { @pscat=('all'); }
                   3233:         $pschp='';
1.57      albertel 3234:         $parmlev = 'full';
1.43      albertel 3235:     } else {
1.473     amueller 3236:         $env{'form.url'}='';
1.43      albertel 3237:     }
                   3238: 
1.190     albertel 3239:     my $id=$env{'form.id'};
1.43      albertel 3240:     if (($id) && ($udom)) {
1.555     raeburn  3241:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3242:         if ($uname) {
                   3243:             $id='';
                   3244:         } else {
                   3245:             $message=
1.540     bisitz   3246:                 '<p class="LC_warning">'.
                   3247:                 &mt('Unknown ID [_1] at domain [_2]',
                   3248:                     "'".$id."'","'".$udom."'").
                   3249:                 '</p>';
1.473     amueller 3250:         }
1.43      albertel 3251:     } else {
1.473     amueller 3252:         $uname=$env{'form.uname'};
1.43      albertel 3253:     }
                   3254:     unless ($udom) { $uname=''; }
                   3255:     $uhome='';
                   3256:     if ($uname) {
1.473     amueller 3257:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3258:         if ($uhome eq 'no_host') {
1.473     amueller 3259:             $message=
1.540     bisitz   3260:                 '<p class="LC_warning">'.
                   3261:                 &mt('Unknown user [_1] at domain [_2]',
                   3262:                     "'".$uname."'","'".$udom."'").
                   3263:                 '</p>';
1.473     amueller 3264:             $uname='';
1.12      www      3265:         } else {
1.473     amueller 3266:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3267:                           $env{'request.course.id'});
                   3268:             if ($csec eq '-1') {
1.596     raeburn  3269:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3270:                 if ($env{'form.userroles'} eq 'any') {
                   3271:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3272:                         $csec = $env{'request.course.sec'};
                   3273:                         $message = '<span class="LC_info">';
                   3274:                         if ($crstype eq 'Community') {
                   3275:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3276:                                             $uname,$udom);
                   3277:                         } else {
                   3278:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3279:                                             $uname,$udom);
                   3280:                         }
                   3281:                         $message .= '</span>';
                   3282:                     } else {
                   3283:                         my @possroles = ('in','ep','ta','cr');
                   3284:                         if ($crstype eq 'Community') {
                   3285:                             unshift(@possroles,'co');
                   3286:                         } else {
                   3287:                             unshift(@possroles,'cc');
                   3288:                         }
                   3289:                         my %not_student_roles =
                   3290:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3291:                                                           \@possroles,[$udom],1,1);
                   3292:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3293:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3294:                         my %sections_by_role;
                   3295:                         foreach my $role (keys(%not_student_roles)) {
                   3296:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3297:                                 my ($rolename,$sec) = ($1,$2);
                   3298:                                 if ($rolename =~ m{^cr/}) {
                   3299:                                     $rolename = 'cr';
                   3300:                                 }
                   3301:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3302:                             }
                   3303:                         }
                   3304:                         my $numroles = scalar(keys(%sections_by_role));
                   3305:                         if ($numroles) {
                   3306:                             foreach my $role (@possroles) {
                   3307:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3308:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3309:                                     $csec = $secs[0];
                   3310:                                     last;
                   3311:                                 }
                   3312:                             }
                   3313:                         }
                   3314:                         if ($csec eq '-1') {
                   3315:                             $message = '<span class="LC_warning">';
                   3316:                             if ($crstype eq 'Community') {
                   3317:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3318:                                                 $uname,$udom);
                   3319:                             } else {
                   3320:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3321:                                                 $uname,$udom);
                   3322:                             }
                   3323:                             $message .= '</span>';
                   3324:                             $uname='';
                   3325:                             if ($env{'request.course.sec'} ne '') {
                   3326:                                 $csec=$env{'request.course.sec'};
                   3327:                             } else {
                   3328:                                 $csec=$env{'form.csec'};
                   3329:                             }
                   3330:                             $cgroup=$env{'form.cgroup'};
                   3331:                         } else {
                   3332:                             $message = '<span class="LC_info">';
                   3333:                             if ($crstype eq 'Community') {
                   3334:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3335:                                          $uname,$udom);
                   3336:                             } else {
                   3337:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3338:                                                 $uname,$udom);
                   3339:                             }
                   3340:                             $message .= '</span>';
                   3341:                         }
                   3342:                     }
1.594     raeburn  3343:                 } else {
1.596     raeburn  3344:                     $message = '<span class="LC_warning">';
                   3345:                     if ($crstype eq 'Community') {
                   3346:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3347:                                          $uname,$udom);
                   3348:                     } else {
                   3349:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3350:                                          $uname,$udom);
                   3351:                     }
                   3352:                     $message .= '</span>';
                   3353:                     $uname='';
                   3354:                     if ($env{'request.course.sec'} ne '') {
                   3355:                         $csec=$env{'request.course.sec'};
                   3356:                     } else {
                   3357:                         $csec=$env{'form.csec'};
                   3358:                     }
                   3359:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3360:                 }
                   3361:             } elsif ($env{'request.course.sec'} ne '') {
                   3362:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3363:                     $message='<span class="LC_warning">'.
1.594     raeburn  3364:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3365:                                   $uname,$udom,$env{'request.course.sec'}).
                   3366:                               '</span>';
                   3367:                     $uname='';
                   3368:                     $csec=$env{'request.course.sec'};
                   3369:                 }
1.269     raeburn  3370:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3371:             }
                   3372:             if ($uname ne '') {
1.473     amueller 3373:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3374:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3375:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3376:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3377:                             .$name{'lastname'}.' '.$name{'generation'}
                   3378:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3379:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3380:                                    $udom,$uname,$env{'request.course.id'});
                   3381:                 if (@usersgroups > 0) {
                   3382:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3383:                         $cgroup = $usersgroups[0];
                   3384:                     }
                   3385:                 } else {
                   3386:                     $cgroup = '';
1.297     raeburn  3387:                 }
1.269     raeburn  3388:             }
1.12      www      3389:         }
1.43      albertel 3390:     }
1.2       www      3391: 
1.43      albertel 3392:     unless ($csec) { $csec=''; }
1.269     raeburn  3393:     unless ($cgroup) { $cgroup=''; }
1.12      www      3394: 
1.14      www      3395: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3396:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3397:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3398:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3399: 
1.582     raeburn  3400:     %allmaps_inverted = reverse(%allmaps);
                   3401: 
1.57      albertel 3402:     $mapp{'0.0'} = '';
                   3403:     $symbp{'0.0'} = '';
1.99      albertel 3404: 
1.14      www      3405: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3406:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3407:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3408:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3409:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3410:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3411:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3412:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3413:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3414:         my $totalstored = 0;
1.605     raeburn  3415:         my $totalskippeduser = 0;
1.546     raeburn  3416:         my $now = time;
1.473     amueller 3417:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3418:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3419:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3420:                 next if ($csec ne $env{'request.course.sec'});
                   3421:             }
1.556     raeburn  3422:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3423:                 next if ($noeditgrp);
1.605     raeburn  3424:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3425:                 if ($uname eq '') {
                   3426:                     $totalskippeduser ++;
                   3427:                     next;
                   3428:                 }
1.557     raeburn  3429:             }
                   3430:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3431:                 $namematch = 'maplevelrecurse';
                   3432:             }
1.556     raeburn  3433:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3434:                 my (@ok_slots,@fail_slots,@del_slots);
                   3435:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3436:                 my ($level,@all) =
                   3437:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3438:                                      $csec,$cgroup,$courseopt);
                   3439:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3440:                     next if ($slot_name eq '');
                   3441:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3442:                         push(@ok_slots,$slot_name);
                   3443: 
                   3444:                     } else {
                   3445:                         push(@fail_slots,$slot_name);
                   3446:                     }
                   3447:                 }
                   3448:                 if (@ok_slots) {
                   3449:                     $values[$i] = join(':',@ok_slots);
                   3450:                 } else {
                   3451:                     $values[$i] = '';
                   3452:                 }
                   3453:                 if ($all[$level] ne '') {
                   3454:                     my @existing = split(/:/,$all[$level]);
                   3455:                     foreach my $slot_name (@existing) {
                   3456:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3457:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3458:                                 push(@del_slots,$slot_name);
                   3459:                             }
                   3460:                         }
                   3461:                     }
                   3462:                 }
1.554     raeburn  3463:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3464:                 $name = $1;
1.533     raeburn  3465:                 my $val = $values[$i];
1.549     raeburn  3466:                 my $valmatch = '';
1.533     raeburn  3467:                 if ($name eq 'examcode') {
1.544     raeburn  3468:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3469:                         $val = 'valid';
                   3470:                     }
1.546     raeburn  3471:                 } elsif ($name eq 'printstartdate') {
                   3472:                     if ($val =~ /^\d+$/) {
                   3473:                         if ($val > $now) {
                   3474:                             $val = 'future';
                   3475:                         }
                   3476:                     } 
                   3477:                 } elsif ($name eq 'printenddate') {
                   3478:                     if ($val =~ /^\d+$/) {
                   3479:                         if ($val < $now) {
                   3480:                             $val = 'past';
                   3481:                         }
                   3482:                     }
1.549     raeburn  3483:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3484:                     my $stringtype = &get_stringtype($name);
                   3485:                     my $stringmatch = &standard_string_matches($stringtype);
                   3486:                     if (ref($stringmatch) eq 'ARRAY') {
                   3487:                         foreach my $item (@{$stringmatch}) {
                   3488:                             if (ref($item) eq 'ARRAY') {
                   3489:                                 my ($regexpname,$pattern) = @{$item};
                   3490:                                 if ($pattern ne '') {
                   3491:                                     if ($val =~ /$pattern/) {
                   3492:                                         $valmatch = $regexpname;
                   3493:                                         $val = '';
                   3494:                                         last;
                   3495:                                     }
                   3496:                                 }
                   3497:                             }
                   3498:                         }
                   3499:                     }
1.554     raeburn  3500:                 } elsif ($name eq 'interval') {
                   3501:                     my $intervaltype = &get_intervaltype($name);
                   3502:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3503:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3504:                         foreach my $item (@{$intervalmatch}) {
                   3505:                             if (ref($item) eq 'ARRAY') {
                   3506:                                 my ($regexpname,$pattern) = @{$item};
                   3507:                                 if ($pattern ne '') {
                   3508:                                     if ($val =~ /$pattern/) {
                   3509:                                         $valmatch = $regexpname;
                   3510:                                         $val = '';
                   3511:                                         last;
                   3512:                                     }
                   3513:                                 }
                   3514:                             }
                   3515:                         }
                   3516:                     }
1.533     raeburn  3517:                 }
1.504     raeburn  3518:                 $needsrelease =
1.557     raeburn  3519:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3520:                 if ($needsrelease) {
1.505     raeburn  3521:                     unless ($got_chostname) {
1.514     raeburn  3522:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3523:                         $got_chostname = 1;
1.546     raeburn  3524:                     } 
1.557     raeburn  3525:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3526:                                                           $needsrelease,
                   3527:                                                           $cmajor,$cminor);
1.500     raeburn  3528:                 }
1.437     raeburn  3529:             }
1.504     raeburn  3530:             if ($needsnewer) {
1.557     raeburn  3531:                 undef($namematch);
                   3532:             } else {
                   3533:                 my $currneeded;
                   3534:                 if ($needsrelease) {
                   3535:                     $currneeded = $needsrelease;
                   3536:                 }
                   3537:                 if ($namematch) {
                   3538:                     $needsrelease =
                   3539:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3540:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3541:                         unless ($got_chostname) {
                   3542:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3543:                             $got_chostname = 1;
                   3544:                         }
                   3545:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3546:                                                               $needsrelease,
                   3547:                                                               $cmajor,$cminor);
                   3548:                     } else {
                   3549:                         undef($namematch);
                   3550:                     }
                   3551:                 }
                   3552:             }
                   3553:             if ($needsnewer) {
                   3554:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3555:                                                 $cminor,$needsrelease);
                   3556:             } else {
                   3557:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3558:                                      $values[$i],
                   3559:                                      $types[$i],
                   3560:                                      $uname,$udom,$csec,$cgroup);
                   3561:                 $totalstored ++;
                   3562:             }
1.473     amueller 3563:         }
1.68      www      3564: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3565:         if ($totalstored) {
                   3566:             $message.='<p class="LC_warning">'
1.605     raeburn  3567:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3568:                      .'<br />'
1.504     raeburn  3569:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3570:                      .&Apache::loncommon::help_open_topic('Caching')
                   3571:                      .'</p>';
1.605     raeburn  3572:         } else {
                   3573:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3574:         }
                   3575:         if ($totalskippeduser) {
                   3576:             $message .= '<p class="LC_warning">';
                   3577:             if ($uhome eq 'no_host') {
                   3578:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3579:                                 $totalskippeduser);
                   3580:             } elsif ($env{'form.userroles'} eq 'any') {
                   3581:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3582:                                 $totalskippeduser);
                   3583:             } else {
                   3584:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3585:                                 $totalskippeduser);
                   3586:             }
                   3587:             $message .= '</p>';
1.504     raeburn  3588:         }
1.68      www      3589:     }
1.584     raeburn  3590: 
1.57      albertel 3591: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3592:     if ($pscat[0] eq "all") {
                   3593:         @pscat = (keys(%allparms));
                   3594:     }
                   3595:     if (!@pscat) {
                   3596:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3597:     };
                   3598:     if ($psprt[0] eq "all" || !@psprt) {
                   3599:         @psprt = (keys(%allparts));
                   3600:     }
1.2       www      3601: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3602: 
1.531     raeburn  3603:     my $crstype = &Apache::loncommon::course_type();
                   3604:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3605: 
1.548     raeburn  3606:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3607:             'date_interval','int','float','string','string_lenient',
                   3608:             'string_examcode','string_deeplink','string_discussvote',
                   3609:             'string_useslots','string_problemstatus','string_ip',
                   3610:             'string_questiontype') {
1.473     amueller 3611:         $r->print('<input type="hidden" value="'.
1.563     damieng  3612:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3613:             '" name="recent_'.$item.'" />');
1.44      albertel 3614:     }
1.446     bisitz   3615: 
1.459     bisitz   3616:     # ----- Start Parameter Selection
                   3617: 
1.606     raeburn  3618:     # Hide parm selection and possibly table?
                   3619:     my ($tablejs,$tabledivsty);
                   3620:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
                   3621:         ($env{'form.dis'}) && ($pssymb eq '')) {
                   3622:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
                   3623:         $tabledivsty = ' style="display:none"';
                   3624:     }
1.459     bisitz   3625:     $r->print(<<ENDPARMSELSCRIPT);
                   3626: <script type="text/javascript">
                   3627: // <![CDATA[
                   3628: function parmsel_show() {
1.562     damieng  3629:     document.getElementById('parmsel').style.display = "";
                   3630:     document.getElementById('parmsellink').style.display = "none";
1.606     raeburn  3631:     $tablejs
1.459     bisitz   3632: }
                   3633: // ]]>
                   3634: </script>
                   3635: ENDPARMSELSCRIPT
1.474     amueller 3636:     
1.445     neumanie 3637:     if (!$pssymb) {
1.563     damieng  3638:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3639:         my $parmselhiddenstyle=' style="display:none"';
                   3640:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3641:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3642:         } else  {
                   3643:            $r->print('<div id="parmsel">');
                   3644:         }
                   3645: 
1.491     bisitz   3646:         # Step 1
1.523     raeburn  3647:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3648:         $r->print('
1.474     amueller 3649: <script type="text/javascript">
1.523     raeburn  3650: // <![CDATA['.
                   3651:                  &showhide_js().'
1.474     amueller 3652: // ]]>
                   3653: </script>
1.523     raeburn  3654: ');
                   3655:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3656:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3657:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.610   ! raeburn  3658:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491     bisitz   3659:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3660:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3661:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3662:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3663:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3664: 
                   3665:         # Step 2
1.523     raeburn  3666:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3667:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3668: 
                   3669:         # Step 3
1.523     raeburn  3670:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3671:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3672:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3673:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3674:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3675: 
                   3676:         # Update Display Button
1.486     www      3677:         $r->print('<p>'
                   3678:              .'<input type="submit" name="dis"'
1.511     www      3679:              .' value="'.&mt('Update Display').'" />'
1.486     www      3680:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3681:              .'</p>');
                   3682:         $r->print('</div>');
1.491     bisitz   3683: 
1.486     www      3684:         # Offer link to display parameter selection again
                   3685:         $r->print('<p id="parmsellink"');
                   3686:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3687:            $r->print($parmselhiddenstyle);
                   3688:         }
                   3689:         $r->print('>'
                   3690:              .'<a href="javascript:parmsel_show()">'
                   3691:              .&mt('Change Parameter Selection')
                   3692:              .'</a>'
                   3693:              .'</p>');
1.44      albertel 3694:     } else {
1.478     amueller 3695:         # parameter screen for a single resource. 
1.486     www      3696:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3697:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3698:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3699:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3700:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3701:                   '<br />');
                   3702:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3703:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3704:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3705:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3706:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3707:         $r->print('<p>'
1.459     bisitz   3708:              .'<input type="submit" name="dis"'
1.511     www      3709:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3710:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3711:              .'</p>');
1.459     bisitz   3712:     }
1.478     amueller 3713:     
1.486     www      3714:     # ----- End Parameter Selection
1.57      albertel 3715: 
1.459     bisitz   3716:     # Display Messages
                   3717:     $r->print('<div>'.$message.'</div>');
1.210     www      3718: 
1.57      albertel 3719: 
                   3720:     my @temp_pscat;
                   3721:     map {
                   3722:         my $cat = $_;
                   3723:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3724:     } @pscat;
                   3725: 
                   3726:     @pscat = @temp_pscat;
                   3727: 
1.548     raeburn  3728: 
1.209     www      3729:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3730: # ----------------------------------------------------------------- Start Table
1.57      albertel 3731:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3732:         my $csuname=$env{'user.name'};
                   3733:         my $csudom=$env{'user.domain'};
1.568     raeburn  3734:         my $readonly = 1;
                   3735:         if ($parm_permission->{'edit'}) {
                   3736:             undef($readonly); 
                   3737:         }
1.606     raeburn  3738:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3739: 
1.203     www      3740:         if ($parmlev eq 'full') {
1.506     www      3741: #
                   3742: # This produces the cascading table output of parameters
                   3743: #
1.578     raeburn  3744:             my $coursespan=$csec?8:5;
                   3745:             my $userspan=3;
1.560     damieng  3746:             if ($cgroup ne '') {
1.578     raeburn  3747:                 $coursespan += 3;
1.560     damieng  3748:             }
1.473     amueller 3749: 
1.560     damieng  3750:             $r->print(&Apache::loncommon::start_data_table());
                   3751:             #
                   3752:             # This produces the headers
                   3753:             #
                   3754:             $r->print('<tr><td colspan="5"></td>');
                   3755:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3756:             if ($uname) {
1.473     amueller 3757:                 if (@usersgroups > 1) {
1.560     damieng  3758:                     $userspan ++;
                   3759:                 }
                   3760:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3761:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3762:             }
                   3763:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3764:                 'pie'    => "Parameter in Effect",
                   3765:                 'csv'    => "Current Session Value",
1.472     amueller 3766:                 'rl'     => "Resource Level",
1.473     amueller 3767:                 'ic'     => 'in Course',
                   3768:                 'aut'    => "Assessment URL and Title",
                   3769:                 'type'   => 'Type',
                   3770:                 'emof'   => "Enclosing Map or Folder",
                   3771:                 'part'   => 'Part',
1.472     amueller 3772:                 'pn'     => 'Parameter Name',
1.473     amueller 3773:                 'def'    => 'default',
                   3774:                 'femof'  => 'from Enclosing Map or Folder',
                   3775:                 'gen'    => 'general',
                   3776:                 'foremf' => 'for Enclosing Map or Folder',
                   3777:                 'fr'     => 'for Resource'
                   3778:             );
1.560     damieng  3779:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3780: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3781: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3782: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3783: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3784: 
1.10      www      3785: ENDTABLETWO
1.560     damieng  3786:             if ($csec) {
1.578     raeburn  3787:                 $r->print('<th colspan="3">'.
1.560     damieng  3788:                 &mt("in Section")." $csec</th>");
                   3789:             }
                   3790:             if ($cgroup) {
1.578     raeburn  3791:                 $r->print('<th colspan="3">'.
1.472     amueller 3792:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3793:             }
                   3794:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3795: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3796: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3797: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3798: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3799: ENDTABLEHEADFOUR
1.57      albertel 3800: 
1.560     damieng  3801:             if ($csec) {
1.578     raeburn  3802:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3803:             }
1.473     amueller 3804: 
1.560     damieng  3805:             if ($cgroup) {
1.578     raeburn  3806:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3807:             }
                   3808: 
                   3809:             if ($uname) {
                   3810:                 if (@usersgroups > 1) {
                   3811:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3812:                 }
1.578     raeburn  3813:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3814:             }
                   3815: 
                   3816:             $r->print('</tr>');
1.506     www      3817: #
                   3818: # Done with the headers
                   3819: # 
1.560     damieng  3820:             my $defbgone='';
                   3821:             my $defbgtwo='';
                   3822:             my $defbgthree = '';
1.57      albertel 3823: 
1.560     damieng  3824:             foreach my $rid (@ids) {
1.57      albertel 3825: 
                   3826:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3827:                 if ((!$pssymb &&
1.560     damieng  3828:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3829:                         ||
                   3830:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3831: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3832:                     if ($defbgone eq '#E0E099') {
                   3833:                         $defbgone='#E0E0DD';
1.57      albertel 3834:                     } else {
1.419     bisitz   3835:                         $defbgone='#E0E099';
1.57      albertel 3836:                     }
1.419     bisitz   3837:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3838:                         $defbgtwo='#FFFFDD';
1.57      albertel 3839:                     } else {
1.473     amueller 3840:                         $defbgtwo='#FFFF99';
1.57      albertel 3841:                     }
1.419     bisitz   3842:                     if ($defbgthree eq '#FFBB99') {
                   3843:                         $defbgthree='#FFBBDD';
1.269     raeburn  3844:                     } else {
1.419     bisitz   3845:                         $defbgthree='#FFBB99';
1.269     raeburn  3846:                     }
                   3847: 
1.57      albertel 3848:                     my $thistitle='';
                   3849:                     my %name=   ();
                   3850:                     undef %name;
                   3851:                     my %part=   ();
                   3852:                     my %display=();
                   3853:                     my %type=   ();
                   3854:                     my %default=();
1.196     www      3855:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3856:                     my $toolsymb;
                   3857:                     if ($uri =~ /ext\.tool$/) {
                   3858:                         $toolsymb = $symbp{$rid};
                   3859:                     }
1.57      albertel 3860: 
1.506     www      3861:                     my $filter=$env{'form.filter'};
1.548     raeburn  3862:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3863:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3864:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3865:     # We may only want certain parameters listed
                   3866:                             if ($filter) {
                   3867:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3868:                             }
                   3869:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3870:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3871: 
1.584     raeburn  3872:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3873:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3874:                                 my $identifier;
                   3875:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3876:                                     $identifier = $1;
                   3877:                                 }
                   3878:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3879:                             } else {
                   3880:                                 $display{$tempkeyp} = $parmdis;
                   3881:                             }
                   3882:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3883:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3884:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3885:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3886:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3887:                         }
                   3888:                     }
1.548     raeburn  3889:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3890:                     if ($totalparms>0) {
1.560     damieng  3891:                         my $firstrow=1;
1.473     amueller 3892:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3893:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3894:                         my @recurseup;
                   3895:                         if (ref($navmap) && $mapp{$rid}) {
                   3896:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3897:                         }
1.419     bisitz   3898:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3899:                              ' rowspan='.$totalparms.
1.419     bisitz   3900:                              '><tt><font size="-1">'.
1.57      albertel 3901:                              join(' / ',split(/\//,$uri)).
                   3902:                              '</font></tt><p><b>'.
1.154     albertel 3903:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3904:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3905:                           &escape($symbp{$rid}).
1.336     albertel 3906:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3907:                              " target=\"_self\">$title");
1.57      albertel 3908: 
                   3909:                         if ($thistitle) {
1.473     amueller 3910:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3911:                         }
                   3912:                         $r->print('</a></b></td>');
1.419     bisitz   3913:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3914:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3915:                                       '</td>');
                   3916: 
1.419     bisitz   3917:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3918:                                       ' rowspan='.$totalparms.
1.238     www      3919:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3920:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3921:                             unless ($firstrow) {
                   3922:                                 $r->print('<tr>');
                   3923:                             } else {
                   3924:                                 undef $firstrow;
                   3925:                             }
1.548     raeburn  3926:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3927:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3928:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  3929:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   3930:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   3931:                                        \$numreclinks);
1.57      albertel 3932:                         }
                   3933:                     }
                   3934:                 }
                   3935:             } # end foreach ids
1.43      albertel 3936: # -------------------------------------------------- End entry for one resource
1.517     www      3937:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3938:         } # end of  full
1.57      albertel 3939: #--------------------------------------------------- Entry for parm level map
                   3940:         if ($parmlev eq 'map') {
1.419     bisitz   3941:             my $defbgone = '#E0E099';
                   3942:             my $defbgtwo = '#FFFF99';
                   3943:             my $defbgthree = '#FFBB99';
1.57      albertel 3944: 
                   3945:             my %maplist;
                   3946: 
                   3947:             if ($pschp eq 'all') {
1.446     bisitz   3948:                 %maplist = %allmaps;
1.57      albertel 3949:             } else {
                   3950:                 %maplist = ($pschp => $mapp{$pschp});
                   3951:             }
                   3952: 
                   3953: #-------------------------------------------- for each map, gather information
                   3954:             my $mapid;
1.607     raeburn  3955:             foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60      albertel 3956:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3957: 
                   3958: #-----------------------  loop through ids and get all parameter types for map
                   3959: #-----------------------------------------          and associated information
                   3960:                 my %name = ();
                   3961:                 my %part = ();
                   3962:                 my %display = ();
                   3963:                 my %type = ();
                   3964:                 my %default = ();
                   3965:                 my $map = 0;
                   3966: 
1.473     amueller 3967: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3968: 
1.548     raeburn  3969:                 foreach my $id (@ids) {
                   3970:                     ($map)=($id =~ /([\d]*?)\./);
                   3971:                     my $rid = $id;
1.446     bisitz   3972: 
1.57      albertel 3973: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3974: 
1.560     damieng  3975:                     if ($map eq $mapid) {
1.473     amueller 3976:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3977:                         my $toolsymb;
                   3978:                         if ($uri =~ /ext\.tool$/) {
                   3979:                             $toolsymb = $symbp{$rid};
                   3980:                         }
1.582     raeburn  3981: 
1.57      albertel 3982: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3983: 
                   3984: #--------------------------------------------------------------------
                   3985: # @catmarker contains list of all possible parameters including part #s
                   3986: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3987: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3988: # When storing information, store as part 0
                   3989: # When requesting information, request from full part
                   3990: #-------------------------------------------------------------------
1.548     raeburn  3991:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3992:                             my $tempkeyp = $fullkeyp;
                   3993:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 3994: 
1.548     raeburn  3995:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3996:                                 $part{$tempkeyp}="0";
1.584     raeburn  3997:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   3998:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 3999:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   4000:                                     my $identifier;
                   4001:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4002:                                         $identifier = $1;
                   4003:                                     }
                   4004:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4005:                                 } else {
                   4006:                                     $display{$tempkeyp} = $parmdis;
                   4007:                                 }
                   4008:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4009:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4010:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4011:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4012:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 4013:                               }
                   4014:                         } # end loop through keys
1.560     damieng  4015:                     }
1.57      albertel 4016:                 } # end loop through ids
1.446     bisitz   4017: 
1.57      albertel 4018: #---------------------------------------------------- print header information
1.133     www      4019:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4020:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4021:                 my $tmp="";
1.57      albertel 4022:                 if ($uname) {
1.473     amueller 4023:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4024:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4025:                         &mt('in')." \n";
1.57      albertel 4026:                 } else {
1.401     bisitz   4027:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4028:                 }
1.269     raeburn  4029:                 if ($cgroup) {
1.401     bisitz   4030:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4031:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4032:                     $csec = '';
                   4033:                 } elsif ($csec) {
1.401     bisitz   4034:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4035:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4036:                 }
1.401     bisitz   4037:                 $r->print('<div align="center"><h4>'
                   4038:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4039:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4040:                              ,$tmp
                   4041:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4042:                              )
                   4043:                          ."<br /></h4>\n"
1.422     bisitz   4044:                 );
1.57      albertel 4045: #---------------------------------------------------------------- print table
1.419     bisitz   4046:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4047:                          .&Apache::loncommon::start_data_table_header_row()
                   4048:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4049:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4050:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4051:                          .&Apache::loncommon::end_data_table_header_row()
                   4052:                 );
1.57      albertel 4053: 
1.582     raeburn  4054:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4055:                 my @recurseup;
                   4056:                 if (ref($navmap)) {
                   4057:                      my $mapres = $navmap->getByMapPc($mapid);
                   4058:                      if (ref($mapres)) {
                   4059:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4060:                      }
                   4061:                 }
                   4062: 
                   4063: 
1.548     raeburn  4064:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4065:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4066:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4067:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4068:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4069:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4070:                            \$numreclinks);
1.57      albertel 4071:                 }
1.422     bisitz   4072:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4073:                          .'</div>'
                   4074:                 );
1.57      albertel 4075:             } # end each map
                   4076:         } # end of $parmlev eq map
                   4077: #--------------------------------- Entry for parm level general (Course level)
                   4078:         if ($parmlev eq 'general') {
1.473     amueller 4079:             my $defbgone = '#E0E099';
1.419     bisitz   4080:             my $defbgtwo = '#FFFF99';
                   4081:             my $defbgthree = '#FFBB99';
1.57      albertel 4082: 
                   4083: #-------------------------------------------- for each map, gather information
                   4084:             my $mapid="0.0";
                   4085: #-----------------------  loop through ids and get all parameter types for map
                   4086: #-----------------------------------------          and associated information
                   4087:             my %name = ();
                   4088:             my %part = ();
                   4089:             my %display = ();
                   4090:             my %type = ();
                   4091:             my %default = ();
1.446     bisitz   4092: 
1.548     raeburn  4093:             foreach $id (@ids) {
                   4094:                 my $rid = $id;
1.446     bisitz   4095: 
1.196     www      4096:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4097:                 my $toolsymb;
                   4098:                 if ($uri =~ /ext\.tool$/) {
                   4099:                     $toolsymb = $symbp{$rid};
                   4100:                 }
1.57      albertel 4101: 
                   4102: #--------------------------------------------------------------------
                   4103: # @catmarker contains list of all possible parameters including part #s
                   4104: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4105: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4106: # When storing information, store as part 0
                   4107: # When requesting information, request from full part
                   4108: #-------------------------------------------------------------------
1.548     raeburn  4109:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4110:                     my $tempkeyp = $fullkeyp;
                   4111:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4112:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4113:                         $part{$tempkeyp}="0";
1.584     raeburn  4114:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4115:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4116:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4117:                             my $identifier;
                   4118:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4119:                                 $identifier = $1;
                   4120:                             }
                   4121:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4122:                         } else {
                   4123:                             $display{$tempkeyp} = $parmdis;
                   4124:                         }
                   4125:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4126:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4127:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4128:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4129:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4130:                     }
1.57      albertel 4131:                 } # end loop through keys
                   4132:             } # end loop through ids
1.446     bisitz   4133: 
1.57      albertel 4134: #---------------------------------------------------- print header information
1.473     amueller 4135:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4136:             $r->print(<<ENDMAPONE);
1.419     bisitz   4137: <center>
                   4138: <h4>$setdef
1.135     albertel 4139: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4140: ENDMAPONE
                   4141:             if ($uname) {
1.473     amueller 4142:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4143:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4144:             } else {
1.135     albertel 4145:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4146:             }
1.446     bisitz   4147: 
1.135     albertel 4148:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4149:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4150:             $r->print("</h4>\n");
1.57      albertel 4151: #---------------------------------------------------------------- print table
1.419     bisitz   4152:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4153:                      .&Apache::loncommon::start_data_table_header_row()
                   4154:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4155:                      .'<th>'.&mt('Default Value').'</th>'
                   4156:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4157:                      .&Apache::loncommon::end_data_table_header_row()
                   4158:             );
1.57      albertel 4159: 
1.548     raeburn  4160:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4161:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4162:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4163:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4164:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4165:                            $readonly);
1.57      albertel 4166:             }
1.419     bisitz   4167:             $r->print(&Apache::loncommon::end_data_table()
                   4168:                      .'</p>'
                   4169:                      .'</center>'
                   4170:             );
1.57      albertel 4171:         } # end of $parmlev eq general
1.606     raeburn  4172:         $r->print('</div>');
1.43      albertel 4173:     }
1.507     www      4174:     $r->print('</form>');
1.582     raeburn  4175:     if ($numreclinks) {
                   4176:         $r->print(<<"END");
                   4177: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4178: <input type="hidden" name="pschp" />
                   4179: <input type="hidden" name="pscat" />
                   4180: <input type="hidden" name="psprt" />
                   4181: <input type="hidden" name="hideparmsel" value="hidden" />
                   4182: </form>
                   4183: <script type="text/javascript">
                   4184: function pjumprec(rid,name,part) {
                   4185:     document.forms.recurseform.pschp.value = rid;
                   4186:     document.forms.recurseform.pscat.value = name;
                   4187:     document.forms.recurseform.psprt.value = part;
                   4188:     document.forms.recurseform.submit();
                   4189:     return false;
                   4190: }
                   4191: </script>
                   4192: END
                   4193:     }
1.507     www      4194:     &endSettingsScreen($r);
                   4195:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4196: } # end sub assessparms
1.30      www      4197: 
1.560     damieng  4198: 
                   4199: 
1.120     www      4200: ##################################################
1.560     damieng  4201: # OVERVIEW MODE
1.207     www      4202: ##################################################
1.124     www      4203: 
1.563     damieng  4204: my $tableopen; # boolean, true if HTML table is already opened
                   4205: 
                   4206: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4207: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4208: # @returns {string}
1.124     www      4209: sub tablestart {
1.576     raeburn  4210:     my ($readonly,$is_map) = @_;
1.124     www      4211:     if ($tableopen) {
1.552     raeburn  4212:         return '';
1.124     www      4213:     } else {
1.552     raeburn  4214:         $tableopen=1;
                   4215:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4216:         if ($readonly) {
                   4217:             $output .= '<th>'.&mt('Current value').'</th>';
                   4218:         } else {
1.576     raeburn  4219:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4220:                        '<th>'.&mt('Set to ...').'</th>';
                   4221:             if ($is_map) {
                   4222:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4223:             }
1.552     raeburn  4224:         }
                   4225:         $output .= '</tr>';
                   4226:         return $output;
1.124     www      4227:     }
                   4228: }
                   4229: 
1.563     damieng  4230: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4231: # @returns {string}
1.124     www      4232: sub tableend {
                   4233:     if ($tableopen) {
1.560     damieng  4234:         $tableopen=0;
                   4235:         return &Apache::loncommon::end_data_table();
1.124     www      4236:     } else {
1.560     damieng  4237:         return'';
1.124     www      4238:     }
                   4239: }
                   4240: 
1.563     damieng  4241: # Reads course and user information.
                   4242: # 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).
                   4243: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4244: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4245: # @param {string} $crs - course number
                   4246: # @param {string} $dom - course domain
                   4247: # @returns {hash reference|Array}
1.207     www      4248: sub readdata {
                   4249:     my ($crs,$dom)=@_;
                   4250: # Read coursedata
                   4251:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4252: # Read userdata
                   4253: 
                   4254:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4255:     foreach my $user (keys(%$classlist)) {
                   4256:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4257:             my ($tuname,$tudom)=($1,$2);
                   4258:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4259:             foreach my $userkey (keys(%{$useropt})) {
                   4260:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4261:                     my $newkey=$userkey;
1.548     raeburn  4262:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4263:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4264:                 }
                   4265:             }
1.473     amueller 4266:         }
                   4267:     }
1.552     raeburn  4268:     if (wantarray) {
                   4269:         return ($resourcedata,$classlist);
                   4270:     } else {
                   4271:         return $resourcedata;
                   4272:     }
1.207     www      4273: }
                   4274: 
                   4275: 
1.563     damieng  4276: # Stores parameter data, using form parameters directly.
                   4277: #
                   4278: # 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  4279: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4280: # del_* - remove a parameter
                   4281: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4282: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4283: # key_* - date values
                   4284: # days_* - for date intervals
                   4285: # hours_* - for date intervals
                   4286: # minutes_* - for date intervals
                   4287: # seconds_* - for date intervals
                   4288: # done_* - for date intervals
                   4289: # typeof_* - parameter type
                   4290: # 
                   4291: # @param {Apache2::RequestRec} $r - the Apache request
                   4292: # @param {string} $crs - course number
                   4293: # @param {string} $dom - course domain
1.208     www      4294: sub storedata {
                   4295:     my ($r,$crs,$dom)=@_;
1.207     www      4296: # Set userlevel immediately
                   4297: # Do an intermediate store of course level
                   4298:     my $olddata=&readdata($crs,$dom);
1.124     www      4299:     my %newdata=();
                   4300:     undef %newdata;
                   4301:     my @deldata=();
1.576     raeburn  4302:     my @delrec=();
                   4303:     my @delnonrec=();
1.124     www      4304:     undef @deldata;
1.504     raeburn  4305:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4306:     my $now = time;
1.560     damieng  4307:     foreach my $key (keys(%env)) {
                   4308:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4309:             my $cmd=$1;
                   4310:             my $thiskey=$2;
1.576     raeburn  4311:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4312:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4313:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4314:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4315:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4316:                     $altkey = $thiskey;
                   4317:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4318:                     if ($env{'form.rec_'.$thiskey}) {
                   4319:                         $recursive = 1;
                   4320:                     }
                   4321:                 }
                   4322:             }
1.560     damieng  4323:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4324:             if ($tuname) {
1.576     raeburn  4325:                 $tkey=$thiskey;
1.560     damieng  4326:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4327:                 if ($altkey) {
                   4328:                     $tkeynonrec = $tkey; 
                   4329:                     $tkeyrec = $altkey;
                   4330:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4331:                 }
1.560     damieng  4332:             }
                   4333:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4334:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4335:                 if ($cmd eq 'set') {
                   4336:                     $data=$env{$key};
                   4337:                     $valmatch = '';
                   4338:                     $valchk = $data;
                   4339:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4340:                     $text = &mt('Saved modified parameter for');
                   4341:                     if ($typeof eq 'string_questiontype') {
                   4342:                         $name = 'type';
1.588     raeburn  4343:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4344:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4345:                         my $stringmatch = &standard_string_matches($typeof);
                   4346:                         if (ref($stringmatch) eq 'ARRAY') {
                   4347:                             foreach my $item (@{$stringmatch}) {
                   4348:                                 if (ref($item) eq 'ARRAY') {
                   4349:                                     my ($regexpname,$pattern) = @{$item};
                   4350:                                     if ($pattern ne '') {
                   4351:                                         if ($data =~ /$pattern/) {
                   4352:                                             $valmatch = $regexpname;
                   4353:                                             $valchk = '';
                   4354:                                             last;
                   4355:                                         }
1.560     damieng  4356:                                     }
1.549     raeburn  4357:                                 }
                   4358:                             }
                   4359:                         }
1.563     damieng  4360:                     } elsif ($typeof eq 'string_discussvote') {
                   4361:                         $name = 'discussvote';
                   4362:                     } elsif ($typeof eq 'string_examcode') {
                   4363:                         $name = 'examcode';
                   4364:                         if (&Apache::lonnet::validCODE($data)) {
                   4365:                             $valchk = 'valid';
                   4366:                         }
                   4367:                     } elsif ($typeof eq 'string_yesno') {
                   4368:                         if ($thiskey =~ /\.retrypartial$/) {
                   4369:                             $name = 'retrypartial';
                   4370:                         }
1.549     raeburn  4371:                     }
1.563     damieng  4372:                 } elsif ($cmd eq 'datepointer') {
                   4373:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4374:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4375:                     $text = &mt('Saved modified date for');
                   4376:                     if ($typeof eq 'date_start') {
                   4377:                         if ($thiskey =~ /\.printstartdate$/) {
                   4378:                             $name = 'printstartdate';
                   4379:                             if (($data) && ($data > $now)) {
                   4380:                                 $valchk = 'future';
                   4381:                             }
1.560     damieng  4382:                         }
1.563     damieng  4383:                     } elsif ($typeof eq 'date_end') {
                   4384:                         if ($thiskey =~ /\.printenddate$/) {
                   4385:                             $name = 'printenddate';
                   4386:                             if (($data) && ($data < $now)) {
                   4387:                                 $valchk = 'past';
                   4388:                             }
1.560     damieng  4389:                         }
1.504     raeburn  4390:                     }
1.563     damieng  4391:                 } elsif ($cmd eq 'dateinterval') {
                   4392:                     $data=&get_date_interval_from_form($thiskey);
                   4393:                     if ($thiskey =~ /\.interval$/) {
                   4394:                         $name = 'interval';
                   4395:                         my $intervaltype = &get_intervaltype($name);
                   4396:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4397:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4398:                             foreach my $item (@{$intervalmatch}) {
                   4399:                                 if (ref($item) eq 'ARRAY') {
                   4400:                                     my ($regexpname,$pattern) = @{$item};
                   4401:                                     if ($pattern ne '') {
                   4402:                                         if ($data =~ /$pattern/) {
                   4403:                                             $valmatch = $regexpname;
                   4404:                                             $valchk = '';
                   4405:                                             last;
                   4406:                                         }
1.560     damieng  4407:                                     }
1.554     raeburn  4408:                                 }
                   4409:                             }
                   4410:                         }
                   4411:                     }
1.563     damieng  4412:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4413:                     $text = &mt('Saved modified date for');
1.554     raeburn  4414:                 }
1.576     raeburn  4415:                 if ($recursive) {
1.563     damieng  4416:                     $namematch = 'maplevelrecurse';
1.560     damieng  4417:                 }
1.563     damieng  4418:                 if (($name ne '') || ($namematch ne '')) {
                   4419:                     my ($needsrelease,$needsnewer);
                   4420:                     if ($name ne '') {
                   4421:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4422:                         if ($needsrelease) {
                   4423:                             unless ($got_chostname) {
1.563     damieng  4424:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4425:                                 $got_chostname = 1;
                   4426:                             }
1.563     damieng  4427:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4428:                                                                 $needsrelease,
                   4429:                                                                 $cmajor,$cminor);
                   4430:                         }
                   4431:                     }
                   4432:                     if ($namematch ne '') {
                   4433:                         if ($needsnewer) {
                   4434:                             undef($namematch);
1.560     damieng  4435:                         } else {
1.563     damieng  4436:                             my $currneeded;
                   4437:                             if ($needsrelease) {
                   4438:                                 $currneeded = $needsrelease;
                   4439:                             }
                   4440:                             $needsrelease =
                   4441:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4442:                             if (($needsrelease) &&
                   4443:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4444:                                 unless ($got_chostname) {
                   4445:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4446:                                     $got_chostname = 1;
                   4447:                                 }
                   4448:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4449:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4450:                             } else {
                   4451:                                 undef($namematch);
                   4452:                             }
1.560     damieng  4453:                         }
1.557     raeburn  4454:                     }
1.563     damieng  4455:                     if ($needsnewer) {
                   4456:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4457:                                                             $chostname,$cmajor,
                   4458:                                                             $cminor,$needsrelease));
                   4459:                         next;
                   4460:                     }
1.504     raeburn  4461:                 }
1.576     raeburn  4462:                 my ($reconlychg,$haschange,$storekey);
                   4463:                 if ($tuname) {
                   4464:                     my $ustorekey;
                   4465:                     if ($altkey) {
                   4466:                         if ($recursive) {
                   4467:                             if (exists($$olddata{$thiskey})) {
                   4468:                                 if ($$olddata{$thiskey} eq $data) {
                   4469:                                     $reconlychg = 1;
                   4470:                                 }
                   4471:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4472:                             }
                   4473:                             if (exists($$olddata{$altkey})) {
                   4474:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4475:                                     $haschange = 1;
                   4476:                                 }
                   4477:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4478:                                 $haschange = 1;
                   4479:                             }
                   4480:                             $ustorekey = $tkeyrec;
                   4481:                         } else {
                   4482:                             if (exists($$olddata{$altkey})) {
                   4483:                                 if ($$olddata{$altkey} eq $data) {
                   4484:                                     $reconlychg = 1;
                   4485:                                 }
                   4486:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4487:                             }
                   4488:                             if (exists($$olddata{$thiskey})) {
                   4489:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4490:                                     $haschange = 1;
                   4491:                                 }
                   4492:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4493:                                 $haschange = 1;
                   4494:                             }
                   4495:                             $ustorekey = $tkeynonrec;
                   4496:                         }
                   4497:                     } else {
                   4498:                         if (exists($$olddata{$tkey})) {
                   4499:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4500:                                 $haschange = 1;
                   4501:                             }
                   4502:                             $ustorekey = $tkey;
                   4503:                         }
                   4504:                     }
                   4505:                     if ($haschange || $reconlychg)  {
                   4506:                         unless ($env{'form.del_'.$thiskey}) {
                   4507:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4508:                                                                      $ustorekey.'.type' => $typeof},
                   4509:                                                                      $tudom,$tuname) eq 'ok') {
                   4510:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4511:                                 $r->print('<br />'.$text.' '.
                   4512:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4513:                             } else {
                   4514:                                 $r->print('<div class="LC_error">'.
                   4515:                                           &mt('Error saving parameters').'</div>');
                   4516:                             }
                   4517:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4518:                         }
                   4519:                     }
                   4520:                 } else {
                   4521:                     if ($altkey) {
                   4522:                         if ($recursive) {
                   4523:                             if (exists($$olddata{$thiskey})) {
                   4524:                                 if ($$olddata{$thiskey} eq $data) {
                   4525:                                     $reconlychg = 1;
                   4526:                                 }
                   4527:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4528:                             }
                   4529:                             if (exists($$olddata{$altkey})) {
                   4530:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4531:                                     $haschange = 1;
                   4532:                                 }
                   4533:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4534:                                 $haschange = 1;
                   4535:                             }
                   4536:                             $storekey = $altkey;
1.563     damieng  4537:                         } else {
1.576     raeburn  4538:                             if (exists($$olddata{$altkey})) {
                   4539:                                 if ($$olddata{$altkey} eq $data) {
                   4540:                                     $reconlychg = 1;
                   4541:                                 }
                   4542:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4543:                             } 
                   4544:                             if (exists($$olddata{$thiskey})) {
                   4545:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4546:                                     $haschange = 1;
                   4547:                                 }
                   4548:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4549:                                 $haschange = 1;
                   4550:                             }
                   4551:                             $storekey = $thiskey;
1.563     damieng  4552:                         }
1.560     damieng  4553:                     } else {
1.576     raeburn  4554:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4555:                             $haschange = 1;
                   4556:                             $storekey = $thiskey;
                   4557:                         }
                   4558:                     }
                   4559:                 }
                   4560:                 if ($reconlychg || $haschange) {
                   4561:                     unless ($env{'form.del_'.$thiskey}) {
                   4562:                         $newdata{$storekey}=$data;
                   4563:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4564:                     }
                   4565:                 }
                   4566:             } elsif ($cmd eq 'del') {
                   4567:                 if ($tuname) {
1.576     raeburn  4568:                     my $error;
                   4569:                     if ($altkey) {  
                   4570:                         if (exists($$olddata{$altkey})) {
                   4571:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4572:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4573:                                 if ($recursive) {
                   4574:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4575:                                 }
                   4576:                             } elsif ($recursive) {
                   4577:                                 $error = 1;
                   4578:                             }
                   4579:                         }
                   4580:                         if (exists($$olddata{$thiskey})) {
                   4581:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4582:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4583:                                 unless ($recursive) {
                   4584:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4585:                                 }
                   4586:                             } elsif (!$recursive) {
                   4587:                                 $error = 1;
                   4588:                             }
                   4589:                         }
1.560     damieng  4590:                     } else {
1.576     raeburn  4591:                         if (exists($$olddata{$thiskey})) {
                   4592:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4593:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4594:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4595:                             } else {
                   4596:                                 $error = 1;
                   4597:                             }
                   4598:                         }
                   4599:                     }
                   4600:                     if ($error) { 
1.560     damieng  4601:                         $r->print('<div class="LC_error">'.
                   4602:                             &mt('Error deleting parameters').'</div>');
                   4603:                     }
                   4604:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4605:                 } else {
1.576     raeburn  4606:                     if ($altkey) {
                   4607:                         if (exists($$olddata{$altkey})) {
                   4608:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4609:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4610:                             }
                   4611:                         }
                   4612:                         if (exists($$olddata{$thiskey})) {
                   4613:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4614:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4615:                             }
                   4616:                         }
                   4617:                     } elsif (exists($$olddata{$thiskey})) {
                   4618:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4619:                     }
1.560     damieng  4620:                 }
1.473     amueller 4621:             }
                   4622:         }
                   4623:     }
1.207     www      4624: # Store all course level
1.144     www      4625:     my $delentries=$#deldata+1;
1.576     raeburn  4626:     my @alldels;
                   4627:     if (@delrec) {
                   4628:         push(@alldels,@delrec);
                   4629:     }
                   4630:     if (@delnonrec) {
                   4631:         push(@alldels,@delnonrec);
                   4632:     }
                   4633:     if (@deldata) {
                   4634:         push(@alldels,@deldata);
                   4635:     }
1.548     raeburn  4636:     my @newdatakeys=keys(%newdata);
1.144     www      4637:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4638:     my ($delresult,$devalidate);
                   4639:     if (@alldels) {
                   4640:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4641:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4642:             &log_parmset(\%loghash,1);
1.576     raeburn  4643:             if ($delentries) {
                   4644:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4645:             }
                   4646:         } elsif ($delentries) {
1.560     damieng  4647:             $r->print('<div class="LC_error">'.
                   4648:                 &mt('Error deleting parameters').'</div>');
                   4649:         }
1.576     raeburn  4650:         $devalidate = 1; 
1.144     www      4651:     }
                   4652:     if ($putentries) {
1.560     damieng  4653:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4654:                     &log_parmset(\%newdata,0);
                   4655:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4656:         } else {
                   4657:             $r->print('<div class="LC_error">'.
                   4658:                 &mt('Error saving parameters').'</div>');
                   4659:         }
1.576     raeburn  4660:         $devalidate = 1; 
                   4661:     }
                   4662:     if ($devalidate) {
1.560     damieng  4663:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4664:     }
1.208     www      4665: }
1.207     www      4666: 
1.563     damieng  4667: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4668: #
                   4669: # @param {string} $key - the key
                   4670: # @returns {Array}
1.208     www      4671: sub extractuser {
                   4672:     my $key=shift;
1.350     albertel 4673:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4674: }
1.206     www      4675: 
1.563     damieng  4676: # Parses a parameter key and returns the components.
                   4677: #
                   4678: # @param {string} $key - 
                   4679: # @param {hash reference} $listdata - 
                   4680: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4681: sub parse_listdata_key {
                   4682:     my ($key,$listdata) = @_;
                   4683:     # split into student/section affected, and
                   4684:     # the realm (folder/resource part and parameter
1.446     bisitz   4685:     my ($student,$realm) =
1.473     amueller 4686:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4687:     # if course wide student would be undefined
                   4688:     if (!defined($student)) {
1.560     damieng  4689:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4690:     }
                   4691:     # strip off the .type if it's not the Question type parameter
                   4692:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4693:         $realm=~s/\.type//;
1.381     albertel 4694:     }
                   4695:     # split into resource+part and parameter name
1.388     albertel 4696:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4697:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4698:     return ($student,$res,$part,$parm);
                   4699: }
                   4700: 
1.563     damieng  4701: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4702: #
                   4703: # @param {Apache2::RequestRec} $r - the Apache request
                   4704: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4705: # @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
                   4706: # @param {string} $sortorder - realmstudent|studentrealm
                   4707: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4708: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4709: # @param {boolean} $readonly - true if editing not allowed
1.608     raeburn  4710: # @param {string} $parmlev - full|map
                   4711: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
                   4712: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4713: # @returns{integer} - number of $listdata parameters processed
1.208     www      4714: sub listdata {
1.608     raeburn  4715:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552     raeburn  4716:     
1.207     www      4717: # Start list output
1.206     www      4718: 
1.122     www      4719:     my $oldsection='';
                   4720:     my $oldrealm='';
                   4721:     my $oldpart='';
1.123     www      4722:     my $pointer=0;
1.124     www      4723:     $tableopen=0;
1.145     www      4724:     my $foundkeys=0;
1.248     albertel 4725:     my %keyorder=&standardkeyorder();
1.594     raeburn  4726:     my $readonlyall = $readonly;
1.381     albertel 4727: 
1.552     raeburn  4728:     my ($secidx,%grouphash);
                   4729:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4730:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4731:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4732:             %grouphash = &Apache::longroup::coursegroups();
                   4733:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4734:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4735:         }
1.552     raeburn  4736:     }
                   4737: 
1.576     raeburn  4738:     foreach my $key (sort {
1.560     damieng  4739:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4740:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608     raeburn  4741:         my ($aid,$bid);
                   4742:         if ($caller eq 'newoverview') {
                   4743:             if (ref($hash_for_realm) eq 'HASH') {
                   4744:                 if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4745:                     my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4746:                     my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4747:                     $aid = $hash_for_realm->{$aurl};
                   4748:                     $bid = $hash_for_realm->{$burl};
                   4749:                 } elsif ($parmlev eq 'full') {
                   4750:                     $aid = $hash_for_realm->{$ares};
                   4751:                     $bid = $hash_for_realm->{$bres};
                   4752:                 }
                   4753:             }
                   4754:         }
1.381     albertel 4755: 
1.560     damieng  4756:         # get the numerical order for the param
                   4757:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4758:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4759: 
1.560     damieng  4760:         my $result=0;
1.381     albertel 4761: 
1.560     damieng  4762:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4763:             if ($ares     ne $bres    ) {
1.608     raeburn  4764:                 if ($caller eq 'newoverview') {
                   4765:                     if (ref($hash_for_realm) eq 'HASH') {
                   4766:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4767:                             $result = ($aid <=> $bid);
                   4768:                         } elsif ($parmlev eq 'full') {
                   4769:                             $result = ($aid <=> $bid);
                   4770:                         } else {
                   4771:                             $result = ($ares cmp $bres);
                   4772:                         }
                   4773:                     } else {
                   4774:                         $result = ($ares cmp $bres);
                   4775:                     }
                   4776:                 } else {
                   4777:                     $result = ($ares cmp $bres);
                   4778:                 }
1.446     bisitz   4779:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4780:                 $result = ($astudent cmp $bstudent);
                   4781:             } elsif ($apart    ne $bpart   ) {
                   4782:                 $result = ($apart    cmp $bpart);
                   4783:             }
                   4784:         } else {
                   4785:             if      ($astudent ne $bstudent) {
                   4786:                 $result = ($astudent cmp $bstudent);
                   4787:             } elsif ($ares     ne $bres    ) {
1.608     raeburn  4788:                 if ($caller eq 'newoverview') {
                   4789:                     if (ref($hash_for_realm) eq 'HASH') {
                   4790:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4791:                             $result = ($aid <=> $bid);
                   4792:                         } elsif ($parmlev eq 'full') {
                   4793:                             $result = ($aid <=> $bid);
                   4794:                         } else {
                   4795:                             $result = ($ares cmp $bres);
                   4796:                         }
                   4797:                     } else {
                   4798:                         $result = ($ares cmp $bres);
                   4799:                     }
                   4800:                 } else {
                   4801:                     $result = ($ares cmp $bres);
                   4802:                 }
1.560     damieng  4803:             } elsif ($apart    ne $bpart   ) {
                   4804:                 $result = ($apart    cmp $bpart);
                   4805:             }
1.473     amueller 4806:         }
1.446     bisitz   4807: 
1.560     damieng  4808:         if (!$result) {
1.381     albertel 4809:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4810:                 $result = ($aparm <=> $bparm);
1.381     albertel 4811:             } elsif (defined($aparm)) {
1.560     damieng  4812:                 $result = -1;
1.381     albertel 4813:             } elsif (defined($bparm)) {
1.560     damieng  4814:                 $result = 1;
                   4815:             }
1.473     amueller 4816:         }
1.381     albertel 4817: 
1.560     damieng  4818:         $result;
                   4819:         
1.576     raeburn  4820:     } keys(%{$listdata})) { # foreach my $key
                   4821:         my $thiskey = $key;
1.560     damieng  4822:         if ($$listdata{$thiskey.'.type'}) {
                   4823:             my $thistype=$$listdata{$thiskey.'.type'};
                   4824:             if ($$resourcedata{$thiskey.'.type'}) {
                   4825:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4826:             }
                   4827:             my ($middle,$part,$name)=
1.572     damieng  4828:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4829:             my $section=&mt('All Students');
1.594     raeburn  4830:             $readonly = $readonlyall;
1.599     raeburn  4831:             my $userscope;
1.576     raeburn  4832:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4833:             if ($middle=~/^\[(.*)\]/) {
                   4834:                 my $issection=$1;
                   4835:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4836:                     my ($stuname,$studom) = ($1,$2);
                   4837:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4838:                         if (ref($classlist) eq 'HASH') {
                   4839:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4840:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4841:                             }
                   4842:                         }
                   4843:                     }
                   4844:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4845:                     $userscope = 1;
1.560     damieng  4846:                 } else {
                   4847:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4848:                         if (exists($grouphash{$issection})) {
                   4849:                             $section=&mt('Group').': '.$issection;
                   4850:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4851:                             $section = &mt('Section').': '.$issection;
                   4852:                         } else {
                   4853:                             next; 
1.552     raeburn  4854:                         }
1.560     damieng  4855:                     } else {
                   4856:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4857:                     }
                   4858:                 }
1.560     damieng  4859:                 $middle=~s/^\[(.*)\]//;
                   4860:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4861:                 $readonly = 1;
                   4862:             }
                   4863:             $middle=~s/\.+$//;
                   4864:             $middle=~s/^\.+//;
                   4865:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4866:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4867:             if ($caller eq 'overview') {
                   4868:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4869:                     $mapurl = $1;
                   4870:                     $maplevel = $2;
                   4871:                     $is_map = 1;
                   4872:                 }
                   4873:             } elsif ($caller eq 'newoverview') {
                   4874:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4875:                     $mapurl = $1;
                   4876:                     $maplevel = $2;
                   4877:                     $is_map = 1;
                   4878:                 }
                   4879:             }
                   4880:             if ($is_map) {
1.560     damieng  4881:                 my $leveltitle = &mt('Folder/Map');
1.608     raeburn  4882:                 my $title = &Apache::lonnet::gettitle($1);
                   4883:                 if (ref($hash_for_realm) eq 'HASH') {
                   4884:                     if ($hash_for_realm->{$mapurl} eq '1') {
                   4885:                         $title = &mt('Main Content');
                   4886:                     }
                   4887:                 }
1.576     raeburn  4888:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4889:                     if ($caller eq 'newoverview') {
                   4890:                         my $altkey = $thiskey;
                   4891:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4892:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4893:                             $is_recursive = 1;
                   4894:                             if ($$resourcedata{$altkey.'.type'}) {
                   4895:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4896:                             }
                   4897:                             $showval = $$resourcedata{$altkey};
                   4898:                         }
                   4899:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4900:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4901:                         $is_recursive = 1;
                   4902:                     }
1.560     damieng  4903:                 }
1.608     raeburn  4904:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560     damieng  4905:             } elsif ($middle) {
                   4906:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609     raeburn  4907:                 next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560     damieng  4908:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4909:                     ': '.&Apache::lonnet::gettitle($middle).
                   4910:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4911:                     $id.')</span></span>';
                   4912:             }
                   4913:             if ($sortorder eq 'realmstudent') {
                   4914:                 if ($realm ne $oldrealm) {
                   4915:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4916:                     $oldrealm=$realm;
                   4917:                     $oldsection='';
                   4918:                 }
                   4919:                 if ($section ne $oldsection) {
                   4920:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4921:                     $oldsection=$section;
                   4922:                     $oldpart='';
                   4923:                 }
1.552     raeburn  4924:             } else {
1.560     damieng  4925:                 if ($section ne $oldsection) {
                   4926:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4927:                     $oldsection=$section;
                   4928:                     $oldrealm='';
                   4929:                 }
                   4930:                 if ($realm ne $oldrealm) {
                   4931:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4932:                     $oldrealm=$realm;
                   4933:                     $oldpart='';
1.552     raeburn  4934:                 }
                   4935:             }
1.560     damieng  4936:             if ($part ne $oldpart) {
                   4937:                 $r->print(&tableend().
                   4938:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4939:                 $oldpart=$part;
1.556     raeburn  4940:             }
1.560     damieng  4941:     #
                   4942:     # Ready to print
                   4943:     #
1.470     raeburn  4944:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  4945:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  4946:                 &Apache::loncommon::start_data_table_row().
                   4947:                 '<td><b>'.&mt($parmitem).
                   4948:                 '</b></td>');
                   4949:             unless ($readonly) {
1.599     raeburn  4950:                 my $disabled;
                   4951:                 if (($name eq 'availablestudent') &&
                   4952:                     (($showval eq '') || ($userscope))) {
                   4953:                     $disabled = ' disabled="disabled"';
                   4954:                 }
1.560     damieng  4955:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  4956:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  4957:             }
                   4958:             $r->print('<td>');
                   4959:             $foundkeys++;
                   4960:             if (&isdateparm($thistype)) {
                   4961:                 my $jskey='key_'.$pointer;
                   4962:                 my $state;
                   4963:                 $pointer++;
                   4964:                 if ($readonly) {
                   4965:                     $state = 'disabled';
                   4966:                 }
                   4967:                 $r->print(
                   4968:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4969:                                                         $jskey,
1.576     raeburn  4970:                                                         $showval,
1.560     damieng  4971:                                                         '',1,$state));
                   4972:                 unless  ($readonly) {
                   4973:                     $r->print(
                   4974:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  4975:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  4976:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  4977:     &date_sanity_info($showval)
1.560     damieng  4978:                     );
                   4979:                 }
                   4980:             } elsif ($thistype eq 'date_interval') {
                   4981:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  4982:                           $showval,$readonly));
1.560     damieng  4983:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  4984:                 if ($name eq 'availablestudent') {
                   4985:                     $readonly = 1;
                   4986:                 }
1.560     damieng  4987:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  4988:                           $showval,$name,$readonly));
1.560     damieng  4989:             } else {
1.576     raeburn  4990:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  4991:             }
1.560     damieng  4992:             unless ($readonly) {
                   4993:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   4994:                         $thistype.'" />');
1.552     raeburn  4995:             }
1.576     raeburn  4996:             $r->print('</td>');
                   4997:             if ($is_map) {
                   4998:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   4999:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   5000:                 } else {
                   5001:                     my ($disabled,$recon,$recoff);
                   5002:                     if ($readonly) {
                   5003:                         $disabled = ' disabled="disabled"';
                   5004:                     }
                   5005:                     if ($is_recursive) {
                   5006:                         $recon = ' checked="checked"';
                   5007:                     } else {
                   5008:                         $recoff = ' checked="checked"';
                   5009:                     }
                   5010:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   5011:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   5012:                 }
                   5013:             }
                   5014:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 5015:         }
1.121     www      5016:     }
1.208     www      5017:     return $foundkeys;
                   5018: }
                   5019: 
1.563     damieng  5020: # Returns a string representing the interval, directly using form data matching the given key.
                   5021: # The returned string may also include information related to proctored exams.
                   5022: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   5023: #
                   5024: # @param {string} $key - suffix for form fields related to the interval
                   5025: # @returns {string}
1.385     albertel 5026: sub get_date_interval_from_form {
                   5027:     my ($key) = @_;
                   5028:     my $seconds = 0;
                   5029:     foreach my $which (['days', 86400],
1.473     amueller 5030:                ['hours', 3600],
                   5031:                ['minutes', 60],
                   5032:                ['seconds',  1]) {
1.560     damieng  5033:         my ($name, $factor) = @{ $which };
                   5034:         if (defined($env{'form.'.$name.'_'.$key})) {
                   5035:             $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   5036:         }
1.473     amueller 5037:     }
1.560     damieng  5038:     if (($key =~ /\.interval$/) &&
                   5039:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  5040:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   5041:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   5042:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   5043:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   5044:                 $seconds .= '_proctor';
                   5045:             }
                   5046:         } else {
                   5047:             $seconds .= $env{'form.done_'.$key}; 
                   5048:         }
                   5049:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  5050:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  5051:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   5052:         }
1.554     raeburn  5053:     }
1.385     albertel 5054:     return $seconds;
                   5055: }
                   5056: 
                   5057: 
1.563     damieng  5058: # Returns HTML to enter a text value for a parameter.
                   5059: #
                   5060: # @param {string} $thiskey - parameter key
                   5061: # @param {string} $showval - the current value
                   5062: # @param {boolean} $readonly - true if the field should not be made editable
                   5063: # @returns {string}
1.383     albertel 5064: sub default_selector {
1.552     raeburn  5065:     my ($thiskey, $showval, $readonly) = @_;
                   5066:     my $disabled;
                   5067:     if ($readonly) {
                   5068:         $disabled = ' disabled="disabled"';
                   5069:     }
                   5070:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 5071: }
                   5072: 
1.563     damieng  5073: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5074: #
                   5075: # @param {string} $thiskey - parameter key
                   5076: # @param {string} $showval - the current value
                   5077: # @param {boolean} $readonly - true if the fields should not be made editable
                   5078: # @returns {string}
1.549     raeburn  5079: sub string_ip_selector {
1.552     raeburn  5080:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5081:     my %access = (
                   5082:                    allow => [],
                   5083:                    deny  => [],
                   5084:                  );
                   5085:     if ($showval ne '') {
                   5086:         my @current;
                   5087:         if ($showval =~ /,/) {
                   5088:             @current = split(/,/,$showval);
                   5089:         } else {
                   5090:             @current = ($showval);
                   5091:         }
                   5092:         foreach my $item (@current) {
                   5093:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5094:                 push(@{$access{'deny'}},$1);
                   5095:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5096:                 push(@{$access{'allow'}},$item);
                   5097:             }
                   5098:         }
                   5099:     }
                   5100:     if (!@{$access{'allow'}}) {
                   5101:         @{$access{'allow'}} = ('');
                   5102:     }
                   5103:     if (!@{$access{'deny'}}) {
                   5104:         @{$access{'deny'}} = ('');
                   5105:     }
1.552     raeburn  5106:     my ($disabled,$addmore);
1.567     raeburn  5107:     if ($readonly) {
1.552     raeburn  5108:         $disabled=' disabled="disabled"';
                   5109:     } else {
                   5110:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5111:     }
1.549     raeburn  5112:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5113: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5114:     foreach my $acctype ('allow','deny') {
                   5115:         $output .= '
                   5116: <td valign="top">
                   5117: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5118:   <div class="LC_string_ipacc_inner">'."\n";
                   5119:         my $num = 0;
                   5120:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5121:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5122:             if ($num > 0) {
                   5123:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5124:             }
                   5125:             $output .= '</div>'."\n";
                   5126:             $num ++;
                   5127:         }
                   5128:         $output .= '
1.552     raeburn  5129:   </div>'.$addmore.'
1.549     raeburn  5130: </div>
                   5131: </td>';
                   5132:    }
                   5133:    $output .= '
                   5134: </tr>
                   5135: </table>'."\n";
                   5136:     return $output;
                   5137: }
                   5138: 
1.588     raeburn  5139: sub string_deeplink_selector {
                   5140:     my ($thiskey, $showval, $readonly) = @_;
1.597     raeburn  5141:     my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601     raeburn  5142:         %selectnull,%domlti,%crslti,@possmenus);
                   5143:     @components = ('state','others','listing','scope','protect','menus');
1.588     raeburn  5144:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5145:                   state   => 'Access status',
                   5146:                   others  => 'Hide other resources',
1.588     raeburn  5147:                   listing => 'In Contents and/or Gradebook',
                   5148:                   scope   => 'Access scope for link',
1.601     raeburn  5149:                   protect => 'Link protection',
1.597     raeburn  5150:                   menus   => 'Menu Items Displayed',
1.588     raeburn  5151:               );
                   5152:     %options = (
1.601     raeburn  5153:                    state   => ['only','off','both'],
                   5154:                    others  => ['hide','unhide'],
1.588     raeburn  5155:                    listing => ['full','absent','grades','details','datestatus'],
                   5156:                    scope   => ['res','map','rec'],
1.601     raeburn  5157:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5158:                    menus   => ['std','colls'],
1.588     raeburn  5159:                );
                   5160:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5161:                     only       => 'deep only',
                   5162:                     off        => 'deeplink off',
                   5163:                     both       => 'regular + deep',
                   5164:                     hide       => 'Hidden',
                   5165:                     unhide     => 'Unhidden',
1.588     raeburn  5166:                     full       => 'Listed (linked) in both',
                   5167:                     absent     => 'Not listed',
                   5168:                     grades     => 'Listed in grades only',
                   5169:                     details    => 'Listed (unlinked) in both',
                   5170:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5171:                     res        => 'resource only',
                   5172:                     map        => 'enclosing map/folder',
                   5173:                     rec        => 'recursive map/folder',
1.601     raeburn  5174:                     none       => 'not in use',
                   5175:                     key        => 'key access',
                   5176:                     ltic       => 'LTI access (course)',
                   5177:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5178:                     std        => 'Standard (all menus)',
                   5179:                     colls      => 'Numbered collection',
                   5180:                   );
                   5181:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5182:                     ltic => 'Select Launcher',
                   5183:                     ltid => 'Select Launcher', 
1.597     raeburn  5184:                     colls => 'Select',
1.588     raeburn  5185:                   );
                   5186:     if ($showval =~ /,/) {
1.597     raeburn  5187:         %values=();
1.588     raeburn  5188:         @current = split(/,/,$showval);
1.601     raeburn  5189:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5190:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5191:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5192:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5193:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5194:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.588     raeburn  5195:     } else {
1.601     raeburn  5196:         $defaults{'state'} = 'off',
                   5197:         $defaults{'others'} = 'unhide',
1.588     raeburn  5198:         $defaults{'listing'} = 'full';
                   5199:         $defaults{'scope'} = 'res';
1.601     raeburn  5200:         $defaults{'protect'} = 'none';
1.597     raeburn  5201:         $defaults{'menus'} = '0';
1.588     raeburn  5202:     }
                   5203:     my $disabled;
                   5204:     if ($readonly) {
                   5205:         $disabled=' disabled="disabled"';
                   5206:     }
1.601     raeburn  5207:     my %courselti =
                   5208:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5209:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5210:     foreach my $item (keys(%courselti)) {
                   5211:         if (ref($courselti{$item}) eq 'HASH') {
                   5212:             $crslti{$item} = $courselti{$item}{'name'};
                   5213:         }
                   5214:     }
                   5215:     my %lti =
1.588     raeburn  5216:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5217:                                         'linkprot');
1.588     raeburn  5218:     foreach my $item (keys(%lti)) {
1.604     raeburn  5219:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5220:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5221:         }
                   5222:     }
1.597     raeburn  5223:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5224:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5225:             my ($num,$value) = split(/\%/,$item);
                   5226:             if ($num =~ /^\d+$/) {
                   5227:                 push(@possmenus,$num);
                   5228:             }
                   5229:         }
                   5230:     }
                   5231: 
1.588     raeburn  5232:     my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597     raeburn  5233:     foreach my $item (@components) {
1.588     raeburn  5234:         $output .= '<th>'.$titles{$item}.'</th>';
                   5235:     }
                   5236:     $output .= '</tr><tr>';
                   5237:     foreach my $item (@components) {
                   5238:         $output .= '<td>';
1.601     raeburn  5239:         if (($item eq 'protect') || ($item eq 'menus')) {
1.588     raeburn  5240:             my $selected = $values{$item};
                   5241:             foreach my $option (@{$options{$item}}) {
1.601     raeburn  5242:                 if ($item eq 'protect') { 
                   5243:                     if ($option eq 'ltid') {
                   5244:                         next unless (keys(%domlti));
                   5245:                     } elsif ($option eq 'ltic') {
                   5246:                         next unless (keys(%crslti));
                   5247:                     }
1.597     raeburn  5248:                 } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5249:                     next unless (@possmenus);
1.588     raeburn  5250:                 }
                   5251:                 my $checked;
1.597     raeburn  5252:                 if ($item eq 'menus') {
                   5253:                     if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5254:                         (grep(/^\Q$selected\E$/,@possmenus))) {
                   5255:                         if ($option eq 'colls') {
                   5256:                             $checked = ' checked="checked"';
                   5257:                         }
                   5258:                     } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
                   5259:                         $checked = ' checked="checked"';
                   5260:                     }
                   5261:                 } elsif ($selected =~ /^\Q$option\E/) {
1.588     raeburn  5262:                     $checked = ' checked="checked"';
                   5263:                 }
                   5264:                 my $onclick;
                   5265:                 unless ($readonly) {
                   5266:                     my $esc_key = &js_escape($thiskey);
                   5267:                     $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5268:                 }
                   5269:                 $output .= '<span class="LC_nobreak"><label>'.
                   5270:                            '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5271:                            $optiontext{$option}.'</label>';
1.601     raeburn  5272:                 if (($item eq 'protect') && ($option eq 'key')) {
1.588     raeburn  5273:                     my $visibility="hidden";
                   5274:                     my $currkey;
                   5275:                     if ($checked) {
                   5276:                         $visibility = "text";
                   5277:                         $currkey = (split(/\:/,$values{$item}))[1];
                   5278:                     }
                   5279:                     $output .= '&nbsp;'.
1.597     raeburn  5280:                         '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601     raeburn  5281:                 } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588     raeburn  5282:                     my $display="none";
1.597     raeburn  5283:                     my ($current,$blankcheck,@possibles);
1.588     raeburn  5284:                     if ($checked) {
                   5285:                         $display = 'inline-block';
1.601     raeburn  5286:                         if (($option eq 'ltic') || ($option eq 'ltid'))  {
1.597     raeburn  5287:                             $current = (split(/\:/,$selected))[1];
                   5288:                         } else {
                   5289:                             $current = $selected;
                   5290:                         }
1.588     raeburn  5291:                     } else {
                   5292:                         $blankcheck = ' selected="selected"';
                   5293:                     }
1.601     raeburn  5294:                     if ($option eq 'ltid') {
                   5295:                         @possibles = keys(%domlti);
                   5296:                     } elsif ($option eq 'ltic') {
                   5297:                         @possibles = keys(%crslti); 
1.597     raeburn  5298:                     } else {
                   5299:                         @possibles = @possmenus;
                   5300:                     }
1.588     raeburn  5301:                     $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5302:                                ' style="display: '.$display.'">&nbsp;<select name="'.
1.597     raeburn  5303:                                'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5304:                     if (@possibles > 1) {
                   5305:                         $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5306:                                    '</option>'."\n";
                   5307:                     }
                   5308:                     foreach my $poss (sort { $a <=> $b } @possibles) {
1.588     raeburn  5309:                         my $selected;
1.597     raeburn  5310:                         if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588     raeburn  5311:                             $selected = ' selected="selected"';
                   5312:                         }
1.597     raeburn  5313:                         my $shown = $poss;
1.601     raeburn  5314:                         if ($option eq 'ltid') {
                   5315:                             $shown = $domlti{$poss};
                   5316:                         } elsif ($option eq 'ltic') {
                   5317:                             $shown = $crslti{$poss};
1.597     raeburn  5318:                         }
                   5319:                         $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588     raeburn  5320:                     }
                   5321:                     $output .= '</select></div>';
                   5322:                 }
                   5323:                 $output .= '</span> ';
                   5324:             }
                   5325:         } else {
                   5326:             my $selected = $values{$item};
                   5327:             my $defsel;
                   5328:             if ($selected eq '') {
                   5329:                 $defsel = ' selected="selected"';
                   5330:             }
                   5331:             $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5332:                        '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5333:             foreach my $option (@{$options{$item}}) {
                   5334:                 $output .= '<option value="'.$option.'"';
                   5335:                 if ($option eq $selected) {
                   5336:                     $output .= ' selected="selected"';
                   5337:                 }
                   5338:                 $output .= '>'.$optiontext{$option}.'</option>';
                   5339:             }
                   5340:             $output .= '</select>';
                   5341:         }
                   5342:         $output .= '</td>';
                   5343:     }
                   5344:     $output .= '</tr></table>'."\n";
                   5345:     return $output;
                   5346: }
                   5347: 
1.560     damieng  5348: 
                   5349: { # block using some constants related to parameter types (overview mode)
                   5350: 
1.446     bisitz   5351: my %strings =
1.383     albertel 5352:     (
                   5353:      'string_yesno'
                   5354:              => [[ 'yes', 'Yes' ],
1.560     damieng  5355:                  [ 'no', 'No' ]],
1.383     albertel 5356:      'string_problemstatus'
                   5357:              => [[ 'yes', 'Yes' ],
1.473     amueller 5358:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5359:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5360:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5361:      'string_questiontype'
                   5362:              => [[ 'problem', 'Standard Problem'],
                   5363:                  [ 'survey', 'Survey'],
                   5364:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5365:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5366:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5367:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5368:                  [ 'practice', 'Practice'],
                   5369:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5370:      'string_lenient'
                   5371:              => [['yes', 'Yes' ],
                   5372:                  [ 'no', 'No' ],
1.549     raeburn  5373:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5374:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5375:      'string_discussvote'
                   5376:              => [['yes','Yes'],
                   5377:                  ['notended','Yes, unless discussion ended'],
                   5378:                  ['no','No']],
1.549     raeburn  5379:      'string_ip'
                   5380:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5381:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5382:      'string_deeplink'
1.597     raeburn  5383:              => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
1.587     raeburn  5384:     );
                   5385:    
1.383     albertel 5386: 
1.549     raeburn  5387: my %stringmatches = (
                   5388:          'string_lenient'
                   5389:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5390:          'string_ip'
                   5391:               => [['_allowfrom_','[^\!]+'],
                   5392:                   ['_denyfrom_','\!']],
1.588     raeburn  5393:          'string_deeplink'
1.602     raeburn  5394:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)$']],
1.549     raeburn  5395:     );
                   5396: 
                   5397: my %stringtypes = (
                   5398:                     type         => 'string_questiontype',
                   5399:                     lenient      => 'string_lenient',
                   5400:                     retrypartial => 'string_yesno',
                   5401:                     discussvote  => 'string_discussvote',
                   5402:                     examcode     => 'string_examcode',
                   5403:                     acc          => 'string_ip',
1.587     raeburn  5404:                     deeplink     => 'string_deeplink',
1.549     raeburn  5405:                   );
                   5406: 
1.563     damieng  5407: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5408: # Used by courseprefs.
                   5409: #
                   5410: # @param {string} $string_type - a parameter type for strings
                   5411: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5412: sub standard_string_options {
                   5413:     my ($string_type) = @_;
                   5414:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5415:         return $strings{$string_type};
                   5416:     }
                   5417:     return;
                   5418: }
1.383     albertel 5419: 
1.563     damieng  5420: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5421: #
                   5422: # @param {string} $string_type - a parameter type for strings
                   5423: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5424: sub standard_string_matches {
                   5425:     my ($string_type) = @_;
                   5426:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5427:         return $stringmatches{$string_type};
                   5428:     }
                   5429:     return;
                   5430: }
                   5431: 
1.563     damieng  5432: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5433: #
                   5434: # @param {string} $name - parameter name
                   5435: # @returns {string}
1.549     raeburn  5436: sub get_stringtype {
                   5437:     my ($name) = @_;
                   5438:     if (exists($stringtypes{$name})) {
                   5439:         return $stringtypes{$name};
                   5440:     }
                   5441:     return;
                   5442: }
                   5443: 
1.563     damieng  5444: # Returns HTML to edit a string parameter.
                   5445: #
                   5446: # @param {string} $thistype - parameter type
                   5447: # @param {string} $thiskey - parameter key
                   5448: # @param {string} $showval - parameter current value
                   5449: # @param {string} $name - parameter name
                   5450: # @param {boolean} $readonly - true if the values should not be made editable
                   5451: # @returns {string}
1.383     albertel 5452: sub string_selector {
1.552     raeburn  5453:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5454: 
1.383     albertel 5455:     if (!exists($strings{$thistype})) {
1.552     raeburn  5456:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5457:     }
                   5458: 
1.504     raeburn  5459:     my %skiptype;
1.514     raeburn  5460:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5461:             ($thistype eq 'string_lenient') ||
                   5462:             ($thistype eq 'string_discussvote') ||
                   5463:             ($thistype eq 'string_ip') ||
1.588     raeburn  5464:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5465:             ($name eq 'retrypartial')) {
1.504     raeburn  5466:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5467:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5468:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5469:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5470:             my $parmmatch;
                   5471:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5472:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5473:                     if (ref($item) eq 'ARRAY') {
                   5474:                         if ($parmval eq $item->[0]) {
                   5475:                             $parmmatch = $parmval;
                   5476:                             $parmval = '';
                   5477:                             last;
                   5478:                         }
                   5479:                     }
                   5480:                 }
                   5481:             }
                   5482:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5483:             if ($needsrelease) {
                   5484:                 unless ($got_chostname) {
1.514     raeburn  5485:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5486:                     $got_chostname = 1;
                   5487:                 }
1.557     raeburn  5488:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5489:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5490:                 if ($needsnewer) {
1.549     raeburn  5491:                     if ($parmmatch ne '') {
                   5492:                         $skiptype{$parmmatch} = 1;
                   5493:                     } elsif ($parmval ne '') {
                   5494:                         $skiptype{$parmval} = 1;
                   5495:                     }
1.504     raeburn  5496:                 }
                   5497:             }
                   5498:         }
                   5499:     }
1.549     raeburn  5500: 
                   5501:     if ($thistype eq 'string_ip') {
1.552     raeburn  5502:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5503:     } elsif ($thistype eq 'string_deeplink') {
                   5504:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5505:     }
1.504     raeburn  5506: 
1.552     raeburn  5507:     my ($result,$disabled);
                   5508: 
                   5509:     if ($readonly) {
                   5510:         $disabled = ' disabled="disabled"';
                   5511:     }
1.504     raeburn  5512:     my $numinrow = 3;
                   5513:     if ($thistype eq 'string_problemstatus') {
                   5514:         $numinrow = 2;
                   5515:     } elsif ($thistype eq 'string_questiontype') {
                   5516:         if (keys(%skiptype) > 0) {
                   5517:              $numinrow = 4;
                   5518:         }
                   5519:     }
                   5520:     my $rem;
                   5521:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5522:         my $i=0;
                   5523:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5524:             next unless (ref($possibilities) eq 'ARRAY');
                   5525:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5526:             next if ($skiptype{$name});
1.504     raeburn  5527:             $rem = $i%($numinrow);
                   5528:             if ($rem == 0) {
                   5529:                 if ($i > 0) {
                   5530:                     $result .= '</tr>';
                   5531:                 }
                   5532:                 $result .= '<tr>';
                   5533:             }
1.549     raeburn  5534:             my $colspan;
                   5535:             if ($i == @{ $strings{$thistype} }-1) {
                   5536:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5537:                 if ($rem) {
                   5538:                     my $colsleft = $numinrow - $rem;
                   5539:                     if ($colsleft) {
                   5540:                         $colspan = $colsleft+1;
                   5541:                         $colspan = ' colspan="'.$colspan.'"';
                   5542:                     }
                   5543:                 }
                   5544:             }
                   5545:             my ($add,$onchange,$css_class);
                   5546:             if ($thistype eq 'string_lenient') {
                   5547:                 if ($name eq 'weighted') {
                   5548:                     my $display;
                   5549:                     my %relatives = &Apache::lonlocal::texthash(
                   5550:                                         corrchkd     => 'Correct (checked)',
                   5551:                                         corrunchkd   => 'Correct (unchecked)',
                   5552:                                         incorrchkd   => 'Incorrect (checked)',
                   5553:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5554:                     );
                   5555:                     my %textval = (
                   5556:                                     corrchkd     => '1.0',
                   5557:                                     corrunchkd   => '1.0',
                   5558:                                     incorrchkd   => '0.0',
                   5559:                                     incorrunchkd => '0.0',
                   5560:                     );
                   5561:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5562:                         $textval{'corrchkd'} = $1;
                   5563:                         $textval{'corrunchkd'} = $2;
                   5564:                         $textval{'incorrchkd'} = $3;
                   5565:                         $textval{'incorrunchkd'} = $4;
                   5566:                         $display = 'inline';
                   5567:                         $showval = $name;
                   5568:                     } else {
                   5569:                         $display = 'none';
                   5570:                     }
                   5571:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5572:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5573:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5574:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5575:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5576:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5577:                                 '</td></tr>';
                   5578:                     }
                   5579:                     $add .= '</table></div>'."\n";
                   5580:                 }
                   5581:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5582:                 $css_class = ' class="LC_lenient_radio"';
                   5583:             }
                   5584:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5585:                        '<span class="LC_nobreak"><label>'.
                   5586:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5587:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5588:             if ($showval eq $name) {
                   5589:                 $result .= ' checked="checked"';
                   5590:             }
1.549     raeburn  5591:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5592:             $i++;
                   5593:         }
                   5594:         $result .= '</tr>';
1.473     amueller 5595:     }
1.504     raeburn  5596:     if ($result) {
                   5597:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5598:     }
                   5599:     return $result;
                   5600: }
                   5601: 
1.554     raeburn  5602: my %intervals =
                   5603:     (
                   5604:      'date_interval'
                   5605:              => [[ 'done', 'Yes' ],
1.558     raeburn  5606:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5607:                  [ '', 'No' ]],
                   5608:     );
                   5609: 
                   5610: my %intervalmatches = (
                   5611:          'date_interval'
1.559     raeburn  5612:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5613:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5614:     );
                   5615: 
                   5616: my %intervaltypes = (
                   5617:                       interval => 'date_interval',
                   5618:     );
                   5619: 
1.563     damieng  5620: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5621: #
                   5622: # @param {string} $interval_type - a parameter type for intervals
                   5623: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5624: sub standard_interval_matches {
                   5625:     my ($interval_type) = @_;
                   5626:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5627:         return $intervalmatches{$interval_type};
                   5628:     }
                   5629:     return;
                   5630: }
                   5631: 
1.563     damieng  5632: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5633: #
                   5634: # @param {string} $name - parameter name
                   5635: # @returns {string}
1.554     raeburn  5636: sub get_intervaltype {
                   5637:     my ($name) = @_;
                   5638:     if (exists($intervaltypes{$name})) {
                   5639:         return $intervaltypes{$name};
                   5640:     }
                   5641:     return;
                   5642: }
                   5643: 
1.563     damieng  5644: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5645: # Used by courseprefs.
                   5646: #
                   5647: # @param {string} $interval_type - a parameter type for intervals
                   5648: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5649: sub standard_interval_options {
                   5650:     my ($interval_type) = @_;
                   5651:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5652:         return $intervals{$interval_type};
                   5653:     }
                   5654:     return;
                   5655: }
                   5656: 
1.563     damieng  5657: # Returns HTML to edit a date interval parameter.
                   5658: #
                   5659: # @param {string} $thiskey - parameter key
                   5660: # @param {string} $name - parameter name
                   5661: # @param {string} $showval - parameter current value
                   5662: # @param {boolean} $readonly - true if the values should not be made editable
                   5663: # @returns {string}
1.554     raeburn  5664: sub date_interval_selector {
                   5665:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5666:     my ($result,%skipval);
                   5667:     if ($name eq 'interval') {
                   5668:         my $intervaltype = &get_intervaltype($name);
                   5669:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5670:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5671:             next unless (ref($possibilities) eq 'ARRAY');
                   5672:             my ($parmval, $description) = @{ $possibilities };
                   5673:             my $parmmatch;
                   5674:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5675:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5676:                     if (ref($item) eq 'ARRAY') {
                   5677:                         if ($parmval eq $item->[0]) {
                   5678:                             $parmmatch = $parmval;
                   5679:                             $parmval = '';
                   5680:                             last;
                   5681:                         }
                   5682:                     }
                   5683:                 }
                   5684:             }
                   5685:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5686:             if ($needsrelease) {
                   5687:                 unless ($got_chostname) {
                   5688:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5689:                     $got_chostname = 1;
                   5690:                 }
1.557     raeburn  5691:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5692:                                                        $needsrelease,$cmajor,$cminor);
                   5693:                 if ($needsnewer) {
                   5694:                     if ($parmmatch ne '') {
                   5695:                         $skipval{$parmmatch} = 1;
                   5696:                     } elsif ($parmval ne '') {
                   5697:                         $skipval{$parmval} = 1;
                   5698:                     }
                   5699:                 }
                   5700:             }
                   5701:         }
                   5702:     }
                   5703: 
                   5704:     my $currval = $showval;
                   5705:     foreach my $which (['days', 86400, 31],
                   5706:                ['hours', 3600, 23],
                   5707:                ['minutes', 60, 59],
                   5708:                ['seconds',  1, 59]) {
1.560     damieng  5709:         my ($name, $factor, $max) = @{ $which };
                   5710:         my $amount = int($showval/$factor);
                   5711:         $showval  %= $factor;
                   5712:         my %select = ((map {$_ => $_} (0..$max)),
                   5713:                 'select_form_order' => [0..$max]);
                   5714:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5715:                             \%select,'',$readonly);
                   5716:         $result .= ' '.&mt($name);
1.554     raeburn  5717:     }
                   5718:     if ($name eq 'interval') {
                   5719:         unless ($skipval{'done'}) {
                   5720:             my $checkedon = '';
1.558     raeburn  5721:             my $checkedproc = '';
                   5722:             my $currproctorkey = '';
                   5723:             my $currprocdisplay = 'hidden';
1.559     raeburn  5724:             my $currdonetext = &mt('Done');
1.554     raeburn  5725:             my $checkedoff = ' checked="checked"';
1.559     raeburn  5726:             if ($currval =~ /^(?:\d+)_done$/) {
                   5727:                 $checkedon = ' checked="checked"';
                   5728:                 $checkedoff = '';
                   5729:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5730:                 $currdonetext = $1;
1.554     raeburn  5731:                 $checkedon = ' checked="checked"';
                   5732:                 $checkedoff = '';
1.558     raeburn  5733:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5734:                 $currproctorkey = $1;
                   5735:                 $checkedproc = ' checked="checked"';
                   5736:                 $checkedoff = '';
                   5737:                 $currprocdisplay = 'text';
1.559     raeburn  5738:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5739:                 $currdonetext = $1;
                   5740:                 $currproctorkey = $2;
                   5741:                 $checkedproc = ' checked="checked"';
                   5742:                 $checkedoff = '';
                   5743:                 $currprocdisplay = 'text';
1.554     raeburn  5744:             }
1.558     raeburn  5745:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5746:             my $disabled;
                   5747:             if ($readonly) {
                   5748:                 $disabled = ' disabled="disabled"';
                   5749:             }
1.558     raeburn  5750:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5751:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5752:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5753:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5754:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5755:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5756:                        &mt('Yes, with proctor key').'</label>'.
                   5757:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5758:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5759:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567     raeburn  5760:                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5761:         }
                   5762:     }
                   5763:     unless ($readonly) {
                   5764:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5765:     }
                   5766:     return $result;
                   5767: }
                   5768: 
1.563     damieng  5769: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5770: #
                   5771: # @param {string} $name - parameter name
                   5772: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5773: # @param {string} $value - parameter value
                   5774: # @param {string} $chostname - course server name
                   5775: # @param {integer} $cmajor - major version number
                   5776: # @param {integer} $cminor - minor version number
                   5777: # @param {string} $needsrelease - release version needed (major.minor)
                   5778: # @returns {string}
1.549     raeburn  5779: sub oldversion_warning {
1.557     raeburn  5780:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5781:     my $standard_name = &standard_parameter_names($name);
                   5782:     if ($namematch) {
                   5783:         my $level = &standard_parameter_levels($namematch);
                   5784:         my $msg = '';
                   5785:         if ($level) {
                   5786:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5787:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5788:         } else {
                   5789:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5790:                       $standard_name,'<b>','</b>');
                   5791:         }
                   5792:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5793:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5794:                    $cmajor.'.'.$cminor,$chostname,
                   5795:                    $needsrelease).
                   5796:                    '</p>';
                   5797:     }
1.549     raeburn  5798:     my $desc;
                   5799:     my $stringtype = &get_stringtype($name);
                   5800:     if ($stringtype ne '') {
                   5801:         if ($name eq 'examcode') {
                   5802:             $desc = $value;
                   5803:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5804:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5805:                 next unless (ref($possibilities) eq 'ARRAY');
                   5806:                 my ($parmval, $description) = @{ $possibilities };
                   5807:                 my $parmmatch;
                   5808:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5809:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5810:                         if (ref($item) eq 'ARRAY') {
                   5811:                             my ($regexpname,$pattern) = @{$item};
                   5812:                             if ($parmval eq $regexpname) {
                   5813:                                 if ($value =~ /$pattern/) {
                   5814:                                     $desc = $description; 
                   5815:                                     $parmmatch = 1;
                   5816:                                     last;
                   5817:                                 }
                   5818:                             }
                   5819:                         }
                   5820:                     }
                   5821:                     last if ($parmmatch);
                   5822:                 } elsif ($parmval eq $value) {
                   5823:                     $desc = $description;
                   5824:                     last;
                   5825:                 }
                   5826:             }
                   5827:         }
                   5828:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5829:         my $now = time;
                   5830:         if ($value =~ /^\d+$/) {
                   5831:             if ($name eq 'printstartdate') {
                   5832:                 if ($value > $now) {
                   5833:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5834:                 }
                   5835:             } elsif ($name eq 'printenddate') {
                   5836:                 if ($value < $now) {
                   5837:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5838:                 }
                   5839:             }
                   5840:         }
                   5841:     }
                   5842:     return '<p class="LC_warning">'.
1.557     raeburn  5843:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5844:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5845:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5846:        $cmajor.'.'.$cminor,$chostname,
                   5847:        $needsrelease).
                   5848:        '</p>';
1.549     raeburn  5849: }
                   5850: 
1.560     damieng  5851: } # end of block using some constants related to parameter types
                   5852: 
1.549     raeburn  5853: 
1.563     damieng  5854: 
                   5855: # Shifts all start and end dates in the current course by $shift.
1.389     www      5856: #
1.563     damieng  5857: # @param {integer} $shift - time to shift, in seconds
                   5858: # @returns {string} - error name or 'ok'
1.389     www      5859: sub dateshift {
1.594     raeburn  5860:     my ($shift,$numchanges)=@_;
1.389     www      5861:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5862:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  5863:     my $sec = $env{'request.course.sec'};
1.595     raeburn  5864:     my $secgrpregex;
                   5865:     if ($sec ne '') {
                   5866:         my @groups;
                   5867:         if ($env{'request.course.groups'} ne '') {
                   5868:             @groups = split(/:/,$env{'request.course.groups'});
                   5869:         }
                   5870:         if (@groups) {
                   5871:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   5872:         } else {
                   5873:             $secgrpregex = $sec;
                   5874:         }
                   5875:     }
1.389     www      5876:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   5877: # ugly retro fix for broken version of types
1.548     raeburn  5878:     foreach my $key (keys(%data)) {
1.389     www      5879:         if ($key=~/\wtype$/) {
                   5880:             my $newkey=$key;
                   5881:             $newkey=~s/type$/\.type/;
                   5882:             $data{$newkey}=$data{$key};
                   5883:             delete $data{$key};
                   5884:         }
                   5885:     }
1.391     www      5886:     my %storecontent=();
1.389     www      5887: # go through all parameters and look for dates
1.548     raeburn  5888:     foreach my $key (keys(%data)) {
1.389     www      5889:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  5890:           if ($sec ne '') {
1.595     raeburn  5891:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  5892:           }
1.389     www      5893:           my $newdate=$data{$key}+$shift;
1.594     raeburn  5894:           $$numchanges ++;
1.391     www      5895:           $storecontent{$key}=$newdate;
1.389     www      5896:        }
                   5897:     }
1.391     www      5898:     my $reply=&Apache::lonnet::cput
                   5899:                 ('resourcedata',\%storecontent,$dom,$crs);
                   5900:     if ($reply eq 'ok') {
                   5901:        &log_parmset(\%storecontent);
                   5902:     }
                   5903:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   5904:     return $reply;
1.389     www      5905: }
                   5906: 
1.563     damieng  5907: # Overview mode UI to edit course parameters.
                   5908: #
                   5909: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5910: sub newoverview {
1.568     raeburn  5911:     my ($r,$parm_permission) = @_;
1.280     albertel 5912: 
1.208     www      5913:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5914:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5915:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5916:     my $readonly = 1;
                   5917:     if ($parm_permission->{'edit'}) {
                   5918:         undef($readonly);
                   5919:     }
1.414     droeschl 5920:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5921:         text=>"Overview Mode"});
1.523     raeburn  5922: 
                   5923:     my %loaditems = (
1.549     raeburn  5924:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  5925:                     );
                   5926:     my $js = '
                   5927: <script type="text/javascript">
                   5928: // <![CDATA[
                   5929: '.
                   5930:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   5931:             &showhide_js()."\n".
1.549     raeburn  5932:             &toggleparmtextbox_js()."\n".
                   5933:             &validateparms_js()."\n".
                   5934:             &ipacc_boxes_js()."\n".
1.558     raeburn  5935:             &done_proctor_js()."\n".
1.588     raeburn  5936:             &deeplink_js()."\n".
1.523     raeburn  5937: '// ]]>
                   5938: </script>
                   5939: ';
1.549     raeburn  5940: 
1.523     raeburn  5941:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   5942:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 5943:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5944:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5945:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      5946:     $r->print(<<ENDOVER);
1.549     raeburn  5947: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      5948: ENDOVER
1.211     www      5949:     my @ids=();
                   5950:     my %typep=();
                   5951:     my %keyp=();
                   5952:     my %allparms=();
                   5953:     my %allparts=();
                   5954:     my %allmaps=();
                   5955:     my %mapp=();
                   5956:     my %symbp=();
                   5957:     my %maptitles=();
                   5958:     my %uris=();
                   5959:     my %keyorder=&standardkeyorder();
                   5960:     my %defkeytype=();
                   5961: 
                   5962:     my %alllevs=();
                   5963:     $alllevs{'Resource Level'}='full';
1.215     www      5964:     $alllevs{'Map/Folder Level'}='map';
1.211     www      5965:     $alllevs{'Course Level'}='general';
                   5966: 
                   5967:     my $csec=$env{'form.csec'};
1.269     raeburn  5968:     my $cgroup=$env{'form.cgroup'};
1.211     www      5969: 
                   5970:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   5971:     my $pschp=$env{'form.pschp'};
1.506     www      5972: 
1.211     www      5973:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      5974:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      5975: 
1.446     bisitz   5976:     my @selected_sections =
1.473     amueller 5977:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      5978:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 5979:     foreach my $sec (@selected_sections) {
                   5980:         if ($sec eq 'all') {
1.211     www      5981:             @selected_sections = ('all');
                   5982:         }
                   5983:     }
1.552     raeburn  5984:     if ($env{'request.course.sec'} ne '') {
                   5985:         @selected_sections = ($env{'request.course.sec'});
                   5986:     }
1.269     raeburn  5987:     my @selected_groups =
                   5988:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      5989: 
                   5990:     my $pssymb='';
                   5991:     my $parmlev='';
1.446     bisitz   5992: 
1.211     www      5993:     unless ($env{'form.parmlev'}) {
                   5994:         $parmlev = 'map';
                   5995:     } else {
                   5996:         $parmlev = $env{'form.parmlev'};
                   5997:     }
                   5998: 
1.446     bisitz   5999:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6000:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  6001:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      6002: 
1.374     albertel 6003:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 6004:         @psprt = keys(%allparts);
1.374     albertel 6005:     }
1.211     www      6006: # Menu to select levels, etc
                   6007: 
1.456     bisitz   6008:     $r->print('<div class="LC_Box">');
1.445     neumanie 6009:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   6010:     $r->print('<div>');
1.523     raeburn  6011:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      6012:     &levelmenu($r,\%alllevs,$parmlev);
1.610   ! raeburn  6013:     $r->print(&Apache::lonhtmlcommon::row_closure());
        !          6014:     &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447     bisitz   6015:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6016:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6017:     $r->print('</div></div>');
1.446     bisitz   6018: 
1.456     bisitz   6019:     $r->print('<div class="LC_Box">');
1.452     bisitz   6020:     $r->print('<div>');
1.581     raeburn  6021:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 6022:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   6023:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  6024:     my $sectionselector = &sectionmenu(\@selected_sections);
                   6025:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 6026:     $r->print('<table>'.
1.553     raeburn  6027:               '<tr><th>'.&mt('Parts').'</th>');
                   6028:     if ($sectionselector) {
                   6029:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   6030:     }
                   6031:     if ($groupselector) {
                   6032:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   6033:     }
                   6034:     $r->print('</tr><tr><td>');
1.211     www      6035:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  6036:     $r->print('</td>');
                   6037:     if ($sectionselector) { 
                   6038:         $r->print('<td>'.$sectionselector.'</td>');
                   6039:     }
                   6040:     if ($groupselector) {
                   6041:         $r->print('<td>'.$groupselector.'</td>');
                   6042:     }
                   6043:     $r->print('</tr></table>');
1.447     bisitz   6044:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6045:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6046:     $r->print('</div></div>');
                   6047: 
1.456     bisitz   6048:     $r->print('<div class="LC_Box">');
1.452     bisitz   6049:     $r->print('<div>');
1.214     www      6050:     my $sortorder=$env{'form.sortorder'};
                   6051:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6052:     &sortmenu($r,$sortorder,'newoverview'));
1.445     neumanie 6053:     $r->print('</div></div>');
1.446     bisitz   6054: 
1.214     www      6055:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   6056: 
1.211     www      6057: # Build the list data hash from the specified parms
                   6058: 
                   6059:     my $listdata;
                   6060:     %{$listdata}=();
                   6061: 
                   6062:     foreach my $cat (@pscat) {
1.269     raeburn  6063:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   6064:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      6065:     }
                   6066: 
1.212     www      6067:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      6068: 
1.481     amueller 6069:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6070: 
                   6071: # Read modified data
                   6072: 
1.481     amueller 6073:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6074: 
                   6075: # List data
                   6076: 
1.608     raeburn  6077:         my $hash_for_realm;
                   6078:         if (($parmlev eq 'map') && (keys(%allmaps))) {
                   6079:             %{$hash_for_realm} = reverse(%allmaps);
                   6080:         } elsif (($parmlev eq 'full') && (keys(%symbp))) {
                   6081:             for (my $i=0; $i<@ids; $i++) {
                   6082:                 $hash_for_realm->{$symbp{$ids[$i]}} = $i;
                   6083:             }
                   6084:         }
                   6085:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568     raeburn  6086:     }
                   6087:     $r->print(&tableend());
                   6088:     unless ($readonly) {
                   6089:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6090:     }
1.568     raeburn  6091:     $r->print('</form>');
1.507     www      6092:     &endSettingsScreen($r);
                   6093:     $r->print(&Apache::loncommon::end_page());
1.208     www      6094: }
                   6095: 
1.563     damieng  6096: # Fills $listdata with parameter information.
                   6097: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6098: # The non-type value is always 1.
                   6099: #
                   6100: # @param {string} $cat - parameter name
1.566     damieng  6101: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6102: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6103: # @param {hash reference} $listdata - the parameter data that will be modified
                   6104: # @param {array reference} $psprt - selected parts
                   6105: # @param {array reference} $selections - selected sections
                   6106: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6107: # @param {hash reference} $allmaps - hash map pc -> map src
                   6108: # @param {array reference} $ids - resource and map ids
                   6109: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6110: sub secgroup_lister {
                   6111:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6112:     foreach my $item (@{$selections}) {
                   6113:         foreach my $part (@{$psprt}) {
                   6114:             my $rootparmkey=$env{'request.course.id'};
                   6115:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6116:                 $rootparmkey.='.['.$item.']';
                   6117:             }
                   6118:             if ($parmlev eq 'general') {
                   6119: # course-level parameter
                   6120:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6121:                 $$listdata{$newparmkey}=1;
                   6122:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6123:             } elsif ($parmlev eq 'map') {
                   6124: # map-level parameter
1.548     raeburn  6125:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6126:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6127:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6128:                     $$listdata{$newparmkey}=1;
                   6129:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6130:                 }
                   6131:             } else {
                   6132: # resource-level parameter
                   6133:                 foreach my $rid (@{$ids}) {
                   6134:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6135:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6136:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6137:                     $$listdata{$newparmkey}=1;
                   6138:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6139:                 }
                   6140:             }
                   6141:         }
                   6142:     }
                   6143: }
                   6144: 
1.563     damieng  6145: # UI to edit parameter settings starting with a list of all existing parameters.
                   6146: # (called by setoverview action)
                   6147: #
                   6148: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6149: sub overview {
1.568     raeburn  6150:     my ($r,$parm_permission) = @_;
1.208     www      6151:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6152:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6153:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6154:     my $readonly = 1;
                   6155:     if ($parm_permission->{'edit'}) {
                   6156:         undef($readonly);
                   6157:     }
1.549     raeburn  6158:     my $js = '<script type="text/javascript">'."\n".
                   6159:              '// <![CDATA['."\n".
                   6160:              &toggleparmtextbox_js()."\n".
                   6161:              &validateparms_js()."\n".
                   6162:              &ipacc_boxes_js()."\n".
1.558     raeburn  6163:              &done_proctor_js()."\n".
1.588     raeburn  6164:              &deeplink_js()."\n".
1.549     raeburn  6165:              '// ]]>'."\n".
                   6166:              '</script>'."\n";
1.414     droeschl 6167:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6168:     text=>"Overview Mode"});
1.549     raeburn  6169:     my %loaditems = (
                   6170:                       'onload'   => "showHideLenient();",
                   6171:                     );
                   6172: 
                   6173:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6174:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6175:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6176:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6177:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6178: 
1.208     www      6179: # Store modified
                   6180: 
1.568     raeburn  6181:     unless ($readonly) {
                   6182:         &storedata($r,$crs,$dom);
                   6183:     }
1.208     www      6184: 
                   6185: # Read modified data
                   6186: 
1.552     raeburn  6187:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6188: 
1.214     www      6189: 
                   6190:     my $sortorder=$env{'form.sortorder'};
                   6191:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6192:     &sortmenu($r,$sortorder,'overview');
1.214     www      6193: 
1.568     raeburn  6194:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6195: 
                   6196:     if ($readonly) {
                   6197:         $r->print('<p>'.$submitbutton.'</p>');
                   6198:     }
                   6199: 
1.208     www      6200: # List data
                   6201: 
1.568     raeburn  6202:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6203:     $r->print(&tableend().'<p>');
                   6204:     if ($foundkeys) {
                   6205:         unless ($readonly) {
                   6206:             $r->print('<p>'.$submitbutton.'</p>');
                   6207:         }
                   6208:     } else {
                   6209:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6210:     }
                   6211:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6212: }
1.121     www      6213: 
1.560     damieng  6214: # Unused sub.
1.563     damieng  6215: #
                   6216: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6217: sub clean_parameters {
                   6218:     my ($r) = @_;
                   6219:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6220:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6221: 
1.414     droeschl 6222:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6223:         text=>"Clean Parameters"});
1.333     albertel 6224:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6225:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6226:     $r->print(<<ENDOVER);
                   6227: $start_page
                   6228: $breadcrumbs
                   6229: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6230: ENDOVER
                   6231: # Store modified
                   6232: 
                   6233:     &storedata($r,$crs,$dom);
                   6234: 
                   6235: # Read modified data
                   6236: 
                   6237:     my $resourcedata=&readdata($crs,$dom);
                   6238: 
                   6239: # List data
                   6240: 
                   6241:     $r->print('<h3>'.
1.473     amueller 6242:           &mt('These parameters refer to resources that do not exist.').
                   6243:           '</h3>'.
                   6244:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6245:           '<br />');
1.333     albertel 6246:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6247:           '<tr>'.
                   6248:           '<th>'.&mt('Delete').'</th>'.
                   6249:           '<th>'.&mt('Parameter').'</th>'.
                   6250:           '</tr>');
1.333     albertel 6251:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6252:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6253:             && $thiskey=~/\.type$/);
                   6254:         my %data = &parse_key($thiskey);
                   6255:         if (1) { #exists($data{'realm_exists'})
                   6256:             #&& !$data{'realm_exists'}) {
                   6257:             $r->print(&Apache::loncommon::start_data_table_row().
                   6258:                 '<tr>'.
                   6259:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6260: 
                   6261:             $r->print('<td>');
                   6262:             my $display_value = $resourcedata->{$thiskey};
                   6263:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6264:             $display_value =
                   6265:                 &Apache::lonlocal::locallocaltime($display_value);
                   6266:             }
1.470     raeburn  6267:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6268:             $parmitem = &mt($parmitem);
1.560     damieng  6269:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6270:                 $parmitem,$resourcedata->{$thiskey}));
                   6271:             $r->print('<br />');
                   6272:             if ($data{'scope_type'} eq 'all') {
                   6273:                 $r->print(&mt('All users'));
                   6274:             } elsif ($data{'scope_type'} eq 'user') {
                   6275:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6276:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6277:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6278:             }
                   6279:             $r->print('<br />');
                   6280:             if ($data{'realm_type'} eq 'all') {
                   6281:                 $r->print(&mt('All Resources'));
                   6282:             } elsif ($data{'realm_type'} eq 'folder') {
                   6283:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6284:             } elsif ($data{'realm_type'} eq 'symb') {
                   6285:             my ($map,$resid,$url) =
                   6286:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6287:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6288:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6289:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6290:             }
                   6291:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6292:             $r->print('</td></tr>');
                   6293: 
1.473     amueller 6294:         }
1.333     albertel 6295:     }
                   6296:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6297:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6298:           '</p></form>');
                   6299:     &endSettingsScreen($r);
                   6300:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6301: }
                   6302: 
1.563     damieng  6303: # UI to shift all dates (called by dateshift1 action).
                   6304: # Used by overview mode.
                   6305: #
                   6306: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6307: sub date_shift_one {
                   6308:     my ($r) = @_;
                   6309:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6310:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6311:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6312:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6313:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6314:         text=>"Shifting Dates"});
1.594     raeburn  6315:     my $submit_text = &mt('Shift all dates accordingly');
                   6316:     if ($sec ne '') {
1.595     raeburn  6317:         my @groups;
                   6318:         if ($env{'request.course.groups'} ne '') {
                   6319:             @groups = split(/:/,$env{'request.course.groups'});
                   6320:         }
                   6321:         if (@groups) {
                   6322:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6323:         } else {
                   6324:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6325:         }
1.594     raeburn  6326:     }
1.390     www      6327:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6328:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6329:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6330:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6331:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6332:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6333:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6334:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6335:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6336:                                                         'timeshifted',
                   6337:                                                         $env{'form.timebase'},,
                   6338:                                                         '').
                   6339:               '</td></tr></table>'.
                   6340:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6341:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6342:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6343:     &endSettingsScreen($r);
1.390     www      6344:     $r->print(&Apache::loncommon::end_page());
                   6345: }
                   6346: 
1.563     damieng  6347: # UI to shift all dates (second form).
                   6348: #
                   6349: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6350: sub date_shift_two {
                   6351:     my ($r) = @_;
                   6352:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6353:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6354:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6355:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6356:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6357:         text=>"Shifting Dates"});
1.390     www      6358:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6359:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6360:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6361:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6362:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6363:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6364:     if ($sec ne '') {
1.595     raeburn  6365:         my @groups;
                   6366:         if ($env{'request.course.groups'} ne '') {
                   6367:             @groups = split(/:/,$env{'request.course.groups'});
                   6368:         }
                   6369:         if (@groups) {
                   6370:             $r->print('<p>'.
                   6371:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6372:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6373:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6374:                       '</p>');
                   6375:         } else {
                   6376:             $r->print('<p>'.
                   6377:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6378:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6379:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6380:                       '</p>');
                   6381:         }
1.594     raeburn  6382:     } else {
                   6383:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6384:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6385:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6386:                   '</p>');
                   6387:     }
1.390     www      6388:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6389:     my $numchanges = 0;
                   6390:     my $result = &dateshift($delta,\$numchanges);
                   6391:     if ($result eq 'ok') {
                   6392:         $r->print(
                   6393:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6394:                                                     $numchanges)));
                   6395:     } elsif ($result eq 'con_delayed') {
                   6396:         $r->print(
                   6397:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6398:                                                         $numchanges)));
                   6399:     } else {
                   6400:         $r->print(
                   6401:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6402:     }
1.543     bisitz   6403:     $r->print(
                   6404:         '<br /><br />'.
                   6405:         &Apache::lonhtmlcommon::actionbox(
                   6406:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6407:     &endSettingsScreen($r);
1.390     www      6408:     $r->print(&Apache::loncommon::end_page());
                   6409: }
                   6410: 
1.563     damieng  6411: # Returns the different components of a resourcedata key.
                   6412: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6413: #       realm_exists, parameter_part, parameter_name.
                   6414: # Was used by clean_parameters (which is unused).
                   6415: #
                   6416: # @param {string} $key - the parameter key
                   6417: # @returns {hash}
1.333     albertel 6418: sub parse_key {
                   6419:     my ($key) = @_;
                   6420:     my %data;
                   6421:     my ($middle,$part,$name)=
1.572     damieng  6422:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6423:     $data{'scope_type'} = 'all';
                   6424:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6425:         $data{'scope'} = $1;
                   6426:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6427:             $data{'scope_type'} = 'user';
                   6428:             $data{'scope'} = [$1,$2];
                   6429:         } else {
1.581     raeburn  6430:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6431:         }
                   6432:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6433:     }
                   6434:     $middle=~s/\.+$//;
                   6435:     $middle=~s/^\.+//;
                   6436:     $data{'realm_type'}='all';
                   6437:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6438:         $data{'realm'} = $1;
                   6439:         $data{'realm_type'} = 'folder';
                   6440:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6441:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6442:     } elsif ($middle) {
1.560     damieng  6443:         $data{'realm'} = $middle;
                   6444:         $data{'realm_type'} = 'symb';
                   6445:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6446:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6447:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6448:     }
1.446     bisitz   6449: 
1.333     albertel 6450:     $data{'parameter_part'} = $part;
                   6451:     $data{'parameter_name'} = $name;
                   6452: 
                   6453:     return %data;
                   6454: }
                   6455: 
1.239     raeburn  6456: 
1.563     damieng  6457: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6458: sub header {
1.507     www      6459:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6460: }
1.193     albertel 6461: 
                   6462: 
                   6463: 
1.560     damieng  6464: ##################################################
                   6465: # MAIN MENU
                   6466: ##################################################
                   6467: 
1.563     damieng  6468: # Content and problem settings main menu.
                   6469: #
                   6470: # @param {Apache2::RequestRec} $r - the Apache request
                   6471: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6472: sub print_main_menu {
                   6473:     my ($r,$parm_permission)=@_;
                   6474:     #
1.414     droeschl 6475:     $r->print(&header());
1.507     www      6476:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6477:     my $crstype = &Apache::loncommon::course_type();
                   6478:     my $lc_crstype = lc($crstype);
                   6479: 
                   6480:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6481:     $r->print(<<ENDMAINFORMHEAD);
                   6482: <form method="post" enctype="multipart/form-data"
                   6483:       action="/adm/parmset" name="studentform">
                   6484: ENDMAINFORMHEAD
                   6485: #
1.195     albertel 6486:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6487:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6488:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6489:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6490:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6491:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6492:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6493:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6494:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6495:                                         '/'.$env{'request.course.sec'});
                   6496:     }
1.568     raeburn  6497:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6498:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6499:                                         '/'.$env{'request.course.sec'});
                   6500:     }
                   6501:     my (%linktext,%linktitle,%url);
                   6502:     if ($parm_permission->{'edit'}) {
                   6503:         %linktext = (
                   6504:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6505:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6506:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6507:                     );
                   6508:         %linktitle = (
                   6509:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6510:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6511:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6512:                      );
                   6513:     } else {
                   6514:         %linktext = (
                   6515:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6516:                      settable        => 'View Resource Parameters - Table Mode',
                   6517:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6518:                    );
                   6519:         %linktitle = (
                   6520:                      newoverview     => 'Display resource parameters in overview mode.',
                   6521:                      settable        => 'Display resource parameters in table mode.',
                   6522:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6523:                      );
                   6524:     }
                   6525:     if ($mgr) {
                   6526:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6527:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6528:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6529:     } elsif ($vgr) {
                   6530:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6531:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6532:         $url{'resettimes'} = '/adm/accesstimes';
                   6533:     }
1.193     albertel 6534:     my @menu =
1.507     www      6535:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6536:         items => [
                   6537:           { linktext => 'Portfolio Metadata',
                   6538:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6539:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6540:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6541:             icon =>'contact-new.png'   ,
                   6542:             },
1.568     raeburn  6543:           { linktext => $linktext{'resettimes'},
                   6544:             url => $url{'resettimes'},
                   6545:             permission => ($vgr || $mgr),
                   6546:             linktitle => $linktitle{'resettimes'},
                   6547:             icon => 'start-here.png',
1.473     amueller 6548:             },
1.520     raeburn  6549:           { linktext => 'Blocking Communication/Resource Access',
                   6550:             url => '/adm/setblock',
1.568     raeburn  6551:             permission => ($vcb || $dcm),
1.520     raeburn  6552:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6553:             icon => 'comblock.png',
                   6554:             },
1.473     amueller 6555:           { linktext => 'Set Parameter Setting Default Actions',
                   6556:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6557:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6558:             linktitle =>'Set default actions for parameters.'  ,
                   6559:             icon => 'folder-new.png'  ,
                   6560:             }]},
                   6561:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6562:         items => [
                   6563:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6564:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6565:             permission => $parm_permission->{'helper'},
1.473     amueller 6566:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6567:             icon => 'dialog-information.png'  ,
                   6568:             #help => 'Parameter_Helper',
                   6569:             },
1.568     raeburn  6570:           { linktext => $linktext{'newoverview'},
1.473     amueller 6571:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6572:             permission => $parm_permission->{'newoverview'},
                   6573:             linktitle => $linktitle{'newoverview'},
                   6574:             icon => 'edit-find.png',
1.473     amueller 6575:             #help => 'Parameter_Overview',
                   6576:             },
1.568     raeburn  6577:           { linktext => $linktext{'settable'},
1.473     amueller 6578:             url => '/adm/parmset?action=settable',
1.568     raeburn  6579:             permission => $parm_permission->{'settable'},
                   6580:             linktitle => $linktitle{'settable'},
                   6581:             icon => 'edit-copy.png',
1.473     amueller 6582:             #help => 'Table_Mode',
                   6583:             }]},
1.417     droeschl 6584:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6585:          items => [
1.570     raeburn  6586:           { linktext => $linktext{'setoverview'},
1.473     amueller 6587:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6588:             permission => $parm_permission->{'setoverview'},
                   6589:             linktitle => $linktitle{'setoverview'},
                   6590:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6591:             #help => 'Parameter_Overview',
                   6592:             },
                   6593:           { linktext => 'Change Log',
                   6594:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6595:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6596:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6597:             icon => 'document-properties.png',
1.473     amueller 6598:             }]}
1.193     albertel 6599:           );
1.414     droeschl 6600:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6601:     $r->print('</form>');
1.507     www      6602:     &endSettingsScreen($r);
1.539     raeburn  6603:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6604:     return;
                   6605: }
1.414     droeschl 6606: 
1.416     jms      6607: 
                   6608: 
1.560     damieng  6609: ##################################################
                   6610: # PORTFOLIO METADATA
                   6611: ##################################################
                   6612: 
1.563     damieng  6613: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6614: # It looks like field titles are not localized.
                   6615: #
                   6616: # @param {Apache2::RequestRec} $r - the Apache request
                   6617: # @param {string} $field_name - metadata field name
                   6618: # @param {string} $field_text - metadata field title, in English unless manually added
                   6619: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6620: sub output_row {
1.347     banghart 6621:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6622:     my $output;
1.263     banghart 6623:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6624:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6625:     if (!defined($options)) {
1.254     banghart 6626:         $options = 'active,stuadd';
1.261     banghart 6627:         $values = '';
1.252     banghart 6628:     }
1.337     banghart 6629:     if (!($options =~ /deleted/)) {
                   6630:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6631:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6632:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6633: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6634:         if ($added_flag) {
                   6635:             push @options,['deleted', 'Delete Metadata Field'];
                   6636:         }
1.351     banghart 6637:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6638:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6639:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6640:         foreach my $opt (@options) {
1.560     damieng  6641:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6642:             $output .= &Apache::loncommon::continue_data_table_row();
                   6643:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6644:                     <input type="checkbox" name="'.
                   6645:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6646:                     &mt($opt->[1]).'</label></td>';
                   6647:             $output .= &Apache::loncommon::end_data_table_row();
                   6648:         }
1.351     banghart 6649:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6650:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6651:         $output .= &Apache::loncommon::end_data_table_row();
                   6652:         my $multiple_checked;
                   6653:         my $single_checked;
                   6654:         if ($options =~ m/onlyone/) {
1.422     bisitz   6655:             $multiple_checked = '';
1.423     bisitz   6656:             $single_checked = ' checked="checked"';
1.351     banghart 6657:         } else {
1.423     bisitz   6658:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6659:             $single_checked = '';
1.351     banghart 6660:         }
1.560     damieng  6661:         $output .= &Apache::loncommon::continue_data_table_row();
                   6662:         $output .= '<td>'.('&nbsp;' x 10).'
                   6663:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6664:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6665:         $output .= &Apache::loncommon::end_data_table_row();
                   6666:         $output .= &Apache::loncommon::continue_data_table_row();
                   6667:         $output .= '<td>'.('&nbsp;' x 10).'
                   6668:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6669:                     '.&mt('Student may select only one choice from list').'</td>';
                   6670:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6671:     }
                   6672:     return ($output);
                   6673: }
1.416     jms      6674: 
                   6675: 
1.560     damieng  6676: # UI to order portfolio metadata fields.
1.563     damieng  6677: # Currently useless because addmetafield does not work.
                   6678: #
                   6679: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6680: sub order_meta_fields {
                   6681:     my ($r)=@_;
                   6682:     my $idx = 1;
                   6683:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6684:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6685:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6686:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6687:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6688:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6689:         text=>"Add Metadata Field"});
1.560     damieng  6690:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6691:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6692:         text=>"Restrict Metadata"},
                   6693:         {text=>"Order Metadata"});
1.345     banghart 6694:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6695:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6696:     if ($env{'form.storeorder'}) {
                   6697:         my $newpos = $env{'form.newpos'} - 1;
                   6698:         my $currentpos = $env{'form.currentpos'} - 1;
                   6699:         my @neworder = ();
1.548     raeburn  6700:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6701:         my $i;
1.341     banghart 6702:         if ($newpos > $currentpos) {
1.340     banghart 6703:         # moving stuff up
                   6704:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6705:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6706:             }
                   6707:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6708:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6709:             }
                   6710:             $neworder[$newpos]=$oldorder[$currentpos];
                   6711:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6712:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6713:             }
                   6714:         } else {
                   6715:         # moving stuff down
1.473     amueller 6716:             for ($i=0;$i<$newpos;$i++) {
                   6717:                 $neworder[$i]=$oldorder[$i];
                   6718:             }
                   6719:             $neworder[$newpos]=$oldorder[$currentpos];
                   6720:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6721:                 $neworder[$i]=$oldorder[$i-1];
                   6722:             }
                   6723:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6724:                 $neworder[$i]=$oldorder[$i];
                   6725:             }
1.340     banghart 6726:         }
1.560     damieng  6727:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6728:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6729:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6730:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6731:     }
1.357     raeburn  6732:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6733:     my $ordered_fields;
1.548     raeburn  6734:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6735:     if (!@fields_in_order) {
                   6736:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6737:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6738:             push @fields_in_order, $key;
1.341     banghart 6739:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6740:         }
1.341     banghart 6741:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6742:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6743:     }
1.340     banghart 6744:     $r->print('<table>');
                   6745:     my $num_fields = scalar(@fields_in_order);
                   6746:     foreach my $key (@fields_in_order) {
                   6747:         $r->print('<tr><td>');
                   6748:         $r->print('<form method="post" action="">');
1.537     bisitz   6749:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6750:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6751:             if ($i eq $idx) {
                   6752:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6753:             } else {
                   6754:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6755:             }
                   6756:         }
                   6757:         $r->print('</select></td><td>');
                   6758:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6759:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6760:         $r->print('</form>');
                   6761:         $r->print($$fields{$key}.'</td></tr>');
                   6762:         $idx ++;
                   6763:     }
                   6764:     $r->print('</table>');
1.507     www      6765:     &endSettingsScreen($r);
1.340     banghart 6766:     return 'ok';
                   6767: }
1.416     jms      6768: 
                   6769: 
1.563     damieng  6770: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6771: # @returns {string}
1.359     banghart 6772: sub continue {
                   6773:     my $output;
                   6774:     $output .= '<form action="" method="post">';
                   6775:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6776:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6777:     return ($output);
                   6778: }
1.416     jms      6779: 
                   6780: 
1.563     damieng  6781: # UI to add a metadata field.
                   6782: # Currenly does not work because of an HTML error (the field is not visible).
                   6783: #
                   6784: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6785: sub addmetafield {
                   6786:     my ($r)=@_;
1.414     droeschl 6787:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6788:         text=>"Add Metadata Field"});
1.334     banghart 6789:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6790:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6791:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6792:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6793:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6794:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6795:     if (exists($env{'form.undelete'})) {
1.358     banghart 6796:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6797:         foreach my $meta_field(@meta_fields) {
                   6798:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6799:             $options =~ s/deleted//;
                   6800:             $options =~ s/,,/,/;
                   6801:             my $put_result = &Apache::lonnet::put('environment',
                   6802:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6803: 
1.586     raeburn  6804:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6805:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6806:                           '</strong>',$put_result).
                   6807:                       '<br />');
1.339     banghart 6808:         }
1.359     banghart 6809:         $r->print(&continue());
1.339     banghart 6810:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6811:         my $meta_field = $env{'form.fieldname'};
                   6812:         my $display_field = $env{'form.fieldname'};
                   6813:         $meta_field =~ s/\W/_/g;
1.338     banghart 6814:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6815:         my $put_result = &Apache::lonnet::put('environment',
                   6816:                             {'metadata.'.$meta_field.'.values'=>"",
                   6817:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6818:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6819:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6820:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6821:                   '<br />');
1.359     banghart 6822:         $r->print(&continue());
1.335     banghart 6823:     } else {
1.357     raeburn  6824:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6825:         if ($fields) {
1.586     raeburn  6826:             $r->print(&mt('You may undelete previously deleted fields.').
                   6827:                       '<br />'.
                   6828:                       &mt('Check those you wish to undelete and click Undelete.').
                   6829:                       '<br />');
1.339     banghart 6830:             $r->print('<form method="post" action="">');
                   6831:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6832:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6833:             }
1.586     raeburn  6834:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6835:             $r->print('</form>');
                   6836:         }
1.586     raeburn  6837:         $r->print('<hr />'.
                   6838:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6839:                       '<strong>','</strong>').
1.581     raeburn  6840:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6841:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6842:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6843:         $r->print('</form>');
1.334     banghart 6844:     }
1.507     www      6845:     &endSettingsScreen($r);
1.334     banghart 6846: }
1.416     jms      6847: 
                   6848: 
                   6849: 
1.560     damieng  6850: # Display or save portfolio metadata.
1.563     damieng  6851: #
                   6852: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6853: sub setrestrictmeta {
1.240     banghart 6854:     my ($r)=@_;
1.242     banghart 6855:     my $next_meta;
1.244     banghart 6856:     my $output;
1.245     banghart 6857:     my $item_num;
1.246     banghart 6858:     my $put_result;
1.414     droeschl 6859:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6860:         text=>"Restrict Metadata"});
1.280     albertel 6861:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6862:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6863:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6864:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6865:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6866:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 6867:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 6868:     my $save_field = '';
1.586     raeburn  6869:     my %lt = &Apache::lonlocal::texthash(
                   6870:                                            addm => 'Add Metadata Field',
                   6871:                                            ordm => 'Order Metadata Fields',
                   6872:                                            save => 'Save',
                   6873:                                         );
1.259     banghart 6874:     if ($env{'form.restrictmeta'}) {
1.254     banghart 6875:         foreach my $field (sort(keys(%env))) {
1.252     banghart 6876:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 6877:                 my $options;
1.252     banghart 6878:                 my $meta_field = $1;
                   6879:                 my $meta_key = $2;
1.253     banghart 6880:                 if ($save_field ne $meta_field) {
1.252     banghart 6881:                     $save_field = $meta_field;
1.473     amueller 6882:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   6883:                         $options.='stuadd,';
                   6884:                     }
                   6885:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   6886:                         $options.='choices,';
                   6887:                     }
                   6888:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   6889:                         $options.='onlyone,';
                   6890:                     }
                   6891:                     if ($env{'form.'.$meta_field.'_active'}) {
                   6892:                         $options.='active,';
                   6893:                     }
                   6894:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   6895:                         $options.='deleted,';
                   6896:                     }
1.259     banghart 6897:                     my $name = $save_field;
1.560     damieng  6898:                     $put_result = &Apache::lonnet::put('environment',
                   6899:                         {'metadata.'.$meta_field.'.options'=>$options,
                   6900:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   6901:                         },$dom,$crs);
1.252     banghart 6902:                 }
                   6903:             }
                   6904:         }
                   6905:     }
1.296     albertel 6906:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 6907:                        {'freshen_cache' => 1});
1.335     banghart 6908:     # Get the default metadata fields
1.258     albertel 6909:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 6910:     # Now get possible added metadata fields
1.357     raeburn  6911:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 6912:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 6913:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 6914:         if ($field ne 'courserestricted') {
1.586     raeburn  6915:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  6916:         }
1.255     banghart 6917:     }
1.351     banghart 6918:     my $buttons = (<<ENDButtons);
1.586     raeburn  6919:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 6920:         </form><br />
                   6921:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  6922:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 6923:         </form>
                   6924:         <br />
                   6925:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  6926:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 6927: ENDButtons
1.337     banghart 6928:     my $added_flag = 1;
1.335     banghart 6929:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  6930:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 6931:     }
1.347     banghart 6932:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   6933:     $r->print(<<ENDenv);
1.259     banghart 6934:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 6935:         $output
1.351     banghart 6936:         $buttons
1.340     banghart 6937:         </form>
1.244     banghart 6938: ENDenv
1.507     www      6939:     &endSettingsScreen($r);
1.280     albertel 6940:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 6941:     return 'ok';
                   6942: }
1.416     jms      6943: 
                   6944: 
1.563     damieng  6945: # Returns metadata fields that have been manually added.
                   6946: #
                   6947: # @param {string} $cid - course id
                   6948: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 6949: sub get_added_meta_fieldnames {
1.357     raeburn  6950:     my ($cid) = @_;
1.335     banghart 6951:     my %fields;
                   6952:     foreach my $key(%env) {
1.357     raeburn  6953:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 6954:             my $field_name = $1;
                   6955:             my ($display_field_name) = $env{$key};
                   6956:             $fields{$field_name} = $display_field_name;
                   6957:         }
                   6958:     }
                   6959:     return \%fields;
                   6960: }
1.416     jms      6961: 
                   6962: 
1.563     damieng  6963: # Returns metadata fields that have been manually added and deleted.
                   6964: #
                   6965: # @param {string} $cid - course id
                   6966: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 6967: sub get_deleted_meta_fieldnames {
1.357     raeburn  6968:     my ($cid) = @_;
1.339     banghart 6969:     my %fields;
                   6970:     foreach my $key(%env) {
1.357     raeburn  6971:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 6972:             my $field_name = $1;
                   6973:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   6974:                 my ($display_field_name) = $env{$key};
                   6975:                 $fields{$field_name} = $display_field_name;
                   6976:             }
                   6977:         }
                   6978:     }
                   6979:     return \%fields;
                   6980: }
1.560     damieng  6981: 
                   6982: 
                   6983: ##################################################
                   6984: # PARAMETER SETTINGS DEFAULT ACTIONS
                   6985: ##################################################
                   6986: 
                   6987: # UI to change parameter setting default actions
1.563     damieng  6988: #
                   6989: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      6990: sub defaultsetter {
1.280     albertel 6991:     my ($r) = @_;
                   6992: 
1.414     droeschl 6993:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 6994:         text=>"Set Defaults"});
1.531     raeburn  6995:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6996:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6997:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   6998:     my $start_page =
1.531     raeburn  6999:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 7000:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      7001:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  7002:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      7003:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 7004: 
1.221     www      7005:     my @ids=();
                   7006:     my %typep=();
                   7007:     my %keyp=();
                   7008:     my %allparms=();
                   7009:     my %allparts=();
                   7010:     my %allmaps=();
                   7011:     my %mapp=();
                   7012:     my %symbp=();
                   7013:     my %maptitles=();
                   7014:     my %uris=();
                   7015:     my %keyorder=&standardkeyorder();
                   7016:     my %defkeytype=();
                   7017: 
1.446     bisitz   7018:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 7019:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   7020:                 \%keyorder,\%defkeytype);
1.224     www      7021:     if ($env{'form.storerules'}) {
1.560     damieng  7022:         my %newrules=();
                   7023:         my @delrules=();
                   7024:         my %triggers=();
                   7025:         foreach my $key (keys(%env)) {
1.225     albertel 7026:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  7027:                 my $tempkey=$1;
                   7028:                 my $action=$env{$key};
1.226     www      7029:                 if ($action) {
1.560     damieng  7030:                     $newrules{$tempkey.'_action'}=$action;
                   7031:                     if ($action ne 'default') {
                   7032:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   7033:                         $triggers{$whichparm}.=$tempkey.':';
                   7034:                     }
                   7035:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   7036:                     if (&isdateparm($defkeytype{$tempkey})) {
                   7037:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   7038:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   7039:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   7040:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   7041:                     } else {
                   7042:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   7043:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   7044:                     }
                   7045:                 } else {
                   7046:                     push(@delrules,$tempkey.'_action');
                   7047:                     push(@delrules,$tempkey.'_type');
                   7048:                     push(@delrules,$tempkey.'_hours');
                   7049:                     push(@delrules,$tempkey.'_min');
                   7050:                     push(@delrules,$tempkey.'_sec');
                   7051:                     push(@delrules,$tempkey.'_value');
                   7052:                 }
1.473     amueller 7053:             }
                   7054:         }
1.560     damieng  7055:         foreach my $key (keys(%allparms)) {
                   7056:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 7057:         }
1.560     damieng  7058:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   7059:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   7060:         &resetrulescache();
1.224     www      7061:     }
1.227     www      7062:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 7063:                        'hours' => 'Hours',
                   7064:                        'min' => 'Minutes',
                   7065:                        'sec' => 'Seconds',
                   7066:                        'yes' => 'Yes',
                   7067:                        'no' => 'No');
1.222     www      7068:     my @standardoptions=('','default');
                   7069:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   7070:     my @dateoptions=('','default');
                   7071:     my @datedisplay=('',&mt('Default value when manually setting'));
                   7072:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7073:         unless ($tempkey) { next; }
                   7074:         push @standardoptions,'when_setting_'.$tempkey;
                   7075:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   7076:         if (&isdateparm($defkeytype{$tempkey})) {
                   7077:             push @dateoptions,'later_than_'.$tempkey;
                   7078:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7079:             push @dateoptions,'earlier_than_'.$tempkey;
                   7080:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7081:         }
1.222     www      7082:     }
1.563     damieng  7083:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7084:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7085:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7086:           &Apache::loncommon::start_data_table_header_row().
                   7087:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7088:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7089:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7090:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7091:         unless ($tempkey) { next; }
                   7092:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7093:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7094:         my $action=&rulescache($tempkey.'_action');
                   7095:         $r->print('<select name="'.$tempkey.'_action">');
                   7096:         if (&isdateparm($defkeytype{$tempkey})) {
                   7097:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7098:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7099:             $r->print("\n<option value='$dateoptions[$i]'".
                   7100:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7101:                 ">$datedisplay[$i]</option>");
                   7102:             }
                   7103:         } else {
                   7104:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7105:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7106:             $r->print("\n<option value='$standardoptions[$i]'".
                   7107:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7108:                 ">$standarddisplay[$i]</option>");
                   7109:             }
1.473     amueller 7110:         }
1.560     damieng  7111:         $r->print('</select>');
                   7112:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7113:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7114:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7115:         }
1.560     damieng  7116:         $r->print("\n</td><td>\n");
1.222     www      7117: 
1.221     www      7118:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7119:             my $days=&rulescache($tempkey.'_days');
                   7120:             my $hours=&rulescache($tempkey.'_hours');
                   7121:             my $min=&rulescache($tempkey.'_min');
                   7122:             my $sec=&rulescache($tempkey.'_sec');
                   7123:             $r->print(<<ENDINPUTDATE);
                   7124:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7125:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7126:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7127:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7128: ENDINPUTDATE
1.560     damieng  7129:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7130:                 my $yeschecked='';
                   7131:                 my $nochecked='';
                   7132:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7133:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7134: 
                   7135:             $r->print(<<ENDYESNO);
                   7136:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7137:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7138: ENDYESNO
1.221     www      7139:         } else {
1.560     damieng  7140:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7141:         }
1.318     albertel 7142:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7143:     }
1.318     albertel 7144:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7145:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7146:           &mt('Save').'" /></form>'."\n");
                   7147:     &endSettingsScreen($r);
                   7148:     $r->print(&Apache::loncommon::end_page());
1.220     www      7149:     return;
                   7150: }
1.193     albertel 7151: 
1.560     damieng  7152: ##################################################
                   7153: # PARAMETER CHANGES LOG
                   7154: ##################################################
                   7155: 
1.563     damieng  7156: # Returns some info for a parameter log entry.
                   7157: # Returned entries:
                   7158: # $realm - HTML title for the parameter level and resource
                   7159: # $section - parameter section
                   7160: # $name - parameter name
                   7161: # $part - parameter part
                   7162: # $what - $part.'.'.$name
                   7163: # $middle - resource symb ?
                   7164: # $uname - user name (same as given)
                   7165: # $udom - user domain (same as given)
                   7166: # $issection - section or group name
                   7167: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7168: #
                   7169: # @param {string} $key - parameter log key
                   7170: # @param {string} $uname - user name
                   7171: # @param {string} $udom - user domain
                   7172: # @param {boolean} $typeflag - .type log entry
                   7173: # @returns {Array}
1.290     www      7174: sub components {
1.581     raeburn  7175:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7176: 
                   7177:     if ($typeflag) {
1.560     damieng  7178:         $key=~s/\.type$//;
1.290     www      7179:     }
1.330     albertel 7180: 
                   7181:     my ($middle,$part,$name)=
1.572     damieng  7182:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7183:     my $issection;
1.330     albertel 7184: 
1.290     www      7185:     my $section=&mt('All Students');
                   7186:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7187:         $issection=$1;
                   7188:         $section=&mt('Group/Section').': '.$issection;
                   7189:         $middle=~s/^\[(.*)\]//;
1.290     www      7190:     }
                   7191:     $middle=~s/\.+$//;
                   7192:     $middle=~s/^\.+//;
1.291     www      7193:     if ($uname) {
1.560     damieng  7194:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7195:         $issection='';
1.291     www      7196:     }
1.316     albertel 7197:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7198:     my $realmdescription=&mt('all resources');
1.556     raeburn  7199:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7200:         my $mapurl = $1;
                   7201:         my $maplevel = $2;
                   7202:         my $leveltitle = &mt('Folder/Map');
                   7203:         if ($maplevel eq 'rec') {
                   7204:             $leveltitle = &mt('Recursive');
                   7205:         }
1.560     damieng  7206:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7207:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7208:             $mapurl.')</span></span>';
                   7209:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7210:     } elsif ($middle) {
                   7211:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7212:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7213:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7214:             ' in '.$map.' id: '.$id.')</span></span>';
                   7215:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7216:     }
1.291     www      7217:     my $what=$part.'.'.$name;
1.330     albertel 7218:     return ($realm,$section,$name,$part,
1.473     amueller 7219:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7220: }
1.293     www      7221: 
1.563     damieng  7222: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7223: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7224: 
1.563     damieng  7225: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7226: sub load_parameter_names {
1.583     raeburn  7227:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7228:     while (my $configline=<$config>) {
1.560     damieng  7229:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7230:         chomp($configline);
                   7231:         my ($short,$plain)=split(/:/,$configline);
                   7232:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7233:         if ($type eq 'display') {
                   7234:             $standard_parms{$name} = $plain;
1.469     raeburn  7235:         } elsif ($type eq 'type') {
1.560     damieng  7236:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7237:         }
1.328     albertel 7238:     }
                   7239:     close($config);
                   7240:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7241:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7242:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7243: }
                   7244: 
1.563     damieng  7245: # Returns a parameter title for standard parameters, the name for others.
                   7246: #
                   7247: # @param {string} $name - parameter name
                   7248: # @returns {string}
1.292     www      7249: sub standard_parameter_names {
                   7250:     my ($name)=@_;
1.328     albertel 7251:     if (!%standard_parms) {
1.560     damieng  7252:         &load_parameter_names();
1.328     albertel 7253:     }
1.292     www      7254:     if ($standard_parms{$name}) {
1.560     damieng  7255:         return $standard_parms{$name};
1.446     bisitz   7256:     } else {
1.560     damieng  7257:         return $name;
1.292     www      7258:     }
                   7259: }
1.290     www      7260: 
1.563     damieng  7261: # Returns a parameter type for standard parameters, undef for others.
                   7262: #
                   7263: # @param {string} $name - parameter name
                   7264: # @returns {string}
1.469     raeburn  7265: sub standard_parameter_types {
                   7266:     my ($name)=@_;
                   7267:     if (!%standard_parms_types) {
                   7268:         &load_parameter_names();
                   7269:     }
                   7270:     if ($standard_parms_types{$name}) {
                   7271:         return $standard_parms_types{$name};
                   7272:     }
                   7273:     return;
                   7274: }
1.309     www      7275: 
1.563     damieng  7276: # Returns a parameter level title (not localized) from the parameter level name.
                   7277: #
                   7278: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7279: # @returns {string}
1.557     raeburn  7280: sub standard_parameter_levels {
                   7281:     my ($name)=@_;
                   7282:     my %levels = (
                   7283:                     'resourcelevel'   => 'a single resource',
                   7284:                     'maplevel'        => 'the enclosing map/folder', 
                   7285:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7286:                     'courselevel'     => 'the general (course) level',
                   7287:                  );
                   7288:     if ($levels{$name}) {
                   7289:         return $levels{$name};
                   7290:     }
                   7291:     return;
                   7292: }
                   7293: 
1.560     damieng  7294: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7295: #
                   7296: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7297: sub parm_change_log {
1.568     raeburn  7298:     my ($r,$parm_permission)=@_;
1.531     raeburn  7299:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7300:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7301:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7302:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7303:     text=>"Parameter Change Log"});
1.522     raeburn  7304:     my $js = '<script type="text/javascript">'."\n".
                   7305:              '// <![CDATA['."\n".
                   7306:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7307:              '// ]]>'."\n".
                   7308:              '</script>'."\n";
                   7309:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7310:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7311:     &startSettingsScreen($r,'parmset',$crstype);
                   7312:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7313: 
1.301     www      7314:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7315: 
1.522     raeburn  7316:     $r->print('<div class="LC_left_float">'.
                   7317:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7318:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7319:                      method="post" name="parameterlog">');
1.446     bisitz   7320: 
1.311     albertel 7321:     my %saveable_parameters = ('show' => 'scalar',);
                   7322:     &Apache::loncommon::store_course_settings('parameter_log',
                   7323:                                               \%saveable_parameters);
                   7324:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7325:                                                 \%saveable_parameters);
1.522     raeburn  7326:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7327:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7328:               '</form></fieldset></div><br clear="all" />');
1.301     www      7329: 
1.568     raeburn  7330:     my $readonly = 1;
                   7331:     if ($parm_permission->{'edit'}) {
                   7332:         undef($readonly);
                   7333:     }
1.531     raeburn  7334:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7335:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7336:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7337:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7338:     unless ($readonly) {
                   7339:         $r->print('<th>'.&mt('Announce').'</th>');
                   7340:     }
                   7341:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7342:     my $shown=0;
1.349     www      7343:     my $folder='';
                   7344:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7345:         my $last='';
                   7346:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7347:                 &GDBM_READER(),0640)) {
                   7348:             $last=$hash{'last_known'};
                   7349:             untie(%hash);
                   7350:         }
                   7351:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7352:     }
1.595     raeburn  7353:     my $numgroups = 0;
                   7354:     my @groups;
                   7355:     if ($env{'request.course.groups'} ne '') {
                   7356:         @groups = split(/:/,$env{'request.course.groups'});
                   7357:         $numgroups = scalar(@groups);
                   7358:     }
1.560     damieng  7359:     foreach my $id (sort {
                   7360:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7361:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7362:                 }
                   7363:                 my $aid = (split('00000',$a))[-1];
                   7364:                 my $bid = (split('00000',$b))[-1];
                   7365:                 return $bid<=>$aid;
1.473     amueller 7366:             } (keys(%parmlog))) {
1.294     www      7367:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7368:         my $count = 0;
                   7369:         my $time =
                   7370:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7371:         my $plainname =
                   7372:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7373:                         $parmlog{$id}{'exe_udom'});
                   7374:         my $about_me_link =
                   7375:             &Apache::loncommon::aboutmewrapper($plainname,
                   7376:                             $parmlog{$id}{'exe_uname'},
                   7377:                             $parmlog{$id}{'exe_udom'});
                   7378:         my $send_msg_link='';
1.568     raeburn  7379:         if ((!$readonly) && 
                   7380:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7381:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7382:             $send_msg_link ='<br />'.
                   7383:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7384:                             $parmlog{$id}{'exe_uname'},
                   7385:                             $parmlog{$id}{'exe_udom'});
                   7386:         }
                   7387:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7388:         my $makenewrow=0;
                   7389:         my %istype=();
                   7390:         my $output;
                   7391:         foreach my $changed (reverse(sort(@changes))) {
                   7392:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7393:             my $typeflag = ($changed =~/\.type$/ &&
                   7394:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7395:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7396:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7397:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7398:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7399:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7400:                 if ($uname ne '') {
                   7401:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7402:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7403:                 }
                   7404:             }
                   7405:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7406:                 if ($folder) {
                   7407:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7408:                 }
                   7409:             }
                   7410:             if ($typeflag) {
                   7411:                 $istype{$parmname}=$value;
                   7412:                 if (!$env{'form.includetypes'}) { next; }
                   7413:             }
                   7414:             $count++;
                   7415:             if ($makenewrow) {
                   7416:                 $output .= $row_start;
                   7417:             } else {
                   7418:                 $makenewrow=1;
                   7419:             }
1.470     raeburn  7420:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7421:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7422:                 &mt($parmitem).'</td><td>'.
                   7423:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7424:             my $stillactive=0;
                   7425:             if ($parmlog{$id}{'delflag'}) {
                   7426:                 $output .= &mt('Deleted');
                   7427:             } else {
                   7428:                 if ($typeflag) {
1.470     raeburn  7429:                     my $parmitem = &standard_parameter_names($value); 
                   7430:                     $parmitem = &mt($parmitem);
1.560     damieng  7431:                     $output .= &mt('Type: [_1]',$parmitem);
                   7432:                 } else {
1.584     raeburn  7433:                     my $toolsymb;
                   7434:                     if ($middle =~ /ext\.tool$/) {
                   7435:                         $toolsymb = $middle;
                   7436:                     }
1.560     damieng  7437:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7438:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7439:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7440:                     my $showvalue = $value;
                   7441:                     if ($istype{$parmname} eq '') {
                   7442:                         my $type = &standard_parameter_types($parmname);
                   7443:                         if ($type ne '') {
                   7444:                             if (&isdateparm($type)) {
                   7445:                                 $showvalue =
                   7446:                                     &Apache::lonlocal::locallocaltime($value);
                   7447:                             }
                   7448:                         }
                   7449:                     } else {
1.560     damieng  7450:                         if (&isdateparm($istype{$parmname})) {
                   7451:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7452:                         }
1.469     raeburn  7453:                     }
                   7454:                     $output .= $showvalue;
1.560     damieng  7455:                     if ($value ne $all[$level]) {
                   7456:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7457:                     } else {
                   7458:                         $stillactive=1;
                   7459:                     }
                   7460:                 }
1.473     amueller 7461:             }
1.568     raeburn  7462:             $output .= '</td>';
                   7463: 
                   7464:             unless ($readonly) { 
                   7465:                 $output .= '<td>';
                   7466:                 if ($stillactive) {
                   7467:                     my $parmitem = &standard_parameter_names($parmname);
                   7468:                     $parmitem = &mt($parmitem);
                   7469:                     my $title=&mt('Changed [_1]',$parmitem);
                   7470:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7471:                         $parmitem,$realmdescription,
                   7472:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7473:                     if (($uname) && ($udom)) {
                   7474:                         $output .=
                   7475:                         &Apache::loncommon::messagewrapper('Notify User',
                   7476:                                                            $uname,$udom,$title,
                   7477:                                                            $description);
                   7478:                     } else {
                   7479:                         $output .=
                   7480:                             &Apache::lonrss::course_blog_link($id,$title,
                   7481:                                                               $description);
                   7482:                     }
1.560     damieng  7483:                 }
1.568     raeburn  7484:                 $output .= '</td>';
1.560     damieng  7485:             }
1.568     raeburn  7486:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7487:         }
1.560     damieng  7488:         if ($env{'form.displayfilter'} eq 'containing') {
                   7489:             my $wholeentry=$about_me_link.':'.
                   7490:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7491:             $output;
                   7492:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7493:         }
1.349     www      7494:         if ($count) {
1.560     damieng  7495:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7496:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7497:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7498:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7499:             $send_msg_link.'</td>'.$output);
                   7500:             $shown++;
                   7501:         }
                   7502:         if (!($env{'form.show'} eq &mt('all')
                   7503:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7504:     }
1.301     www      7505:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7506:     &endSettingsScreen($r);
1.284     www      7507:     $r->print(&Apache::loncommon::end_page());
                   7508: }
                   7509: 
1.560     damieng  7510: ##################################################
                   7511: # MISC !
                   7512: ##################################################
                   7513: 
1.563     damieng  7514: # Stores slot information.
1.560     damieng  7515: # Used by table UI
1.563     damieng  7516: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7517: #
                   7518: # @param {string} $slot_name - slot name
                   7519: # @param {string} $cdom - course domain
                   7520: # @param {string} $cnum - course number
                   7521: # @param {string} $symb - resource symb
                   7522: # @param {string} $uname - user name
                   7523: # @param {string} $udom - user domain
                   7524: # @returns {string} - 'ok' or error name
1.437     raeburn  7525: sub update_slots {
                   7526:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7527:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7528:     if (!keys(%slot)) {
                   7529:         return 'error: slot does not exist';
                   7530:     }
                   7531:     my $max=$slot{'maxspace'};
                   7532:     if (!defined($max)) { $max=99999; }
                   7533: 
                   7534:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7535:                                        "^$slot_name\0");
                   7536:     my ($tmp)=%consumed;
                   7537:     if ($tmp=~/^error: 2 / ) {
                   7538:         return 'error: unable to determine current slot status';
                   7539:     }
                   7540:     my $last=0;
                   7541:     foreach my $key (keys(%consumed)) {
                   7542:         my $num=(split('\0',$key))[1];
                   7543:         if ($num > $last) { $last=$num; }
                   7544:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7545:             return 'ok';
                   7546:         }
                   7547:     }
                   7548: 
                   7549:     if (scalar(keys(%consumed)) >= $max) {
                   7550:         return 'error: no space left in slot';
                   7551:     }
                   7552:     my $wanted=$last+1;
                   7553: 
                   7554:     my %reservation=('name'      => $uname.':'.$udom,
                   7555:                      'timestamp' => time,
                   7556:                      'symb'      => $symb);
                   7557: 
                   7558:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7559:                                         {"$slot_name\0$wanted" =>
                   7560:                                              \%reservation},
                   7561:                                         $cdom, $cnum);
1.438     raeburn  7562:     if ($success eq 'ok') {
                   7563:         my %storehash = (
                   7564:                           symb    => $symb,
                   7565:                           slot    => $slot_name,
                   7566:                           action  => 'reserve',
                   7567:                           context => 'parameter',
                   7568:                         );
1.526     raeburn  7569:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7570:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7571: 
1.526     raeburn  7572:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7573:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7574:     }
1.437     raeburn  7575:     return $success;
                   7576: }
                   7577: 
1.563     damieng  7578: # Deletes a slot reservation.
1.560     damieng  7579: # Used by table UI
1.563     damieng  7580: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7581: #
                   7582: # @param {string} $slot_name - slot name
                   7583: # @param {string} $cdom - course domain
                   7584: # @param {string} $cnum - course number
                   7585: # @param {string} $uname - user name
                   7586: # @param {string} $udom - user domain
                   7587: # @param {string} $symb - resource symb
                   7588: # @returns {string} - 'ok' or error name
1.437     raeburn  7589: sub delete_slots {
                   7590:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7591:     my $delresult;
                   7592:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7593:                                          $cnum, "^$slot_name\0");
                   7594:     if (&Apache::lonnet::error(%consumed)) {
                   7595:         return 'error: unable to determine current slot status';
                   7596:     }
                   7597:     my ($tmp)=%consumed;
                   7598:     if ($tmp=~/^error: 2 /) {
                   7599:         return 'error: unable to determine current slot status';
                   7600:     }
                   7601:     foreach my $key (keys(%consumed)) {
                   7602:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7603:             my $num=(split('\0',$key))[1];
                   7604:             my $entry = $slot_name.'\0'.$num;
                   7605:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7606:                                               $cdom,$cnum);
                   7607:             if ($delresult eq 'ok') {
                   7608:                 my %storehash = (
                   7609:                                   symb    => $symb,
                   7610:                                   slot    => $slot_name,
                   7611:                                   action  => 'release',
                   7612:                                   context => 'parameter',
                   7613:                                 );
1.526     raeburn  7614:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7615:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7616:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7617:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7618:             }
                   7619:         }
                   7620:     }
                   7621:     return $delresult;
                   7622: }
                   7623: 
1.563     damieng  7624: # Returns true if there is a current course.
1.560     damieng  7625: # Used by handler
1.563     damieng  7626: #
                   7627: # @returns {boolean}
1.355     albertel 7628: sub check_for_course_info {
                   7629:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7630:     return 1 if ($navmap);
                   7631:     return 0;
                   7632: }
                   7633: 
1.563     damieng  7634: # Returns the current course host and host LON-CAPA version.
                   7635: #
                   7636: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7637: sub parameter_release_vars { 
1.504     raeburn  7638:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7639:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7640:    my $chostname = &Apache::lonnet::hostname($chome);
                   7641:    my ($cmajor,$cminor) = 
                   7642:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7643:    return ($chostname,$cmajor,$cminor);
                   7644: }
                   7645: 
1.563     damieng  7646: # Checks if the course host version can handle a parameter required version,
                   7647: # and if it does, stores the release needed for the course.
                   7648: #
                   7649: # @param {string} $name - parameter name
                   7650: # @param {string} $value - parameter value
                   7651: # @param {string} $valmatch - name of the test used for checking the value
                   7652: # @param {string} $namematch - name of the test used for checking the name
                   7653: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7654: # @param {integer} $cmajor - course major version number
                   7655: # @param {integer} $cminor - course minor version number
                   7656: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7657: sub parameter_releasecheck {
1.557     raeburn  7658:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7659:     my $needsnewer;
                   7660:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7661:     if (($cmajor < $needsmajor) || 
                   7662:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7663:         $needsnewer = 1;
1.557     raeburn  7664:     } elsif ($name) {
                   7665:         if ($valmatch) {
                   7666:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7667:         } elsif ($value) { 
                   7668:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7669:         }
                   7670:     } elsif ($namematch) {
                   7671:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7672:     }
                   7673:     return $needsnewer;
                   7674: }
                   7675: 
1.568     raeburn  7676: sub get_permission {
                   7677:     my %permission;
                   7678:     my $allowed = 0;
                   7679:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7680:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7681:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7682:                   $env{'request.course.sec'}))) {
                   7683:         %permission= (
                   7684:                        'edit'               => 1,
                   7685:                        'set'                => 1,
                   7686:                        'setoverview'        => 1,
                   7687:                        'addmetadata'        => 1,
                   7688:                        'ordermetadata'      => 1,
                   7689:                        'setrestrictmeta'    => 1,
                   7690:                        'newoverview'        => 1,
                   7691:                        'setdefaults'        => 1,
                   7692:                        'settable'           => 1,
                   7693:                        'parameterchangelog' => 1,
                   7694:                        'cleanparameters'    => 1,
                   7695:                        'dateshift1'         => 1,
                   7696:                        'dateshift2'         => 1,
                   7697:                        'helper'             => 1,
                   7698:          );
                   7699:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7700:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7701:                   $env{'request.course.sec'}))) {
                   7702:         %permission = (
                   7703:                        'set'                => 1,
                   7704:                        'settable'           => 1,
                   7705:                        'newoverview'        => 1,
                   7706:                        'setoverview'        => 1,
                   7707:                        'parameterchangelog' => 1,
                   7708:                       );
                   7709:     }
                   7710:     foreach my $perm (values(%permission)) {
                   7711:         if ($perm) { $allowed=1; last; }
                   7712:     }
                   7713:     return (\%permission,$allowed);
                   7714: }
                   7715: 
1.560     damieng  7716: ##################################################
                   7717: # HANDLER
                   7718: ##################################################
                   7719: 
                   7720: # Main handler for lonparmset.
                   7721: # Sub called based on request parameters action and command:
                   7722: # no command or action: print_main_menu
                   7723: # command 'set': assessparms (direct access to table mode for a resource)
                   7724: #                (this can also be accessed simply with the symb parameter)
                   7725: # action 'setoverview': overview (display all existing parameter settings)
                   7726: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7727: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7728: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7729: # action 'newoverview': newoverview (overview mode)
                   7730: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7731: # action 'settable': assessparms (table mode)
                   7732: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7733: #                              blog postings, user notification changes)
                   7734: # action 'cleanparameters': clean_parameters (unused)
                   7735: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7736: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7737: sub handler {
1.43      albertel 7738:     my $r=shift;
1.30      www      7739: 
1.376     albertel 7740:     &reset_caches();
                   7741: 
1.414     droeschl 7742:     &Apache::loncommon::content_type($r,'text/html');
                   7743:     $r->send_http_header;
                   7744:     return OK if $r->header_only;
                   7745: 
1.193     albertel 7746:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7747:                         ['action','state',
1.205     www      7748:                                              'pres_marker',
                   7749:                                              'pres_value',
1.206     www      7750:                                              'pres_type',
1.506     www      7751:                                              'filter','part',
1.390     www      7752:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7753: 
1.83      bowersj2 7754: 
1.193     albertel 7755:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7756:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7757:                         text=>"Content and Problem Settings",
1.473     amueller 7758:                         faq=>10,
                   7759:                         bug=>'Instructor Interface',
1.442     droeschl 7760:                                             help =>
                   7761:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7762: 
1.30      www      7763: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7764:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7765:     my $exists = &check_for_course_info();
                   7766: 
1.568     raeburn  7767:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7768:         #
                   7769:         # Main switch on form.action and form.state, as appropriate
                   7770:         #
                   7771:         # Check first if coming from someone else headed directly for
                   7772:         #  the table mode
1.568     raeburn  7773:         if (($parm_permission->{'set'}) && 
                   7774:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7775:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7776:             &assessparms($r,$parm_permission);
1.193     albertel 7777:         } elsif (! exists($env{'form.action'})) {
                   7778:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7779:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7780:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7781:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7782:             &overview($r,$parm_permission);
1.560     damieng  7783:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7784:             &addmetafield($r);
                   7785:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7786:             &order_meta_fields($r);
1.414     droeschl 7787:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7788:             &setrestrictmeta($r);
1.414     droeschl 7789:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7790:             &newoverview($r,$parm_permission);
1.414     droeschl 7791:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7792:             &defaultsetter($r);
                   7793:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7794:             &assessparms($r,$parm_permission);
1.414     droeschl 7795:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7796:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7797:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7798:             &clean_parameters($r);
1.414     droeschl 7799:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7800:             &date_shift_one($r);
1.414     droeschl 7801:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7802:             &date_shift_two($r);
1.446     bisitz   7803:         }
1.43      albertel 7804:     } else {
1.1       www      7805: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7806:         if ($exists) {
                   7807:             $env{'user.error.msg'}=
                   7808:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7809:         } else {
                   7810:             $env{'user.error.msg'}=
                   7811:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7812:         }
                   7813:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7814:     }
1.376     albertel 7815:     &reset_caches();
                   7816: 
1.43      albertel 7817:     return OK;
1.1       www      7818: }
                   7819: 
                   7820: 1;
                   7821: __END__
                   7822: 
                   7823: 

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