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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.617   ! raeburn     4: # $Id: lonparmset.pm,v 1.616 2022/07/07 03:37:01 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.617   ! raeburn   332: use Text::Wrap();
1.416     jms       333: use LONCAPA qw(:DEFAULT :match);
                    334: 
                    335: 
1.560     damieng   336: ##################################################
                    337: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    338: ##################################################
                    339: 
                    340: # Page header
1.561     damieng   341: #
                    342: # @param {Apache2::RequestRec} $r - Apache request object
                    343: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    344: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       345: sub startSettingsScreen {
1.531     raeburn   346:     my ($r,$mode,$crstype)=@_;
1.507     www       347: 
1.531     raeburn   348:     my $tabtext = &mt('Course Settings');
                    349:     if ($crstype eq 'Community') {
                    350:         $tabtext = &mt('Community Settings');
                    351:     } 
1.507     www       352:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    353:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   354:                                           $tabtext.
1.507     www       355:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    356: 
1.523     raeburn   357:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       358:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    359:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   360:     $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       361: }
                    362: 
1.560     damieng   363: # Page footer
1.507     www       364: sub endSettingsScreen {
                    365:    my ($r)=@_;
                    366:    $r->print('</div></div></div>');
                    367: }
                    368: 
                    369: 
                    370: 
1.560     damieng   371: ##################################################
1.563     damieng   372: # (mostly) TABLE MODE
1.560     damieng   373: # (parmval is also used for the log of parameter changes)
                    374: ##################################################
                    375: 
1.566     damieng   376: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   377: #
                    378: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   379: # @param {string} $id - resource id or map pc
1.561     damieng   380: # @param {string} $def - the resource's default value for this parameter
                    381: # @param {string} $uname - user name
                    382: # @param {string} $udom - user domain
                    383: # @param {string} $csec - section name
                    384: # @param {string} $cgroup - group name
                    385: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    386: # @returns {Array}
1.2       www       387: sub parmval {
1.275     raeburn   388:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    389:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    390:                                                            $cgroup,$courseopt);
1.201     www       391: }
                    392: 
1.561     damieng   393: # Returns an array containing
                    394: # - the most specific level that is defined for that parameter (integer)
                    395: # - an array with the level as index and the parameter value as value (when defined)
                    396: #   (level 1 is the most specific and will have precedence)
                    397: #
                    398: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   399: # @param {string} $symb - resource symb or map src
1.561     damieng   400: # @param {string} $def - the resource's default value for this parameter
                    401: # @param {string} $uname - user name
                    402: # @param {string} $udom - user domain
                    403: # @param {string} $csec - section name
                    404: # @param {string} $cgroup - group name
                    405: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    406: # @returns {Array}
1.201     www       407: sub parmval_by_symb {
1.275     raeburn   408:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       409: 
1.352     albertel  410:     my $useropt;
                    411:     if ($uname ne '' && $udom ne '') {
1.561     damieng   412:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  413:     }
1.200     www       414: 
1.8       www       415:     my $result='';
1.44      albertel  416:     my @outpar=();
1.2       www       417: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    418:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  419:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   420:     
                    421:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    422:     # any change should be reflected there.
                    423:     
1.201     www       424:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   425:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       426:     my $mapparm=$map.'___(all).'.$what;
1.10      www       427: 
1.269     raeburn   428:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    429:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   430:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   431:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    432: 
1.190     albertel  433:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    434:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   435:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  436:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    437: 
                    438:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    439:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   440:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  441:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       442: 
1.11      www       443: 
1.182     albertel  444: # --------------------------------------------------------- first, check course
1.11      www       445: 
1.561     damieng   446: # 18 - General Course
1.200     www       447:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   448:         $outpar[18]=$$courseopt{$courselevel};
                    449:         $result=18;
                    450:     }
                    451: 
1.561     damieng   452: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   453:     if (defined($$courseopt{$courseleveli})) {
                    454:         $outpar[17]=$$courseopt{$courseleveli};
                    455:         $result=17;
1.43      albertel  456:     }
1.11      www       457: 
1.561     damieng   458: # 16 - Map or Folder level in course (non-recursive)
1.200     www       459:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   460:         $outpar[16]=$$courseopt{$courselevelm};
                    461:         $result=16;
1.43      albertel  462:     }
1.11      www       463: 
1.182     albertel  464: # ------------------------------------------------------- second, check default
                    465: 
1.561     damieng   466: # 15 - resource default
1.556     raeburn   467:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  468: 
                    469: # ------------------------------------------------------ third, check map parms
                    470: 
1.556     raeburn   471:     
1.561     damieng   472: # 14 - map default
1.376     albertel  473:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   474:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  475: 
1.561     damieng   476: # 13 - resource level in course
1.200     www       477:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   478:         $outpar[13]=$$courseopt{$courselevelr};
                    479:         $result=13;
1.43      albertel  480:     }
1.11      www       481: 
1.182     albertel  482: # ------------------------------------------------------ fourth, back to course
1.352     albertel  483:     if ($csec ne '') {
1.561     damieng   484: # 12 - General for section
1.200     www       485:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   486:             $outpar[12]=$$courseopt{$seclevel};
                    487:             $result=12;
                    488:         }
1.561     damieng   489: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   490:         if (defined($$courseopt{$secleveli})) {
                    491:             $outpar[11]=$$courseopt{$secleveli};
                    492:             $result=11;
                    493:         }
1.561     damieng   494: # 10 - Map or Folder level for section (non-recursive)
1.200     www       495:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   496:             $outpar[10]=$$courseopt{$seclevelm};
                    497:             $result=10;
                    498:         }
1.561     damieng   499: # 9 - resource level in section
1.200     www       500:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   501:             $outpar[9]=$$courseopt{$seclevelr};
                    502:             $result=9;
                    503:         }
1.43      albertel  504:     }
1.275     raeburn   505: # ------------------------------------------------------ fifth, check course group
1.352     albertel  506:     if ($cgroup ne '') {
1.561     damieng   507: # 8 - General for group
1.269     raeburn   508:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   509:             $outpar[8]=$$courseopt{$grplevel};
                    510:             $result=8;
                    511:         }
1.561     damieng   512: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   513:         if (defined($$courseopt{$grpleveli})) {
                    514:             $outpar[7]=$$courseopt{$grpleveli};
                    515:             $result=7;
1.269     raeburn   516:         }
1.561     damieng   517: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   518:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   519:             $outpar[6]=$$courseopt{$grplevelm};
                    520:             $result=6;
1.269     raeburn   521:         }
1.561     damieng   522: # 5 - resource level in group
1.269     raeburn   523:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   524:             $outpar[5]=$$courseopt{$grplevelr};
                    525:             $result=5;
1.269     raeburn   526:         }
                    527:     }
1.11      www       528: 
1.556     raeburn   529: # ---------------------------------------------------------- sixth, check user
1.11      www       530: 
1.352     albertel  531:     if ($uname ne '') {
1.561     damieng   532: # 4 - General for specific student
                    533:         if (defined($$useropt{$courselevel})) {
                    534:             $outpar[4]=$$useropt{$courselevel};
                    535:             $result=4;
                    536:         }
1.556     raeburn   537: 
1.561     damieng   538: # 3 - Map or Folder level for specific student (recursive)
                    539:         if (defined($$useropt{$courseleveli})) {
                    540:             $outpar[3]=$$useropt{$courseleveli};
                    541:             $result=3;
                    542:         }
1.473     amueller  543: 
1.561     damieng   544: # 2 - Map or Folder level for specific student (non-recursive)
                    545:         if (defined($$useropt{$courselevelm})) {
                    546:             $outpar[2]=$$useropt{$courselevelm};
                    547:             $result=2;
                    548:         }
1.473     amueller  549: 
1.561     damieng   550: # 1 - resource level for specific student
                    551:         if (defined($$useropt{$courselevelr})) {
                    552:             $outpar[1]=$$useropt{$courselevelr};
                    553:             $result=1;
                    554:         }
1.43      albertel  555:     }
1.44      albertel  556:     return ($result,@outpar);
1.2       www       557: }
                    558: 
1.198     www       559: 
                    560: 
1.376     albertel  561: # --- Caches local to lonparmset
                    562: 
1.446     bisitz    563: 
1.561     damieng   564: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  565: sub reset_caches {
                    566:     &resetparmhash();
                    567:     &resetsymbcache();
                    568:     &resetrulescache();
1.203     www       569: }
                    570: 
1.561     damieng   571: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    572: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  573: {
1.561     damieng   574:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    575:     my %parmhash; # the parameter cache
                    576:     # reset map parameter hash
1.376     albertel  577:     sub resetparmhash {
1.560     damieng   578:         undef($parmhashid);
                    579:         undef(%parmhash);
1.376     albertel  580:     }
1.446     bisitz    581: 
1.561     damieng   582:     # dump the _parms.db database into %parmhash
1.376     albertel  583:     sub cacheparmhash {
1.560     damieng   584:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    585:         my %parmhashfile;
                    586:         if (tie(%parmhashfile,'GDBM_File',
                    587:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    588:             %parmhash=%parmhashfile;
                    589:             untie(%parmhashfile);
                    590:             $parmhashid=$env{'request.course.fn'};
                    591:         }
1.201     www       592:     }
1.446     bisitz    593: 
1.561     damieng   594:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  595:     sub parmhash {
1.560     damieng   596:         my ($id) = @_;
                    597:         &cacheparmhash();
                    598:         return $parmhash{$id};
1.376     albertel  599:     }
1.560     damieng   600: }
1.376     albertel  601: 
1.566     damieng   602: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    603: {
1.561     damieng   604:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    605:     my %symbs; # hash id->symb
                    606:     # reset the id->symb cache
1.376     albertel  607:     sub resetsymbcache {
1.560     damieng   608:         undef($symbsid);
                    609:         undef(%symbs);
1.376     albertel  610:     }
1.446     bisitz    611: 
1.566     damieng   612:     # returns the resource symb or map src corresponding to a resource id or map pc
                    613:     # (using lonnavmaps and a cache)
1.376     albertel  614:     sub symbcache {
1.560     damieng   615:         my $id=shift;
                    616:         if ($symbsid ne $env{'request.course.id'}) {
                    617:             undef(%symbs);
                    618:         }
                    619:         if (!$symbs{$id}) {
                    620:             my $navmap = Apache::lonnavmaps::navmap->new();
                    621:             if ($id=~/\./) {
                    622:                 my $resource=$navmap->getById($id);
                    623:                 $symbs{$id}=$resource->symb();
                    624:             } else {
                    625:                 my $resource=$navmap->getByMapPc($id);
                    626:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    627:             }
                    628:             $symbsid=$env{'request.course.id'};
1.473     amueller  629:         }
1.560     damieng   630:         return $symbs{$id};
1.473     amueller  631:     }
1.560     damieng   632: }
1.201     www       633: 
1.561     damieng   634: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    635: {
1.561     damieng   636:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    637:     my %rules; # parameter default actions hash
1.376     albertel  638:     sub resetrulescache {
1.560     damieng   639:         undef($rulesid);
                    640:         undef(%rules);
1.376     albertel  641:     }
1.446     bisitz    642: 
1.561     damieng   643:     # returns the value for a given key in the parameter default action hash
1.376     albertel  644:     sub rulescache {
1.560     damieng   645:         my $id=shift;
                    646:         if ($rulesid ne $env{'request.course.id'}
                    647:             && !defined($rules{$id})) {
                    648:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    649:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    650:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    651:             $rulesid=$env{'request.course.id'};
                    652:         }
                    653:         return $rules{$id};
1.221     www       654:     }
                    655: }
                    656: 
1.416     jms       657: 
1.561     damieng   658: # Returns the values of the parameter type default action
                    659: # "default value when manually setting".
                    660: # If none is defined, ('','','','','') is returned.
                    661: #
                    662: # @param {string} $type - parameter type
                    663: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       664: sub preset_defaults {
                    665:     my $type=shift;
                    666:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   667:         # yes, there is something
                    668:         return (&rulescache($type.'_hours'),
                    669:             &rulescache($type.'_min'),
                    670:             &rulescache($type.'_sec'),
                    671:             &rulescache($type.'_value'));
1.229     www       672:     } else {
1.560     damieng   673:         # nothing there or something else
                    674:         return ('','','','','');
1.229     www       675:     }
                    676: }
                    677: 
1.416     jms       678: 
1.561     damieng   679: # Checks that a date is after enrollment start date and before
                    680: # enrollment end date.
                    681: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    682: # This is used by both overview and table modes.
                    683: #
                    684: # @param {integer} $checkdate - the date to check.
                    685: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       686: sub date_sanity_info {
                    687:    my $checkdate=shift;
                    688:    unless ($checkdate) { return ''; }
                    689:    my $result='';
                    690:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    691:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    692:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    693:          $result.='<div class="LC_warning">'
                    694:                  .&mt('After course enrollment end!')
                    695:                  .'</div>';
1.277     www       696:       }
                    697:    }
                    698:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    699:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    700:          $result.='<div class="LC_warning">'
                    701:                  .&mt('Before course enrollment start!')
                    702:                  .'</div>';
1.277     www       703:       }
                    704:    }
1.413     bisitz    705: # Preparation for additional warnings about dates in the past/future.
                    706: # An improved, more context sensitive version is recommended,
                    707: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    708: #   if ($checkdate<time) {
                    709: #      $result.='<div class="LC_info">'
                    710: #              .'('.&mt('in the past').')'
                    711: #              .'</div>';
                    712: #      }
                    713: #   if ($checkdate>time) {
                    714: #      $result.='<div class="LC_info">'
                    715: #              .'('.&mt('in the future').')'
                    716: #              .'</div>';
                    717: #      }
1.277     www       718:    return $result;
                    719: }
1.561     damieng   720: 
                    721: 
                    722: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       723: #
1.566     damieng   724: # @param {string} $sresid - resource id or map pc
1.565     damieng   725: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   726: # @param {integer} $snum - level
                    727: # @param {string} $nval - new value
                    728: # @param {string} $ntype - new type
                    729: # @param {string} $uname - username
                    730: # @param {string} $udom - userdomain
                    731: # @param {string} $csec - section name
                    732: # @param {string} $cgroup - group name
1.186     www       733: sub storeparm {
1.269     raeburn   734:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   735:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       736: }
                    737: 
1.561     damieng   738: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    739: 
                    740: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    741: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    742: #
1.566     damieng   743: # @param {string} $symb - resource symb or map src
1.565     damieng   744: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   745: # @param {integer} $snum - level
                    746: # @param {string} $nval - new value
                    747: # @param {string} $ntype - new type
                    748: # @param {string} $uname - username
                    749: # @param {string} $udom - userdomain
                    750: # @param {string} $csec - section name
                    751: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    752: # @param {string} $cgroup - group name
1.197     www       753: sub storeparm_by_symb {
1.275     raeburn   754:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       755:     unless ($recflag) {
1.560     damieng   756:         # first time call
                    757:         %recstack=();
                    758:         $recflag=1;
1.226     www       759:     }
1.560     damieng   760:     # store parameter
1.226     www       761:     &storeparm_by_symb_inner
1.473     amueller  762:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   763:     # don't do anything if parameter was reset
1.266     www       764:     unless ($nval) { return; }
1.226     www       765:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   766:     # remember that this was set
1.226     www       767:     $recstack{$parm}=1;
1.560     damieng   768:     # what does this trigger?
1.226     www       769:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   770:         # don't backfire
                    771:         unless ((!$triggered) || ($recstack{$triggered})) {
                    772:             my $action=&rulescache($triggered.'_action');
                    773:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    774:             # set triggered parameter on same level
                    775:             my $newspnam=$prefix.$triggered;
                    776:             my $newvalue='';
                    777:             my $active=1;
                    778:             if ($action=~/^when\_setting/) {
                    779:             # are there restrictions?
                    780:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    781:                     $active=0;
1.565     damieng   782:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   783:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    784:                     }
                    785:                 }
                    786:                 $newvalue=&rulescache($triggered.'_value');
                    787:             } else {
                    788:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    789:                 if ($action=~/^later\_than/) {
                    790:                     $newvalue=$nval+$totalsecs;
                    791:                 } else {
                    792:                     $newvalue=$nval-$totalsecs;
                    793:                 }
                    794:             }
                    795:             if ($active) {
                    796:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    797:                         $uname,$udom,$csec,$recflag,$cgroup);
                    798:             }
                    799:         }
1.226     www       800:     }
                    801:     return '';
                    802: }
                    803: 
1.561     damieng   804: # Adds all given arguments to the course parameter log.
                    805: # @returns {string} - the answer to the lonnet query.
1.293     www       806: sub log_parmset {
1.525     raeburn   807:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       808: }
                    809: 
1.561     damieng   810: # Store a parameter value and type by symb, without using the parameter default actions.
                    811: # Expire related sheets.
                    812: #
1.566     damieng   813: # @param {string} $symb - resource symb or map src
1.561     damieng   814: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    815: # @param {integer} $snum - level
                    816: # @param {string} $nval - new value
                    817: # @param {string} $ntype - new type
                    818: # @param {string} $uname - username
                    819: # @param {string} $udom - userdomain
                    820: # @param {string} $csec - section name
                    821: # @param {string} $cgroup - group name
                    822: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       823: sub storeparm_by_symb_inner {
1.197     www       824: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   825:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       826: # ---------------------------------------------------------- Construct prefixes
1.186     www       827:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    828:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  829:     $map = &Apache::lonnet::deversion($map);
                    830: 
1.197     www       831:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   832:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       833:     my $mapparm=$map.'___(all).'.$spnam;
                    834: 
1.269     raeburn   835:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    836:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   837:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   838:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    839: 
1.190     albertel  840:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    841:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   842:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  843:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    844: 
1.190     albertel  845:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    846:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   847:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  848:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    849: 
1.186     www       850:     my $storeunder='';
1.578     raeburn   851:     my $possreplace='';
1.556     raeburn   852:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   853:     if (($snum==17) || ($snum==3)) { 
                    854:         $storeunder=$courseleveli;
                    855:         $possreplace=$courselevelm; 
                    856:     } 
                    857:     if (($snum==16) || ($snum==2)) { 
                    858:         $storeunder=$courselevelm;
                    859:         $possreplace=$courseleveli;
                    860:     }
1.556     raeburn   861:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    862:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   863:     if ($snum==11) { 
                    864:         $storeunder=$secleveli;
                    865:         $possreplace=$seclevelm; 
                    866:     }
                    867:     if ($snum==10) { 
                    868:         $storeunder=$seclevelm;
                    869:         $possreplace=$secleveli;
                    870:     }
1.556     raeburn   871:     if ($snum==9) { $storeunder=$seclevelr; }
                    872:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   873:     if ($snum==7) { 
                    874:         $storeunder=$grpleveli;
                    875:         $possreplace=$grplevelm;
                    876:     }
                    877:     if ($snum==6) {
                    878:         $storeunder=$grplevelm;
                    879:         $possreplace=$grpleveli;
                    880:     }
1.556     raeburn   881:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   882: 
1.446     bisitz    883: 
1.186     www       884:     my $delete;
                    885:     if ($nval eq '') { $delete=1;}
                    886:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  887:             $storeunder.'.type' => $ntype);
1.186     www       888:     my $reply='';
1.560     damieng   889:     
1.556     raeburn   890:     if ($snum>4) {
1.186     www       891: # ---------------------------------------------------------------- Store Course
                    892: #
1.560     damieng   893:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    894:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    895:         # Expire sheets
                    896:         &Apache::lonnet::expirespread('','','studentcalc');
                    897:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    898:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   899:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   900:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    901:         } else {
                    902:             &Apache::lonnet::expirespread('','','assesscalc');
                    903:         }
                    904:         # Store parameter
                    905:         if ($delete) {
                    906:             $reply=&Apache::lonnet::del
                    907:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    908:                 &log_parmset(\%storecontent,1);
                    909:         } else {
                    910:             $reply=&Apache::lonnet::cput
                    911:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    912:             &log_parmset(\%storecontent);
1.578     raeburn   913:             if ($possreplace) {
                    914:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    915:                 if (ref($resdata) eq 'HASH') {
                    916:                     if (exists($resdata->{$possreplace})) {
                    917:                         if (&Apache::lonnet::del
                    918:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    919:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    920:                         }
                    921:                     }
                    922:                 }
                    923:             }
1.560     damieng   924:         }
                    925:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       926:     } else {
                    927: # ------------------------------------------------------------------ Store User
                    928: #
1.560     damieng   929:         # Expire sheets
                    930:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    931:         if ($snum==1) {
                    932:             &Apache::lonnet::expirespread
                    933:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   934:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   935:             &Apache::lonnet::expirespread
                    936:             ($uname,$udom,'assesscalc',$map);
                    937:         } else {
                    938:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    939:         }
                    940:         # Store parameter
                    941:         if ($delete) {
                    942:             $reply=&Apache::lonnet::del
                    943:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    944:             &log_parmset(\%storecontent,1,$uname,$udom);
                    945:         } else {
                    946:             $reply=&Apache::lonnet::cput
                    947:             ('resourcedata',\%storecontent,$udom,$uname);
                    948:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   949:             if ($possreplace) {
                    950:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    951:                 if (ref($resdata) eq 'HASH') {
                    952:                     if (exists($resdata->{$possreplace})) {
                    953:                         if (&Apache::lonnet::del
                    954:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    955:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    956:                                           $uname,$udom);
                    957:                         }
                    958:                     }
                    959:                 }
                    960:             }
1.560     damieng   961:         }
                    962:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       963:     }
1.446     bisitz    964: 
1.186     www       965:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   966:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       967:     }
                    968:     return '';
                    969: }
                    970: 
1.9       www       971: 
1.561     damieng   972: # Returns HTML with the value of the given parameter,
                    973: # using a readable format for dates, and
                    974: # a warning if there is a problem with a date.
                    975: # Used by table mode.
                    976: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    977: #
                    978: # @param {string} $value - the parameter value
                    979: # @param {string} $type - the parameter type
                    980: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       981: sub valout {
1.600     raeburn   982:     my ($value,$type,$editable)=@_;
1.59      matthew   983:     my $result = '';
                    984:     # Values of zero are valid.
                    985:     if (! $value && $value ne '0') {
1.528     bisitz    986:         if ($editable) {
                    987:             $result =
                    988:                 '<img src="/res/adm/pages/editmap.png"'
                    989:                .' alt="'.&mt('Change').'"'
1.539     raeburn   990:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    991:         } else {
                    992:             $result='&nbsp;';
                    993:         }
1.59      matthew   994:     } else {
1.66      www       995:         if ($type eq 'date_interval') {
1.559     raeburn   996:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    997:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    998:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    999:                 $donebuttontext = $1;
                   1000:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1001:                 $usesdone = 'done';
                   1002:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1003:                 $donebuttontext = &mt('Done');
                   1004:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1005:             }
1.554     raeburn  1006:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1007:             my @timer;
1.66      www      1008:             $year=$year-70;
                   1009:             $mday--;
                   1010:             if ($year) {
1.413     bisitz   1011: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1012:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1013:             }
                   1014:             if ($mon) {
1.413     bisitz   1015: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1016:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1017:             }
                   1018:             if ($mday) {
1.413     bisitz   1019: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1020:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1021:             }
                   1022:             if ($hour) {
1.413     bisitz   1023: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1024:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1025:             }
                   1026:             if ($min) {
1.413     bisitz   1027: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1028:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1029:             }
                   1030:             if ($sec) {
1.413     bisitz   1031: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1032:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1033:             }
1.413     bisitz   1034: #           $result=~s/\s+$//;
                   1035:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1036:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1037:             }
                   1038:             $result.=join(", ",@timer);
1.559     raeburn  1039:             if ($usesdone eq 'done') {
1.558     raeburn  1040:                 if ($secretkey) {
1.559     raeburn  1041:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1042:                 } else {
1.559     raeburn  1043:                     $result .= ' + "'.$donebuttontext.'"';
                   1044:                 }
1.554     raeburn  1045:             }
1.213     www      1046:         } elsif (&isdateparm($type)) {
1.361     albertel 1047:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1048:                 &date_sanity_info($value);
1.59      matthew  1049:         } else {
                   1050:             $result = $value;
1.517     www      1051:             $result=~s/\,/\, /gs;
1.560     damieng  1052:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1053:         }
                   1054:     }
                   1055:     return $result;
1.9       www      1056: }
                   1057: 
1.59      matthew  1058: 
1.561     damieng  1059: # Returns HTML containing a link on a parameter value, for table mode.
                   1060: # The link uses the javascript function 'pjump'.
                   1061: #
                   1062: # @param {string} $type - parameter type
                   1063: # @param {string} $dis - dialog title for editing the parameter value and type
                   1064: # @param {string} $value - parameter value
                   1065: # @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.
                   1066: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1067: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1068: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1069: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1070: sub plink {
1.588     raeburn  1071:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1072:     my $winvalue=$value;
                   1073:     unless ($winvalue) {
1.592     raeburn  1074:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1075:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1076:         } elsif ($type eq 'string_yesno') {
                   1077:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1078:                 $winvalue=$env{'form.recent_string'};
                   1079:             }
1.23      www      1080:         } else {
1.190     albertel 1081:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1082:         }
                   1083:     }
1.229     www      1084:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1085:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1086:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1087:     my $valout = &valout($value,$type,1);
1.429     raeburn  1088:     my $unencmarker = $marker;
1.378     albertel 1089:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1090:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1091:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1092:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1093:     }
1.429     raeburn  1094:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1095:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1096:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1097:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1098:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1099: 
1.5       www      1100: }
                   1101: 
1.561     damieng  1102: # Javascript for table mode.
1.280     albertel 1103: sub page_js {
                   1104: 
1.81      www      1105:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1106:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1107: 
                   1108:     return(<<ENDJS);
                   1109: <script type="text/javascript">
1.454     bisitz   1110: // <![CDATA[
1.44      albertel 1111: 
1.88      matthew  1112:     $pjump_def
1.44      albertel 1113: 
                   1114:     function psub() {
1.591     raeburn  1115:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1116:         if (document.parmform.pres_marker.value!='') {
                   1117:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1118:             var typedef=new Array();
                   1119:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1120:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1121:                 if ((typedef[0]=='date') || 
1.591     raeburn  1122:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1123:                     eval('document.parmform.recent_'+
                   1124:                         document.parmform.pres_type.value+
                   1125:                         '.value=document.parmform.pres_value.value;');
                   1126:                 } else {
                   1127:                     eval('document.parmform.recent_'+typedef[0]+
                   1128:                         '.value=document.parmform.pres_value.value;');
                   1129:                 }
1.44      albertel 1130:             }
                   1131:             document.parmform.submit();
                   1132:         } else {
                   1133:             document.parmform.pres_value.value='';
                   1134:             document.parmform.pres_marker.value='';
                   1135:         }
                   1136:     }
                   1137: 
1.57      albertel 1138:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1139:         var options = "width=" + w + ",height=" + h + ",";
                   1140:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1141:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1142:         var newWin = window.open(url, wdwName, options);
                   1143:         newWin.focus();
                   1144:     }
1.523     raeburn  1145: 
1.454     bisitz   1146: // ]]>
1.523     raeburn  1147: 
1.44      albertel 1148: </script>
1.81      www      1149: $selscript
1.280     albertel 1150: ENDJS
                   1151: 
                   1152: }
1.507     www      1153: 
1.561     damieng  1154: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1155: # for table and overview modes.
1.523     raeburn  1156: sub showhide_js {
                   1157:     return <<"COURSECONTENTSCRIPT";
                   1158: 
                   1159: function showHide_courseContent() {
                   1160:     var parmlevValue=document.getElementById("parmlev").value;
                   1161:     if (parmlevValue == 'general') {
                   1162:         document.getElementById('mapmenu').style.display="none";
                   1163:     } else {
                   1164:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1165:             document.getElementById('mapmenu').style.display ="";
                   1166:         } else {
                   1167:             document.getElementById('mapmenu').style.display="none";
                   1168:         }
                   1169:     }
                   1170:     return;
                   1171: }
                   1172: 
                   1173: COURSECONTENTSCRIPT
                   1174: }
                   1175: 
1.561     damieng  1176: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1177: sub toggleparmtextbox_js {
                   1178:     return <<"ENDSCRIPT";
                   1179: 
                   1180: if (!document.getElementsByClassName) {
                   1181:     function getElementsByClassName(node, classname) {
                   1182:         var a = [];
                   1183:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1184:         var els = node.getElementsByTagName("*");
                   1185:         for(var i=0,j=els.length; i<j; i++)
                   1186:             if(re.test(els[i].className))a.push(els[i]);
                   1187:         return a;
                   1188:     }
                   1189: }
                   1190: 
                   1191: function showHideLenient() {
                   1192:     var lenients;
                   1193:     var setRegExp = /^set_/;
                   1194:     if (document.getElementsByClassName) {
                   1195:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1196:     } else {
                   1197:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1198:     }
                   1199:     if (lenients != 'undefined') {
                   1200:         for (var i=0; i<lenients.length; i++) {
                   1201:             if (lenients[i].checked) {
                   1202:                 if (lenients[i].value == 'weighted') {
                   1203:                     if (setRegExp.test(lenients[i].name)) {
                   1204:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1205:                         toggleParmTextbox(document.parmform,identifier);
                   1206:                     }
                   1207:                 }
                   1208:             }
                   1209:         }
                   1210:     }
                   1211:     return;
                   1212: }
                   1213: 
                   1214: function toggleParmTextbox(form,key) {
                   1215:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1216:     if (divfortext) {
                   1217:         var caller = form.elements['set_'+key];
                   1218:         if (caller.length) {
                   1219:             for (i=0; i<caller.length; i++) {
                   1220:                 if (caller[i].checked) {
                   1221:                     if (caller[i].value == 'weighted') {
                   1222:                         divfortext.style.display = 'inline';
                   1223:                     } else {
                   1224:                         divfortext.style.display = 'none';
                   1225:                     }
                   1226:                 }
                   1227:             }
                   1228:         }
                   1229:     }
                   1230:     return;
                   1231: }
                   1232: 
                   1233: ENDSCRIPT
                   1234: }
                   1235: 
1.561     damieng  1236: # Javascript function validateParms, for overview mode
1.549     raeburn  1237: sub validateparms_js {
                   1238:     return <<'ENDSCRIPT';
                   1239: 
                   1240: function validateParms() {
                   1241:     var textRegExp = /^settext_/;
                   1242:     var tailLenient = /\.lenient$/;
                   1243:     var patternRelWeight = /^\-?[\d.]+$/;
                   1244:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1245:     var ipRegExp = /^setip/;
1.549     raeburn  1246:     var ipallowRegExp = /^setipallow_/;
                   1247:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1248:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1249:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1250:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1251:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1252:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1253:     var dlKeyRegExp = /^deeplink_key_/;
                   1254:     var dlMenusRegExp = /^deeplink_menus_/;
                   1255:     var dlCollsRegExp = /^deeplink_colls_/;
1.613     raeburn  1256:     var dlTargetRegExp = /^deeplink_target_/;
1.616     raeburn  1257:     var dlExitRegExp = /^deeplink_exit_/;
                   1258:     var dlExitTextRegExp = /^deeplink_exittext_/;
1.549     raeburn  1259:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1.616     raeburn  1260:     var numelements = document.parmform.elements.length;
                   1261:     if ((typeof(numelements) != 'undefined') && (numelements != null)) {
                   1262:         if (numelements) {
                   1263:             for (i=0; i<numelements; i++) {
1.549     raeburn  1264:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1265:                 if (textRegExp.test(name)) {
1.549     raeburn  1266:                     var identifier = name.replace(textRegExp,'');
                   1267:                     if (tailLenient.test(identifier)) {
                   1268:                         if (document.parmform.elements['set_'+identifier].length) {
                   1269:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1270:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1271:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1272:                                         var relweight = document.parmform.elements[i].value;
                   1273:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1274:                                         if (!patternRelWeight.test(relweight)) {
                   1275:                                             relweight = '0.0';
                   1276:                                         }
                   1277:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1278:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1279:                                         } else {
                   1280:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1281:                                         }
                   1282:                                     }
                   1283:                                     break;
                   1284:                                 }
                   1285:                             }
                   1286:                         }
                   1287:                     }
1.597     raeburn  1288:                 } else if (ipRegExp.test(name)) {
                   1289:                     if (ipallowRegExp.test(name)) {
                   1290:                         var identifier = name.replace(ipallowRegExp,'');
                   1291:                         var possallow = document.parmform.elements[i].value;
                   1292:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1293:                         if (patternIP.test(possallow)) {
                   1294:                             if (document.parmform.elements['set_'+identifier].value) {
                   1295:                                 possallow = ','+possallow;
                   1296:                             }
                   1297:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1298:                         }
                   1299:                     } else if (ipdenyRegExp.test(name)) {
                   1300:                         var identifier = name.replace(ipdenyRegExp,'');
                   1301:                         var possdeny = document.parmform.elements[i].value;
                   1302:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1303:                         if (patternIP.test(possdeny)) {
                   1304:                             possdeny = '!'+possdeny;
                   1305:                             if (document.parmform.elements['set_'+identifier].value) {
                   1306:                                 possdeny = ','+possdeny;
                   1307:                             }
                   1308:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1309:                         }
                   1310:                     }
                   1311:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1312:                     if (dlListScopeRegExp.test(name)) {
                   1313:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1314:                         var idx = document.parmform.elements[i].selectedIndex;
                   1315:                         if (idx > 0) { 
                   1316:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1317:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1318:                             if (document.parmform.elements['set_'+identifier].value) {
                   1319:                                 possdeeplink = ','+possdeeplink;
                   1320:                             }
                   1321:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1322:                         }
1.601     raeburn  1323:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1324:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1325:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1326:                             var posslinkurl = document.parmform.elements[i].value;
                   1327:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1328:                             if (document.parmform.elements['set_'+identifier].value) {
                   1329:                                 posslinkurl = ','+posslinkurl;
                   1330:                             }
                   1331:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1332:                         }
1.601     raeburn  1333:                     } else if (dlLtidRegExp.test(name)) {
                   1334:                         var identifier = name.replace(dlLtidRegExp,'');
                   1335:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1336:                             var possltid = document.parmform.elements[i].value;
                   1337:                             possltid = possltid.replace(/\D+/g,'');
                   1338:                             if (possltid.length) {
1.597     raeburn  1339:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1340:                                     possltid = ':'+possltid;
1.597     raeburn  1341:                                 }
1.601     raeburn  1342:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1343:                             } else {
                   1344:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1345:                                 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  1346:                                 return false;  
                   1347:                             }
                   1348:                         }
1.601     raeburn  1349:                     } else if (dlLticRegExp.test(name)) {
                   1350:                         var identifier = name.replace(dlLticRegExp,'');
                   1351:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1352:                             var possltic = document.parmform.elements[i].value;
                   1353:                             possltic = possltic.replace(/\D+/g,'');
                   1354:                             if (possltic.length) {
                   1355:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1356:                                     possltic = ':'+possltic;
                   1357:                                 }
                   1358:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1359:                             } else {
                   1360:                                 document.parmform.elements['set_'+identifier].value = '';
                   1361:                                 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.");
                   1362:                                 return false;
                   1363:                             }
                   1364:                         }
1.597     raeburn  1365:                     } else if (dlKeyRegExp.test(name)) {
                   1366:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1367:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1368:                             var posskey = document.parmform.elements[i].value;
                   1369:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1370:                             var origlength = posskey.length;
                   1371:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1372:                             var newlength = posskey.length;
                   1373:                             if (newlength > 0) {
                   1374:                                 var change = origlength - newlength;
                   1375:                                 if (change) {
                   1376:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1377:                                 }
                   1378:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1379:                                     posskey = ':'+posskey;
                   1380:                                 }
                   1381:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1382:                             } else {
                   1383:                                 document.parmform.elements['set_'+identifier].value = '';
                   1384:                                 if (newlength < origlength) {
                   1385:                                     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_.!@#$%^&*()+=-");
                   1386:                                 } else {
                   1387:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1388:                                 }
                   1389:                                 return false;
                   1390:                             }
                   1391:                         }
                   1392:                     } else if (dlMenusRegExp.test(name)) {
                   1393:                         if (document.parmform.elements[i].checked) {
                   1394:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1395:                             var posslinkmenu = document.parmform.elements[i].value;
                   1396:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1397:                             if (posslinkmenu == 'std') {
                   1398:                                 posslinkmenu = '0';
                   1399:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1400:                                     posslinkmenu = ','+posslinkmenu;
                   1401:                                 }
                   1402:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1403:                             }
                   1404:                         }
                   1405:                     } else if (dlCollsRegExp.test(name)) {
                   1406:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1407:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1408:                             var posslinkmenu = document.parmform.elements[i].value;
                   1409:                             if (document.parmform.elements['set_'+identifier].value) {
                   1410:                                 posslinkmenu = ','+posslinkmenu;
                   1411:                             }
                   1412:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1413:                         }
1.614     raeburn  1414:                     } else if (dlTargetRegExp.test(name)) {
                   1415:                         var identifier =  name.replace(dlTargetRegExp,'');
1.613     raeburn  1416:                         var idx = document.parmform.elements[i].selectedIndex;
                   1417:                         if (idx > 0) {
1.616     raeburn  1418:                             var linktarget = document.parmform.elements[i].options[idx].value
                   1419:                             linktarget = linktarget.replace(/^\s+|\s+$/g,'');
                   1420:                             if (document.parmform.elements['set_'+identifier].value) {
                   1421:                                 linktarget = ','+linktarget;
                   1422:                             }
                   1423:                             document.parmform.elements['set_'+identifier].value += linktarget;
                   1424:                         }
                   1425:                     } else if (dlExitRegExp.test(name)) {
                   1426:                         if (document.parmform.elements[i].checked) {
                   1427:                             var identifier =  name.replace(dlExitRegExp,'');
                   1428:                             var posslinkexit = document.parmform.elements[i].value;
                   1429:                             posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');
1.613     raeburn  1430:                             if (document.parmform.elements['set_'+identifier].value) {
1.616     raeburn  1431:                                 posslinkexit = ','+posslinkexit;
                   1432:                             }
                   1433:                             document.parmform.elements['set_'+identifier].value += posslinkexit;
                   1434:                         }
                   1435:                     } else if (dlExitTextRegExp.test(name)) {
                   1436:                         var identifier = name.replace(dlExitTextRegExp,'');
                   1437:                         if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
                   1438:                             (isRadioSet('deeplink_exit_'+identifier,'url'))) {
                   1439:                             var posstext = document.parmform.elements[i].value;
                   1440:                             posstext = posstext.replace(/^\s+|\s+$/g,'');
                   1441:                             var origlength = posstext.length;
                   1442:                             posstext = posstext.replace(/[:;'",]/g,'');
                   1443:                             var newlength = posstext.length;
                   1444:                             if (newlength > 0) {
                   1445:                                 var change = origlength - newlength;
                   1446:                                 if (change) {
                   1447:                                     alert(change+' disallowed character(s) removed from Exit Button text');
                   1448:                                 }
                   1449:                                 if (posstext !== 'Exit Tool') {
                   1450:                                     posstext = ':'+posstext;
                   1451:                                     document.parmform.elements['set_'+identifier].value += posstext;
                   1452:                                 }
                   1453:                             } else {
                   1454:                                 document.parmform.elements['set_'+identifier].value = '';
                   1455:                                 if (newlength < origlength) {
                   1456:                                     alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");
                   1457:                                 } else {
                   1458:                                     alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");
                   1459:                                 }
                   1460:                                 return false;
1.613     raeburn  1461:                             }
                   1462:                         }
1.549     raeburn  1463:                     }
                   1464:                 }
                   1465:             }
                   1466:         }
                   1467:     }
                   1468:     return true;
                   1469: }
                   1470: 
1.597     raeburn  1471: function isRadioSet(name,expected) {
                   1472:     var menuitems = document.getElementsByName(name);
                   1473:     var radioLength = menuitems.length;
                   1474:     result = false;
                   1475:     if (radioLength  > 1) {
                   1476:         for (var j=0; j<radioLength; j++) {
                   1477:             if (menuitems[j].checked) {
                   1478:                 if (menuitems[j].value == expected) {
                   1479:                     result = true;
                   1480:                     break;
                   1481:                 }
                   1482:             }
                   1483:         }
                   1484:     }
                   1485:     return result;
                   1486: }
                   1487: 
1.549     raeburn  1488: ENDSCRIPT
                   1489: }
                   1490: 
1.561     damieng  1491: # Javascript initialization, for overview mode
1.549     raeburn  1492: sub ipacc_boxes_js  {
                   1493:     my $remove = &mt('Remove');
                   1494:     return <<"END";
                   1495: \$(document).ready(function() {
                   1496:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1497:     var add_button      = \$(".LC_add_ipacc_button");
                   1498:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1499: 
                   1500:     \$(add_button).click(function(e){
                   1501:         e.preventDefault();
                   1502:         var identifier = \$(this).closest("div").attr("id");
                   1503:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1504:         \$(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  1505:     });
                   1506: 
                   1507:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1508:         e.preventDefault(); \$(this).closest("div").remove();
                   1509:     })
                   1510: });
                   1511: 
                   1512: 
                   1513: END
                   1514: }
                   1515: 
1.561     damieng  1516: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1517: sub done_proctor_js {
1.611     raeburn  1518:     my $defaultdone = &mt('Done');
                   1519:     &js_escape(\$defaultdone);
1.558     raeburn  1520:     return <<"END";
                   1521: function toggleSecret(form,radio,key) {
                   1522:     var radios = form[radio+key];
                   1523:     if (radios.length) {
                   1524:         for (var i=0; i<radios.length; i++) {
                   1525:             if (radios[i].checked) {
                   1526:                 if (radios[i].value == '_done_proctor') {
                   1527:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1528:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1529:                     }
                   1530:                 } else {
                   1531:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1532:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1533:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1534:                     }
                   1535:                 }
1.611     raeburn  1536:                 if (document.getElementById('done_'+key+'_buttontext')) {
                   1537:                     if (radios[i].value == '') {
                   1538:                         document.getElementById('done_'+key+'_buttontext').value = '';
                   1539:                     } else {
                   1540:                         if (document.getElementById('done_'+key+'_buttontext').value == '') {
                   1541:                             document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
                   1542:                         }
                   1543:                     }
                   1544:                 }
1.558     raeburn  1545:             }
                   1546:         }
                   1547:     }
                   1548: }
                   1549: END
                   1550: 
                   1551: }
                   1552: 
1.588     raeburn  1553: # Javascript function toggle
                   1554: sub deeplink_js {
                   1555:     return <<"END";
                   1556: function toggleDeepLink(form,item,key) {
                   1557:     var radios = form['deeplink_'+item+'_'+key];
                   1558:     if (radios.length) {
                   1559:         var keybox;
                   1560:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1561:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1562:         }
1.601     raeburn  1563:         var divoptions = new Array();
                   1564:         if (item == 'protect') {
                   1565:             divoptions = ['ltic','ltid'];
1.597     raeburn  1566:         } else {
                   1567:             if (item == 'menus') {
1.601     raeburn  1568:                 divoptions = ['colls'];
1.597     raeburn  1569:             }
                   1570:         }
1.601     raeburn  1571:         var seldivs = new Array();
                   1572:         if ((item == 'protect') || (item == 'menus')) {
                   1573:             for (var i=0; i<divoptions.length; i++) {
                   1574:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1575:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1576:                 } else {
                   1577:                     seldivs[i] = '';
                   1578:                 }
                   1579:             }
1.588     raeburn  1580:         }
                   1581:         for (var i=0; i<radios.length; i++) {
                   1582:             if (radios[i].checked) {
1.601     raeburn  1583:                 if ((item == 'protect') || (item == 'menus')) {
                   1584:                     for (var j=0; j<seldivs.length; j++) {
                   1585:                         if (radios[i].value == divoptions[j]) {
                   1586:                             if (seldivs[j] != '') {
                   1587:                                 seldivs[j].style.display = 'inline-block';
                   1588:                             }
                   1589:                             if (item == 'protect') {
                   1590:                                 keybox.type = 'hidden';
                   1591:                                 keybox.value = '';
                   1592:                             }
                   1593:                         } else {
                   1594:                             if (seldivs[j] != '') {
                   1595:                                 seldivs[j].style.display = 'none';
                   1596:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1597:                             }
                   1598:                         }
1.597     raeburn  1599:                     }
1.601     raeburn  1600:                     if (item == 'protect') {
1.597     raeburn  1601:                         if (radios[i].value == 'key') {
                   1602:                             keybox.type = 'text';
                   1603:                         } else {
                   1604:                             keybox.type = 'hidden';
                   1605:                         }
1.588     raeburn  1606:                     }
1.616     raeburn  1607:                 } else if (item == 'exit') {
                   1608:                     if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
                   1609:                         if (radios[i].value == 'no') {
                   1610:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';          
                   1611:                             if (document.getElementById('deeplink_exittext_'+key)) {
                   1612:                                 if (document.getElementById('deeplink_exittext_'+key).value != '') {
                   1613:                                     document.getElementById('deeplink_exittext_'+key).value = '';    
                   1614:                                 }
                   1615:                             }
                   1616:                         } else {
                   1617:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
                   1618:                             if (document.getElementById('deeplink_exittext_'+key)) {
                   1619:                                 if (document.getElementById('deeplink_exittext_'+key).value == '') {
                   1620:                                     document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
                   1621:                                 }
                   1622:                             }
                   1623:                         }
                   1624:                     }
1.588     raeburn  1625:                 }
                   1626:             }
                   1627:         }
                   1628:     }
                   1629: }
                   1630: END
                   1631: 
                   1632: }
                   1633: 
1.561     damieng  1634: # Prints HTML page start for table mode.
                   1635: # @param {Apache2::RequestRec} $r - the Apache request
                   1636: # @param {string} $psymb - resource symb
                   1637: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1638: sub startpage {
1.531     raeburn  1639:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1640: 
1.515     raeburn  1641:     my %loaditems = (
                   1642:                       'onload'   => "group_or_section('cgroup')",
                   1643:                     );
                   1644:     if (!$psymb) {
1.523     raeburn  1645:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1646:     }
1.280     albertel 1647: 
1.560     damieng  1648:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1649:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1650:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1651:             text=>"Problem Parameters"});
1.414     droeschl 1652:     } else {
1.560     damieng  1653:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1654:             text=>"Table Mode",
                   1655:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1656:     }
1.523     raeburn  1657:     my $js = &page_js().'
                   1658: <script type="text/javascript">
                   1659: // <![CDATA[
                   1660: '.
                   1661:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1662: // ]]>
                   1663: </script>
                   1664: ';
1.446     bisitz   1665:     my $start_page =
1.523     raeburn  1666:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1667:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1668:     my $breadcrumbs =
1.473     amueller 1669:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1670:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1671:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1672:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1673:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1674:     $r->print(<<ENDHEAD);
1.193     albertel 1675: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1676: <input type="hidden" value="" name="pres_value" />
                   1677: <input type="hidden" value="" name="pres_type" />
                   1678: <input type="hidden" value="" name="pres_marker" />
                   1679: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1680: <input type="hidden" value="$escfilter" name="filter" />
                   1681: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1682: ENDHEAD
                   1683: }
                   1684: 
1.209     www      1685: 
1.561     damieng  1686: # Prints a row for table mode (except for the tr start).
                   1687: # Every time a hash reference is passed, a single entry is used, so print_row
                   1688: # could just use these values, but why make it simple when it can be complicated ?
                   1689: #
                   1690: # @param {Apache2::RequestRec} $r - the Apache request
                   1691: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1692: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1693: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1694: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1695: # @param {string} $rid - resource id
                   1696: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1697: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1698: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1699: # @param {string} $defbgone - user level and other levels background color
                   1700: # @param {string} $defbgtwo - section level background color, also used for part number
                   1701: # @param {string} $defbgthree - group level background color
                   1702: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1703: # @param {string} $uname - user name
                   1704: # @param {string} $udom - user domain
                   1705: # @param {string} $csec - section name
                   1706: # @param {string} $cgroup - group name
                   1707: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1708: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1709: # @param {boolean} $readonly - true if no editing allowed.
                   1710: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1711: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1712: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1713: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1714: sub print_row {
1.201     www      1715:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1716:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1717:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1718:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1719:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1720:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1721:     my $numlinks = 0;
1.553     raeburn  1722: 
1.560     damieng  1723:     # get the values for the parameter in cascading order
                   1724:     # empty levels will remain empty
1.44      albertel 1725:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1726:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1727:     # get the type for the parameters
                   1728:     # problem: these may not be set for all levels
1.66      www      1729:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1730:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1731:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1732:     # cascade down manually
1.182     albertel 1733:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1734:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1735:         if ($typeoutpar[$i]) {
1.66      www      1736:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1737:         } else {
1.66      www      1738:             $typeoutpar[$i]=$cascadetype;
                   1739:         }
                   1740:     }
1.57      albertel 1741:     my $parm=$$display{$which};
                   1742: 
1.203     www      1743:     if ($parmlev eq 'full') {
1.419     bisitz   1744:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1745:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1746:     } else {
1.57      albertel 1747:         $parm=~s|\[.*\]\s||g;
                   1748:     }
1.231     www      1749:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1750:     if ($automatic) {
1.560     damieng  1751:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1752:     }
1.427     bisitz   1753:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1754: 
1.44      albertel 1755:     my $thismarker=$which;
                   1756:     $thismarker=~s/^parameter\_//;
                   1757:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1758:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1759:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1760:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1761:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1762:         if ($result eq '') {
                   1763:             $recurse_check = 1;
                   1764:         } elsif (($uname ne '') && ($result > 3)) {
                   1765:             $recurse_check = 1;
                   1766:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1767:             $recurse_check = 1;
                   1768:         } elsif (($csec ne '') && ($result > 11)) {
                   1769:             $recurse_check = 1;
                   1770:         } elsif ($result > 17) {
                   1771:             $recurse_check = 1;
                   1772:         }
                   1773:         if ($recurse_check) {
                   1774:             my $what = $$part{$which}.'.'.$$name{$which};
                   1775:             my $prefix;
                   1776:             if (($uname ne '') && ($udom ne '')) {
                   1777:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1778:                 $prefix = $env{'request.course.id'};
                   1779:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1780:                 if (ref($recursinfo) eq 'ARRAY') {
                   1781:                     $effparm_rec = 1;
                   1782:                     $effparm_level = &mt('user: [_1]',$uname);
                   1783:                 }
                   1784:             }
                   1785:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1786:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1787:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1788:                 if (ref($recursinfo) eq 'ARRAY') {
                   1789:                     $effparm_rec = 1;
                   1790:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1791:                 }
                   1792:             }
                   1793:             if (($csec ne '') && (!$effparm_rec)) {
                   1794:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1795:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1796:                 if (ref($recursinfo) eq 'ARRAY') {
                   1797:                     $effparm_rec = 1;
                   1798:                     $effparm_level = &mt('section: [_1]',$csec);
                   1799:                 }
                   1800:             }
                   1801:             if (!$effparm_rec) {
                   1802:                 $prefix = $env{'request.course.id'};
                   1803:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1804:                 if (ref($recursinfo) eq 'ARRAY') {
                   1805:                     $effparm_rec = 1;
                   1806:                 }
                   1807:             }
                   1808:         }
                   1809:     }
                   1810:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1811:         $effparm_rec = 1;
                   1812:     }
                   1813:     if ((!$effparm_rec) && 
                   1814:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1815:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1816:         $effparm_rec = 1;
                   1817:     }
1.588     raeburn  1818:     if ($parmname eq 'deeplink') {
1.601     raeburn  1819:         my ($domltistr,$crsltistr);
1.588     raeburn  1820:         my %lti =
                   1821:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1822:                                             'linkprot');
1.601     raeburn  1823:         if (keys(%lti)) {
                   1824:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1825:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1826:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1827:                 }
                   1828:             }
1.601     raeburn  1829:             $domltistr =~ s/,$//;
                   1830:             if ($domltistr) {
                   1831:                 $extra = 'ltid_'.$domltistr;
                   1832:             }
1.588     raeburn  1833:         }
1.601     raeburn  1834:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1835:         if (keys(%courselti)) {
                   1836:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1837:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1838:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1839:                 }
                   1840:             }
                   1841:             $crsltistr =~ s/,$//;
                   1842:             if ($crsltistr) {
                   1843:                 if ($extra) {
                   1844:                     $extra .= '&';
                   1845:                 }
                   1846:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1847:             }
                   1848:         }
1.597     raeburn  1849:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1850:             my @colls;
                   1851:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1852:                 my ($num,$value) = split(/\%/,$item);
                   1853:                 if ($num =~ /^\d+$/) {
                   1854:                     push(@colls,$num);
                   1855:                 }
                   1856:             }
                   1857:             if (@colls) {
                   1858:                 if ($extra) {
                   1859:                     $extra .= '&';
                   1860:                 }
                   1861:                 $extra .= 'menus_'.join(',',@colls);
                   1862:             }
                   1863:         }
1.588     raeburn  1864:     }
1.57      albertel 1865:     if ($parmlev eq 'general') {
                   1866:         if ($uname) {
1.588     raeburn  1867:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1868:         } elsif ($cgroup) {
1.588     raeburn  1869:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1870:         } elsif ($csec) {
1.588     raeburn  1871:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1872:         } else {
1.588     raeburn  1873:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1874:         }
                   1875:     } elsif ($parmlev eq 'map') {
                   1876:         if ($uname) {
1.588     raeburn  1877:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1878:         } elsif ($cgroup) {
1.588     raeburn  1879:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1880:         } elsif ($csec) {
1.588     raeburn  1881:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1882:         } else {
1.588     raeburn  1883:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1884:         }
                   1885:     } else {
1.275     raeburn  1886:         if ($uname) {
                   1887:             if (@{$usersgroups} > 1) {
1.582     raeburn  1888:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1889:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1890:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1891:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1892:                     if (defined($controlgrp)) {
                   1893:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1894:                             $eff_groupparm = $grp_parm;
                   1895:                             undef($result);
                   1896:                             undef($effparm_rec);
                   1897:                             if ($grp_is_rec) {
                   1898:                                  $effparm_rec = 1;
                   1899:                             }
1.275     raeburn  1900:                         }
                   1901:                     }
                   1902:                 }
                   1903:             }
                   1904:         }
1.57      albertel 1905: 
1.588     raeburn  1906:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1907:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1908:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1909:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1910:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1911: 
                   1912:         if ($csec) {
1.588     raeburn  1913:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1914:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1915:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1916:         }
1.269     raeburn  1917: 
                   1918:         if ($cgroup) {
1.588     raeburn  1919:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1920:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1921:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1922:         }
1.446     bisitz   1923: 
1.548     raeburn  1924:         if ($uname) {
1.275     raeburn  1925:             if ($othergrp) {
                   1926:                 $r->print($othergrp);
                   1927:             }
1.588     raeburn  1928:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1929:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1930:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1931:         }
1.57      albertel 1932:     } # end of $parmlev if/else
1.582     raeburn  1933:     if (ref($recursinfo) eq 'ARRAY') {
                   1934:         my $rectitle = &mt('recursive');
                   1935:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1936:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1937:                 $rectitle = &mt('set in: [_1]','"'.
                   1938:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1939:                                                               "'$parmname','$$part{$which}'".');">'.
                   1940:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1941:               
                   1942:                 $numlinks ++;
                   1943:             }
                   1944:         }
                   1945:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1946:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1947:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1948:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1949:                   $effparm_level.'</span></td>');
                   1950:     } else {
                   1951:         if ($result) {
1.593     raeburn  1952:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1953:         }
                   1954:         if ($eff_groupparm) {
                   1955:             $effective_parm = $eff_groupparm;
                   1956:         }
                   1957:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1958:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1959:                                 '</span>':'').'</td>');
                   1960:     }
1.203     www      1961:     if ($parmlev eq 'full') {
1.136     albertel 1962:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1963:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1964:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1965:         if (!defined($sessionvaltype)) {
                   1966:             $sessionvaltype=$$defaulttype{$which};
                   1967:         }
1.419     bisitz   1968:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1969:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1970:                   '</font></td>');
1.136     albertel 1971:     }
1.44      albertel 1972:     $r->print('</tr>');
1.57      albertel 1973:     $r->print("\n");
1.582     raeburn  1974:     if (($numlinks) && (ref($reclinks))) {
                   1975:         $$reclinks = $numlinks;
                   1976:     }
1.44      albertel 1977: }
1.59      matthew  1978: 
1.561     damieng  1979: # Prints a cell for table mode.
                   1980: #
                   1981: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1982: # Also, it would make more sense to pass the display for this cell rather
                   1983: # than the full display hash and the key to use.
                   1984: #
                   1985: # @param {Apache2::RequestRec} $r - the Apache request
                   1986: # @param {integer} $which - level
                   1987: # @param {string} $defbg - cell background color
                   1988: # @param {integer} $result - the most specific level that is defined for that parameter
                   1989: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1990: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1991: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1992: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1993: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1994: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1995: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1996: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1997: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1998: sub print_td {
1.578     raeburn  1999:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  2000:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  2001:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   2002:     $ineffect = 0;
                   2003:     $currval = $$outpar[$which];
                   2004:     $currtype = $$typeoutpar[$which];
                   2005:     $currlevel = $which;
                   2006:     if (($result) && ($result == $which)) {
                   2007:         $ineffect = 1;
                   2008:     } 
                   2009:     if ($ismaplevel) {
                   2010:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   2011:             if (($result) && ($result == $which)) {
                   2012:                 $recursive = 1;
                   2013:             }
                   2014:         } elsif ($$outpar[$which+1] ne '') {
                   2015:             $recursive = 1;
                   2016:             $currlevel = $which+1;
                   2017:             $currval = $$outpar[$currlevel];
                   2018:             $currtype = $$typeoutpar[$currlevel];
                   2019:             if (($result) && ($result == $currlevel)) {
                   2020:                 $ineffect = 1;
                   2021:             }
                   2022:         }
                   2023:     }
                   2024:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   2025:               ';" align="center">');
1.437     raeburn  2026:     my $nolink = 0;
1.568     raeburn  2027:     if ($readonly) {
1.552     raeburn  2028:         $nolink = 1;
1.568     raeburn  2029:     } else { 
1.578     raeburn  2030:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  2031:             $nolink = 1;
1.568     raeburn  2032:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  2033:             $nolink = 1;
1.568     raeburn  2034:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   2035:             if ($noeditgrp) {
                   2036:                 $nolink = 1;
                   2037:             }
                   2038:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  2039:             $nolink = 1;
1.568     raeburn  2040:         } elsif ($mprefix =~ /examcode\&$/) {
                   2041:             unless ($which == 2) {
                   2042:                 $nolink = 1;
                   2043:             }
1.533     raeburn  2044:         }
1.437     raeburn  2045:     }
                   2046:     if ($nolink) {
1.577     raeburn  2047:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  2048:         $r->print(&valout($currval,$currtype));
1.114     www      2049:     } else {
1.578     raeburn  2050:         $r->print(&plink($currtype,
                   2051:                          $$display{$value},$currval,
1.588     raeburn  2052:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   2053:                          $extra));
1.114     www      2054:     }
                   2055:     $r->print('</td>'."\n");
1.57      albertel 2056: }
                   2057: 
1.561     damieng  2058: # Returns HTML and other info for the cell added when a user is selected
                   2059: # and that user is in several groups. This is the cell with the title "Control by other group".
                   2060: #
                   2061: # @param {string} $what - parameter part.'.'.parameter name
                   2062: # @param {string} $rid - resource id
                   2063: # @param {string} $cgroup - group name
                   2064: # @param {string} $defbg - cell background color
                   2065: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2066: # @param {integer} $result - level
                   2067: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  2068: # @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  2069: sub check_other_groups {
                   2070:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  2071:     my $courseid = $env{'request.course.id'};
                   2072:     my $output;
                   2073:     my $symb = &symbcache($rid);
                   2074:     my $symbparm=$symb.'.'.$what;
                   2075:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  2076:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  2077:     my $mapparm=$map.'___(all).'.$what;
                   2078:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  2079:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   2080:                               $recurseparm,$what,$courseopt);
1.275     raeburn  2081:     my $bgcolor = $defbg;
1.582     raeburn  2082:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2083:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2084:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2085:         if ($result > 3) {
1.419     bisitz   2086:             $bgcolor = '#AAFFAA';
1.275     raeburn  2087:         }
1.593     raeburn  2088:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2089:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2090:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2091:             if ($resultlevel eq 'recursive') {
                   2092:                 $resultlevel = 'map/folder';
                   2093:                 $grp_is_rec = 1;
                   2094:             }
                   2095:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2096:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2097:              
1.275     raeburn  2098:         } else {
                   2099:             $output .= '&nbsp;';
                   2100:         }
                   2101:         $output .= '</td>';
                   2102:     } else {
1.419     bisitz   2103:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2104:     }
1.582     raeburn  2105:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2106: }
                   2107: 
1.561     damieng  2108: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2109: # Used by check_other_groups.
1.561     damieng  2110: #
                   2111: # @param {string} $courseid - the course id
                   2112: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2113: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2114: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2115: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2116: # @param {string} $what - parameter part.'.'.parameter name
                   2117: # @param {hash reference} $courseopt - course parameters hash
                   2118: # @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  2119: sub parm_control_group {
1.556     raeburn  2120:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2121:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2122:     my $grpfound = 0;
1.556     raeburn  2123:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2124:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2125:     foreach my $group (@{$usersgroups}) {
                   2126:         if ($grpfound) { last; }
                   2127:         for (my $i=0; $i<@levels; $i++) {
                   2128:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2129:             if (defined($$courseopt{$item})) {
                   2130:                 $coursereply = $$courseopt{$item};
                   2131:                 $resultitem = $item;
                   2132:                 $resultgroup = $group;
                   2133:                 $resultlevel = $levelnames[$i];
                   2134:                 $resulttype = $$courseopt{$item.'.type'};
                   2135:                 $grpfound = 1;
                   2136:                 last;
                   2137:             }
                   2138:         }
                   2139:     }
                   2140:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2141: }
1.201     www      2142: 
1.63      bowersj2 2143: 
                   2144: 
1.562     damieng  2145: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2146: # All the parameters are references and are filled by the sub.
                   2147: #
1.566     damieng  2148: # @param {array reference} $ids - resource and map ids
                   2149: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2150: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2151: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2152: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2153: # @param {hash reference} $allmaps - hash map pc -> map src
                   2154: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2155: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2156: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2157: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2158: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2159: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608     raeburn  2160: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63      bowersj2 2161: sub extractResourceInformation {
                   2162:     my $ids = shift;
                   2163:     my $typep = shift;
                   2164:     my $keyp = shift;
                   2165:     my $allparms = shift;
                   2166:     my $allparts = shift;
                   2167:     my $allmaps = shift;
                   2168:     my $mapp = shift;
                   2169:     my $symbp = shift;
1.82      www      2170:     my $maptitles=shift;
1.196     www      2171:     my $uris=shift;
1.210     www      2172:     my $keyorder=shift;
1.211     www      2173:     my $defkeytype=shift;
1.603     raeburn  2174:     my $pssymb=shift;
1.196     www      2175: 
1.210     www      2176:     my $keyordercnt=100;
1.63      bowersj2 2177: 
1.196     www      2178:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2179:     return unless(ref($navmap));
                   2180:     my @allres;
                   2181:     if ($pssymb ne '') {
                   2182:         my $res = $navmap->getBySymb($pssymb);
                   2183:         if (ref($res)) {
                   2184:             @allres = ($res);
                   2185:         }
                   2186:     }
                   2187:     if (!@allres) { 
                   2188:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2189:     }
1.196     www      2190:     foreach my $resource (@allres) {
1.480     amueller 2191:         my $id=$resource->id();
1.196     www      2192:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2193:         if ($mapid eq '0') { next; }
                   2194:         $$ids[$#$ids+1]=$id;
                   2195:         my $srcf=$resource->src();
                   2196:         $srcf=~/\.(\w+)$/;
                   2197:         $$typep{$id}=$1;
1.584     raeburn  2198:         my $toolsymb;
                   2199:         if ($srcf =~ /ext\.tool$/) {
                   2200:             $toolsymb = $resource->symb();
                   2201:         }
1.480     amueller 2202:         $$keyp{$id}='';
1.196     www      2203:         $$uris{$id}=$srcf;
1.512     foxr     2204: 
1.584     raeburn  2205:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2206:             next if ($key!~/^parameter_/);
1.363     albertel 2207: 
1.209     www      2208: # Hidden parameters
1.584     raeburn  2209:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2210: #
                   2211: # allparms is a hash of parameter names
                   2212: #
1.584     raeburn  2213:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2214:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2215:                 my ($display,$parmdis);
                   2216:                 $display = &standard_parameter_names($name);
                   2217:                 if ($display eq '') {
1.584     raeburn  2218:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2219:                     $parmdis = $display;
                   2220:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2221:                 } else {
                   2222:                     $parmdis = &mt($display);
                   2223:                 }
                   2224:                 $$allparms{$name}=$parmdis;
                   2225:                 if (ref($defkeytype)) {
                   2226:                     $$defkeytype{$name}=
1.584     raeburn  2227:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2228:                 }
                   2229:             }
1.363     albertel 2230: 
1.209     www      2231: #
                   2232: # allparts is a hash of all parts
                   2233: #
1.584     raeburn  2234:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2235:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2236: #
                   2237: # Remember all keys going with this resource
                   2238: #
1.480     amueller 2239:             if ($$keyp{$id}) {
                   2240:                 $$keyp{$id}.=','.$key;
                   2241:             } else {
                   2242:                 $$keyp{$id}=$key;
                   2243:             }   
1.210     www      2244: #
                   2245: # Put in order
1.446     bisitz   2246: #
1.480     amueller 2247:             unless ($$keyorder{$key}) {
                   2248:                 $$keyorder{$key}=$keyordercnt;
                   2249:                 $keyordercnt++;
                   2250:             }
1.473     amueller 2251:         }
                   2252: 
                   2253: 
1.480     amueller 2254:         if (!exists($$mapp{$mapid})) {
                   2255:             $$mapp{$id}=
                   2256:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2257:             $$mapp{$mapid}=$$mapp{$id};
                   2258:             $$allmaps{$mapid}=$$mapp{$id};
                   2259:             if ($mapid eq '1') {
1.532     raeburn  2260:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2261:             } else {
                   2262:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2263:             }
                   2264:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2265:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2266:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2267:                                                      # are commented out in rev. 1.57
1.473     amueller 2268:         } else {
1.480     amueller 2269:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2270:         }
1.480     amueller 2271:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2272:     }
                   2273: }
                   2274: 
1.582     raeburn  2275: sub get_recursive {
                   2276:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2277:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2278:         foreach my $item (@{$recurseup}) {
                   2279:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2280:             if (defined($resdata->{$norecursechk})) {
                   2281:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2282:                     my $type = $resdata->{$norecursechk.'.type'};
                   2283:                     return [$resdata->{$norecursechk},$type,$item];
                   2284:                 } else {
                   2285:                     last;
                   2286:                 }
                   2287:             }
                   2288:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2289:             if (defined($resdata->{$recursechk})) {
                   2290:                 my $type = $resdata->{$recursechk.'.type'};
                   2291:                 return [$resdata->{$recursechk},$type,$item];
                   2292:             }
                   2293:         }
                   2294:     }
                   2295:     return;
                   2296: }
                   2297: 
1.208     www      2298: 
1.562     damieng  2299: # Tells if a parameter type is a date.
                   2300: #
                   2301: # @param {string} type - parameter type
                   2302: # @returns{boolean} - true if it is a date
1.213     www      2303: sub isdateparm {
                   2304:     my $type=shift;
                   2305:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2306: }
                   2307: 
1.589     raeburn  2308: # Determine if parameter type is specialized string type (i.e.,
                   2309: # not just string or string_yesno.  
                   2310: 
                   2311: sub is_specialstring {
                   2312:     my $type=shift;
1.603     raeburn  2313:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2314: }
                   2315: 
1.562     damieng  2316: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2317: #
1.581     raeburn  2318: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2319: sub parmmenu {
1.581     raeburn  2320:     my ($r)=@_;
1.208     www      2321:     $r->print(<<ENDSCRIPT);
                   2322: <script type="text/javascript">
1.454     bisitz   2323: // <![CDATA[
1.208     www      2324:     function checkall(value, checkName) {
1.453     schualex 2325: 
                   2326:         var li = "_li";
                   2327:         var displayOverview = "";
                   2328:         
                   2329:         if (value == false) {
                   2330:             displayOverview = "none"
                   2331:         }
                   2332: 
1.562     damieng  2333:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2334:             ele = document.forms.parmform.elements[i];
                   2335:             if (ele.name == checkName) {
                   2336:                 document.forms.parmform.elements[i].checked=value;
                   2337:             }
                   2338:         }
                   2339:     }
1.210     www      2340: 
                   2341:     function checkthis(thisvalue, checkName) {
1.562     damieng  2342:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2343:             ele = document.forms.parmform.elements[i];
                   2344:             if (ele.name == checkName) {
1.562     damieng  2345:                 if (ele.value == thisvalue) {
                   2346:                     document.forms.parmform.elements[i].checked=true;
                   2347:                 }
1.210     www      2348:             }
                   2349:         }
                   2350:     }
                   2351: 
                   2352:     function checkdates() {
1.562     damieng  2353:         checkthis('duedate','pscat');
                   2354:         checkthis('opendate','pscat');
                   2355:         checkthis('answerdate','pscat');
1.218     www      2356:     }
                   2357: 
                   2358:     function checkdisset() {
1.562     damieng  2359:         checkthis('discussend','pscat');
                   2360:         checkthis('discusshide','pscat');
                   2361:         checkthis('discussvote','pscat');
1.218     www      2362:     }
                   2363: 
                   2364:     function checkcontdates() {
1.562     damieng  2365:         checkthis('contentopen','pscat');
                   2366:         checkthis('contentclose','pscat');
1.218     www      2367:     }
1.446     bisitz   2368: 
1.210     www      2369:     function checkvisi() {
1.562     damieng  2370:         checkthis('hiddenresource','pscat');
                   2371:         checkthis('encrypturl','pscat');
                   2372:         checkthis('problemstatus','pscat');
                   2373:         checkthis('contentopen','pscat');
                   2374:         checkthis('opendate','pscat');
1.210     www      2375:     }
                   2376: 
                   2377:     function checkparts() {
1.562     damieng  2378:         checkthis('hiddenparts','pscat');
                   2379:         checkthis('display','pscat');
                   2380:         checkthis('ordered','pscat');
1.210     www      2381:     }
                   2382: 
                   2383:     function checkstandard() {
                   2384:         checkall(false,'pscat');
1.562     damieng  2385:         checkdates();
                   2386:         checkthis('weight','pscat');
                   2387:         checkthis('maxtries','pscat');
                   2388:         checkthis('type','pscat');
                   2389:         checkthis('problemstatus','pscat');
1.210     www      2390:     }
                   2391: 
1.454     bisitz   2392: // ]]>
1.208     www      2393: </script>
                   2394: ENDSCRIPT
1.453     schualex 2395: 
1.491     bisitz   2396:     $r->print('<hr />');
1.581     raeburn  2397:     &shortCuts($r);
1.491     bisitz   2398:     $r->print('<hr />');
1.453     schualex 2399: }
1.562     damieng  2400: 
                   2401: # Returns parameter categories.
                   2402: #
                   2403: # @returns {hash} - category name -> title in English
1.465     amueller 2404: sub categories {
                   2405:     return ('time_settings' => 'Time Settings',
                   2406:     'grading' => 'Grading',
                   2407:     'tries' => 'Tries',
                   2408:     'problem_appearance' => 'Problem Appearance',
                   2409:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2410:     'hiding' => 'Hiding',
                   2411:     'high_level_randomization' => 'High Level Randomization',
                   2412:     'slots' => 'Slots',
                   2413:     'file_submission' => 'File Submission',
                   2414:     'misc' => 'Miscellaneous' ); 
                   2415: }
                   2416: 
1.562     damieng  2417: # Returns the category for each parameter.
                   2418: #
                   2419: # @returns {hash} - parameter name -> category name
1.465     amueller 2420: sub lookUpTableParameter {
                   2421:  
                   2422:     return ( 
                   2423:         'opendate' => 'time_settings',
                   2424:         'duedate' => 'time_settings',
                   2425:         'answerdate' => 'time_settings',
                   2426:         'interval' => 'time_settings',
                   2427:         'contentopen' => 'time_settings',
                   2428:         'contentclose' => 'time_settings',
                   2429:         'discussend' => 'time_settings',
1.560     damieng  2430:         'printstartdate' => 'time_settings',
                   2431:         'printenddate' => 'time_settings',
1.465     amueller 2432:         'weight' => 'grading',
                   2433:         'handgrade' => 'grading',
                   2434:         'maxtries' => 'tries',
                   2435:         'hinttries' => 'tries',
1.503     raeburn  2436:         'randomizeontries' => 'tries',
1.465     amueller 2437:         'type' => 'problem_appearance',
                   2438:         'problemstatus' => 'problem_appearance',
                   2439:         'display' => 'problem_appearance',
                   2440:         'ordered' => 'problem_appearance',
                   2441:         'numbubbles' => 'problem_appearance',
                   2442:         'tol' => 'behaviour_of_input_fields',
                   2443:         'sig' => 'behaviour_of_input_fields',
                   2444:         'turnoffunit' => 'behaviour_of_input_fields',
                   2445:         'hiddenresource' => 'hiding',
                   2446:         'hiddenparts' => 'hiding',
                   2447:         'discusshide' => 'hiding',
                   2448:         'buttonshide' => 'hiding',
                   2449:         'turnoffeditor' => 'hiding',
                   2450:         'encrypturl' => 'hiding',
1.587     raeburn  2451:         'deeplink' => 'hiding',
1.465     amueller 2452:         'randomorder' => 'high_level_randomization',
                   2453:         'randompick' => 'high_level_randomization',
                   2454:         'available' => 'slots',
                   2455:         'useslots' => 'slots',
                   2456:         'availablestudent' => 'slots',
                   2457:         'uploadedfiletypes' => 'file_submission',
                   2458:         'maxfilesize' => 'file_submission',
                   2459:         'cssfile' => 'misc',
                   2460:         'mapalias' => 'misc',
                   2461:         'acc' => 'misc',
                   2462:         'maxcollaborators' => 'misc',
                   2463:         'scoreformat' => 'misc',
1.514     raeburn  2464:         'lenient' => 'grading',
1.519     raeburn  2465:         'retrypartial' => 'tries',
1.521     raeburn  2466:         'discussvote'  => 'misc',
1.584     raeburn  2467:         'examcode' => 'high_level_randomization',
1.575     raeburn  2468:     );
1.465     amueller 2469: }
                   2470: 
1.562     damieng  2471: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2472: #
                   2473: # @param {string} $name - parameter name
                   2474: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2475: sub whatIsMyCategory {
                   2476:     my $name = shift;
                   2477:     my $catList = shift;
                   2478:     my @list;
                   2479:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2480:     my $cat = $lookUpList{$name};
                   2481:     if (defined($cat)) {
                   2482:         if (!defined($$catList{$cat})){
                   2483:             push @list, ($name);
                   2484:             $$catList{$cat} = \@list;
                   2485:         } else {
                   2486:             push @{${$catList}{$cat}}, ($name);     
                   2487:         }
                   2488:     } else {
                   2489:         if (!defined($$catList{'misc'})){
                   2490:             push @list, ($name);
                   2491:             $$catList{'misc'} = \@list;
                   2492:         } else {
                   2493:             push @{${$catList}{'misc'}}, ($name);     
                   2494:         }
                   2495:     }        
                   2496: }
                   2497: 
1.562     damieng  2498: # Sorts parameter names based on appearance order.
                   2499: #
                   2500: # @param {array reference} name - array reference of parameter names
                   2501: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2502: # @returns {Array} - array of parameter names
1.465     amueller 2503: sub keysindisplayorderCategory {
                   2504:     my ($name,$keyorder)=@_;
                   2505:     return sort {
1.473     amueller 2506:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2507:     } ( @{$name});
                   2508: }
                   2509: 
1.562     damieng  2510: # Returns a hash category name -> order, starting at 1 (integer)
                   2511: #
                   2512: # @returns {hash}
1.467     amueller 2513: sub category_order {
                   2514:     return (
                   2515:         'time_settings' => 1,
                   2516:         'grading' => 2,
                   2517:         'tries' => 3,
                   2518:         'problem_appearance' => 4,
                   2519:         'hiding' => 5,
                   2520:         'behaviour_of_input_fields' => 6,
                   2521:         'high_level_randomization'  => 7,
                   2522:         'slots' => 8,
                   2523:         'file_submission' => 9,
                   2524:         'misc' => 10
                   2525:     );
                   2526: 
                   2527: }
1.453     schualex 2528: 
1.562     damieng  2529: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2530: #
                   2531: # @param {Apache2::RequestRec} $r - the Apache request
                   2532: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2533: # @param {array reference} $pscat - list of selected parameter names
                   2534: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2535: sub parmboxes {
                   2536:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2537:     my %categories = &categories();
1.467     amueller 2538:     my %category_order = &category_order();
1.465     amueller 2539:     my %categoryList = (
                   2540:         'time_settings' => [],
                   2541:         'grading' => [],
                   2542:         'tries' => [],
                   2543:         'problem_appearance' => [],
                   2544:         'behaviour_of_input_fields' => [],
                   2545:         'hiding' => [],
                   2546:         'high_level_randomization' => [],
                   2547:         'slots' => [],
                   2548:         'file_submission' => [],
                   2549:         'misc' => [],
1.489     bisitz   2550:     );
1.510     www      2551: 
1.548     raeburn  2552:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2553:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2554:     }
1.453     schualex 2555:     #part to print the parm-list
1.536     raeburn  2556:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2557:         next if (@{$categoryList{$key}} == 0);
                   2558:         next if ($key eq '');
                   2559:         $r->print('<div class="LC_Box LC_400Box">'
                   2560:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2561:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2562:             next if ($tempkey eq '');
1.536     raeburn  2563:             $r->print('<span class="LC_nobreak">'
                   2564:                      .'<label><input type="checkbox" name="pscat" '
                   2565:                      .'value="'.$tempkey.'" ');
                   2566:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2567:                 $r->print( ' checked="checked"');
                   2568:             }
1.617   ! raeburn  2569:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? 
        !          2570:                              Text::Wrap::wrap('','&nbsp;'x4,$$allparms{$tempkey})
        !          2571:                              : $tempkey)
1.536     raeburn  2572:                      .'</label></span><br />'."\n");
1.465     amueller 2573:         }
1.536     raeburn  2574:         $r->print('</div>');
1.465     amueller 2575:     }
1.536     raeburn  2576:     $r->print("\n");
1.453     schualex 2577: }
1.562     damieng  2578: 
                   2579: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2580: #
1.562     damieng  2581: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2582: sub shortCuts {
1.581     raeburn  2583:     my ($r)=@_;
1.453     schualex 2584: 
1.491     bisitz   2585:     # Parameter Selection
                   2586:     $r->print(
                   2587:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2588:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2589:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2590:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2591:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2592:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2593:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2594:        .&Apache::lonhtmlcommon::end_funclist()
                   2595:     );
                   2596: 
                   2597:     # Add Selection for...
                   2598:     $r->print(
                   2599:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2600:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2601:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2602:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2603:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2604:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2605:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2606:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2607:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2608:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2609:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2610:        .&Apache::lonhtmlcommon::end_funclist()
                   2611:     );
1.208     www      2612: }
                   2613: 
1.562     damieng  2614: # Prints HTML to select parts to view (except for the title).
                   2615: # Used by table and overview modes.
                   2616: #
                   2617: # @param {Apache2::RequestRec} $r - the Apache request
                   2618: # @param {hash reference} $allparts - hash parameter part -> part title
                   2619: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2620: sub partmenu {
1.446     bisitz   2621:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2622:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2623:     if ($selsize > 8) {
                   2624:         $selsize = 8;
                   2625:     }
1.446     bisitz   2626: 
1.523     raeburn  2627:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2628:     $r->print('<option value="all"');
1.562     damieng  2629:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2630:     $r->print('>'.&mt('All Parts').'</option>');
                   2631:     my %temphash=();
                   2632:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2633:     foreach my $tempkey (sort {
1.560     damieng  2634:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2635:             } keys(%{$allparts})) {
                   2636:         unless ($tempkey =~ /\./) {
                   2637:             $r->print('<option value="'.$tempkey.'"');
                   2638:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2639:                 $r->print(' selected="selected"');
                   2640:             }
                   2641:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2642:         }
1.208     www      2643:     }
1.446     bisitz   2644:     $r->print('</select>');
1.209     www      2645: }
                   2646: 
1.562     damieng  2647: # Prints HTML to select a user and/or a group.
                   2648: # Used by table mode.
                   2649: #
                   2650: # @param {Apache2::RequestRec} $r - the Apache request
                   2651: # @param {string} $uname - selected user name
                   2652: # @param {string} $id - selected Student/Employee ID
                   2653: # @param {string} $udom - selected user domain
                   2654: # @param {string} $csec - selected section name
                   2655: # @param {string} $cgroup - selected group name
                   2656: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2657: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2658: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2659: sub usermenu {
1.553     raeburn  2660:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2661:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2662:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2663:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2664: function setCourseadv(form,caller) {
                   2665:     if (caller.value == 'st') {
                   2666:         form.courseadv.value = 'none';
                   2667:     } else {
                   2668:         form.courseadv.value = '';
                   2669:     }
                   2670:     return;
                   2671: }
                   2672: ENDJS
1.412     bisitz   2673: 
1.596     raeburn  2674:     my (%chkroles,$stuonly,$courseadv);
                   2675:     if ($env{'form.userroles'} eq 'any') {
                   2676:         $chkroles{'any'} = ' checked="checked"';
                   2677:     } else {
                   2678:         $chkroles{'st'} = ' checked="checked"';
                   2679:         $courseadv = 'none';
                   2680:     }
                   2681:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2682:     if ($crstype eq 'Community') {
                   2683:         $stuonly = &mt('member only');
                   2684:     } else {
                   2685:         $stuonly = &mt('student only');
                   2686:     }
                   2687:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2688:                   &mt("User's role").':&nbsp;'.
                   2689:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2690:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2691:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2692:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2693:     my $sections='';
1.300     albertel 2694:     my %sectionhash = &Apache::loncommon::get_sections();
                   2695: 
1.269     raeburn  2696:     my $groups;
1.553     raeburn  2697:     my %grouphash;
                   2698:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2699:         %grouphash = &Apache::longroup::coursegroups();
                   2700:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2701:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2702:     }
1.299     albertel 2703: 
1.412     bisitz   2704:     my $g_s_header='';
                   2705:     my $g_s_footer='';
1.446     bisitz   2706: 
1.552     raeburn  2707:     my $currsec = $env{'request.course.sec'};
                   2708:     if ($currsec) {
                   2709:         $sections=&mt('Section:').' '.$currsec;
                   2710:         if (%grouphash) {
                   2711:             $sections .= ';'.('&nbsp;' x2);
                   2712:         }
                   2713:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2714:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2715:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2716:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2717:         }
                   2718:         $sections .= '>';
1.548     raeburn  2719:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2720:         $sections.='<option value="'.$section.'" '.
                   2721:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2722:                                                               '</option>';
1.209     www      2723:         }
                   2724:         $sections.='</select>';
1.269     raeburn  2725:     }
1.412     bisitz   2726: 
1.552     raeburn  2727:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2728:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2729:         $sections .= qq|
                   2730: <script type="text/javascript">
1.454     bisitz   2731: // <![CDATA[
1.269     raeburn  2732: function group_or_section(caller) {
                   2733:    if (caller == "cgroup") {
                   2734:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2735:            document.parmform.csec.selectedIndex = 0;
                   2736:        }
                   2737:    } else {
                   2738:        if (document.parmform.csec.selectedIndex != 0) {
                   2739:            document.parmform.cgroup.selectedIndex = 0;
                   2740:        }
                   2741:    }
                   2742: }
1.454     bisitz   2743: // ]]>
1.269     raeburn  2744: </script>
                   2745: |;
1.554     raeburn  2746:     } else {
1.269     raeburn  2747:         $sections .= qq|
                   2748: <script type="text/javascript">
1.454     bisitz   2749: // <![CDATA[
1.269     raeburn  2750: function group_or_section(caller) {
                   2751:     return;
                   2752: }
1.454     bisitz   2753: // ]]>
1.269     raeburn  2754: </script>
                   2755: |;
1.446     bisitz   2756:     }
1.299     albertel 2757: 
                   2758:     if (%grouphash) {
1.597     raeburn  2759:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2760:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2761:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2762:         }
                   2763:         $groups .= '>';
1.548     raeburn  2764:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2765:             $groups.='<option value="'.$grp.'" ';
                   2766:             if ($grp eq $cgroup) {
                   2767:                 unless ((defined($uname)) && ($grp eq '')) {
                   2768:                     $groups .=  'selected="selected" ';
                   2769:                 }
                   2770:             } elsif (!defined($cgroup)) {
                   2771:                 if (@{$usersgroups} == 1) {
                   2772:                     if ($grp eq $$usersgroups[0]) {
                   2773:                         $groups .=  'selected="selected" ';
                   2774:                     }
                   2775:                 }
                   2776:             }
                   2777:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2778:         }
                   2779:         $groups.='</select>';
                   2780:     }
1.412     bisitz   2781: 
1.445     neumanie 2782:     if (%sectionhash || %grouphash) {
1.446     bisitz   2783:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2784:         $r->print($sections.$groups);
1.448     bisitz   2785:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2786:     } else {
                   2787:         $r->print($sections); 
1.445     neumanie 2788:     }
1.446     bisitz   2789: 
                   2790:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2791:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2792:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2793:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2794:                  ,$chooseopt));
1.209     www      2795: }
                   2796: 
1.562     damieng  2797: # Prints HTML to select parameters from a list of all parameters.
                   2798: # Uses parmmenu and parmboxes.
                   2799: # Used by table and overview modes.
1.468     amueller 2800: #
1.562     damieng  2801: # @param {Apache2::RequestRec} $r - the Apache request
                   2802: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2803: # @param {array reference} $pscat - list of selected parameter names
                   2804: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2805: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2806: sub displaymenu {
1.581     raeburn  2807:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2808: 
1.445     neumanie 2809:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2810:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2811: 
1.581     raeburn  2812:     &parmmenu($r);
1.536     raeburn  2813:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2814:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2815:     $r->print(&Apache::loncommon::end_scrollbox());
                   2816: 
                   2817:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2818:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2819:  
1.209     www      2820: }
                   2821: 
1.562     damieng  2822: # Prints HTML to select a map.
                   2823: # Used by table mode and overview mode.
                   2824: #
                   2825: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2826: # @param {hash reference} $allmaps - hash map pc -> map src
                   2827: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2828: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2829: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610     raeburn  2830: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445     neumanie 2831: sub mapmenu {
1.610     raeburn  2832:     my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468     amueller 2833:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2834:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2835:     my $tree=[];
                   2836:     my $treeinfo={};
                   2837:     if (defined($navmap)) {
1.499     raeburn  2838:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2839:         my $curRes;
                   2840:         my $depth = 0;
1.468     amueller 2841:         my %parent = ();
                   2842:         my $startcount = 5;
                   2843:         my $lastcontainer = $startcount;
                   2844: # preparing what is to show ...
1.461     neumanie 2845:         while ($curRes = $it->next()) {
                   2846:             if ($curRes == $it->BEGIN_MAP()) {
                   2847:                 $depth++;
1.468     amueller 2848:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2849:             }
                   2850:             if ($curRes == $it->END_MAP()) {
                   2851:                 $depth--;
1.468     amueller 2852:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2853:             }
                   2854:             if (ref($curRes)) {
1.468     amueller 2855:                 my $symb = $curRes->symb();
                   2856:                 my $ressymb = $symb;
1.461     neumanie 2857:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2858:                     my $type = 'sequence';
                   2859:                     if ($curRes->is_page()) {
                   2860:                         $type = 'page';
                   2861:                     }
                   2862:                     my $id= $curRes->id();
1.468     amueller 2863:                     my $srcf = $curRes->src();
                   2864:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2865:                     if(!exists($treeinfo->{$id})) {
                   2866:                         push(@$tree,$id);
1.473     amueller 2867:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2868:                         $treeinfo->{$id} = {
1.461     neumanie 2869:                                     depth => $depth,
                   2870:                                     type  => $type,
1.468     amueller 2871:                                     name  => $resource_name,
                   2872:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2873:                                     };
1.462     neumanie 2874:                     }
1.461     neumanie 2875:                 }
                   2876:             }
                   2877:         }
1.462     neumanie 2878:     }
1.473     amueller 2879: # Show it ...    
1.610     raeburn  2880:     my $rowattr = ' id="mapmenu"';
                   2881:     if ($parmlev eq 'general') {
                   2882:         $rowattr .= ' style="display:none"';
                   2883:     }
                   2884:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461     neumanie 2885:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2886:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2887:         my $whitespace =
                   2888:             '<img src="'
                   2889:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2890:            .'" alt="" />';
                   2891: 
1.498     bisitz   2892:         # Info about selectable folders/maps
                   2893:         $r->print(
                   2894:             '<div class="LC_info">'
1.508     www      2895:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2896:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2897:            .'</div>'
                   2898:         );
                   2899: 
1.536     raeburn  2900:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2901:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2902: 
1.498     bisitz   2903:         # Display row: "All Maps or Folders"
                   2904:         $r->print(
1.523     raeburn  2905:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2906:            .'<td>'
                   2907:            .'<label>'
                   2908:            .'<input type="radio" name="pschp"'
1.497     bisitz   2909:         );
                   2910:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2911:         $r->print(
                   2912:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2913:            .&mt('All Maps or Folders')
                   2914:            .'</label>'
                   2915:            .'<hr /></td>'
                   2916:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2917:         );
1.497     bisitz   2918: 
1.532     raeburn  2919:         # Display row: "Main Content"
1.468     amueller 2920:         if (exists($$allmaps{1})) {
1.498     bisitz   2921:             $r->print(
                   2922:                 &Apache::loncommon::start_data_table_row()
                   2923:                .'<td>'
                   2924:                .'<label>'
                   2925:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2926:             );
1.497     bisitz   2927:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2928:             $r->print(
                   2929:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2930:                .$$maptitles{1}
                   2931:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2932:                .'</label>'
                   2933:                .'</td>'
                   2934:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2935:             );
                   2936:         }
1.497     bisitz   2937: 
                   2938:         # Display rows for all course maps and folders
1.468     amueller 2939:         foreach my $id (@{$tree}) {
                   2940:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2941:             # Indentation
1.468     amueller 2942:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2943:             my $indent;
                   2944:             for (my $i = 0; $i < $depth; $i++) {
                   2945:                 $indent.= $whitespace;
                   2946:             }
1.461     neumanie 2947:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2948:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2949:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2950:             }
1.468     amueller 2951:             my $symb_name = $$symbp{$id};
                   2952:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2953:             $symb_name = $tail;
1.498     bisitz   2954:             $r->print(
                   2955:                 &Apache::loncommon::start_data_table_row()
                   2956:                .'<td>'
                   2957:                .'<label>'
1.463     bisitz   2958:             );
1.498     bisitz   2959:             # Only offer radio button for folders/maps which can be parameterized
                   2960:             if ($allmaps_inverted{$symb_name}) {
                   2961:                 $r->print(
                   2962:                     '<input type ="radio" name="pschp"'
                   2963:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2964:                 );
                   2965:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2966:                 $r->print('/>');
                   2967:             } else {
                   2968:                 $r->print($whitespace);
1.461     neumanie 2969:             }
1.498     bisitz   2970:             $r->print(
                   2971:                 $indent.$icon.'&nbsp;'
                   2972:                .$treeinfo->{$id}->{name}
                   2973:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2974:                .'</label>'
                   2975:                .'</td>'
                   2976:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2977:             );
1.461     neumanie 2978:         }
1.497     bisitz   2979: 
1.523     raeburn  2980:         $r->print(&Apache::loncommon::end_data_table().
                   2981:                   '<br style="line-height:2px;" />'.
                   2982:                   &Apache::loncommon::end_scrollbox());
1.209     www      2983:     }
                   2984: }
                   2985: 
1.563     damieng  2986: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2987: # Used by table and overview modes.
                   2988: #
                   2989: # @param {Apache2::RequestRec} $r - the Apache request
                   2990: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2991: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2992: sub levelmenu {
1.446     bisitz   2993:     my ($r,$alllevs,$parmlev)=@_;
                   2994: 
1.548     raeburn  2995:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2996:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2997:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2998:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2999:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   3000:         if ($parmlev eq $$alllevs{$lev}) {
                   3001:             $r->print(' selected="selected"');
                   3002:         }
                   3003:         $r->print('>'.&mt($lev).'</option>');
1.208     www      3004:     }
1.446     bisitz   3005:     $r->print("</select>");
1.208     www      3006: }
                   3007: 
1.211     www      3008: 
1.563     damieng  3009: # Returns HTML to select a section (with a select HTML element).
                   3010: # Used by overview mode.
                   3011: #
                   3012: # @param {array reference} $selectedsections - list of selected section ids
                   3013: # @returns {string}
1.211     www      3014: sub sectionmenu {
1.553     raeburn  3015:     my ($selectedsections)=@_;
1.300     albertel 3016:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  3017:     return '' if (!%sectionhash);
1.300     albertel 3018: 
1.552     raeburn  3019:     my (@possibles,$disabled);
                   3020:     if ($env{'request.course.sec'} ne '') {
                   3021:         @possibles = ($env{'request.course.sec'});
                   3022:         $selectedsections = [$env{'request.course.sec'}];
                   3023:         $disabled = ' disabled="disabled"';
                   3024:     } else {
                   3025:         @possibles = ('all',sort(keys(%sectionhash)));
                   3026:     }
1.553     raeburn  3027:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  3028:     foreach my $s (@possibles) {
1.553     raeburn  3029:         $output .= '    <option value="'.$s.'"';
                   3030:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   3031:             $output .= ' selected="selected"';
1.473     amueller 3032:         }
1.553     raeburn  3033:         $output .= '>'."$s</option>\n";
1.300     albertel 3034:     }
1.553     raeburn  3035:     $output .= "</select>\n";
                   3036:     return $output;
1.269     raeburn  3037: }
                   3038: 
1.563     damieng  3039: # Returns HTML to select a group (with a select HTML element).
                   3040: # Used by overview mode.
                   3041: #
                   3042: # @param {array reference} $selectedgroups - list of selected group names
                   3043: # @returns {string}
1.269     raeburn  3044: sub groupmenu {
1.553     raeburn  3045:     my ($selectedgroups)=@_;
                   3046:     my %grouphash;
                   3047:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3048:         %grouphash = &Apache::longroup::coursegroups();
                   3049:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  3050:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  3051:     }
                   3052:     return '' if (!%grouphash);
1.299     albertel 3053: 
1.553     raeburn  3054:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 3055:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  3056:         $output .= '    <option value="'.$group.'"';
                   3057:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   3058:             $output .=  ' selected="selected"';
1.473     amueller 3059:         }
1.553     raeburn  3060:         $output .= '>'."$group</option>\n";
1.211     www      3061:     }
1.553     raeburn  3062:     $output .= "</select>\n";
                   3063:     return $output;
1.211     www      3064: }
                   3065: 
1.563     damieng  3066: # Returns an array with the given parameter split by comma.
                   3067: # Used by assessparms (table mode).
                   3068: #
                   3069: # @param {string} $keyp - the string to split
                   3070: # @returns {Array<string>}
1.210     www      3071: sub keysplit {
                   3072:     my $keyp=shift;
                   3073:     return (split(/\,/,$keyp));
                   3074: }
                   3075: 
1.563     damieng  3076: # Returns the keys in $name, sorted using $keyorder.
                   3077: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   3078: # Used by assessparms (table mode) for resource level.
                   3079: #
                   3080: # @param {hash reference} $name - parameter key -> parameter name
                   3081: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3082: # @returns {Array<string>}
1.210     www      3083: sub keysinorder {
                   3084:     my ($name,$keyorder)=@_;
                   3085:     return sort {
1.560     damieng  3086:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  3087:     } (keys(%{$name}));
1.210     www      3088: }
                   3089: 
1.563     damieng  3090: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3091: # Used by assessparms (table mode) for map and general levels.
                   3092: #
                   3093: # @param {hash reference} $name - parameter key -> parameter name
                   3094: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3095: # @returns {Array<string>}
1.236     albertel 3096: sub keysinorder_bytype {
                   3097:     my ($name,$keyorder)=@_;
                   3098:     return sort {
1.563     damieng  3099:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3100:         my $tb=(split('_',$b))[-1];
                   3101:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3102:             return ($a cmp $b);
                   3103:         }
                   3104:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3105:     } (keys(%{$name}));
1.236     albertel 3106: }
                   3107: 
1.563     damieng  3108: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3109: # Used by defaultsetter (parameter settings default actions).
                   3110: #
                   3111: # @param {hash reference} $name - hash parameter name -> parameter title
                   3112: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3113: # @returns {Array<string>}
1.211     www      3114: sub keysindisplayorder {
                   3115:     my ($name,$keyorder)=@_;
                   3116:     return sort {
1.560     damieng  3117:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3118:     } (keys(%{$name}));
1.211     www      3119: }
                   3120: 
1.563     damieng  3121: # Prints HTML with a choice to sort results by realm or student first.
                   3122: # Used by overview mode.
                   3123: #
                   3124: # @param {Apache2::RequestRec} $r - the Apache request
                   3125: # @param {string} $sortorder - realmstudent|studentrealm
1.608     raeburn  3126: # @param {string} $context - newoverview|overview
1.214     www      3127: sub sortmenu {
1.608     raeburn  3128:     my ($r,$sortorder,$context)=@_;
                   3129:     my %text;
                   3130:     if ($context eq 'newoverview') {
                   3131:         %text = &Apache::lonlocal::texthash (
                   3132:                    realmstudent => 'Sort by location in course first, then student (group/section)',
                   3133:                    studentrealm => 'Sort by student (group/section) first, then location in course',
                   3134:         );
                   3135:     } else {
                   3136:         %text = &Apache::lonlocal::texthash (
                   3137:                    realmstudent => 'Sort by realm first, then student (group/section)',
                   3138:                    studentrealm => 'Sort by student (group/section) first, then realm',
                   3139:         );
1.214     www      3140:     }
1.608     raeburn  3141:     my %sortchecked = (
                   3142:        realmstudent => ' checked="checked"',
                   3143:        studentrealm => '',
                   3144:     );
1.214     www      3145:     if ($sortorder eq 'studentrealm') {
1.608     raeburn  3146:         $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
                   3147:         $sortchecked{'realmstudent'} = '';
                   3148:     }
                   3149:     foreach my $sorttype ('realmstudent','studentrealm') {
                   3150:         $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                   3151:                   $text{$sorttype}.'</label>');
1.214     www      3152:     }
                   3153: }
                   3154: 
1.563     damieng  3155: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3156: #
                   3157: # @returns {hash}
1.211     www      3158: sub standardkeyorder {
                   3159:     return ('parameter_0_opendate' => 1,
1.473     amueller 3160:         'parameter_0_duedate' => 2,
                   3161:         'parameter_0_answerdate' => 3,
                   3162:         'parameter_0_interval' => 4,
                   3163:         'parameter_0_weight' => 5,
                   3164:         'parameter_0_maxtries' => 6,
                   3165:         'parameter_0_hinttries' => 7,
                   3166:         'parameter_0_contentopen' => 8,
                   3167:         'parameter_0_contentclose' => 9,
                   3168:         'parameter_0_type' => 10,
                   3169:         'parameter_0_problemstatus' => 11,
                   3170:         'parameter_0_hiddenresource' => 12,
                   3171:         'parameter_0_hiddenparts' => 13,
                   3172:         'parameter_0_display' => 14,
                   3173:         'parameter_0_ordered' => 15,
                   3174:         'parameter_0_tol' => 16,
                   3175:         'parameter_0_sig' => 17,
                   3176:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3177:         'parameter_0_discussend' => 19,
                   3178:         'parameter_0_discusshide' => 20,
                   3179:         'parameter_0_discussvote' => 21,
1.560     damieng  3180:         'parameter_0_printstartdate'  =>  22,
                   3181:         'parameter_0_printenddate' =>  23);
1.211     www      3182: }
                   3183: 
1.59      matthew  3184: 
1.560     damieng  3185: # Table mode UI.
1.563     damieng  3186: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3187: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3188: #
                   3189: # Parameters used from the request:
                   3190: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3191: # cgroup - selected group
                   3192: # command - 'set': direct access to table mode for a resource
                   3193: # csec - selected section
                   3194: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3195: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3196: # id - student/employee ID
                   3197: # parmlev - selected level (full|map|general)
                   3198: # part - selected part (unused ?)
                   3199: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3200: # pres_type - &&&-separated parameter types
                   3201: # pres_value - &&&-separated parameter values
                   3202: # prevvisit - '1' if the user has submitted the form before
                   3203: # pscat (multiple values) - selected parameter names
1.566     damieng  3204: # pschp - selected map pc, or 'all'
1.563     damieng  3205: # psprt (multiple values) - list of selected parameter parts
                   3206: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3207: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3208: # symb - resource symb (when a single resource is selected)
                   3209: # udom - selected user domain
                   3210: # uname - selected user name
                   3211: # url - used only with command 'set', the resource url
                   3212: #
                   3213: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3214: # @param $parm_permission - ref to hash of permissions
                   3215: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3216: sub assessparms {
1.1       www      3217: 
1.568     raeburn  3218:     my ($r,$parm_permission) = @_;
1.201     www      3219: 
1.512     foxr     3220: 
                   3221: # -------------------------------------------------------- Variable declaration
1.566     damieng  3222:     my @ids=(); # resource and map ids
                   3223:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3224:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3225:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3226:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3227:     my %uris=(); # hash resource/map id -> resource src
                   3228:     my %maptitles=(); # hash map pc or src -> map title
                   3229:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3230:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3231:     my %alllevs=(); # hash English level title -> value
                   3232: 
                   3233:     my $uname; # selected user name
                   3234:     my $udom; # selected user domain
                   3235:     my $uhome; # server with the user's files, or 'no_host'
                   3236:     my $csec; # selected section name
                   3237:     my $cgroup; # selected group name
                   3238:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3239:     my $numreclinks = 0;
1.446     bisitz   3240: 
1.190     albertel 3241:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3242: 
1.57      albertel 3243:     $alllevs{'Resource Level'}='full';
1.215     www      3244:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3245:     $alllevs{'Course Level'}='general';
                   3246: 
1.563     damieng  3247:     my %allparms; # hash parameter name -> parameter title
                   3248:     my %allparts; # hash parameter part -> part title
1.512     foxr     3249: # ------------------------------------------------------------------------------
                   3250: 
1.210     www      3251: #
                   3252: # Order in which these parameters will be displayed
                   3253: #
1.211     www      3254:     my %keyorder=&standardkeyorder();
                   3255: 
1.512     foxr     3256: #    @ids=();
                   3257: #    %symbp=();       # These seem defined above already.
                   3258: #    %typep=();
1.43      albertel 3259: 
                   3260:     my $message='';
                   3261: 
1.190     albertel 3262:     $csec=$env{'form.csec'};
1.552     raeburn  3263:     if ($env{'request.course.sec'} ne '') {
                   3264:         $csec = $env{'request.course.sec'};    
                   3265:     }
                   3266: 
1.553     raeburn  3267: # Check group privs.
1.269     raeburn  3268:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3269:     my $noeditgrp; 
                   3270:     if ($cgroup ne '') {
                   3271:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3272:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3273:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3274:                 $noeditgrp = 1;
                   3275:             }
                   3276:         }
                   3277:     }
1.188     www      3278: 
1.190     albertel 3279:     if      ($udom=$env{'form.udom'}) {
                   3280:     } elsif ($udom=$env{'request.role.domain'}) {
                   3281:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3282:     } else {
1.473     amueller 3283:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3284:     }
1.468     amueller 3285:     
1.43      albertel 3286: 
1.134     albertel 3287:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3288:     my $pschp=$env{'form.pschp'};
1.506     www      3289: 
                   3290: 
1.134     albertel 3291:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3292:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3293:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3294: 
1.43      albertel 3295:     my $pssymb='';
1.57      albertel 3296:     my $parmlev='';
1.446     bisitz   3297: 
1.190     albertel 3298:     unless ($env{'form.parmlev'}) {
1.57      albertel 3299:         $parmlev = 'map';
                   3300:     } else {
1.190     albertel 3301:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3302:     }
1.26      www      3303: 
1.29      www      3304: # ----------------------------------------------- Was this started from grades?
                   3305: 
1.560     damieng  3306:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3307:             (!$env{'form.dis'})) {
1.473     amueller 3308:         my $url=$env{'form.url'};
                   3309:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3310:         $pssymb=&Apache::lonnet::symbread($url);
                   3311:         if (!@pscat) { @pscat=('all'); }
                   3312:         $pschp='';
1.57      albertel 3313:         $parmlev = 'full';
1.190     albertel 3314:     } elsif ($env{'form.symb'}) {
1.473     amueller 3315:         $pssymb=$env{'form.symb'};
                   3316:         if (!@pscat) { @pscat=('all'); }
                   3317:         $pschp='';
1.57      albertel 3318:         $parmlev = 'full';
1.43      albertel 3319:     } else {
1.473     amueller 3320:         $env{'form.url'}='';
1.43      albertel 3321:     }
                   3322: 
1.190     albertel 3323:     my $id=$env{'form.id'};
1.43      albertel 3324:     if (($id) && ($udom)) {
1.555     raeburn  3325:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3326:         if ($uname) {
                   3327:             $id='';
                   3328:         } else {
                   3329:             $message=
1.540     bisitz   3330:                 '<p class="LC_warning">'.
                   3331:                 &mt('Unknown ID [_1] at domain [_2]',
                   3332:                     "'".$id."'","'".$udom."'").
                   3333:                 '</p>';
1.473     amueller 3334:         }
1.43      albertel 3335:     } else {
1.473     amueller 3336:         $uname=$env{'form.uname'};
1.43      albertel 3337:     }
                   3338:     unless ($udom) { $uname=''; }
                   3339:     $uhome='';
                   3340:     if ($uname) {
1.473     amueller 3341:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3342:         if ($uhome eq 'no_host') {
1.473     amueller 3343:             $message=
1.540     bisitz   3344:                 '<p class="LC_warning">'.
                   3345:                 &mt('Unknown user [_1] at domain [_2]',
                   3346:                     "'".$uname."'","'".$udom."'").
                   3347:                 '</p>';
1.473     amueller 3348:             $uname='';
1.12      www      3349:         } else {
1.473     amueller 3350:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3351:                           $env{'request.course.id'});
                   3352:             if ($csec eq '-1') {
1.596     raeburn  3353:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3354:                 if ($env{'form.userroles'} eq 'any') {
                   3355:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3356:                         $csec = $env{'request.course.sec'};
                   3357:                         $message = '<span class="LC_info">';
                   3358:                         if ($crstype eq 'Community') {
                   3359:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3360:                                             $uname,$udom);
                   3361:                         } else {
                   3362:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3363:                                             $uname,$udom);
                   3364:                         }
                   3365:                         $message .= '</span>';
                   3366:                     } else {
                   3367:                         my @possroles = ('in','ep','ta','cr');
                   3368:                         if ($crstype eq 'Community') {
                   3369:                             unshift(@possroles,'co');
                   3370:                         } else {
                   3371:                             unshift(@possroles,'cc');
                   3372:                         }
                   3373:                         my %not_student_roles =
                   3374:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3375:                                                           \@possroles,[$udom],1,1);
                   3376:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3377:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3378:                         my %sections_by_role;
                   3379:                         foreach my $role (keys(%not_student_roles)) {
                   3380:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3381:                                 my ($rolename,$sec) = ($1,$2);
                   3382:                                 if ($rolename =~ m{^cr/}) {
                   3383:                                     $rolename = 'cr';
                   3384:                                 }
                   3385:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3386:                             }
                   3387:                         }
                   3388:                         my $numroles = scalar(keys(%sections_by_role));
                   3389:                         if ($numroles) {
                   3390:                             foreach my $role (@possroles) {
                   3391:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3392:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3393:                                     $csec = $secs[0];
                   3394:                                     last;
                   3395:                                 }
                   3396:                             }
                   3397:                         }
                   3398:                         if ($csec eq '-1') {
                   3399:                             $message = '<span class="LC_warning">';
                   3400:                             if ($crstype eq 'Community') {
                   3401:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3402:                                                 $uname,$udom);
                   3403:                             } else {
                   3404:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3405:                                                 $uname,$udom);
                   3406:                             }
                   3407:                             $message .= '</span>';
                   3408:                             $uname='';
                   3409:                             if ($env{'request.course.sec'} ne '') {
                   3410:                                 $csec=$env{'request.course.sec'};
                   3411:                             } else {
                   3412:                                 $csec=$env{'form.csec'};
                   3413:                             }
                   3414:                             $cgroup=$env{'form.cgroup'};
                   3415:                         } else {
                   3416:                             $message = '<span class="LC_info">';
                   3417:                             if ($crstype eq 'Community') {
                   3418:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3419:                                          $uname,$udom);
                   3420:                             } else {
                   3421:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3422:                                                 $uname,$udom);
                   3423:                             }
                   3424:                             $message .= '</span>';
                   3425:                         }
                   3426:                     }
1.594     raeburn  3427:                 } else {
1.596     raeburn  3428:                     $message = '<span class="LC_warning">';
                   3429:                     if ($crstype eq 'Community') {
                   3430:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3431:                                          $uname,$udom);
                   3432:                     } else {
                   3433:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3434:                                          $uname,$udom);
                   3435:                     }
                   3436:                     $message .= '</span>';
                   3437:                     $uname='';
                   3438:                     if ($env{'request.course.sec'} ne '') {
                   3439:                         $csec=$env{'request.course.sec'};
                   3440:                     } else {
                   3441:                         $csec=$env{'form.csec'};
                   3442:                     }
                   3443:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3444:                 }
                   3445:             } elsif ($env{'request.course.sec'} ne '') {
                   3446:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3447:                     $message='<span class="LC_warning">'.
1.594     raeburn  3448:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3449:                                   $uname,$udom,$env{'request.course.sec'}).
                   3450:                               '</span>';
                   3451:                     $uname='';
                   3452:                     $csec=$env{'request.course.sec'};
                   3453:                 }
1.269     raeburn  3454:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3455:             }
                   3456:             if ($uname ne '') {
1.473     amueller 3457:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3458:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3459:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3460:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3461:                             .$name{'lastname'}.' '.$name{'generation'}
                   3462:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3463:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3464:                                    $udom,$uname,$env{'request.course.id'});
                   3465:                 if (@usersgroups > 0) {
                   3466:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3467:                         $cgroup = $usersgroups[0];
                   3468:                     }
                   3469:                 } else {
                   3470:                     $cgroup = '';
1.297     raeburn  3471:                 }
1.269     raeburn  3472:             }
1.12      www      3473:         }
1.43      albertel 3474:     }
1.2       www      3475: 
1.43      albertel 3476:     unless ($csec) { $csec=''; }
1.269     raeburn  3477:     unless ($cgroup) { $cgroup=''; }
1.12      www      3478: 
1.14      www      3479: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3480:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3481:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3482:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3483: 
1.582     raeburn  3484:     %allmaps_inverted = reverse(%allmaps);
                   3485: 
1.57      albertel 3486:     $mapp{'0.0'} = '';
                   3487:     $symbp{'0.0'} = '';
1.99      albertel 3488: 
1.14      www      3489: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3490:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3491:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3492:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3493:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3494:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3495:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3496:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3497:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3498:         my $totalstored = 0;
1.605     raeburn  3499:         my $totalskippeduser = 0;
1.546     raeburn  3500:         my $now = time;
1.473     amueller 3501:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3502:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3503:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3504:                 next if ($csec ne $env{'request.course.sec'});
                   3505:             }
1.556     raeburn  3506:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3507:                 next if ($noeditgrp);
1.605     raeburn  3508:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3509:                 if ($uname eq '') {
                   3510:                     $totalskippeduser ++;
                   3511:                     next;
                   3512:                 }
1.557     raeburn  3513:             }
                   3514:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3515:                 $namematch = 'maplevelrecurse';
                   3516:             }
1.556     raeburn  3517:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3518:                 my (@ok_slots,@fail_slots,@del_slots);
                   3519:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3520:                 my ($level,@all) =
                   3521:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3522:                                      $csec,$cgroup,$courseopt);
                   3523:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3524:                     next if ($slot_name eq '');
                   3525:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3526:                         push(@ok_slots,$slot_name);
                   3527: 
                   3528:                     } else {
                   3529:                         push(@fail_slots,$slot_name);
                   3530:                     }
                   3531:                 }
                   3532:                 if (@ok_slots) {
                   3533:                     $values[$i] = join(':',@ok_slots);
                   3534:                 } else {
                   3535:                     $values[$i] = '';
                   3536:                 }
                   3537:                 if ($all[$level] ne '') {
                   3538:                     my @existing = split(/:/,$all[$level]);
                   3539:                     foreach my $slot_name (@existing) {
                   3540:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3541:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3542:                                 push(@del_slots,$slot_name);
                   3543:                             }
                   3544:                         }
                   3545:                     }
                   3546:                 }
1.554     raeburn  3547:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3548:                 $name = $1;
1.533     raeburn  3549:                 my $val = $values[$i];
1.549     raeburn  3550:                 my $valmatch = '';
1.533     raeburn  3551:                 if ($name eq 'examcode') {
1.544     raeburn  3552:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3553:                         $val = 'valid';
                   3554:                     }
1.546     raeburn  3555:                 } elsif ($name eq 'printstartdate') {
                   3556:                     if ($val =~ /^\d+$/) {
                   3557:                         if ($val > $now) {
                   3558:                             $val = 'future';
                   3559:                         }
                   3560:                     } 
                   3561:                 } elsif ($name eq 'printenddate') {
                   3562:                     if ($val =~ /^\d+$/) {
                   3563:                         if ($val < $now) {
                   3564:                             $val = 'past';
                   3565:                         }
                   3566:                     }
1.549     raeburn  3567:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3568:                     my $stringtype = &get_stringtype($name);
                   3569:                     my $stringmatch = &standard_string_matches($stringtype);
                   3570:                     if (ref($stringmatch) eq 'ARRAY') {
                   3571:                         foreach my $item (@{$stringmatch}) {
                   3572:                             if (ref($item) eq 'ARRAY') {
                   3573:                                 my ($regexpname,$pattern) = @{$item};
                   3574:                                 if ($pattern ne '') {
                   3575:                                     if ($val =~ /$pattern/) {
                   3576:                                         $valmatch = $regexpname;
                   3577:                                         $val = '';
                   3578:                                         last;
                   3579:                                     }
                   3580:                                 }
                   3581:                             }
                   3582:                         }
                   3583:                     }
1.554     raeburn  3584:                 } elsif ($name eq 'interval') {
                   3585:                     my $intervaltype = &get_intervaltype($name);
                   3586:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3587:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3588:                         foreach my $item (@{$intervalmatch}) {
                   3589:                             if (ref($item) eq 'ARRAY') {
                   3590:                                 my ($regexpname,$pattern) = @{$item};
                   3591:                                 if ($pattern ne '') {
                   3592:                                     if ($val =~ /$pattern/) {
                   3593:                                         $valmatch = $regexpname;
                   3594:                                         $val = '';
                   3595:                                         last;
                   3596:                                     }
                   3597:                                 }
                   3598:                             }
                   3599:                         }
                   3600:                     }
1.533     raeburn  3601:                 }
1.504     raeburn  3602:                 $needsrelease =
1.557     raeburn  3603:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3604:                 if ($needsrelease) {
1.505     raeburn  3605:                     unless ($got_chostname) {
1.514     raeburn  3606:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3607:                         $got_chostname = 1;
1.546     raeburn  3608:                     } 
1.557     raeburn  3609:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3610:                                                           $needsrelease,
                   3611:                                                           $cmajor,$cminor);
1.500     raeburn  3612:                 }
1.437     raeburn  3613:             }
1.504     raeburn  3614:             if ($needsnewer) {
1.557     raeburn  3615:                 undef($namematch);
                   3616:             } else {
                   3617:                 my $currneeded;
                   3618:                 if ($needsrelease) {
                   3619:                     $currneeded = $needsrelease;
                   3620:                 }
                   3621:                 if ($namematch) {
                   3622:                     $needsrelease =
                   3623:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3624:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3625:                         unless ($got_chostname) {
                   3626:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3627:                             $got_chostname = 1;
                   3628:                         }
                   3629:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3630:                                                               $needsrelease,
                   3631:                                                               $cmajor,$cminor);
                   3632:                     } else {
                   3633:                         undef($namematch);
                   3634:                     }
                   3635:                 }
                   3636:             }
                   3637:             if ($needsnewer) {
                   3638:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3639:                                                 $cminor,$needsrelease);
                   3640:             } else {
                   3641:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3642:                                      $values[$i],
                   3643:                                      $types[$i],
                   3644:                                      $uname,$udom,$csec,$cgroup);
                   3645:                 $totalstored ++;
                   3646:             }
1.473     amueller 3647:         }
1.68      www      3648: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3649:         if ($totalstored) {
                   3650:             $message.='<p class="LC_warning">'
1.605     raeburn  3651:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3652:                      .'<br />'
1.504     raeburn  3653:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3654:                      .&Apache::loncommon::help_open_topic('Caching')
                   3655:                      .'</p>';
1.605     raeburn  3656:         } else {
                   3657:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3658:         }
                   3659:         if ($totalskippeduser) {
                   3660:             $message .= '<p class="LC_warning">';
                   3661:             if ($uhome eq 'no_host') {
                   3662:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3663:                                 $totalskippeduser);
                   3664:             } elsif ($env{'form.userroles'} eq 'any') {
                   3665:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3666:                                 $totalskippeduser);
                   3667:             } else {
                   3668:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3669:                                 $totalskippeduser);
                   3670:             }
                   3671:             $message .= '</p>';
1.504     raeburn  3672:         }
1.68      www      3673:     }
1.584     raeburn  3674: 
1.57      albertel 3675: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3676:     if ($pscat[0] eq "all") {
                   3677:         @pscat = (keys(%allparms));
                   3678:     }
                   3679:     if (!@pscat) {
                   3680:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3681:     };
                   3682:     if ($psprt[0] eq "all" || !@psprt) {
                   3683:         @psprt = (keys(%allparts));
                   3684:     }
1.2       www      3685: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3686: 
1.531     raeburn  3687:     my $crstype = &Apache::loncommon::course_type();
                   3688:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3689: 
1.548     raeburn  3690:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3691:             'date_interval','int','float','string','string_lenient',
                   3692:             'string_examcode','string_deeplink','string_discussvote',
                   3693:             'string_useslots','string_problemstatus','string_ip',
                   3694:             'string_questiontype') {
1.473     amueller 3695:         $r->print('<input type="hidden" value="'.
1.563     damieng  3696:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3697:             '" name="recent_'.$item.'" />');
1.44      albertel 3698:     }
1.446     bisitz   3699: 
1.459     bisitz   3700:     # ----- Start Parameter Selection
                   3701: 
1.606     raeburn  3702:     # Hide parm selection and possibly table?
                   3703:     my ($tablejs,$tabledivsty);
                   3704:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
                   3705:         ($env{'form.dis'}) && ($pssymb eq '')) {
                   3706:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
                   3707:         $tabledivsty = ' style="display:none"';
                   3708:     }
1.459     bisitz   3709:     $r->print(<<ENDPARMSELSCRIPT);
                   3710: <script type="text/javascript">
                   3711: // <![CDATA[
                   3712: function parmsel_show() {
1.562     damieng  3713:     document.getElementById('parmsel').style.display = "";
                   3714:     document.getElementById('parmsellink').style.display = "none";
1.606     raeburn  3715:     $tablejs
1.459     bisitz   3716: }
                   3717: // ]]>
                   3718: </script>
                   3719: ENDPARMSELSCRIPT
1.474     amueller 3720:     
1.445     neumanie 3721:     if (!$pssymb) {
1.563     damieng  3722:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3723:         my $parmselhiddenstyle=' style="display:none"';
                   3724:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3725:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3726:         } else  {
                   3727:            $r->print('<div id="parmsel">');
                   3728:         }
                   3729: 
1.491     bisitz   3730:         # Step 1
1.523     raeburn  3731:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3732:         $r->print('
1.474     amueller 3733: <script type="text/javascript">
1.523     raeburn  3734: // <![CDATA['.
                   3735:                  &showhide_js().'
1.474     amueller 3736: // ]]>
                   3737: </script>
1.523     raeburn  3738: ');
                   3739:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3740:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3741:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.610     raeburn  3742:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491     bisitz   3743:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3744:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3745:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3746:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3747:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3748: 
                   3749:         # Step 2
1.523     raeburn  3750:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3751:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3752: 
                   3753:         # Step 3
1.523     raeburn  3754:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3755:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3756:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3757:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3758:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3759: 
                   3760:         # Update Display Button
1.486     www      3761:         $r->print('<p>'
                   3762:              .'<input type="submit" name="dis"'
1.511     www      3763:              .' value="'.&mt('Update Display').'" />'
1.486     www      3764:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3765:              .'</p>');
                   3766:         $r->print('</div>');
1.491     bisitz   3767: 
1.486     www      3768:         # Offer link to display parameter selection again
                   3769:         $r->print('<p id="parmsellink"');
                   3770:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3771:            $r->print($parmselhiddenstyle);
                   3772:         }
                   3773:         $r->print('>'
                   3774:              .'<a href="javascript:parmsel_show()">'
                   3775:              .&mt('Change Parameter Selection')
                   3776:              .'</a>'
                   3777:              .'</p>');
1.44      albertel 3778:     } else {
1.478     amueller 3779:         # parameter screen for a single resource. 
1.486     www      3780:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3781:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3782:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3783:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3784:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3785:                   '<br />');
                   3786:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3787:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3788:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3789:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3790:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3791:         $r->print('<p>'
1.459     bisitz   3792:              .'<input type="submit" name="dis"'
1.511     www      3793:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3794:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3795:              .'</p>');
1.459     bisitz   3796:     }
1.478     amueller 3797:     
1.486     www      3798:     # ----- End Parameter Selection
1.57      albertel 3799: 
1.459     bisitz   3800:     # Display Messages
                   3801:     $r->print('<div>'.$message.'</div>');
1.210     www      3802: 
1.57      albertel 3803: 
                   3804:     my @temp_pscat;
                   3805:     map {
                   3806:         my $cat = $_;
                   3807:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3808:     } @pscat;
                   3809: 
                   3810:     @pscat = @temp_pscat;
                   3811: 
1.548     raeburn  3812: 
1.209     www      3813:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3814: # ----------------------------------------------------------------- Start Table
1.57      albertel 3815:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3816:         my $csuname=$env{'user.name'};
                   3817:         my $csudom=$env{'user.domain'};
1.568     raeburn  3818:         my $readonly = 1;
                   3819:         if ($parm_permission->{'edit'}) {
                   3820:             undef($readonly); 
                   3821:         }
1.606     raeburn  3822:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3823: 
1.203     www      3824:         if ($parmlev eq 'full') {
1.506     www      3825: #
                   3826: # This produces the cascading table output of parameters
                   3827: #
1.578     raeburn  3828:             my $coursespan=$csec?8:5;
                   3829:             my $userspan=3;
1.560     damieng  3830:             if ($cgroup ne '') {
1.578     raeburn  3831:                 $coursespan += 3;
1.560     damieng  3832:             }
1.473     amueller 3833: 
1.560     damieng  3834:             $r->print(&Apache::loncommon::start_data_table());
                   3835:             #
                   3836:             # This produces the headers
                   3837:             #
                   3838:             $r->print('<tr><td colspan="5"></td>');
                   3839:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3840:             if ($uname) {
1.473     amueller 3841:                 if (@usersgroups > 1) {
1.560     damieng  3842:                     $userspan ++;
                   3843:                 }
                   3844:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3845:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3846:             }
                   3847:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3848:                 'pie'    => "Parameter in Effect",
                   3849:                 'csv'    => "Current Session Value",
1.472     amueller 3850:                 'rl'     => "Resource Level",
1.473     amueller 3851:                 'ic'     => 'in Course',
                   3852:                 'aut'    => "Assessment URL and Title",
                   3853:                 'type'   => 'Type',
                   3854:                 'emof'   => "Enclosing Map or Folder",
                   3855:                 'part'   => 'Part',
1.472     amueller 3856:                 'pn'     => 'Parameter Name',
1.473     amueller 3857:                 'def'    => 'default',
                   3858:                 'femof'  => 'from Enclosing Map or Folder',
                   3859:                 'gen'    => 'general',
                   3860:                 'foremf' => 'for Enclosing Map or Folder',
                   3861:                 'fr'     => 'for Resource'
                   3862:             );
1.560     damieng  3863:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3864: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3865: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3866: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3867: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3868: 
1.10      www      3869: ENDTABLETWO
1.560     damieng  3870:             if ($csec) {
1.578     raeburn  3871:                 $r->print('<th colspan="3">'.
1.560     damieng  3872:                 &mt("in Section")." $csec</th>");
                   3873:             }
                   3874:             if ($cgroup) {
1.578     raeburn  3875:                 $r->print('<th colspan="3">'.
1.472     amueller 3876:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3877:             }
                   3878:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3879: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3880: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3881: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3882: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3883: ENDTABLEHEADFOUR
1.57      albertel 3884: 
1.560     damieng  3885:             if ($csec) {
1.578     raeburn  3886:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3887:             }
1.473     amueller 3888: 
1.560     damieng  3889:             if ($cgroup) {
1.578     raeburn  3890:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3891:             }
                   3892: 
                   3893:             if ($uname) {
                   3894:                 if (@usersgroups > 1) {
                   3895:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3896:                 }
1.578     raeburn  3897:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3898:             }
                   3899: 
                   3900:             $r->print('</tr>');
1.506     www      3901: #
                   3902: # Done with the headers
                   3903: # 
1.560     damieng  3904:             my $defbgone='';
                   3905:             my $defbgtwo='';
                   3906:             my $defbgthree = '';
1.57      albertel 3907: 
1.560     damieng  3908:             foreach my $rid (@ids) {
1.57      albertel 3909: 
                   3910:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3911:                 if ((!$pssymb &&
1.560     damieng  3912:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3913:                         ||
                   3914:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3915: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3916:                     if ($defbgone eq '#E0E099') {
                   3917:                         $defbgone='#E0E0DD';
1.57      albertel 3918:                     } else {
1.419     bisitz   3919:                         $defbgone='#E0E099';
1.57      albertel 3920:                     }
1.419     bisitz   3921:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3922:                         $defbgtwo='#FFFFDD';
1.57      albertel 3923:                     } else {
1.473     amueller 3924:                         $defbgtwo='#FFFF99';
1.57      albertel 3925:                     }
1.419     bisitz   3926:                     if ($defbgthree eq '#FFBB99') {
                   3927:                         $defbgthree='#FFBBDD';
1.269     raeburn  3928:                     } else {
1.419     bisitz   3929:                         $defbgthree='#FFBB99';
1.269     raeburn  3930:                     }
                   3931: 
1.57      albertel 3932:                     my $thistitle='';
                   3933:                     my %name=   ();
                   3934:                     undef %name;
                   3935:                     my %part=   ();
                   3936:                     my %display=();
                   3937:                     my %type=   ();
                   3938:                     my %default=();
1.196     www      3939:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3940:                     my $toolsymb;
                   3941:                     if ($uri =~ /ext\.tool$/) {
                   3942:                         $toolsymb = $symbp{$rid};
                   3943:                     }
1.57      albertel 3944: 
1.506     www      3945:                     my $filter=$env{'form.filter'};
1.548     raeburn  3946:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3947:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3948:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3949:     # We may only want certain parameters listed
                   3950:                             if ($filter) {
                   3951:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3952:                             }
                   3953:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3954:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3955: 
1.584     raeburn  3956:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3957:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3958:                                 my $identifier;
                   3959:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3960:                                     $identifier = $1;
                   3961:                                 }
                   3962:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3963:                             } else {
                   3964:                                 $display{$tempkeyp} = $parmdis;
                   3965:                             }
                   3966:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3967:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3968:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3969:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3970:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3971:                         }
                   3972:                     }
1.548     raeburn  3973:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3974:                     if ($totalparms>0) {
1.560     damieng  3975:                         my $firstrow=1;
1.473     amueller 3976:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3977:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3978:                         my @recurseup;
                   3979:                         if (ref($navmap) && $mapp{$rid}) {
                   3980:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3981:                         }
1.419     bisitz   3982:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3983:                              ' rowspan='.$totalparms.
1.419     bisitz   3984:                              '><tt><font size="-1">'.
1.57      albertel 3985:                              join(' / ',split(/\//,$uri)).
                   3986:                              '</font></tt><p><b>'.
1.154     albertel 3987:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3988:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3989:                           &escape($symbp{$rid}).
1.336     albertel 3990:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3991:                              " target=\"_self\">$title");
1.57      albertel 3992: 
                   3993:                         if ($thistitle) {
1.473     amueller 3994:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3995:                         }
                   3996:                         $r->print('</a></b></td>');
1.419     bisitz   3997:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3998:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3999:                                       '</td>');
                   4000: 
1.419     bisitz   4001:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 4002:                                       ' rowspan='.$totalparms.
1.238     www      4003:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  4004:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 4005:                             unless ($firstrow) {
                   4006:                                 $r->print('<tr>');
                   4007:                             } else {
                   4008:                                 undef $firstrow;
                   4009:                             }
1.548     raeburn  4010:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 4011:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  4012:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  4013:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   4014:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   4015:                                        \$numreclinks);
1.57      albertel 4016:                         }
                   4017:                     }
                   4018:                 }
                   4019:             } # end foreach ids
1.43      albertel 4020: # -------------------------------------------------- End entry for one resource
1.517     www      4021:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      4022:         } # end of  full
1.57      albertel 4023: #--------------------------------------------------- Entry for parm level map
                   4024:         if ($parmlev eq 'map') {
1.419     bisitz   4025:             my $defbgone = '#E0E099';
                   4026:             my $defbgtwo = '#FFFF99';
                   4027:             my $defbgthree = '#FFBB99';
1.57      albertel 4028: 
                   4029:             my %maplist;
                   4030: 
                   4031:             if ($pschp eq 'all') {
1.446     bisitz   4032:                 %maplist = %allmaps;
1.57      albertel 4033:             } else {
                   4034:                 %maplist = ($pschp => $mapp{$pschp});
                   4035:             }
                   4036: 
                   4037: #-------------------------------------------- for each map, gather information
                   4038:             my $mapid;
1.607     raeburn  4039:             foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60      albertel 4040:                 my $maptitle = $maplist{$mapid};
1.57      albertel 4041: 
                   4042: #-----------------------  loop through ids and get all parameter types for map
                   4043: #-----------------------------------------          and associated information
                   4044:                 my %name = ();
                   4045:                 my %part = ();
                   4046:                 my %display = ();
                   4047:                 my %type = ();
                   4048:                 my %default = ();
                   4049:                 my $map = 0;
                   4050: 
1.473     amueller 4051: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   4052: 
1.548     raeburn  4053:                 foreach my $id (@ids) {
                   4054:                     ($map)=($id =~ /([\d]*?)\./);
                   4055:                     my $rid = $id;
1.446     bisitz   4056: 
1.57      albertel 4057: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   4058: 
1.560     damieng  4059:                     if ($map eq $mapid) {
1.473     amueller 4060:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4061:                         my $toolsymb;
                   4062:                         if ($uri =~ /ext\.tool$/) {
                   4063:                             $toolsymb = $symbp{$rid};
                   4064:                         }
1.582     raeburn  4065: 
1.57      albertel 4066: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   4067: 
                   4068: #--------------------------------------------------------------------
                   4069: # @catmarker contains list of all possible parameters including part #s
                   4070: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4071: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4072: # When storing information, store as part 0
                   4073: # When requesting information, request from full part
                   4074: #-------------------------------------------------------------------
1.548     raeburn  4075:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4076:                             my $tempkeyp = $fullkeyp;
                   4077:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 4078: 
1.548     raeburn  4079:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4080:                                 $part{$tempkeyp}="0";
1.584     raeburn  4081:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4082:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4083:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   4084:                                     my $identifier;
                   4085:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4086:                                         $identifier = $1;
                   4087:                                     }
                   4088:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4089:                                 } else {
                   4090:                                     $display{$tempkeyp} = $parmdis;
                   4091:                                 }
                   4092:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4093:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4094:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4095:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4096:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 4097:                               }
                   4098:                         } # end loop through keys
1.560     damieng  4099:                     }
1.57      albertel 4100:                 } # end loop through ids
1.446     bisitz   4101: 
1.57      albertel 4102: #---------------------------------------------------- print header information
1.133     www      4103:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4104:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4105:                 my $tmp="";
1.57      albertel 4106:                 if ($uname) {
1.473     amueller 4107:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4108:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4109:                         &mt('in')." \n";
1.57      albertel 4110:                 } else {
1.401     bisitz   4111:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4112:                 }
1.269     raeburn  4113:                 if ($cgroup) {
1.401     bisitz   4114:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4115:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4116:                     $csec = '';
                   4117:                 } elsif ($csec) {
1.401     bisitz   4118:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4119:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4120:                 }
1.401     bisitz   4121:                 $r->print('<div align="center"><h4>'
                   4122:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4123:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4124:                              ,$tmp
                   4125:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4126:                              )
                   4127:                          ."<br /></h4>\n"
1.422     bisitz   4128:                 );
1.57      albertel 4129: #---------------------------------------------------------------- print table
1.419     bisitz   4130:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4131:                          .&Apache::loncommon::start_data_table_header_row()
                   4132:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4133:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4134:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4135:                          .&Apache::loncommon::end_data_table_header_row()
                   4136:                 );
1.57      albertel 4137: 
1.582     raeburn  4138:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4139:                 my @recurseup;
                   4140:                 if (ref($navmap)) {
                   4141:                      my $mapres = $navmap->getByMapPc($mapid);
                   4142:                      if (ref($mapres)) {
                   4143:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4144:                      }
                   4145:                 }
                   4146: 
                   4147: 
1.548     raeburn  4148:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4149:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4150:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4151:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4152:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4153:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4154:                            \$numreclinks);
1.57      albertel 4155:                 }
1.422     bisitz   4156:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4157:                          .'</div>'
                   4158:                 );
1.57      albertel 4159:             } # end each map
                   4160:         } # end of $parmlev eq map
                   4161: #--------------------------------- Entry for parm level general (Course level)
                   4162:         if ($parmlev eq 'general') {
1.473     amueller 4163:             my $defbgone = '#E0E099';
1.419     bisitz   4164:             my $defbgtwo = '#FFFF99';
                   4165:             my $defbgthree = '#FFBB99';
1.57      albertel 4166: 
                   4167: #-------------------------------------------- for each map, gather information
                   4168:             my $mapid="0.0";
                   4169: #-----------------------  loop through ids and get all parameter types for map
                   4170: #-----------------------------------------          and associated information
                   4171:             my %name = ();
                   4172:             my %part = ();
                   4173:             my %display = ();
                   4174:             my %type = ();
                   4175:             my %default = ();
1.446     bisitz   4176: 
1.548     raeburn  4177:             foreach $id (@ids) {
                   4178:                 my $rid = $id;
1.446     bisitz   4179: 
1.196     www      4180:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4181:                 my $toolsymb;
                   4182:                 if ($uri =~ /ext\.tool$/) {
                   4183:                     $toolsymb = $symbp{$rid};
                   4184:                 }
1.57      albertel 4185: 
                   4186: #--------------------------------------------------------------------
                   4187: # @catmarker contains list of all possible parameters including part #s
                   4188: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4189: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4190: # When storing information, store as part 0
                   4191: # When requesting information, request from full part
                   4192: #-------------------------------------------------------------------
1.548     raeburn  4193:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4194:                     my $tempkeyp = $fullkeyp;
                   4195:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4196:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4197:                         $part{$tempkeyp}="0";
1.584     raeburn  4198:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4199:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4200:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4201:                             my $identifier;
                   4202:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4203:                                 $identifier = $1;
                   4204:                             }
                   4205:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4206:                         } else {
                   4207:                             $display{$tempkeyp} = $parmdis;
                   4208:                         }
                   4209:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4210:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4211:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4212:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4213:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4214:                     }
1.57      albertel 4215:                 } # end loop through keys
                   4216:             } # end loop through ids
1.446     bisitz   4217: 
1.57      albertel 4218: #---------------------------------------------------- print header information
1.473     amueller 4219:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4220:             $r->print(<<ENDMAPONE);
1.419     bisitz   4221: <center>
                   4222: <h4>$setdef
1.135     albertel 4223: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4224: ENDMAPONE
                   4225:             if ($uname) {
1.473     amueller 4226:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4227:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4228:             } else {
1.135     albertel 4229:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4230:             }
1.446     bisitz   4231: 
1.135     albertel 4232:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4233:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4234:             $r->print("</h4>\n");
1.57      albertel 4235: #---------------------------------------------------------------- print table
1.419     bisitz   4236:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4237:                      .&Apache::loncommon::start_data_table_header_row()
                   4238:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4239:                      .'<th>'.&mt('Default Value').'</th>'
                   4240:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4241:                      .&Apache::loncommon::end_data_table_header_row()
                   4242:             );
1.57      albertel 4243: 
1.548     raeburn  4244:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4245:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4246:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4247:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4248:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4249:                            $readonly);
1.57      albertel 4250:             }
1.419     bisitz   4251:             $r->print(&Apache::loncommon::end_data_table()
                   4252:                      .'</p>'
                   4253:                      .'</center>'
                   4254:             );
1.57      albertel 4255:         } # end of $parmlev eq general
1.606     raeburn  4256:         $r->print('</div>');
1.43      albertel 4257:     }
1.507     www      4258:     $r->print('</form>');
1.582     raeburn  4259:     if ($numreclinks) {
                   4260:         $r->print(<<"END");
                   4261: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4262: <input type="hidden" name="pschp" />
                   4263: <input type="hidden" name="pscat" />
                   4264: <input type="hidden" name="psprt" />
                   4265: <input type="hidden" name="hideparmsel" value="hidden" />
                   4266: </form>
                   4267: <script type="text/javascript">
                   4268: function pjumprec(rid,name,part) {
                   4269:     document.forms.recurseform.pschp.value = rid;
                   4270:     document.forms.recurseform.pscat.value = name;
                   4271:     document.forms.recurseform.psprt.value = part;
                   4272:     document.forms.recurseform.submit();
                   4273:     return false;
                   4274: }
                   4275: </script>
                   4276: END
                   4277:     }
1.507     www      4278:     &endSettingsScreen($r);
                   4279:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4280: } # end sub assessparms
1.30      www      4281: 
1.560     damieng  4282: 
                   4283: 
1.120     www      4284: ##################################################
1.560     damieng  4285: # OVERVIEW MODE
1.207     www      4286: ##################################################
1.124     www      4287: 
1.563     damieng  4288: my $tableopen; # boolean, true if HTML table is already opened
                   4289: 
                   4290: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4291: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4292: # @returns {string}
1.124     www      4293: sub tablestart {
1.576     raeburn  4294:     my ($readonly,$is_map) = @_;
1.124     www      4295:     if ($tableopen) {
1.552     raeburn  4296:         return '';
1.124     www      4297:     } else {
1.552     raeburn  4298:         $tableopen=1;
                   4299:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4300:         if ($readonly) {
                   4301:             $output .= '<th>'.&mt('Current value').'</th>';
                   4302:         } else {
1.576     raeburn  4303:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4304:                        '<th>'.&mt('Set to ...').'</th>';
                   4305:             if ($is_map) {
                   4306:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4307:             }
1.552     raeburn  4308:         }
                   4309:         $output .= '</tr>';
                   4310:         return $output;
1.124     www      4311:     }
                   4312: }
                   4313: 
1.563     damieng  4314: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4315: # @returns {string}
1.124     www      4316: sub tableend {
                   4317:     if ($tableopen) {
1.560     damieng  4318:         $tableopen=0;
                   4319:         return &Apache::loncommon::end_data_table();
1.124     www      4320:     } else {
1.560     damieng  4321:         return'';
1.124     www      4322:     }
                   4323: }
                   4324: 
1.563     damieng  4325: # Reads course and user information.
                   4326: # 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).
                   4327: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4328: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4329: # @param {string} $crs - course number
                   4330: # @param {string} $dom - course domain
                   4331: # @returns {hash reference|Array}
1.207     www      4332: sub readdata {
                   4333:     my ($crs,$dom)=@_;
                   4334: # Read coursedata
                   4335:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4336: # Read userdata
                   4337: 
                   4338:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4339:     foreach my $user (keys(%$classlist)) {
                   4340:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4341:             my ($tuname,$tudom)=($1,$2);
                   4342:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4343:             foreach my $userkey (keys(%{$useropt})) {
                   4344:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4345:                     my $newkey=$userkey;
1.548     raeburn  4346:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4347:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4348:                 }
                   4349:             }
1.473     amueller 4350:         }
                   4351:     }
1.552     raeburn  4352:     if (wantarray) {
                   4353:         return ($resourcedata,$classlist);
                   4354:     } else {
                   4355:         return $resourcedata;
                   4356:     }
1.207     www      4357: }
                   4358: 
                   4359: 
1.563     damieng  4360: # Stores parameter data, using form parameters directly.
                   4361: #
                   4362: # 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  4363: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4364: # del_* - remove a parameter
                   4365: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4366: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4367: # key_* - date values
                   4368: # days_* - for date intervals
                   4369: # hours_* - for date intervals
                   4370: # minutes_* - for date intervals
                   4371: # seconds_* - for date intervals
                   4372: # done_* - for date intervals
                   4373: # typeof_* - parameter type
                   4374: # 
                   4375: # @param {Apache2::RequestRec} $r - the Apache request
                   4376: # @param {string} $crs - course number
                   4377: # @param {string} $dom - course domain
1.208     www      4378: sub storedata {
                   4379:     my ($r,$crs,$dom)=@_;
1.207     www      4380: # Set userlevel immediately
                   4381: # Do an intermediate store of course level
                   4382:     my $olddata=&readdata($crs,$dom);
1.124     www      4383:     my %newdata=();
                   4384:     undef %newdata;
                   4385:     my @deldata=();
1.576     raeburn  4386:     my @delrec=();
                   4387:     my @delnonrec=();
1.124     www      4388:     undef @deldata;
1.504     raeburn  4389:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4390:     my $now = time;
1.560     damieng  4391:     foreach my $key (keys(%env)) {
                   4392:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4393:             my $cmd=$1;
                   4394:             my $thiskey=$2;
1.576     raeburn  4395:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4396:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4397:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4398:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4399:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4400:                     $altkey = $thiskey;
                   4401:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4402:                     if ($env{'form.rec_'.$thiskey}) {
                   4403:                         $recursive = 1;
                   4404:                     }
                   4405:                 }
                   4406:             }
1.560     damieng  4407:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4408:             if ($tuname) {
1.576     raeburn  4409:                 $tkey=$thiskey;
1.560     damieng  4410:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4411:                 if ($altkey) {
                   4412:                     $tkeynonrec = $tkey; 
                   4413:                     $tkeyrec = $altkey;
                   4414:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4415:                 }
1.560     damieng  4416:             }
                   4417:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4418:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4419:                 if ($cmd eq 'set') {
                   4420:                     $data=$env{$key};
                   4421:                     $valmatch = '';
                   4422:                     $valchk = $data;
                   4423:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4424:                     $text = &mt('Saved modified parameter for');
                   4425:                     if ($typeof eq 'string_questiontype') {
                   4426:                         $name = 'type';
1.588     raeburn  4427:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4428:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4429:                         my $stringmatch = &standard_string_matches($typeof);
                   4430:                         if (ref($stringmatch) eq 'ARRAY') {
                   4431:                             foreach my $item (@{$stringmatch}) {
                   4432:                                 if (ref($item) eq 'ARRAY') {
                   4433:                                     my ($regexpname,$pattern) = @{$item};
                   4434:                                     if ($pattern ne '') {
                   4435:                                         if ($data =~ /$pattern/) {
                   4436:                                             $valmatch = $regexpname;
                   4437:                                             $valchk = '';
                   4438:                                             last;
                   4439:                                         }
1.560     damieng  4440:                                     }
1.549     raeburn  4441:                                 }
                   4442:                             }
                   4443:                         }
1.563     damieng  4444:                     } elsif ($typeof eq 'string_discussvote') {
                   4445:                         $name = 'discussvote';
                   4446:                     } elsif ($typeof eq 'string_examcode') {
                   4447:                         $name = 'examcode';
                   4448:                         if (&Apache::lonnet::validCODE($data)) {
                   4449:                             $valchk = 'valid';
                   4450:                         }
                   4451:                     } elsif ($typeof eq 'string_yesno') {
                   4452:                         if ($thiskey =~ /\.retrypartial$/) {
                   4453:                             $name = 'retrypartial';
                   4454:                         }
1.549     raeburn  4455:                     }
1.563     damieng  4456:                 } elsif ($cmd eq 'datepointer') {
                   4457:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4458:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4459:                     $text = &mt('Saved modified date for');
                   4460:                     if ($typeof eq 'date_start') {
                   4461:                         if ($thiskey =~ /\.printstartdate$/) {
                   4462:                             $name = 'printstartdate';
                   4463:                             if (($data) && ($data > $now)) {
                   4464:                                 $valchk = 'future';
                   4465:                             }
1.560     damieng  4466:                         }
1.563     damieng  4467:                     } elsif ($typeof eq 'date_end') {
                   4468:                         if ($thiskey =~ /\.printenddate$/) {
                   4469:                             $name = 'printenddate';
                   4470:                             if (($data) && ($data < $now)) {
                   4471:                                 $valchk = 'past';
                   4472:                             }
1.560     damieng  4473:                         }
1.504     raeburn  4474:                     }
1.563     damieng  4475:                 } elsif ($cmd eq 'dateinterval') {
                   4476:                     $data=&get_date_interval_from_form($thiskey);
                   4477:                     if ($thiskey =~ /\.interval$/) {
                   4478:                         $name = 'interval';
                   4479:                         my $intervaltype = &get_intervaltype($name);
                   4480:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4481:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4482:                             foreach my $item (@{$intervalmatch}) {
                   4483:                                 if (ref($item) eq 'ARRAY') {
                   4484:                                     my ($regexpname,$pattern) = @{$item};
                   4485:                                     if ($pattern ne '') {
                   4486:                                         if ($data =~ /$pattern/) {
                   4487:                                             $valmatch = $regexpname;
                   4488:                                             $valchk = '';
                   4489:                                             last;
                   4490:                                         }
1.560     damieng  4491:                                     }
1.554     raeburn  4492:                                 }
                   4493:                             }
                   4494:                         }
                   4495:                     }
1.563     damieng  4496:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4497:                     $text = &mt('Saved modified date for');
1.554     raeburn  4498:                 }
1.576     raeburn  4499:                 if ($recursive) {
1.563     damieng  4500:                     $namematch = 'maplevelrecurse';
1.560     damieng  4501:                 }
1.563     damieng  4502:                 if (($name ne '') || ($namematch ne '')) {
                   4503:                     my ($needsrelease,$needsnewer);
                   4504:                     if ($name ne '') {
                   4505:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4506:                         if ($needsrelease) {
                   4507:                             unless ($got_chostname) {
1.563     damieng  4508:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4509:                                 $got_chostname = 1;
                   4510:                             }
1.563     damieng  4511:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4512:                                                                 $needsrelease,
                   4513:                                                                 $cmajor,$cminor);
                   4514:                         }
                   4515:                     }
                   4516:                     if ($namematch ne '') {
                   4517:                         if ($needsnewer) {
                   4518:                             undef($namematch);
1.560     damieng  4519:                         } else {
1.563     damieng  4520:                             my $currneeded;
                   4521:                             if ($needsrelease) {
                   4522:                                 $currneeded = $needsrelease;
                   4523:                             }
                   4524:                             $needsrelease =
                   4525:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4526:                             if (($needsrelease) &&
                   4527:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4528:                                 unless ($got_chostname) {
                   4529:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4530:                                     $got_chostname = 1;
                   4531:                                 }
                   4532:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4533:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4534:                             } else {
                   4535:                                 undef($namematch);
                   4536:                             }
1.560     damieng  4537:                         }
1.557     raeburn  4538:                     }
1.563     damieng  4539:                     if ($needsnewer) {
                   4540:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4541:                                                             $chostname,$cmajor,
                   4542:                                                             $cminor,$needsrelease));
                   4543:                         next;
                   4544:                     }
1.504     raeburn  4545:                 }
1.576     raeburn  4546:                 my ($reconlychg,$haschange,$storekey);
                   4547:                 if ($tuname) {
                   4548:                     my $ustorekey;
                   4549:                     if ($altkey) {
                   4550:                         if ($recursive) {
                   4551:                             if (exists($$olddata{$thiskey})) {
                   4552:                                 if ($$olddata{$thiskey} eq $data) {
                   4553:                                     $reconlychg = 1;
                   4554:                                 }
                   4555:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4556:                             }
                   4557:                             if (exists($$olddata{$altkey})) {
                   4558:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4559:                                     $haschange = 1;
                   4560:                                 }
                   4561:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4562:                                 $haschange = 1;
                   4563:                             }
                   4564:                             $ustorekey = $tkeyrec;
                   4565:                         } else {
                   4566:                             if (exists($$olddata{$altkey})) {
                   4567:                                 if ($$olddata{$altkey} eq $data) {
                   4568:                                     $reconlychg = 1;
                   4569:                                 }
                   4570:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4571:                             }
                   4572:                             if (exists($$olddata{$thiskey})) {
                   4573:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4574:                                     $haschange = 1;
                   4575:                                 }
                   4576:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4577:                                 $haschange = 1;
                   4578:                             }
                   4579:                             $ustorekey = $tkeynonrec;
                   4580:                         }
                   4581:                     } else {
                   4582:                         if (exists($$olddata{$tkey})) {
                   4583:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4584:                                 $haschange = 1;
                   4585:                             }
                   4586:                             $ustorekey = $tkey;
                   4587:                         }
                   4588:                     }
                   4589:                     if ($haschange || $reconlychg)  {
                   4590:                         unless ($env{'form.del_'.$thiskey}) {
                   4591:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4592:                                                                      $ustorekey.'.type' => $typeof},
                   4593:                                                                      $tudom,$tuname) eq 'ok') {
                   4594:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4595:                                 $r->print('<br />'.$text.' '.
                   4596:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4597:                             } else {
                   4598:                                 $r->print('<div class="LC_error">'.
                   4599:                                           &mt('Error saving parameters').'</div>');
                   4600:                             }
                   4601:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4602:                         }
                   4603:                     }
                   4604:                 } else {
                   4605:                     if ($altkey) {
                   4606:                         if ($recursive) {
                   4607:                             if (exists($$olddata{$thiskey})) {
                   4608:                                 if ($$olddata{$thiskey} eq $data) {
                   4609:                                     $reconlychg = 1;
                   4610:                                 }
                   4611:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4612:                             }
                   4613:                             if (exists($$olddata{$altkey})) {
                   4614:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4615:                                     $haschange = 1;
                   4616:                                 }
                   4617:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4618:                                 $haschange = 1;
                   4619:                             }
                   4620:                             $storekey = $altkey;
1.563     damieng  4621:                         } else {
1.576     raeburn  4622:                             if (exists($$olddata{$altkey})) {
                   4623:                                 if ($$olddata{$altkey} eq $data) {
                   4624:                                     $reconlychg = 1;
                   4625:                                 }
                   4626:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4627:                             } 
                   4628:                             if (exists($$olddata{$thiskey})) {
                   4629:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4630:                                     $haschange = 1;
                   4631:                                 }
                   4632:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4633:                                 $haschange = 1;
                   4634:                             }
                   4635:                             $storekey = $thiskey;
1.563     damieng  4636:                         }
1.560     damieng  4637:                     } else {
1.576     raeburn  4638:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4639:                             $haschange = 1;
                   4640:                             $storekey = $thiskey;
                   4641:                         }
                   4642:                     }
                   4643:                 }
                   4644:                 if ($reconlychg || $haschange) {
                   4645:                     unless ($env{'form.del_'.$thiskey}) {
                   4646:                         $newdata{$storekey}=$data;
                   4647:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4648:                     }
                   4649:                 }
                   4650:             } elsif ($cmd eq 'del') {
                   4651:                 if ($tuname) {
1.576     raeburn  4652:                     my $error;
                   4653:                     if ($altkey) {  
                   4654:                         if (exists($$olddata{$altkey})) {
                   4655:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4656:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4657:                                 if ($recursive) {
                   4658:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4659:                                 }
                   4660:                             } elsif ($recursive) {
                   4661:                                 $error = 1;
                   4662:                             }
                   4663:                         }
                   4664:                         if (exists($$olddata{$thiskey})) {
                   4665:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4666:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4667:                                 unless ($recursive) {
                   4668:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4669:                                 }
                   4670:                             } elsif (!$recursive) {
                   4671:                                 $error = 1;
                   4672:                             }
                   4673:                         }
1.560     damieng  4674:                     } else {
1.576     raeburn  4675:                         if (exists($$olddata{$thiskey})) {
                   4676:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4677:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4678:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4679:                             } else {
                   4680:                                 $error = 1;
                   4681:                             }
                   4682:                         }
                   4683:                     }
                   4684:                     if ($error) { 
1.560     damieng  4685:                         $r->print('<div class="LC_error">'.
                   4686:                             &mt('Error deleting parameters').'</div>');
                   4687:                     }
                   4688:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4689:                 } else {
1.576     raeburn  4690:                     if ($altkey) {
                   4691:                         if (exists($$olddata{$altkey})) {
                   4692:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4693:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4694:                             }
                   4695:                         }
                   4696:                         if (exists($$olddata{$thiskey})) {
                   4697:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4698:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4699:                             }
                   4700:                         }
                   4701:                     } elsif (exists($$olddata{$thiskey})) {
                   4702:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4703:                     }
1.560     damieng  4704:                 }
1.473     amueller 4705:             }
                   4706:         }
                   4707:     }
1.207     www      4708: # Store all course level
1.144     www      4709:     my $delentries=$#deldata+1;
1.576     raeburn  4710:     my @alldels;
                   4711:     if (@delrec) {
                   4712:         push(@alldels,@delrec);
                   4713:     }
                   4714:     if (@delnonrec) {
                   4715:         push(@alldels,@delnonrec);
                   4716:     }
                   4717:     if (@deldata) {
                   4718:         push(@alldels,@deldata);
                   4719:     }
1.548     raeburn  4720:     my @newdatakeys=keys(%newdata);
1.144     www      4721:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4722:     my ($delresult,$devalidate);
                   4723:     if (@alldels) {
                   4724:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4725:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4726:             &log_parmset(\%loghash,1);
1.576     raeburn  4727:             if ($delentries) {
                   4728:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4729:             }
                   4730:         } elsif ($delentries) {
1.560     damieng  4731:             $r->print('<div class="LC_error">'.
                   4732:                 &mt('Error deleting parameters').'</div>');
                   4733:         }
1.576     raeburn  4734:         $devalidate = 1; 
1.144     www      4735:     }
                   4736:     if ($putentries) {
1.560     damieng  4737:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4738:                     &log_parmset(\%newdata,0);
                   4739:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4740:         } else {
                   4741:             $r->print('<div class="LC_error">'.
                   4742:                 &mt('Error saving parameters').'</div>');
                   4743:         }
1.576     raeburn  4744:         $devalidate = 1; 
                   4745:     }
                   4746:     if ($devalidate) {
1.560     damieng  4747:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4748:     }
1.208     www      4749: }
1.207     www      4750: 
1.563     damieng  4751: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4752: #
                   4753: # @param {string} $key - the key
                   4754: # @returns {Array}
1.208     www      4755: sub extractuser {
                   4756:     my $key=shift;
1.350     albertel 4757:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4758: }
1.206     www      4759: 
1.563     damieng  4760: # Parses a parameter key and returns the components.
                   4761: #
                   4762: # @param {string} $key - 
                   4763: # @param {hash reference} $listdata - 
                   4764: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4765: sub parse_listdata_key {
                   4766:     my ($key,$listdata) = @_;
                   4767:     # split into student/section affected, and
                   4768:     # the realm (folder/resource part and parameter
1.446     bisitz   4769:     my ($student,$realm) =
1.473     amueller 4770:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4771:     # if course wide student would be undefined
                   4772:     if (!defined($student)) {
1.560     damieng  4773:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4774:     }
                   4775:     # strip off the .type if it's not the Question type parameter
                   4776:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4777:         $realm=~s/\.type//;
1.381     albertel 4778:     }
                   4779:     # split into resource+part and parameter name
1.388     albertel 4780:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4781:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4782:     return ($student,$res,$part,$parm);
                   4783: }
                   4784: 
1.563     damieng  4785: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4786: #
                   4787: # @param {Apache2::RequestRec} $r - the Apache request
                   4788: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4789: # @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
                   4790: # @param {string} $sortorder - realmstudent|studentrealm
                   4791: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4792: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4793: # @param {boolean} $readonly - true if editing not allowed
1.608     raeburn  4794: # @param {string} $parmlev - full|map
                   4795: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
                   4796: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4797: # @returns{integer} - number of $listdata parameters processed
1.208     www      4798: sub listdata {
1.608     raeburn  4799:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552     raeburn  4800:     
1.207     www      4801: # Start list output
1.206     www      4802: 
1.122     www      4803:     my $oldsection='';
                   4804:     my $oldrealm='';
                   4805:     my $oldpart='';
1.123     www      4806:     my $pointer=0;
1.124     www      4807:     $tableopen=0;
1.145     www      4808:     my $foundkeys=0;
1.248     albertel 4809:     my %keyorder=&standardkeyorder();
1.594     raeburn  4810:     my $readonlyall = $readonly;
1.381     albertel 4811: 
1.552     raeburn  4812:     my ($secidx,%grouphash);
                   4813:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4814:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4815:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4816:             %grouphash = &Apache::longroup::coursegroups();
                   4817:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4818:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4819:         }
1.552     raeburn  4820:     }
                   4821: 
1.576     raeburn  4822:     foreach my $key (sort {
1.560     damieng  4823:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4824:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608     raeburn  4825:         my ($aid,$bid);
                   4826:         if ($caller eq 'newoverview') {
                   4827:             if (ref($hash_for_realm) eq 'HASH') {
                   4828:                 if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4829:                     my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4830:                     my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4831:                     $aid = $hash_for_realm->{$aurl};
                   4832:                     $bid = $hash_for_realm->{$burl};
                   4833:                 } elsif ($parmlev eq 'full') {
                   4834:                     $aid = $hash_for_realm->{$ares};
                   4835:                     $bid = $hash_for_realm->{$bres};
                   4836:                 }
                   4837:             }
                   4838:         }
1.381     albertel 4839: 
1.560     damieng  4840:         # get the numerical order for the param
                   4841:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4842:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4843: 
1.560     damieng  4844:         my $result=0;
1.381     albertel 4845: 
1.560     damieng  4846:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4847:             if ($ares     ne $bres    ) {
1.608     raeburn  4848:                 if ($caller eq 'newoverview') {
                   4849:                     if (ref($hash_for_realm) eq 'HASH') {
                   4850:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4851:                             $result = ($aid <=> $bid);
                   4852:                         } elsif ($parmlev eq 'full') {
                   4853:                             $result = ($aid <=> $bid);
                   4854:                         } else {
                   4855:                             $result = ($ares cmp $bres);
                   4856:                         }
                   4857:                     } else {
                   4858:                         $result = ($ares cmp $bres);
                   4859:                     }
                   4860:                 } else {
                   4861:                     $result = ($ares cmp $bres);
                   4862:                 }
1.446     bisitz   4863:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4864:                 $result = ($astudent cmp $bstudent);
                   4865:             } elsif ($apart    ne $bpart   ) {
                   4866:                 $result = ($apart    cmp $bpart);
                   4867:             }
                   4868:         } else {
                   4869:             if      ($astudent ne $bstudent) {
                   4870:                 $result = ($astudent cmp $bstudent);
                   4871:             } elsif ($ares     ne $bres    ) {
1.608     raeburn  4872:                 if ($caller eq 'newoverview') {
                   4873:                     if (ref($hash_for_realm) eq 'HASH') {
                   4874:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4875:                             $result = ($aid <=> $bid);
                   4876:                         } elsif ($parmlev eq 'full') {
                   4877:                             $result = ($aid <=> $bid);
                   4878:                         } else {
                   4879:                             $result = ($ares cmp $bres);
                   4880:                         }
                   4881:                     } else {
                   4882:                         $result = ($ares cmp $bres);
                   4883:                     }
                   4884:                 } else {
                   4885:                     $result = ($ares cmp $bres);
                   4886:                 }
1.560     damieng  4887:             } elsif ($apart    ne $bpart   ) {
                   4888:                 $result = ($apart    cmp $bpart);
                   4889:             }
1.473     amueller 4890:         }
1.446     bisitz   4891: 
1.560     damieng  4892:         if (!$result) {
1.381     albertel 4893:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4894:                 $result = ($aparm <=> $bparm);
1.381     albertel 4895:             } elsif (defined($aparm)) {
1.560     damieng  4896:                 $result = -1;
1.381     albertel 4897:             } elsif (defined($bparm)) {
1.560     damieng  4898:                 $result = 1;
                   4899:             }
1.473     amueller 4900:         }
1.381     albertel 4901: 
1.560     damieng  4902:         $result;
                   4903:         
1.576     raeburn  4904:     } keys(%{$listdata})) { # foreach my $key
                   4905:         my $thiskey = $key;
1.560     damieng  4906:         if ($$listdata{$thiskey.'.type'}) {
                   4907:             my $thistype=$$listdata{$thiskey.'.type'};
                   4908:             if ($$resourcedata{$thiskey.'.type'}) {
                   4909:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4910:             }
                   4911:             my ($middle,$part,$name)=
1.572     damieng  4912:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4913:             my $section=&mt('All Students');
1.594     raeburn  4914:             $readonly = $readonlyall;
1.599     raeburn  4915:             my $userscope;
1.576     raeburn  4916:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4917:             if ($middle=~/^\[(.*)\]/) {
                   4918:                 my $issection=$1;
                   4919:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4920:                     my ($stuname,$studom) = ($1,$2);
                   4921:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4922:                         if (ref($classlist) eq 'HASH') {
                   4923:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4924:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4925:                             }
                   4926:                         }
                   4927:                     }
                   4928:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4929:                     $userscope = 1;
1.560     damieng  4930:                 } else {
                   4931:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4932:                         if (exists($grouphash{$issection})) {
                   4933:                             $section=&mt('Group').': '.$issection;
                   4934:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4935:                             $section = &mt('Section').': '.$issection;
                   4936:                         } else {
                   4937:                             next; 
1.552     raeburn  4938:                         }
1.560     damieng  4939:                     } else {
                   4940:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4941:                     }
                   4942:                 }
1.560     damieng  4943:                 $middle=~s/^\[(.*)\]//;
                   4944:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4945:                 $readonly = 1;
                   4946:             }
                   4947:             $middle=~s/\.+$//;
                   4948:             $middle=~s/^\.+//;
                   4949:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4950:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4951:             if ($caller eq 'overview') {
                   4952:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4953:                     $mapurl = $1;
                   4954:                     $maplevel = $2;
                   4955:                     $is_map = 1;
                   4956:                 }
                   4957:             } elsif ($caller eq 'newoverview') {
                   4958:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4959:                     $mapurl = $1;
                   4960:                     $maplevel = $2;
                   4961:                     $is_map = 1;
                   4962:                 }
                   4963:             }
                   4964:             if ($is_map) {
1.560     damieng  4965:                 my $leveltitle = &mt('Folder/Map');
1.615     raeburn  4966:                 my $title = &Apache::lonnet::gettitle($mapurl);
1.608     raeburn  4967:                 if (ref($hash_for_realm) eq 'HASH') {
                   4968:                     if ($hash_for_realm->{$mapurl} eq '1') {
                   4969:                         $title = &mt('Main Content');
                   4970:                     }
                   4971:                 }
1.576     raeburn  4972:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4973:                     if ($caller eq 'newoverview') {
                   4974:                         my $altkey = $thiskey;
                   4975:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4976:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4977:                             $is_recursive = 1;
                   4978:                             if ($$resourcedata{$altkey.'.type'}) {
                   4979:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4980:                             }
                   4981:                             $showval = $$resourcedata{$altkey};
                   4982:                         }
                   4983:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4984:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4985:                         $is_recursive = 1;
                   4986:                     }
1.560     damieng  4987:                 }
1.608     raeburn  4988:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560     damieng  4989:             } elsif ($middle) {
                   4990:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609     raeburn  4991:                 next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560     damieng  4992:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4993:                     ': '.&Apache::lonnet::gettitle($middle).
                   4994:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4995:                     $id.')</span></span>';
                   4996:             }
                   4997:             if ($sortorder eq 'realmstudent') {
                   4998:                 if ($realm ne $oldrealm) {
                   4999:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   5000:                     $oldrealm=$realm;
                   5001:                     $oldsection='';
                   5002:                 }
                   5003:                 if ($section ne $oldsection) {
                   5004:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   5005:                     $oldsection=$section;
                   5006:                     $oldpart='';
                   5007:                 }
1.552     raeburn  5008:             } else {
1.560     damieng  5009:                 if ($section ne $oldsection) {
                   5010:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   5011:                     $oldsection=$section;
                   5012:                     $oldrealm='';
                   5013:                 }
                   5014:                 if ($realm ne $oldrealm) {
                   5015:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   5016:                     $oldrealm=$realm;
                   5017:                     $oldpart='';
1.552     raeburn  5018:                 }
                   5019:             }
1.560     damieng  5020:             if ($part ne $oldpart) {
                   5021:                 $r->print(&tableend().
                   5022:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   5023:                 $oldpart=$part;
1.556     raeburn  5024:             }
1.560     damieng  5025:     #
                   5026:     # Ready to print
                   5027:     #
1.470     raeburn  5028:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  5029:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  5030:                 &Apache::loncommon::start_data_table_row().
                   5031:                 '<td><b>'.&mt($parmitem).
                   5032:                 '</b></td>');
                   5033:             unless ($readonly) {
1.599     raeburn  5034:                 my $disabled;
                   5035:                 if (($name eq 'availablestudent') &&
                   5036:                     (($showval eq '') || ($userscope))) {
                   5037:                     $disabled = ' disabled="disabled"';
                   5038:                 }
1.560     damieng  5039:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  5040:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  5041:             }
                   5042:             $r->print('<td>');
                   5043:             $foundkeys++;
                   5044:             if (&isdateparm($thistype)) {
                   5045:                 my $jskey='key_'.$pointer;
                   5046:                 my $state;
                   5047:                 $pointer++;
                   5048:                 if ($readonly) {
                   5049:                     $state = 'disabled';
                   5050:                 }
                   5051:                 $r->print(
                   5052:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   5053:                                                         $jskey,
1.576     raeburn  5054:                                                         $showval,
1.560     damieng  5055:                                                         '',1,$state));
                   5056:                 unless  ($readonly) {
                   5057:                     $r->print(
                   5058:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  5059:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  5060:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  5061:     &date_sanity_info($showval)
1.560     damieng  5062:                     );
                   5063:                 }
                   5064:             } elsif ($thistype eq 'date_interval') {
                   5065:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  5066:                           $showval,$readonly));
1.560     damieng  5067:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  5068:                 if ($name eq 'availablestudent') {
                   5069:                     $readonly = 1;
                   5070:                 }
1.560     damieng  5071:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  5072:                           $showval,$name,$readonly));
1.560     damieng  5073:             } else {
1.576     raeburn  5074:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  5075:             }
1.560     damieng  5076:             unless ($readonly) {
                   5077:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   5078:                         $thistype.'" />');
1.552     raeburn  5079:             }
1.576     raeburn  5080:             $r->print('</td>');
                   5081:             if ($is_map) {
                   5082:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   5083:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   5084:                 } else {
                   5085:                     my ($disabled,$recon,$recoff);
                   5086:                     if ($readonly) {
                   5087:                         $disabled = ' disabled="disabled"';
                   5088:                     }
                   5089:                     if ($is_recursive) {
                   5090:                         $recon = ' checked="checked"';
                   5091:                     } else {
                   5092:                         $recoff = ' checked="checked"';
                   5093:                     }
                   5094:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   5095:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   5096:                 }
                   5097:             }
                   5098:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 5099:         }
1.121     www      5100:     }
1.208     www      5101:     return $foundkeys;
                   5102: }
                   5103: 
1.563     damieng  5104: # Returns a string representing the interval, directly using form data matching the given key.
                   5105: # The returned string may also include information related to proctored exams.
                   5106: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   5107: #
                   5108: # @param {string} $key - suffix for form fields related to the interval
                   5109: # @returns {string}
1.385     albertel 5110: sub get_date_interval_from_form {
                   5111:     my ($key) = @_;
                   5112:     my $seconds = 0;
1.611     raeburn  5113:     my $numnotnull = 0;
1.385     albertel 5114:     foreach my $which (['days', 86400],
1.473     amueller 5115:                ['hours', 3600],
                   5116:                ['minutes', 60],
                   5117:                ['seconds',  1]) {
1.560     damieng  5118:         my ($name, $factor) = @{ $which };
                   5119:         if (defined($env{'form.'.$name.'_'.$key})) {
1.611     raeburn  5120:             unless ($env{'form.'.$name.'_'.$key} eq '') {
                   5121:                 $numnotnull ++;
                   5122:                 $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   5123:             }
1.560     damieng  5124:         }
1.473     amueller 5125:     }
1.560     damieng  5126:     if (($key =~ /\.interval$/) &&
                   5127:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  5128:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   5129:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   5130:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   5131:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   5132:                 $seconds .= '_proctor';
                   5133:             }
                   5134:         } else {
                   5135:             $seconds .= $env{'form.done_'.$key}; 
                   5136:         }
                   5137:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  5138:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  5139:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   5140:         }
1.554     raeburn  5141:     }
1.611     raeburn  5142:     return if (!$numnotnull);
1.385     albertel 5143:     return $seconds;
                   5144: }
                   5145: 
                   5146: 
1.563     damieng  5147: # Returns HTML to enter a text value for a parameter.
                   5148: #
                   5149: # @param {string} $thiskey - parameter key
                   5150: # @param {string} $showval - the current value
                   5151: # @param {boolean} $readonly - true if the field should not be made editable
                   5152: # @returns {string}
1.383     albertel 5153: sub default_selector {
1.552     raeburn  5154:     my ($thiskey, $showval, $readonly) = @_;
                   5155:     my $disabled;
                   5156:     if ($readonly) {
                   5157:         $disabled = ' disabled="disabled"';
                   5158:     }
                   5159:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 5160: }
                   5161: 
1.563     damieng  5162: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5163: #
                   5164: # @param {string} $thiskey - parameter key
                   5165: # @param {string} $showval - the current value
                   5166: # @param {boolean} $readonly - true if the fields should not be made editable
                   5167: # @returns {string}
1.549     raeburn  5168: sub string_ip_selector {
1.552     raeburn  5169:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5170:     my %access = (
                   5171:                    allow => [],
                   5172:                    deny  => [],
                   5173:                  );
                   5174:     if ($showval ne '') {
                   5175:         my @current;
                   5176:         if ($showval =~ /,/) {
                   5177:             @current = split(/,/,$showval);
                   5178:         } else {
                   5179:             @current = ($showval);
                   5180:         }
                   5181:         foreach my $item (@current) {
                   5182:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5183:                 push(@{$access{'deny'}},$1);
                   5184:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5185:                 push(@{$access{'allow'}},$item);
                   5186:             }
                   5187:         }
                   5188:     }
                   5189:     if (!@{$access{'allow'}}) {
                   5190:         @{$access{'allow'}} = ('');
                   5191:     }
                   5192:     if (!@{$access{'deny'}}) {
                   5193:         @{$access{'deny'}} = ('');
                   5194:     }
1.552     raeburn  5195:     my ($disabled,$addmore);
1.567     raeburn  5196:     if ($readonly) {
1.552     raeburn  5197:         $disabled=' disabled="disabled"';
                   5198:     } else {
                   5199:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5200:     }
1.549     raeburn  5201:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5202: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5203:     foreach my $acctype ('allow','deny') {
                   5204:         $output .= '
                   5205: <td valign="top">
                   5206: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5207:   <div class="LC_string_ipacc_inner">'."\n";
                   5208:         my $num = 0;
                   5209:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5210:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5211:             if ($num > 0) {
                   5212:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5213:             }
                   5214:             $output .= '</div>'."\n";
                   5215:             $num ++;
                   5216:         }
                   5217:         $output .= '
1.552     raeburn  5218:   </div>'.$addmore.'
1.549     raeburn  5219: </div>
                   5220: </td>';
                   5221:    }
                   5222:    $output .= '
                   5223: </tr>
                   5224: </table>'."\n";
                   5225:     return $output;
                   5226: }
                   5227: 
1.588     raeburn  5228: sub string_deeplink_selector {
                   5229:     my ($thiskey, $showval, $readonly) = @_;
1.616     raeburn  5230:     my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
                   5231:         %selectnull,%domlti,%crslti,@possmenus,%components);
                   5232:     @tables = ('upper','lower');
                   5233:     %components = (
                   5234:                     upper => ['state','others','listing','scope'],
                   5235:                     lower => ['protect','menus','target','exit'],
                   5236:                   );   
1.588     raeburn  5237:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5238:                   state   => 'Access status',
                   5239:                   others  => 'Hide other resources',
1.588     raeburn  5240:                   listing => 'In Contents and/or Gradebook',
                   5241:                   scope   => 'Access scope for link',
1.601     raeburn  5242:                   protect => 'Link protection',
1.597     raeburn  5243:                   menus   => 'Menu Items Displayed',
1.613     raeburn  5244:                   target  => 'Embedded?',
1.616     raeburn  5245:                   exit    => 'Exit Tool Button?',
1.588     raeburn  5246:               );
                   5247:     %options = (
1.601     raeburn  5248:                    state   => ['only','off','both'],
                   5249:                    others  => ['hide','unhide'],
1.588     raeburn  5250:                    listing => ['full','absent','grades','details','datestatus'],
                   5251:                    scope   => ['res','map','rec'],
1.601     raeburn  5252:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5253:                    menus   => ['std','colls'],
1.613     raeburn  5254:                    target  => ['_self','_top'],
1.616     raeburn  5255:                    exit    => ['no','yes','url'],
1.588     raeburn  5256:                );
                   5257:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5258:                     only       => 'deep only',
                   5259:                     off        => 'deeplink off',
                   5260:                     both       => 'regular + deep',
                   5261:                     hide       => 'Hidden',
                   5262:                     unhide     => 'Unhidden',
1.588     raeburn  5263:                     full       => 'Listed (linked) in both',
                   5264:                     absent     => 'Not listed',
                   5265:                     grades     => 'Listed in grades only',
                   5266:                     details    => 'Listed (unlinked) in both',
                   5267:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5268:                     res        => 'resource only',
                   5269:                     map        => 'enclosing map/folder',
                   5270:                     rec        => 'recursive map/folder',
1.601     raeburn  5271:                     none       => 'not in use',
                   5272:                     key        => 'key access',
                   5273:                     ltic       => 'LTI access (course)',
                   5274:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5275:                     std        => 'Standard (all menus)',
                   5276:                     colls      => 'Numbered collection',
1.614     raeburn  5277:                     _self      => 'Embedded',
1.613     raeburn  5278:                     _top       => 'Not embedded',
1.616     raeburn  5279:                     no         => 'Not in use',
                   5280:                     yes        => 'In use, no URL redirect',
                   5281:                     url        => 'In use, redirect to URL',  
1.597     raeburn  5282:                   );
                   5283:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5284:                     ltic => 'Select Launcher',
                   5285:                     ltid => 'Select Launcher', 
1.597     raeburn  5286:                     colls => 'Select',
1.588     raeburn  5287:                   );
                   5288:     if ($showval =~ /,/) {
1.597     raeburn  5289:         %values=();
1.588     raeburn  5290:         @current = split(/,/,$showval);
1.601     raeburn  5291:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5292:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5293:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5294:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5295:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5296:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613     raeburn  5297:         ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616     raeburn  5298:         ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588     raeburn  5299:     } else {
1.601     raeburn  5300:         $defaults{'state'} = 'off',
                   5301:         $defaults{'others'} = 'unhide',
1.588     raeburn  5302:         $defaults{'listing'} = 'full';
                   5303:         $defaults{'scope'} = 'res';
1.601     raeburn  5304:         $defaults{'protect'} = 'none';
1.597     raeburn  5305:         $defaults{'menus'} = '0';
1.613     raeburn  5306:         $defaults{'target'} = '_top';
1.616     raeburn  5307:         $defaults{'exit'} = 'yes';
1.588     raeburn  5308:     }
                   5309:     my $disabled;
                   5310:     if ($readonly) {
                   5311:         $disabled=' disabled="disabled"';
                   5312:     }
1.601     raeburn  5313:     my %courselti =
                   5314:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5315:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5316:     foreach my $item (keys(%courselti)) {
                   5317:         if (ref($courselti{$item}) eq 'HASH') {
                   5318:             $crslti{$item} = $courselti{$item}{'name'};
                   5319:         }
                   5320:     }
                   5321:     my %lti =
1.588     raeburn  5322:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5323:                                         'linkprot');
1.588     raeburn  5324:     foreach my $item (keys(%lti)) {
1.604     raeburn  5325:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5326:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5327:         }
                   5328:     }
1.597     raeburn  5329:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5330:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5331:             my ($num,$value) = split(/\%/,$item);
                   5332:             if ($num =~ /^\d+$/) {
                   5333:                 push(@possmenus,$num);
                   5334:             }
                   5335:         }
                   5336:     }
                   5337: 
1.616     raeburn  5338:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
                   5339:     foreach my $table ('upper','lower') {
                   5340:         next unless (ref($components{$table}) eq 'ARRAY');
                   5341:         $output .= '<table width="100%"><tr>';
                   5342:         foreach my $item (@{$components{$table}}) {
                   5343:             $output .= '<th>'.$titles{$item}.'</th>';
                   5344:         }
                   5345:         $output .= '</tr><tr>';
                   5346:         foreach my $item (@{$components{$table}}) {
                   5347:             $output .= '<td>';
                   5348:             if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
                   5349:                 my $selected = $values{$item};
                   5350:                 foreach my $option (@{$options{$item}}) {
                   5351:                     if ($item eq 'protect') { 
                   5352:                         if ($option eq 'ltid') {
                   5353:                             next unless (keys(%domlti));
                   5354:                         } elsif ($option eq 'ltic') {
                   5355:                             next unless (keys(%crslti));
                   5356:                         }
                   5357:                     } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5358:                         next unless (@possmenus);
                   5359:                     }
                   5360:                     my $checked;
                   5361:                     if ($item eq 'menus') {
                   5362:                         if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5363:                             (grep(/^\Q$selected\E$/,@possmenus))) {
                   5364:                             if ($option eq 'colls') {
                   5365:                                 $checked = ' checked="checked"';
                   5366:                             }
                   5367:                         } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597     raeburn  5368:                             $checked = ' checked="checked"';
                   5369:                         }
1.616     raeburn  5370:                     } elsif ($selected =~ /^\Q$option\E/) {
1.597     raeburn  5371:                         $checked = ' checked="checked"';
                   5372:                     }
1.616     raeburn  5373:                     my $onclick;
                   5374:                     unless ($readonly) {
                   5375:                         my $esc_key = &js_escape($thiskey);
                   5376:                         $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5377:                     }
                   5378:                     $output .= '<span class="LC_nobreak"><label>'.
                   5379:                                '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5380:                                $optiontext{$option}.'</label>';
                   5381:                     if (($item eq 'protect') && ($option eq 'key')) {
                   5382:                         my $visibility="hidden";
                   5383:                         my $currkey;
                   5384:                         if ($checked) {
                   5385:                             $visibility = "text";
                   5386:                             $currkey = (split(/\:/,$values{$item}))[1];
                   5387:                         }
                   5388:                         $output .= '&nbsp;'.
                   5389:                                    '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
                   5390:                     } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
                   5391:                         my $display="none";
                   5392:                         my ($current,$blankcheck,@possibles);
                   5393:                         if ($checked) {
                   5394:                             $display = 'inline-block';
                   5395:                             if (($option eq 'ltic') || ($option eq 'ltid'))  {
                   5396:                                 $current = (split(/\:/,$selected))[1];
                   5397:                             } else {
                   5398:                                 $current = $selected;
                   5399:                             }
1.597     raeburn  5400:                         } else {
1.616     raeburn  5401:                             $blankcheck = ' selected="selected"';
1.597     raeburn  5402:                         }
1.601     raeburn  5403:                         if ($option eq 'ltid') {
1.616     raeburn  5404:                             @possibles = keys(%domlti);
1.601     raeburn  5405:                         } elsif ($option eq 'ltic') {
1.616     raeburn  5406:                             @possibles = keys(%crslti); 
                   5407:                         } else {
                   5408:                             @possibles = @possmenus;
                   5409:                         }
                   5410:                         $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5411:                                    ' style="display: '.$display.'">&nbsp;<select name="'.
                   5412:                                    'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5413:                         if (@possibles > 1) {
                   5414:                             $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5415:                                        '</option>'."\n";
                   5416:                         }
                   5417:                         foreach my $poss (sort { $a <=> $b } @possibles) {
                   5418:                             my $selected;
                   5419:                             if (($poss == $current) || (scalar(@possibles) ==1)) {
                   5420:                                 $selected = ' selected="selected"';
                   5421:                             }
                   5422:                             my $shown = $poss;
                   5423:                             if ($option eq 'ltid') {
                   5424:                                 $shown = $domlti{$poss};
                   5425:                             } elsif ($option eq 'ltic') {
                   5426:                                 $shown = $crslti{$poss};
                   5427:                             }
                   5428:                             $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
                   5429:                         }
                   5430:                         $output .= '</select></div>';
                   5431:                     }
                   5432:                     $output .= '</span> ';
                   5433:                 }
                   5434:                 if ($item eq 'exit') {
                   5435:                     my $exitsty = 'none';
                   5436:                     my $displayval;
                   5437:                     if ($values{$item} =~ /^(yes|url)/) { 
                   5438:                         $exitsty = 'inline-block';
                   5439:                         my $currval = (split(/\:/,$values{$item}))[1];
                   5440:                         if ($currval eq '') {
                   5441:                             $displayval = 'Exit Tool';
                   5442:                         } else {
                   5443:                             $displayval = $currval;
1.597     raeburn  5444:                         }
1.588     raeburn  5445:                     }
1.616     raeburn  5446:                     $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
                   5447:                                ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
                   5448:                                '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
                   5449:                                ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
                   5450:                                ' size="10"'.$disabled.' /></div>';
1.588     raeburn  5451:                 }
1.616     raeburn  5452:             } else {
                   5453:                 my $selected = $values{$item};
                   5454:                 my $defsel;
                   5455:                 if ($selected eq '') {
                   5456:                     $defsel = ' selected="selected"';
                   5457:                 }
                   5458:                 $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5459:                            '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5460:                 foreach my $option (@{$options{$item}}) {
                   5461:                     $output .= '<option value="'.$option.'"';
                   5462:                     if ($option eq $selected) {
                   5463:                         $output .= ' selected="selected"';
                   5464:                     }
                   5465:                     $output .= '>'.$optiontext{$option}.'</option>';
1.588     raeburn  5466:                 }
1.616     raeburn  5467:                 $output .= '</select>';
1.588     raeburn  5468:             }
1.616     raeburn  5469:             $output .= '</td>';
                   5470:         }
                   5471:         $output .= '</tr></table>'."\n";
                   5472:         if ($table eq 'upper') {
                   5473:             $output .= '<br />';
1.588     raeburn  5474:         }
                   5475:     }
                   5476:     return $output;
                   5477: }
                   5478: 
1.560     damieng  5479: 
                   5480: { # block using some constants related to parameter types (overview mode)
                   5481: 
1.446     bisitz   5482: my %strings =
1.383     albertel 5483:     (
                   5484:      'string_yesno'
                   5485:              => [[ 'yes', 'Yes' ],
1.560     damieng  5486:                  [ 'no', 'No' ]],
1.383     albertel 5487:      'string_problemstatus'
                   5488:              => [[ 'yes', 'Yes' ],
1.473     amueller 5489:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5490:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5491:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5492:      'string_questiontype'
                   5493:              => [[ 'problem', 'Standard Problem'],
                   5494:                  [ 'survey', 'Survey'],
                   5495:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5496:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5497:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5498:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5499:                  [ 'practice', 'Practice'],
                   5500:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5501:      'string_lenient'
                   5502:              => [['yes', 'Yes' ],
                   5503:                  [ 'no', 'No' ],
1.549     raeburn  5504:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5505:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5506:      'string_discussvote'
                   5507:              => [['yes','Yes'],
                   5508:                  ['notended','Yes, unless discussion ended'],
                   5509:                  ['no','No']],
1.549     raeburn  5510:      'string_ip'
                   5511:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5512:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5513:      'string_deeplink'
1.616     raeburn  5514:              => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.587     raeburn  5515:     );
                   5516:    
1.383     albertel 5517: 
1.549     raeburn  5518: my %stringmatches = (
                   5519:          'string_lenient'
                   5520:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5521:          'string_ip'
                   5522:               => [['_allowfrom_','[^\!]+'],
                   5523:                   ['_denyfrom_','\!']],
1.588     raeburn  5524:          'string_deeplink'
1.616     raeburn  5525:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],
1.549     raeburn  5526:     );
                   5527: 
                   5528: my %stringtypes = (
                   5529:                     type         => 'string_questiontype',
                   5530:                     lenient      => 'string_lenient',
                   5531:                     retrypartial => 'string_yesno',
                   5532:                     discussvote  => 'string_discussvote',
                   5533:                     examcode     => 'string_examcode',
                   5534:                     acc          => 'string_ip',
1.587     raeburn  5535:                     deeplink     => 'string_deeplink',
1.549     raeburn  5536:                   );
                   5537: 
1.563     damieng  5538: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5539: # Used by courseprefs.
                   5540: #
                   5541: # @param {string} $string_type - a parameter type for strings
                   5542: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5543: sub standard_string_options {
                   5544:     my ($string_type) = @_;
                   5545:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5546:         return $strings{$string_type};
                   5547:     }
                   5548:     return;
                   5549: }
1.383     albertel 5550: 
1.563     damieng  5551: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5552: #
                   5553: # @param {string} $string_type - a parameter type for strings
                   5554: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5555: sub standard_string_matches {
                   5556:     my ($string_type) = @_;
                   5557:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5558:         return $stringmatches{$string_type};
                   5559:     }
                   5560:     return;
                   5561: }
                   5562: 
1.563     damieng  5563: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5564: #
                   5565: # @param {string} $name - parameter name
                   5566: # @returns {string}
1.549     raeburn  5567: sub get_stringtype {
                   5568:     my ($name) = @_;
                   5569:     if (exists($stringtypes{$name})) {
                   5570:         return $stringtypes{$name};
                   5571:     }
                   5572:     return;
                   5573: }
                   5574: 
1.563     damieng  5575: # Returns HTML to edit a string parameter.
                   5576: #
                   5577: # @param {string} $thistype - parameter type
                   5578: # @param {string} $thiskey - parameter key
                   5579: # @param {string} $showval - parameter current value
                   5580: # @param {string} $name - parameter name
                   5581: # @param {boolean} $readonly - true if the values should not be made editable
                   5582: # @returns {string}
1.383     albertel 5583: sub string_selector {
1.552     raeburn  5584:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5585: 
1.383     albertel 5586:     if (!exists($strings{$thistype})) {
1.552     raeburn  5587:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5588:     }
                   5589: 
1.504     raeburn  5590:     my %skiptype;
1.514     raeburn  5591:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5592:             ($thistype eq 'string_lenient') ||
                   5593:             ($thistype eq 'string_discussvote') ||
                   5594:             ($thistype eq 'string_ip') ||
1.588     raeburn  5595:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5596:             ($name eq 'retrypartial')) {
1.504     raeburn  5597:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5598:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5599:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5600:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5601:             my $parmmatch;
                   5602:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5603:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5604:                     if (ref($item) eq 'ARRAY') {
                   5605:                         if ($parmval eq $item->[0]) {
                   5606:                             $parmmatch = $parmval;
                   5607:                             $parmval = '';
                   5608:                             last;
                   5609:                         }
                   5610:                     }
                   5611:                 }
                   5612:             }
                   5613:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5614:             if ($needsrelease) {
                   5615:                 unless ($got_chostname) {
1.514     raeburn  5616:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5617:                     $got_chostname = 1;
                   5618:                 }
1.557     raeburn  5619:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5620:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5621:                 if ($needsnewer) {
1.549     raeburn  5622:                     if ($parmmatch ne '') {
                   5623:                         $skiptype{$parmmatch} = 1;
                   5624:                     } elsif ($parmval ne '') {
                   5625:                         $skiptype{$parmval} = 1;
                   5626:                     }
1.504     raeburn  5627:                 }
                   5628:             }
                   5629:         }
                   5630:     }
1.549     raeburn  5631: 
                   5632:     if ($thistype eq 'string_ip') {
1.552     raeburn  5633:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5634:     } elsif ($thistype eq 'string_deeplink') {
                   5635:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5636:     }
1.504     raeburn  5637: 
1.552     raeburn  5638:     my ($result,$disabled);
                   5639: 
                   5640:     if ($readonly) {
                   5641:         $disabled = ' disabled="disabled"';
                   5642:     }
1.504     raeburn  5643:     my $numinrow = 3;
                   5644:     if ($thistype eq 'string_problemstatus') {
                   5645:         $numinrow = 2;
                   5646:     } elsif ($thistype eq 'string_questiontype') {
                   5647:         if (keys(%skiptype) > 0) {
                   5648:              $numinrow = 4;
                   5649:         }
                   5650:     }
                   5651:     my $rem;
                   5652:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5653:         my $i=0;
                   5654:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5655:             next unless (ref($possibilities) eq 'ARRAY');
                   5656:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5657:             next if ($skiptype{$name});
1.504     raeburn  5658:             $rem = $i%($numinrow);
                   5659:             if ($rem == 0) {
                   5660:                 if ($i > 0) {
                   5661:                     $result .= '</tr>';
                   5662:                 }
                   5663:                 $result .= '<tr>';
                   5664:             }
1.549     raeburn  5665:             my $colspan;
                   5666:             if ($i == @{ $strings{$thistype} }-1) {
                   5667:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5668:                 if ($rem) {
                   5669:                     my $colsleft = $numinrow - $rem;
                   5670:                     if ($colsleft) {
                   5671:                         $colspan = $colsleft+1;
                   5672:                         $colspan = ' colspan="'.$colspan.'"';
                   5673:                     }
                   5674:                 }
                   5675:             }
                   5676:             my ($add,$onchange,$css_class);
                   5677:             if ($thistype eq 'string_lenient') {
                   5678:                 if ($name eq 'weighted') {
                   5679:                     my $display;
                   5680:                     my %relatives = &Apache::lonlocal::texthash(
                   5681:                                         corrchkd     => 'Correct (checked)',
                   5682:                                         corrunchkd   => 'Correct (unchecked)',
                   5683:                                         incorrchkd   => 'Incorrect (checked)',
                   5684:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5685:                     );
                   5686:                     my %textval = (
                   5687:                                     corrchkd     => '1.0',
                   5688:                                     corrunchkd   => '1.0',
                   5689:                                     incorrchkd   => '0.0',
                   5690:                                     incorrunchkd => '0.0',
                   5691:                     );
                   5692:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5693:                         $textval{'corrchkd'} = $1;
                   5694:                         $textval{'corrunchkd'} = $2;
                   5695:                         $textval{'incorrchkd'} = $3;
                   5696:                         $textval{'incorrunchkd'} = $4;
                   5697:                         $display = 'inline';
                   5698:                         $showval = $name;
                   5699:                     } else {
                   5700:                         $display = 'none';
                   5701:                     }
                   5702:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5703:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5704:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5705:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5706:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5707:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5708:                                 '</td></tr>';
                   5709:                     }
                   5710:                     $add .= '</table></div>'."\n";
                   5711:                 }
                   5712:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5713:                 $css_class = ' class="LC_lenient_radio"';
                   5714:             }
                   5715:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5716:                        '<span class="LC_nobreak"><label>'.
                   5717:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5718:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5719:             if ($showval eq $name) {
                   5720:                 $result .= ' checked="checked"';
                   5721:             }
1.549     raeburn  5722:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5723:             $i++;
                   5724:         }
                   5725:         $result .= '</tr>';
1.473     amueller 5726:     }
1.504     raeburn  5727:     if ($result) {
                   5728:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5729:     }
                   5730:     return $result;
                   5731: }
                   5732: 
1.554     raeburn  5733: my %intervals =
                   5734:     (
                   5735:      'date_interval'
                   5736:              => [[ 'done', 'Yes' ],
1.558     raeburn  5737:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5738:                  [ '', 'No' ]],
                   5739:     );
                   5740: 
                   5741: my %intervalmatches = (
                   5742:          'date_interval'
1.559     raeburn  5743:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5744:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5745:     );
                   5746: 
                   5747: my %intervaltypes = (
                   5748:                       interval => 'date_interval',
                   5749:     );
                   5750: 
1.563     damieng  5751: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5752: #
                   5753: # @param {string} $interval_type - a parameter type for intervals
                   5754: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5755: sub standard_interval_matches {
                   5756:     my ($interval_type) = @_;
                   5757:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5758:         return $intervalmatches{$interval_type};
                   5759:     }
                   5760:     return;
                   5761: }
                   5762: 
1.563     damieng  5763: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5764: #
                   5765: # @param {string} $name - parameter name
                   5766: # @returns {string}
1.554     raeburn  5767: sub get_intervaltype {
                   5768:     my ($name) = @_;
                   5769:     if (exists($intervaltypes{$name})) {
                   5770:         return $intervaltypes{$name};
                   5771:     }
                   5772:     return;
                   5773: }
                   5774: 
1.563     damieng  5775: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5776: # Used by courseprefs.
                   5777: #
                   5778: # @param {string} $interval_type - a parameter type for intervals
                   5779: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5780: sub standard_interval_options {
                   5781:     my ($interval_type) = @_;
                   5782:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5783:         return $intervals{$interval_type};
                   5784:     }
                   5785:     return;
                   5786: }
                   5787: 
1.563     damieng  5788: # Returns HTML to edit a date interval parameter.
                   5789: #
                   5790: # @param {string} $thiskey - parameter key
                   5791: # @param {string} $name - parameter name
                   5792: # @param {string} $showval - parameter current value
                   5793: # @param {boolean} $readonly - true if the values should not be made editable
                   5794: # @returns {string}
1.554     raeburn  5795: sub date_interval_selector {
                   5796:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5797:     my ($result,%skipval);
                   5798:     if ($name eq 'interval') {
                   5799:         my $intervaltype = &get_intervaltype($name);
                   5800:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5801:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5802:             next unless (ref($possibilities) eq 'ARRAY');
                   5803:             my ($parmval, $description) = @{ $possibilities };
                   5804:             my $parmmatch;
                   5805:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5806:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5807:                     if (ref($item) eq 'ARRAY') {
                   5808:                         if ($parmval eq $item->[0]) {
                   5809:                             $parmmatch = $parmval;
                   5810:                             $parmval = '';
                   5811:                             last;
                   5812:                         }
                   5813:                     }
                   5814:                 }
                   5815:             }
                   5816:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5817:             if ($needsrelease) {
                   5818:                 unless ($got_chostname) {
                   5819:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5820:                     $got_chostname = 1;
                   5821:                 }
1.557     raeburn  5822:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5823:                                                        $needsrelease,$cmajor,$cminor);
                   5824:                 if ($needsnewer) {
                   5825:                     if ($parmmatch ne '') {
                   5826:                         $skipval{$parmmatch} = 1;
                   5827:                     } elsif ($parmval ne '') {
                   5828:                         $skipval{$parmval} = 1;
                   5829:                     }
                   5830:                 }
                   5831:             }
                   5832:         }
                   5833:     }
                   5834: 
                   5835:     my $currval = $showval;
                   5836:     foreach my $which (['days', 86400, 31],
                   5837:                ['hours', 3600, 23],
                   5838:                ['minutes', 60, 59],
                   5839:                ['seconds',  1, 59]) {
1.560     damieng  5840:         my ($name, $factor, $max) = @{ $which };
                   5841:         my $amount = int($showval/$factor);
                   5842:         $showval  %= $factor;
                   5843:         my %select = ((map {$_ => $_} (0..$max)),
                   5844:                 'select_form_order' => [0..$max]);
1.611     raeburn  5845:         if ($currval eq '') {
                   5846:             unshift(@{$select{'select_form_order'}},'');
                   5847:             $select{''} = '';
                   5848:             $amount = '';
                   5849:         }
1.560     damieng  5850:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5851:                             \%select,'',$readonly);
                   5852:         $result .= ' '.&mt($name);
1.554     raeburn  5853:     }
                   5854:     if ($name eq 'interval') {
                   5855:         unless ($skipval{'done'}) {
                   5856:             my $checkedon = '';
1.611     raeburn  5857:             my $checkedoff = '';
1.558     raeburn  5858:             my $checkedproc = '';
                   5859:             my $currproctorkey = '';
                   5860:             my $currprocdisplay = 'hidden';
1.559     raeburn  5861:             my $currdonetext = &mt('Done');
                   5862:             if ($currval =~ /^(?:\d+)_done$/) {
                   5863:                 $checkedon = ' checked="checked"';
                   5864:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5865:                 $currdonetext = $1;
1.554     raeburn  5866:                 $checkedon = ' checked="checked"';
1.558     raeburn  5867:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5868:                 $currproctorkey = $1;
                   5869:                 $checkedproc = ' checked="checked"';
                   5870:                 $currprocdisplay = 'text';
1.559     raeburn  5871:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5872:                 $currdonetext = $1;
                   5873:                 $currproctorkey = $2;
                   5874:                 $checkedproc = ' checked="checked"';
                   5875:                 $currprocdisplay = 'text';
1.611     raeburn  5876:             } elsif ($currval ne '') {
                   5877:                 $checkedoff = ' checked="checked"';
                   5878:             } else {
                   5879:                 $currdonetext = '';
1.554     raeburn  5880:             }
1.558     raeburn  5881:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5882:             my $disabled;
                   5883:             if ($readonly) {
                   5884:                 $disabled = ' disabled="disabled"';
                   5885:             }
1.558     raeburn  5886:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5887:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5888:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5889:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5890:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5891:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5892:                        &mt('Yes, with proctor key').'</label>'.
                   5893:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5894:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5895:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611     raeburn  5896:                        '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
                   5897:                        &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5898:         }
                   5899:     }
                   5900:     unless ($readonly) {
                   5901:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5902:     }
                   5903:     return $result;
                   5904: }
                   5905: 
1.563     damieng  5906: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5907: #
                   5908: # @param {string} $name - parameter name
                   5909: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5910: # @param {string} $value - parameter value
                   5911: # @param {string} $chostname - course server name
                   5912: # @param {integer} $cmajor - major version number
                   5913: # @param {integer} $cminor - minor version number
                   5914: # @param {string} $needsrelease - release version needed (major.minor)
                   5915: # @returns {string}
1.549     raeburn  5916: sub oldversion_warning {
1.557     raeburn  5917:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5918:     my $standard_name = &standard_parameter_names($name);
                   5919:     if ($namematch) {
                   5920:         my $level = &standard_parameter_levels($namematch);
                   5921:         my $msg = '';
                   5922:         if ($level) {
                   5923:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5924:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5925:         } else {
                   5926:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5927:                       $standard_name,'<b>','</b>');
                   5928:         }
                   5929:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5930:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5931:                    $cmajor.'.'.$cminor,$chostname,
                   5932:                    $needsrelease).
                   5933:                    '</p>';
                   5934:     }
1.549     raeburn  5935:     my $desc;
                   5936:     my $stringtype = &get_stringtype($name);
                   5937:     if ($stringtype ne '') {
                   5938:         if ($name eq 'examcode') {
                   5939:             $desc = $value;
                   5940:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5941:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5942:                 next unless (ref($possibilities) eq 'ARRAY');
                   5943:                 my ($parmval, $description) = @{ $possibilities };
                   5944:                 my $parmmatch;
                   5945:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5946:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5947:                         if (ref($item) eq 'ARRAY') {
                   5948:                             my ($regexpname,$pattern) = @{$item};
                   5949:                             if ($parmval eq $regexpname) {
                   5950:                                 if ($value =~ /$pattern/) {
                   5951:                                     $desc = $description; 
                   5952:                                     $parmmatch = 1;
                   5953:                                     last;
                   5954:                                 }
                   5955:                             }
                   5956:                         }
                   5957:                     }
                   5958:                     last if ($parmmatch);
                   5959:                 } elsif ($parmval eq $value) {
                   5960:                     $desc = $description;
                   5961:                     last;
                   5962:                 }
                   5963:             }
                   5964:         }
                   5965:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5966:         my $now = time;
                   5967:         if ($value =~ /^\d+$/) {
                   5968:             if ($name eq 'printstartdate') {
                   5969:                 if ($value > $now) {
                   5970:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5971:                 }
                   5972:             } elsif ($name eq 'printenddate') {
                   5973:                 if ($value < $now) {
                   5974:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5975:                 }
                   5976:             }
                   5977:         }
                   5978:     }
                   5979:     return '<p class="LC_warning">'.
1.557     raeburn  5980:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5981:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5982:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5983:        $cmajor.'.'.$cminor,$chostname,
                   5984:        $needsrelease).
                   5985:        '</p>';
1.549     raeburn  5986: }
                   5987: 
1.560     damieng  5988: } # end of block using some constants related to parameter types
                   5989: 
1.549     raeburn  5990: 
1.563     damieng  5991: 
                   5992: # Shifts all start and end dates in the current course by $shift.
1.389     www      5993: #
1.563     damieng  5994: # @param {integer} $shift - time to shift, in seconds
                   5995: # @returns {string} - error name or 'ok'
1.389     www      5996: sub dateshift {
1.594     raeburn  5997:     my ($shift,$numchanges)=@_;
1.389     www      5998:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5999:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6000:     my $sec = $env{'request.course.sec'};
1.595     raeburn  6001:     my $secgrpregex;
                   6002:     if ($sec ne '') {
                   6003:         my @groups;
                   6004:         if ($env{'request.course.groups'} ne '') {
                   6005:             @groups = split(/:/,$env{'request.course.groups'});
                   6006:         }
                   6007:         if (@groups) {
                   6008:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   6009:         } else {
                   6010:             $secgrpregex = $sec;
                   6011:         }
                   6012:     }
1.389     www      6013:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   6014: # ugly retro fix for broken version of types
1.548     raeburn  6015:     foreach my $key (keys(%data)) {
1.389     www      6016:         if ($key=~/\wtype$/) {
                   6017:             my $newkey=$key;
                   6018:             $newkey=~s/type$/\.type/;
                   6019:             $data{$newkey}=$data{$key};
                   6020:             delete $data{$key};
                   6021:         }
                   6022:     }
1.391     www      6023:     my %storecontent=();
1.389     www      6024: # go through all parameters and look for dates
1.548     raeburn  6025:     foreach my $key (keys(%data)) {
1.389     www      6026:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  6027:           if ($sec ne '') {
1.595     raeburn  6028:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  6029:           }
1.389     www      6030:           my $newdate=$data{$key}+$shift;
1.594     raeburn  6031:           $$numchanges ++;
1.391     www      6032:           $storecontent{$key}=$newdate;
1.389     www      6033:        }
                   6034:     }
1.391     www      6035:     my $reply=&Apache::lonnet::cput
                   6036:                 ('resourcedata',\%storecontent,$dom,$crs);
                   6037:     if ($reply eq 'ok') {
                   6038:        &log_parmset(\%storecontent);
                   6039:     }
                   6040:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   6041:     return $reply;
1.389     www      6042: }
                   6043: 
1.563     damieng  6044: # Overview mode UI to edit course parameters.
                   6045: #
                   6046: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6047: sub newoverview {
1.568     raeburn  6048:     my ($r,$parm_permission) = @_;
1.280     albertel 6049: 
1.208     www      6050:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6051:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6052:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6053:     my $readonly = 1;
                   6054:     if ($parm_permission->{'edit'}) {
                   6055:         undef($readonly);
                   6056:     }
1.414     droeschl 6057:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6058:         text=>"Overview Mode"});
1.523     raeburn  6059: 
                   6060:     my %loaditems = (
1.549     raeburn  6061:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  6062:                     );
                   6063:     my $js = '
                   6064: <script type="text/javascript">
                   6065: // <![CDATA[
                   6066: '.
                   6067:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   6068:             &showhide_js()."\n".
1.549     raeburn  6069:             &toggleparmtextbox_js()."\n".
                   6070:             &validateparms_js()."\n".
                   6071:             &ipacc_boxes_js()."\n".
1.558     raeburn  6072:             &done_proctor_js()."\n".
1.588     raeburn  6073:             &deeplink_js()."\n".
1.523     raeburn  6074: '// ]]>
                   6075: </script>
                   6076: ';
1.549     raeburn  6077: 
1.523     raeburn  6078:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   6079:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 6080:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6081:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6082:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      6083:     $r->print(<<ENDOVER);
1.549     raeburn  6084: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      6085: ENDOVER
1.211     www      6086:     my @ids=();
                   6087:     my %typep=();
                   6088:     my %keyp=();
                   6089:     my %allparms=();
                   6090:     my %allparts=();
                   6091:     my %allmaps=();
                   6092:     my %mapp=();
                   6093:     my %symbp=();
                   6094:     my %maptitles=();
                   6095:     my %uris=();
                   6096:     my %keyorder=&standardkeyorder();
                   6097:     my %defkeytype=();
                   6098: 
                   6099:     my %alllevs=();
                   6100:     $alllevs{'Resource Level'}='full';
1.215     www      6101:     $alllevs{'Map/Folder Level'}='map';
1.211     www      6102:     $alllevs{'Course Level'}='general';
                   6103: 
                   6104:     my $csec=$env{'form.csec'};
1.269     raeburn  6105:     my $cgroup=$env{'form.cgroup'};
1.211     www      6106: 
                   6107:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   6108:     my $pschp=$env{'form.pschp'};
1.506     www      6109: 
1.211     www      6110:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      6111:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      6112: 
1.446     bisitz   6113:     my @selected_sections =
1.473     amueller 6114:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      6115:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 6116:     foreach my $sec (@selected_sections) {
                   6117:         if ($sec eq 'all') {
1.211     www      6118:             @selected_sections = ('all');
                   6119:         }
                   6120:     }
1.552     raeburn  6121:     if ($env{'request.course.sec'} ne '') {
                   6122:         @selected_sections = ($env{'request.course.sec'});
                   6123:     }
1.269     raeburn  6124:     my @selected_groups =
                   6125:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      6126: 
                   6127:     my $pssymb='';
                   6128:     my $parmlev='';
1.446     bisitz   6129: 
1.211     www      6130:     unless ($env{'form.parmlev'}) {
                   6131:         $parmlev = 'map';
                   6132:     } else {
                   6133:         $parmlev = $env{'form.parmlev'};
                   6134:     }
                   6135: 
1.446     bisitz   6136:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6137:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  6138:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      6139: 
1.374     albertel 6140:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 6141:         @psprt = keys(%allparts);
1.374     albertel 6142:     }
1.211     www      6143: # Menu to select levels, etc
                   6144: 
1.456     bisitz   6145:     $r->print('<div class="LC_Box">');
1.445     neumanie 6146:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   6147:     $r->print('<div>');
1.523     raeburn  6148:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      6149:     &levelmenu($r,\%alllevs,$parmlev);
1.610     raeburn  6150:     $r->print(&Apache::lonhtmlcommon::row_closure());
                   6151:     &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447     bisitz   6152:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6153:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6154:     $r->print('</div></div>');
1.446     bisitz   6155: 
1.456     bisitz   6156:     $r->print('<div class="LC_Box">');
1.452     bisitz   6157:     $r->print('<div>');
1.581     raeburn  6158:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 6159:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   6160:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  6161:     my $sectionselector = &sectionmenu(\@selected_sections);
                   6162:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 6163:     $r->print('<table>'.
1.553     raeburn  6164:               '<tr><th>'.&mt('Parts').'</th>');
                   6165:     if ($sectionselector) {
                   6166:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   6167:     }
                   6168:     if ($groupselector) {
                   6169:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   6170:     }
                   6171:     $r->print('</tr><tr><td>');
1.211     www      6172:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  6173:     $r->print('</td>');
                   6174:     if ($sectionselector) { 
                   6175:         $r->print('<td>'.$sectionselector.'</td>');
                   6176:     }
                   6177:     if ($groupselector) {
                   6178:         $r->print('<td>'.$groupselector.'</td>');
                   6179:     }
                   6180:     $r->print('</tr></table>');
1.447     bisitz   6181:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6182:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6183:     $r->print('</div></div>');
                   6184: 
1.456     bisitz   6185:     $r->print('<div class="LC_Box">');
1.452     bisitz   6186:     $r->print('<div>');
1.214     www      6187:     my $sortorder=$env{'form.sortorder'};
                   6188:     unless ($sortorder) { $sortorder='realmstudent'; }
1.612     raeburn  6189:     &sortmenu($r,$sortorder,'newoverview');
1.445     neumanie 6190:     $r->print('</div></div>');
1.446     bisitz   6191: 
1.214     www      6192:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   6193: 
1.211     www      6194: # Build the list data hash from the specified parms
                   6195: 
                   6196:     my $listdata;
                   6197:     %{$listdata}=();
                   6198: 
                   6199:     foreach my $cat (@pscat) {
1.269     raeburn  6200:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   6201:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      6202:     }
                   6203: 
1.212     www      6204:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      6205: 
1.481     amueller 6206:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6207: 
                   6208: # Read modified data
                   6209: 
1.481     amueller 6210:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6211: 
                   6212: # List data
                   6213: 
1.608     raeburn  6214:         my $hash_for_realm;
                   6215:         if (($parmlev eq 'map') && (keys(%allmaps))) {
                   6216:             %{$hash_for_realm} = reverse(%allmaps);
                   6217:         } elsif (($parmlev eq 'full') && (keys(%symbp))) {
                   6218:             for (my $i=0; $i<@ids; $i++) {
                   6219:                 $hash_for_realm->{$symbp{$ids[$i]}} = $i;
                   6220:             }
                   6221:         }
                   6222:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568     raeburn  6223:     }
                   6224:     $r->print(&tableend());
                   6225:     unless ($readonly) {
                   6226:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6227:     }
1.568     raeburn  6228:     $r->print('</form>');
1.507     www      6229:     &endSettingsScreen($r);
                   6230:     $r->print(&Apache::loncommon::end_page());
1.208     www      6231: }
                   6232: 
1.563     damieng  6233: # Fills $listdata with parameter information.
                   6234: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6235: # The non-type value is always 1.
                   6236: #
                   6237: # @param {string} $cat - parameter name
1.566     damieng  6238: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6239: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6240: # @param {hash reference} $listdata - the parameter data that will be modified
                   6241: # @param {array reference} $psprt - selected parts
                   6242: # @param {array reference} $selections - selected sections
                   6243: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6244: # @param {hash reference} $allmaps - hash map pc -> map src
                   6245: # @param {array reference} $ids - resource and map ids
                   6246: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6247: sub secgroup_lister {
                   6248:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6249:     foreach my $item (@{$selections}) {
                   6250:         foreach my $part (@{$psprt}) {
                   6251:             my $rootparmkey=$env{'request.course.id'};
                   6252:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6253:                 $rootparmkey.='.['.$item.']';
                   6254:             }
                   6255:             if ($parmlev eq 'general') {
                   6256: # course-level parameter
                   6257:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6258:                 $$listdata{$newparmkey}=1;
                   6259:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6260:             } elsif ($parmlev eq 'map') {
                   6261: # map-level parameter
1.548     raeburn  6262:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6263:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6264:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6265:                     $$listdata{$newparmkey}=1;
                   6266:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6267:                 }
                   6268:             } else {
                   6269: # resource-level parameter
                   6270:                 foreach my $rid (@{$ids}) {
                   6271:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6272:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6273:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6274:                     $$listdata{$newparmkey}=1;
                   6275:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6276:                 }
                   6277:             }
                   6278:         }
                   6279:     }
                   6280: }
                   6281: 
1.563     damieng  6282: # UI to edit parameter settings starting with a list of all existing parameters.
                   6283: # (called by setoverview action)
                   6284: #
                   6285: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6286: sub overview {
1.568     raeburn  6287:     my ($r,$parm_permission) = @_;
1.208     www      6288:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6289:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6290:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6291:     my $readonly = 1;
                   6292:     if ($parm_permission->{'edit'}) {
                   6293:         undef($readonly);
                   6294:     }
1.549     raeburn  6295:     my $js = '<script type="text/javascript">'."\n".
                   6296:              '// <![CDATA['."\n".
                   6297:              &toggleparmtextbox_js()."\n".
                   6298:              &validateparms_js()."\n".
                   6299:              &ipacc_boxes_js()."\n".
1.558     raeburn  6300:              &done_proctor_js()."\n".
1.588     raeburn  6301:              &deeplink_js()."\n".
1.549     raeburn  6302:              '// ]]>'."\n".
                   6303:              '</script>'."\n";
1.414     droeschl 6304:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6305:     text=>"Overview Mode"});
1.549     raeburn  6306:     my %loaditems = (
                   6307:                       'onload'   => "showHideLenient();",
                   6308:                     );
                   6309: 
                   6310:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6311:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6312:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6313:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6314:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6315: 
1.208     www      6316: # Store modified
                   6317: 
1.568     raeburn  6318:     unless ($readonly) {
                   6319:         &storedata($r,$crs,$dom);
                   6320:     }
1.208     www      6321: 
                   6322: # Read modified data
                   6323: 
1.552     raeburn  6324:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6325: 
1.214     www      6326: 
                   6327:     my $sortorder=$env{'form.sortorder'};
                   6328:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6329:     &sortmenu($r,$sortorder,'overview');
1.214     www      6330: 
1.568     raeburn  6331:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6332: 
                   6333:     if ($readonly) {
                   6334:         $r->print('<p>'.$submitbutton.'</p>');
                   6335:     }
                   6336: 
1.208     www      6337: # List data
                   6338: 
1.568     raeburn  6339:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6340:     $r->print(&tableend().'<p>');
                   6341:     if ($foundkeys) {
                   6342:         unless ($readonly) {
                   6343:             $r->print('<p>'.$submitbutton.'</p>');
                   6344:         }
                   6345:     } else {
                   6346:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6347:     }
                   6348:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6349: }
1.121     www      6350: 
1.560     damieng  6351: # Unused sub.
1.563     damieng  6352: #
                   6353: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6354: sub clean_parameters {
                   6355:     my ($r) = @_;
                   6356:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6357:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6358: 
1.414     droeschl 6359:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6360:         text=>"Clean Parameters"});
1.333     albertel 6361:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6362:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6363:     $r->print(<<ENDOVER);
                   6364: $start_page
                   6365: $breadcrumbs
                   6366: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6367: ENDOVER
                   6368: # Store modified
                   6369: 
                   6370:     &storedata($r,$crs,$dom);
                   6371: 
                   6372: # Read modified data
                   6373: 
                   6374:     my $resourcedata=&readdata($crs,$dom);
                   6375: 
                   6376: # List data
                   6377: 
                   6378:     $r->print('<h3>'.
1.473     amueller 6379:           &mt('These parameters refer to resources that do not exist.').
                   6380:           '</h3>'.
                   6381:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6382:           '<br />');
1.333     albertel 6383:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6384:           '<tr>'.
                   6385:           '<th>'.&mt('Delete').'</th>'.
                   6386:           '<th>'.&mt('Parameter').'</th>'.
                   6387:           '</tr>');
1.333     albertel 6388:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6389:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6390:             && $thiskey=~/\.type$/);
                   6391:         my %data = &parse_key($thiskey);
                   6392:         if (1) { #exists($data{'realm_exists'})
                   6393:             #&& !$data{'realm_exists'}) {
                   6394:             $r->print(&Apache::loncommon::start_data_table_row().
                   6395:                 '<tr>'.
                   6396:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6397: 
                   6398:             $r->print('<td>');
                   6399:             my $display_value = $resourcedata->{$thiskey};
                   6400:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6401:             $display_value =
                   6402:                 &Apache::lonlocal::locallocaltime($display_value);
                   6403:             }
1.470     raeburn  6404:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6405:             $parmitem = &mt($parmitem);
1.560     damieng  6406:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6407:                 $parmitem,$resourcedata->{$thiskey}));
                   6408:             $r->print('<br />');
                   6409:             if ($data{'scope_type'} eq 'all') {
                   6410:                 $r->print(&mt('All users'));
                   6411:             } elsif ($data{'scope_type'} eq 'user') {
                   6412:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6413:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6414:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6415:             }
                   6416:             $r->print('<br />');
                   6417:             if ($data{'realm_type'} eq 'all') {
                   6418:                 $r->print(&mt('All Resources'));
                   6419:             } elsif ($data{'realm_type'} eq 'folder') {
                   6420:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6421:             } elsif ($data{'realm_type'} eq 'symb') {
                   6422:             my ($map,$resid,$url) =
                   6423:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6424:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6425:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6426:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6427:             }
                   6428:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6429:             $r->print('</td></tr>');
                   6430: 
1.473     amueller 6431:         }
1.333     albertel 6432:     }
                   6433:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6434:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6435:           '</p></form>');
                   6436:     &endSettingsScreen($r);
                   6437:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6438: }
                   6439: 
1.563     damieng  6440: # UI to shift all dates (called by dateshift1 action).
                   6441: # Used by overview mode.
                   6442: #
                   6443: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6444: sub date_shift_one {
                   6445:     my ($r) = @_;
                   6446:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6447:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6448:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6449:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6450:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6451:         text=>"Shifting Dates"});
1.594     raeburn  6452:     my $submit_text = &mt('Shift all dates accordingly');
                   6453:     if ($sec ne '') {
1.595     raeburn  6454:         my @groups;
                   6455:         if ($env{'request.course.groups'} ne '') {
                   6456:             @groups = split(/:/,$env{'request.course.groups'});
                   6457:         }
                   6458:         if (@groups) {
                   6459:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6460:         } else {
                   6461:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6462:         }
1.594     raeburn  6463:     }
1.390     www      6464:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6465:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6466:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6467:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6468:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6469:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6470:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6471:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6472:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6473:                                                         'timeshifted',
                   6474:                                                         $env{'form.timebase'},,
                   6475:                                                         '').
                   6476:               '</td></tr></table>'.
                   6477:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6478:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6479:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6480:     &endSettingsScreen($r);
1.390     www      6481:     $r->print(&Apache::loncommon::end_page());
                   6482: }
                   6483: 
1.563     damieng  6484: # UI to shift all dates (second form).
                   6485: #
                   6486: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6487: sub date_shift_two {
                   6488:     my ($r) = @_;
                   6489:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6490:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6491:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6492:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6493:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6494:         text=>"Shifting Dates"});
1.390     www      6495:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6496:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6497:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6498:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6499:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6500:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6501:     if ($sec ne '') {
1.595     raeburn  6502:         my @groups;
                   6503:         if ($env{'request.course.groups'} ne '') {
                   6504:             @groups = split(/:/,$env{'request.course.groups'});
                   6505:         }
                   6506:         if (@groups) {
                   6507:             $r->print('<p>'.
                   6508:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6509:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6510:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6511:                       '</p>');
                   6512:         } else {
                   6513:             $r->print('<p>'.
                   6514:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6515:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6516:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6517:                       '</p>');
                   6518:         }
1.594     raeburn  6519:     } else {
                   6520:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6521:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6522:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6523:                   '</p>');
                   6524:     }
1.390     www      6525:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6526:     my $numchanges = 0;
                   6527:     my $result = &dateshift($delta,\$numchanges);
                   6528:     if ($result eq 'ok') {
                   6529:         $r->print(
                   6530:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6531:                                                     $numchanges)));
                   6532:     } elsif ($result eq 'con_delayed') {
                   6533:         $r->print(
                   6534:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6535:                                                         $numchanges)));
                   6536:     } else {
                   6537:         $r->print(
                   6538:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6539:     }
1.543     bisitz   6540:     $r->print(
                   6541:         '<br /><br />'.
                   6542:         &Apache::lonhtmlcommon::actionbox(
                   6543:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6544:     &endSettingsScreen($r);
1.390     www      6545:     $r->print(&Apache::loncommon::end_page());
                   6546: }
                   6547: 
1.563     damieng  6548: # Returns the different components of a resourcedata key.
                   6549: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6550: #       realm_exists, parameter_part, parameter_name.
                   6551: # Was used by clean_parameters (which is unused).
                   6552: #
                   6553: # @param {string} $key - the parameter key
                   6554: # @returns {hash}
1.333     albertel 6555: sub parse_key {
                   6556:     my ($key) = @_;
                   6557:     my %data;
                   6558:     my ($middle,$part,$name)=
1.572     damieng  6559:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6560:     $data{'scope_type'} = 'all';
                   6561:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6562:         $data{'scope'} = $1;
                   6563:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6564:             $data{'scope_type'} = 'user';
                   6565:             $data{'scope'} = [$1,$2];
                   6566:         } else {
1.581     raeburn  6567:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6568:         }
                   6569:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6570:     }
                   6571:     $middle=~s/\.+$//;
                   6572:     $middle=~s/^\.+//;
                   6573:     $data{'realm_type'}='all';
                   6574:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6575:         $data{'realm'} = $1;
                   6576:         $data{'realm_type'} = 'folder';
                   6577:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6578:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6579:     } elsif ($middle) {
1.560     damieng  6580:         $data{'realm'} = $middle;
                   6581:         $data{'realm_type'} = 'symb';
                   6582:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6583:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6584:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6585:     }
1.446     bisitz   6586: 
1.333     albertel 6587:     $data{'parameter_part'} = $part;
                   6588:     $data{'parameter_name'} = $name;
                   6589: 
                   6590:     return %data;
                   6591: }
                   6592: 
1.239     raeburn  6593: 
1.563     damieng  6594: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6595: sub header {
1.507     www      6596:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6597: }
1.193     albertel 6598: 
                   6599: 
                   6600: 
1.560     damieng  6601: ##################################################
                   6602: # MAIN MENU
                   6603: ##################################################
                   6604: 
1.563     damieng  6605: # Content and problem settings main menu.
                   6606: #
                   6607: # @param {Apache2::RequestRec} $r - the Apache request
                   6608: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6609: sub print_main_menu {
                   6610:     my ($r,$parm_permission)=@_;
                   6611:     #
1.414     droeschl 6612:     $r->print(&header());
1.507     www      6613:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6614:     my $crstype = &Apache::loncommon::course_type();
                   6615:     my $lc_crstype = lc($crstype);
                   6616: 
                   6617:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6618:     $r->print(<<ENDMAINFORMHEAD);
                   6619: <form method="post" enctype="multipart/form-data"
                   6620:       action="/adm/parmset" name="studentform">
                   6621: ENDMAINFORMHEAD
                   6622: #
1.195     albertel 6623:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6624:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6625:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6626:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6627:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6628:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6629:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6630:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6631:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6632:                                         '/'.$env{'request.course.sec'});
                   6633:     }
1.568     raeburn  6634:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6635:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6636:                                         '/'.$env{'request.course.sec'});
                   6637:     }
                   6638:     my (%linktext,%linktitle,%url);
                   6639:     if ($parm_permission->{'edit'}) {
                   6640:         %linktext = (
                   6641:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6642:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6643:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6644:                     );
                   6645:         %linktitle = (
                   6646:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6647:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6648:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6649:                      );
                   6650:     } else {
                   6651:         %linktext = (
                   6652:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6653:                      settable        => 'View Resource Parameters - Table Mode',
                   6654:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6655:                    );
                   6656:         %linktitle = (
                   6657:                      newoverview     => 'Display resource parameters in overview mode.',
                   6658:                      settable        => 'Display resource parameters in table mode.',
                   6659:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6660:                      );
                   6661:     }
                   6662:     if ($mgr) {
                   6663:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6664:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6665:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6666:     } elsif ($vgr) {
                   6667:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6668:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6669:         $url{'resettimes'} = '/adm/accesstimes';
                   6670:     }
1.193     albertel 6671:     my @menu =
1.507     www      6672:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6673:         items => [
                   6674:           { linktext => 'Portfolio Metadata',
                   6675:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6676:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6677:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6678:             icon =>'contact-new.png'   ,
                   6679:             },
1.568     raeburn  6680:           { linktext => $linktext{'resettimes'},
                   6681:             url => $url{'resettimes'},
                   6682:             permission => ($vgr || $mgr),
                   6683:             linktitle => $linktitle{'resettimes'},
                   6684:             icon => 'start-here.png',
1.473     amueller 6685:             },
1.520     raeburn  6686:           { linktext => 'Blocking Communication/Resource Access',
                   6687:             url => '/adm/setblock',
1.568     raeburn  6688:             permission => ($vcb || $dcm),
1.520     raeburn  6689:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6690:             icon => 'comblock.png',
                   6691:             },
1.473     amueller 6692:           { linktext => 'Set Parameter Setting Default Actions',
                   6693:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6694:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6695:             linktitle =>'Set default actions for parameters.'  ,
                   6696:             icon => 'folder-new.png'  ,
                   6697:             }]},
                   6698:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6699:         items => [
                   6700:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6701:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6702:             permission => $parm_permission->{'helper'},
1.473     amueller 6703:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6704:             icon => 'dialog-information.png'  ,
                   6705:             #help => 'Parameter_Helper',
                   6706:             },
1.568     raeburn  6707:           { linktext => $linktext{'newoverview'},
1.473     amueller 6708:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6709:             permission => $parm_permission->{'newoverview'},
                   6710:             linktitle => $linktitle{'newoverview'},
                   6711:             icon => 'edit-find.png',
1.473     amueller 6712:             #help => 'Parameter_Overview',
                   6713:             },
1.568     raeburn  6714:           { linktext => $linktext{'settable'},
1.473     amueller 6715:             url => '/adm/parmset?action=settable',
1.568     raeburn  6716:             permission => $parm_permission->{'settable'},
                   6717:             linktitle => $linktitle{'settable'},
                   6718:             icon => 'edit-copy.png',
1.473     amueller 6719:             #help => 'Table_Mode',
                   6720:             }]},
1.417     droeschl 6721:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6722:          items => [
1.570     raeburn  6723:           { linktext => $linktext{'setoverview'},
1.473     amueller 6724:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6725:             permission => $parm_permission->{'setoverview'},
                   6726:             linktitle => $linktitle{'setoverview'},
                   6727:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6728:             #help => 'Parameter_Overview',
                   6729:             },
                   6730:           { linktext => 'Change Log',
                   6731:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6732:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6733:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6734:             icon => 'document-properties.png',
1.473     amueller 6735:             }]}
1.193     albertel 6736:           );
1.414     droeschl 6737:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6738:     $r->print('</form>');
1.507     www      6739:     &endSettingsScreen($r);
1.539     raeburn  6740:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6741:     return;
                   6742: }
1.414     droeschl 6743: 
1.416     jms      6744: 
                   6745: 
1.560     damieng  6746: ##################################################
                   6747: # PORTFOLIO METADATA
                   6748: ##################################################
                   6749: 
1.563     damieng  6750: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6751: # It looks like field titles are not localized.
                   6752: #
                   6753: # @param {Apache2::RequestRec} $r - the Apache request
                   6754: # @param {string} $field_name - metadata field name
                   6755: # @param {string} $field_text - metadata field title, in English unless manually added
                   6756: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6757: sub output_row {
1.347     banghart 6758:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6759:     my $output;
1.263     banghart 6760:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6761:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6762:     if (!defined($options)) {
1.254     banghart 6763:         $options = 'active,stuadd';
1.261     banghart 6764:         $values = '';
1.252     banghart 6765:     }
1.337     banghart 6766:     if (!($options =~ /deleted/)) {
                   6767:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6768:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6769:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6770: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6771:         if ($added_flag) {
                   6772:             push @options,['deleted', 'Delete Metadata Field'];
                   6773:         }
1.351     banghart 6774:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6775:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6776:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6777:         foreach my $opt (@options) {
1.560     damieng  6778:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6779:             $output .= &Apache::loncommon::continue_data_table_row();
                   6780:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6781:                     <input type="checkbox" name="'.
                   6782:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6783:                     &mt($opt->[1]).'</label></td>';
                   6784:             $output .= &Apache::loncommon::end_data_table_row();
                   6785:         }
1.351     banghart 6786:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6787:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6788:         $output .= &Apache::loncommon::end_data_table_row();
                   6789:         my $multiple_checked;
                   6790:         my $single_checked;
                   6791:         if ($options =~ m/onlyone/) {
1.422     bisitz   6792:             $multiple_checked = '';
1.423     bisitz   6793:             $single_checked = ' checked="checked"';
1.351     banghart 6794:         } else {
1.423     bisitz   6795:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6796:             $single_checked = '';
1.351     banghart 6797:         }
1.560     damieng  6798:         $output .= &Apache::loncommon::continue_data_table_row();
                   6799:         $output .= '<td>'.('&nbsp;' x 10).'
                   6800:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6801:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6802:         $output .= &Apache::loncommon::end_data_table_row();
                   6803:         $output .= &Apache::loncommon::continue_data_table_row();
                   6804:         $output .= '<td>'.('&nbsp;' x 10).'
                   6805:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6806:                     '.&mt('Student may select only one choice from list').'</td>';
                   6807:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6808:     }
                   6809:     return ($output);
                   6810: }
1.416     jms      6811: 
                   6812: 
1.560     damieng  6813: # UI to order portfolio metadata fields.
1.563     damieng  6814: # Currently useless because addmetafield does not work.
                   6815: #
                   6816: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6817: sub order_meta_fields {
                   6818:     my ($r)=@_;
                   6819:     my $idx = 1;
                   6820:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6821:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6822:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6823:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6824:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6825:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6826:         text=>"Add Metadata Field"});
1.560     damieng  6827:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6828:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6829:         text=>"Restrict Metadata"},
                   6830:         {text=>"Order Metadata"});
1.345     banghart 6831:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6832:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6833:     if ($env{'form.storeorder'}) {
                   6834:         my $newpos = $env{'form.newpos'} - 1;
                   6835:         my $currentpos = $env{'form.currentpos'} - 1;
                   6836:         my @neworder = ();
1.548     raeburn  6837:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6838:         my $i;
1.341     banghart 6839:         if ($newpos > $currentpos) {
1.340     banghart 6840:         # moving stuff up
                   6841:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6842:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6843:             }
                   6844:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6845:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6846:             }
                   6847:             $neworder[$newpos]=$oldorder[$currentpos];
                   6848:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6849:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6850:             }
                   6851:         } else {
                   6852:         # moving stuff down
1.473     amueller 6853:             for ($i=0;$i<$newpos;$i++) {
                   6854:                 $neworder[$i]=$oldorder[$i];
                   6855:             }
                   6856:             $neworder[$newpos]=$oldorder[$currentpos];
                   6857:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6858:                 $neworder[$i]=$oldorder[$i-1];
                   6859:             }
                   6860:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6861:                 $neworder[$i]=$oldorder[$i];
                   6862:             }
1.340     banghart 6863:         }
1.560     damieng  6864:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6865:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6866:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6867:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6868:     }
1.357     raeburn  6869:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6870:     my $ordered_fields;
1.548     raeburn  6871:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6872:     if (!@fields_in_order) {
                   6873:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6874:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6875:             push @fields_in_order, $key;
1.341     banghart 6876:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6877:         }
1.341     banghart 6878:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6879:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6880:     }
1.340     banghart 6881:     $r->print('<table>');
                   6882:     my $num_fields = scalar(@fields_in_order);
                   6883:     foreach my $key (@fields_in_order) {
                   6884:         $r->print('<tr><td>');
                   6885:         $r->print('<form method="post" action="">');
1.537     bisitz   6886:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6887:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6888:             if ($i eq $idx) {
                   6889:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6890:             } else {
                   6891:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6892:             }
                   6893:         }
                   6894:         $r->print('</select></td><td>');
                   6895:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6896:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6897:         $r->print('</form>');
                   6898:         $r->print($$fields{$key}.'</td></tr>');
                   6899:         $idx ++;
                   6900:     }
                   6901:     $r->print('</table>');
1.507     www      6902:     &endSettingsScreen($r);
1.340     banghart 6903:     return 'ok';
                   6904: }
1.416     jms      6905: 
                   6906: 
1.563     damieng  6907: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6908: # @returns {string}
1.359     banghart 6909: sub continue {
                   6910:     my $output;
                   6911:     $output .= '<form action="" method="post">';
                   6912:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6913:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6914:     return ($output);
                   6915: }
1.416     jms      6916: 
                   6917: 
1.563     damieng  6918: # UI to add a metadata field.
                   6919: # Currenly does not work because of an HTML error (the field is not visible).
                   6920: #
                   6921: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6922: sub addmetafield {
                   6923:     my ($r)=@_;
1.414     droeschl 6924:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6925:         text=>"Add Metadata Field"});
1.334     banghart 6926:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6927:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6928:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6929:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6930:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6931:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6932:     if (exists($env{'form.undelete'})) {
1.358     banghart 6933:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6934:         foreach my $meta_field(@meta_fields) {
                   6935:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6936:             $options =~ s/deleted//;
                   6937:             $options =~ s/,,/,/;
                   6938:             my $put_result = &Apache::lonnet::put('environment',
                   6939:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6940: 
1.586     raeburn  6941:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6942:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6943:                           '</strong>',$put_result).
                   6944:                       '<br />');
1.339     banghart 6945:         }
1.359     banghart 6946:         $r->print(&continue());
1.339     banghart 6947:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6948:         my $meta_field = $env{'form.fieldname'};
                   6949:         my $display_field = $env{'form.fieldname'};
                   6950:         $meta_field =~ s/\W/_/g;
1.338     banghart 6951:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6952:         my $put_result = &Apache::lonnet::put('environment',
                   6953:                             {'metadata.'.$meta_field.'.values'=>"",
                   6954:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6955:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6956:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6957:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6958:                   '<br />');
1.359     banghart 6959:         $r->print(&continue());
1.335     banghart 6960:     } else {
1.357     raeburn  6961:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6962:         if ($fields) {
1.586     raeburn  6963:             $r->print(&mt('You may undelete previously deleted fields.').
                   6964:                       '<br />'.
                   6965:                       &mt('Check those you wish to undelete and click Undelete.').
                   6966:                       '<br />');
1.339     banghart 6967:             $r->print('<form method="post" action="">');
                   6968:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6969:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6970:             }
1.586     raeburn  6971:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6972:             $r->print('</form>');
                   6973:         }
1.586     raeburn  6974:         $r->print('<hr />'.
                   6975:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6976:                       '<strong>','</strong>').
1.581     raeburn  6977:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6978:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6979:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6980:         $r->print('</form>');
1.334     banghart 6981:     }
1.507     www      6982:     &endSettingsScreen($r);
1.334     banghart 6983: }
1.416     jms      6984: 
                   6985: 
                   6986: 
1.560     damieng  6987: # Display or save portfolio metadata.
1.563     damieng  6988: #
                   6989: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6990: sub setrestrictmeta {
1.240     banghart 6991:     my ($r)=@_;
1.242     banghart 6992:     my $next_meta;
1.244     banghart 6993:     my $output;
1.245     banghart 6994:     my $item_num;
1.246     banghart 6995:     my $put_result;
1.414     droeschl 6996:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6997:         text=>"Restrict Metadata"});
1.280     albertel 6998:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6999:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 7000:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7001:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  7002:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   7003:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 7004:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 7005:     my $save_field = '';
1.586     raeburn  7006:     my %lt = &Apache::lonlocal::texthash(
                   7007:                                            addm => 'Add Metadata Field',
                   7008:                                            ordm => 'Order Metadata Fields',
                   7009:                                            save => 'Save',
                   7010:                                         );
1.259     banghart 7011:     if ($env{'form.restrictmeta'}) {
1.254     banghart 7012:         foreach my $field (sort(keys(%env))) {
1.252     banghart 7013:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 7014:                 my $options;
1.252     banghart 7015:                 my $meta_field = $1;
                   7016:                 my $meta_key = $2;
1.253     banghart 7017:                 if ($save_field ne $meta_field) {
1.252     banghart 7018:                     $save_field = $meta_field;
1.473     amueller 7019:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   7020:                         $options.='stuadd,';
                   7021:                     }
                   7022:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   7023:                         $options.='choices,';
                   7024:                     }
                   7025:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   7026:                         $options.='onlyone,';
                   7027:                     }
                   7028:                     if ($env{'form.'.$meta_field.'_active'}) {
                   7029:                         $options.='active,';
                   7030:                     }
                   7031:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   7032:                         $options.='deleted,';
                   7033:                     }
1.259     banghart 7034:                     my $name = $save_field;
1.560     damieng  7035:                     $put_result = &Apache::lonnet::put('environment',
                   7036:                         {'metadata.'.$meta_field.'.options'=>$options,
                   7037:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   7038:                         },$dom,$crs);
1.252     banghart 7039:                 }
                   7040:             }
                   7041:         }
                   7042:     }
1.296     albertel 7043:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 7044:                        {'freshen_cache' => 1});
1.335     banghart 7045:     # Get the default metadata fields
1.258     albertel 7046:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 7047:     # Now get possible added metadata fields
1.357     raeburn  7048:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 7049:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 7050:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 7051:         if ($field ne 'courserestricted') {
1.586     raeburn  7052:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  7053:         }
1.255     banghart 7054:     }
1.351     banghart 7055:     my $buttons = (<<ENDButtons);
1.586     raeburn  7056:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 7057:         </form><br />
                   7058:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  7059:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 7060:         </form>
                   7061:         <br />
                   7062:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  7063:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 7064: ENDButtons
1.337     banghart 7065:     my $added_flag = 1;
1.335     banghart 7066:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  7067:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 7068:     }
1.347     banghart 7069:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   7070:     $r->print(<<ENDenv);
1.259     banghart 7071:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 7072:         $output
1.351     banghart 7073:         $buttons
1.340     banghart 7074:         </form>
1.244     banghart 7075: ENDenv
1.507     www      7076:     &endSettingsScreen($r);
1.280     albertel 7077:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 7078:     return 'ok';
                   7079: }
1.416     jms      7080: 
                   7081: 
1.563     damieng  7082: # Returns metadata fields that have been manually added.
                   7083: #
                   7084: # @param {string} $cid - course id
                   7085: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 7086: sub get_added_meta_fieldnames {
1.357     raeburn  7087:     my ($cid) = @_;
1.335     banghart 7088:     my %fields;
                   7089:     foreach my $key(%env) {
1.357     raeburn  7090:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 7091:             my $field_name = $1;
                   7092:             my ($display_field_name) = $env{$key};
                   7093:             $fields{$field_name} = $display_field_name;
                   7094:         }
                   7095:     }
                   7096:     return \%fields;
                   7097: }
1.416     jms      7098: 
                   7099: 
1.563     damieng  7100: # Returns metadata fields that have been manually added and deleted.
                   7101: #
                   7102: # @param {string} $cid - course id
                   7103: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 7104: sub get_deleted_meta_fieldnames {
1.357     raeburn  7105:     my ($cid) = @_;
1.339     banghart 7106:     my %fields;
                   7107:     foreach my $key(%env) {
1.357     raeburn  7108:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 7109:             my $field_name = $1;
                   7110:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   7111:                 my ($display_field_name) = $env{$key};
                   7112:                 $fields{$field_name} = $display_field_name;
                   7113:             }
                   7114:         }
                   7115:     }
                   7116:     return \%fields;
                   7117: }
1.560     damieng  7118: 
                   7119: 
                   7120: ##################################################
                   7121: # PARAMETER SETTINGS DEFAULT ACTIONS
                   7122: ##################################################
                   7123: 
                   7124: # UI to change parameter setting default actions
1.563     damieng  7125: #
                   7126: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      7127: sub defaultsetter {
1.280     albertel 7128:     my ($r) = @_;
                   7129: 
1.414     droeschl 7130:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 7131:         text=>"Set Defaults"});
1.531     raeburn  7132:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7133:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   7134:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   7135:     my $start_page =
1.531     raeburn  7136:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 7137:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      7138:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  7139:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      7140:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 7141: 
1.221     www      7142:     my @ids=();
                   7143:     my %typep=();
                   7144:     my %keyp=();
                   7145:     my %allparms=();
                   7146:     my %allparts=();
                   7147:     my %allmaps=();
                   7148:     my %mapp=();
                   7149:     my %symbp=();
                   7150:     my %maptitles=();
                   7151:     my %uris=();
                   7152:     my %keyorder=&standardkeyorder();
                   7153:     my %defkeytype=();
                   7154: 
1.446     bisitz   7155:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 7156:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   7157:                 \%keyorder,\%defkeytype);
1.224     www      7158:     if ($env{'form.storerules'}) {
1.560     damieng  7159:         my %newrules=();
                   7160:         my @delrules=();
                   7161:         my %triggers=();
                   7162:         foreach my $key (keys(%env)) {
1.225     albertel 7163:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  7164:                 my $tempkey=$1;
                   7165:                 my $action=$env{$key};
1.226     www      7166:                 if ($action) {
1.560     damieng  7167:                     $newrules{$tempkey.'_action'}=$action;
                   7168:                     if ($action ne 'default') {
                   7169:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   7170:                         $triggers{$whichparm}.=$tempkey.':';
                   7171:                     }
                   7172:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   7173:                     if (&isdateparm($defkeytype{$tempkey})) {
                   7174:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   7175:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   7176:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   7177:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   7178:                     } else {
                   7179:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   7180:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   7181:                     }
                   7182:                 } else {
                   7183:                     push(@delrules,$tempkey.'_action');
                   7184:                     push(@delrules,$tempkey.'_type');
                   7185:                     push(@delrules,$tempkey.'_hours');
                   7186:                     push(@delrules,$tempkey.'_min');
                   7187:                     push(@delrules,$tempkey.'_sec');
                   7188:                     push(@delrules,$tempkey.'_value');
                   7189:                 }
1.473     amueller 7190:             }
                   7191:         }
1.560     damieng  7192:         foreach my $key (keys(%allparms)) {
                   7193:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 7194:         }
1.560     damieng  7195:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   7196:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   7197:         &resetrulescache();
1.224     www      7198:     }
1.227     www      7199:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 7200:                        'hours' => 'Hours',
                   7201:                        'min' => 'Minutes',
                   7202:                        'sec' => 'Seconds',
                   7203:                        'yes' => 'Yes',
                   7204:                        'no' => 'No');
1.222     www      7205:     my @standardoptions=('','default');
                   7206:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   7207:     my @dateoptions=('','default');
                   7208:     my @datedisplay=('',&mt('Default value when manually setting'));
                   7209:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7210:         unless ($tempkey) { next; }
                   7211:         push @standardoptions,'when_setting_'.$tempkey;
                   7212:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   7213:         if (&isdateparm($defkeytype{$tempkey})) {
                   7214:             push @dateoptions,'later_than_'.$tempkey;
                   7215:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7216:             push @dateoptions,'earlier_than_'.$tempkey;
                   7217:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7218:         }
1.222     www      7219:     }
1.563     damieng  7220:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7221:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7222:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7223:           &Apache::loncommon::start_data_table_header_row().
                   7224:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7225:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7226:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7227:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7228:         unless ($tempkey) { next; }
                   7229:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7230:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7231:         my $action=&rulescache($tempkey.'_action');
                   7232:         $r->print('<select name="'.$tempkey.'_action">');
                   7233:         if (&isdateparm($defkeytype{$tempkey})) {
                   7234:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7235:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7236:             $r->print("\n<option value='$dateoptions[$i]'".
                   7237:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7238:                 ">$datedisplay[$i]</option>");
                   7239:             }
                   7240:         } else {
                   7241:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7242:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7243:             $r->print("\n<option value='$standardoptions[$i]'".
                   7244:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7245:                 ">$standarddisplay[$i]</option>");
                   7246:             }
1.473     amueller 7247:         }
1.560     damieng  7248:         $r->print('</select>');
                   7249:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7250:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7251:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7252:         }
1.560     damieng  7253:         $r->print("\n</td><td>\n");
1.222     www      7254: 
1.221     www      7255:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7256:             my $days=&rulescache($tempkey.'_days');
                   7257:             my $hours=&rulescache($tempkey.'_hours');
                   7258:             my $min=&rulescache($tempkey.'_min');
                   7259:             my $sec=&rulescache($tempkey.'_sec');
                   7260:             $r->print(<<ENDINPUTDATE);
                   7261:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7262:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7263:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7264:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7265: ENDINPUTDATE
1.560     damieng  7266:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7267:                 my $yeschecked='';
                   7268:                 my $nochecked='';
                   7269:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7270:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7271: 
                   7272:             $r->print(<<ENDYESNO);
                   7273:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7274:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7275: ENDYESNO
1.221     www      7276:         } else {
1.560     damieng  7277:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7278:         }
1.318     albertel 7279:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7280:     }
1.318     albertel 7281:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7282:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7283:           &mt('Save').'" /></form>'."\n");
                   7284:     &endSettingsScreen($r);
                   7285:     $r->print(&Apache::loncommon::end_page());
1.220     www      7286:     return;
                   7287: }
1.193     albertel 7288: 
1.560     damieng  7289: ##################################################
                   7290: # PARAMETER CHANGES LOG
                   7291: ##################################################
                   7292: 
1.563     damieng  7293: # Returns some info for a parameter log entry.
                   7294: # Returned entries:
                   7295: # $realm - HTML title for the parameter level and resource
                   7296: # $section - parameter section
                   7297: # $name - parameter name
                   7298: # $part - parameter part
                   7299: # $what - $part.'.'.$name
                   7300: # $middle - resource symb ?
                   7301: # $uname - user name (same as given)
                   7302: # $udom - user domain (same as given)
                   7303: # $issection - section or group name
                   7304: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7305: #
                   7306: # @param {string} $key - parameter log key
                   7307: # @param {string} $uname - user name
                   7308: # @param {string} $udom - user domain
                   7309: # @param {boolean} $typeflag - .type log entry
                   7310: # @returns {Array}
1.290     www      7311: sub components {
1.581     raeburn  7312:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7313: 
                   7314:     if ($typeflag) {
1.560     damieng  7315:         $key=~s/\.type$//;
1.290     www      7316:     }
1.330     albertel 7317: 
                   7318:     my ($middle,$part,$name)=
1.572     damieng  7319:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7320:     my $issection;
1.330     albertel 7321: 
1.290     www      7322:     my $section=&mt('All Students');
                   7323:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7324:         $issection=$1;
                   7325:         $section=&mt('Group/Section').': '.$issection;
                   7326:         $middle=~s/^\[(.*)\]//;
1.290     www      7327:     }
                   7328:     $middle=~s/\.+$//;
                   7329:     $middle=~s/^\.+//;
1.291     www      7330:     if ($uname) {
1.560     damieng  7331:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7332:         $issection='';
1.291     www      7333:     }
1.316     albertel 7334:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7335:     my $realmdescription=&mt('all resources');
1.556     raeburn  7336:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7337:         my $mapurl = $1;
                   7338:         my $maplevel = $2;
                   7339:         my $leveltitle = &mt('Folder/Map');
                   7340:         if ($maplevel eq 'rec') {
                   7341:             $leveltitle = &mt('Recursive');
                   7342:         }
1.560     damieng  7343:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7344:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7345:             $mapurl.')</span></span>';
                   7346:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7347:     } elsif ($middle) {
                   7348:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7349:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7350:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7351:             ' in '.$map.' id: '.$id.')</span></span>';
                   7352:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7353:     }
1.291     www      7354:     my $what=$part.'.'.$name;
1.330     albertel 7355:     return ($realm,$section,$name,$part,
1.473     amueller 7356:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7357: }
1.293     www      7358: 
1.563     damieng  7359: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7360: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7361: 
1.563     damieng  7362: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7363: sub load_parameter_names {
1.583     raeburn  7364:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7365:     while (my $configline=<$config>) {
1.560     damieng  7366:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7367:         chomp($configline);
                   7368:         my ($short,$plain)=split(/:/,$configline);
                   7369:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7370:         if ($type eq 'display') {
                   7371:             $standard_parms{$name} = $plain;
1.469     raeburn  7372:         } elsif ($type eq 'type') {
1.560     damieng  7373:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7374:         }
1.328     albertel 7375:     }
                   7376:     close($config);
                   7377:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7378:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7379:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7380: }
                   7381: 
1.563     damieng  7382: # Returns a parameter title for standard parameters, the name for others.
                   7383: #
                   7384: # @param {string} $name - parameter name
                   7385: # @returns {string}
1.292     www      7386: sub standard_parameter_names {
                   7387:     my ($name)=@_;
1.328     albertel 7388:     if (!%standard_parms) {
1.560     damieng  7389:         &load_parameter_names();
1.328     albertel 7390:     }
1.292     www      7391:     if ($standard_parms{$name}) {
1.560     damieng  7392:         return $standard_parms{$name};
1.446     bisitz   7393:     } else {
1.560     damieng  7394:         return $name;
1.292     www      7395:     }
                   7396: }
1.290     www      7397: 
1.563     damieng  7398: # Returns a parameter type for standard parameters, undef for others.
                   7399: #
                   7400: # @param {string} $name - parameter name
                   7401: # @returns {string}
1.469     raeburn  7402: sub standard_parameter_types {
                   7403:     my ($name)=@_;
                   7404:     if (!%standard_parms_types) {
                   7405:         &load_parameter_names();
                   7406:     }
                   7407:     if ($standard_parms_types{$name}) {
                   7408:         return $standard_parms_types{$name};
                   7409:     }
                   7410:     return;
                   7411: }
1.309     www      7412: 
1.563     damieng  7413: # Returns a parameter level title (not localized) from the parameter level name.
                   7414: #
                   7415: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7416: # @returns {string}
1.557     raeburn  7417: sub standard_parameter_levels {
                   7418:     my ($name)=@_;
                   7419:     my %levels = (
                   7420:                     'resourcelevel'   => 'a single resource',
                   7421:                     'maplevel'        => 'the enclosing map/folder', 
                   7422:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7423:                     'courselevel'     => 'the general (course) level',
                   7424:                  );
                   7425:     if ($levels{$name}) {
                   7426:         return $levels{$name};
                   7427:     }
                   7428:     return;
                   7429: }
                   7430: 
1.560     damieng  7431: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7432: #
                   7433: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7434: sub parm_change_log {
1.568     raeburn  7435:     my ($r,$parm_permission)=@_;
1.531     raeburn  7436:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7437:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7438:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7439:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7440:     text=>"Parameter Change Log"});
1.522     raeburn  7441:     my $js = '<script type="text/javascript">'."\n".
                   7442:              '// <![CDATA['."\n".
                   7443:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7444:              '// ]]>'."\n".
                   7445:              '</script>'."\n";
                   7446:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7447:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7448:     &startSettingsScreen($r,'parmset',$crstype);
                   7449:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7450: 
1.301     www      7451:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7452: 
1.522     raeburn  7453:     $r->print('<div class="LC_left_float">'.
                   7454:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7455:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7456:                      method="post" name="parameterlog">');
1.446     bisitz   7457: 
1.311     albertel 7458:     my %saveable_parameters = ('show' => 'scalar',);
                   7459:     &Apache::loncommon::store_course_settings('parameter_log',
                   7460:                                               \%saveable_parameters);
                   7461:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7462:                                                 \%saveable_parameters);
1.522     raeburn  7463:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7464:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7465:               '</form></fieldset></div><br clear="all" />');
1.301     www      7466: 
1.568     raeburn  7467:     my $readonly = 1;
                   7468:     if ($parm_permission->{'edit'}) {
                   7469:         undef($readonly);
                   7470:     }
1.531     raeburn  7471:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7472:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7473:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7474:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7475:     unless ($readonly) {
                   7476:         $r->print('<th>'.&mt('Announce').'</th>');
                   7477:     }
                   7478:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7479:     my $shown=0;
1.349     www      7480:     my $folder='';
                   7481:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7482:         my $last='';
                   7483:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7484:                 &GDBM_READER(),0640)) {
                   7485:             $last=$hash{'last_known'};
                   7486:             untie(%hash);
                   7487:         }
                   7488:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7489:     }
1.595     raeburn  7490:     my $numgroups = 0;
                   7491:     my @groups;
                   7492:     if ($env{'request.course.groups'} ne '') {
                   7493:         @groups = split(/:/,$env{'request.course.groups'});
                   7494:         $numgroups = scalar(@groups);
                   7495:     }
1.560     damieng  7496:     foreach my $id (sort {
                   7497:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7498:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7499:                 }
                   7500:                 my $aid = (split('00000',$a))[-1];
                   7501:                 my $bid = (split('00000',$b))[-1];
                   7502:                 return $bid<=>$aid;
1.473     amueller 7503:             } (keys(%parmlog))) {
1.294     www      7504:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7505:         my $count = 0;
                   7506:         my $time =
                   7507:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7508:         my $plainname =
                   7509:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7510:                         $parmlog{$id}{'exe_udom'});
                   7511:         my $about_me_link =
                   7512:             &Apache::loncommon::aboutmewrapper($plainname,
                   7513:                             $parmlog{$id}{'exe_uname'},
                   7514:                             $parmlog{$id}{'exe_udom'});
                   7515:         my $send_msg_link='';
1.568     raeburn  7516:         if ((!$readonly) && 
                   7517:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7518:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7519:             $send_msg_link ='<br />'.
                   7520:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7521:                             $parmlog{$id}{'exe_uname'},
                   7522:                             $parmlog{$id}{'exe_udom'});
                   7523:         }
                   7524:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7525:         my $makenewrow=0;
                   7526:         my %istype=();
                   7527:         my $output;
                   7528:         foreach my $changed (reverse(sort(@changes))) {
                   7529:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7530:             my $typeflag = ($changed =~/\.type$/ &&
                   7531:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7532:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7533:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7534:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7535:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7536:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7537:                 if ($uname ne '') {
                   7538:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7539:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7540:                 }
                   7541:             }
                   7542:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7543:                 if ($folder) {
                   7544:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7545:                 }
                   7546:             }
                   7547:             if ($typeflag) {
                   7548:                 $istype{$parmname}=$value;
                   7549:                 if (!$env{'form.includetypes'}) { next; }
                   7550:             }
                   7551:             $count++;
                   7552:             if ($makenewrow) {
                   7553:                 $output .= $row_start;
                   7554:             } else {
                   7555:                 $makenewrow=1;
                   7556:             }
1.470     raeburn  7557:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7558:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7559:                 &mt($parmitem).'</td><td>'.
                   7560:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7561:             my $stillactive=0;
                   7562:             if ($parmlog{$id}{'delflag'}) {
                   7563:                 $output .= &mt('Deleted');
                   7564:             } else {
                   7565:                 if ($typeflag) {
1.470     raeburn  7566:                     my $parmitem = &standard_parameter_names($value); 
                   7567:                     $parmitem = &mt($parmitem);
1.560     damieng  7568:                     $output .= &mt('Type: [_1]',$parmitem);
                   7569:                 } else {
1.584     raeburn  7570:                     my $toolsymb;
                   7571:                     if ($middle =~ /ext\.tool$/) {
                   7572:                         $toolsymb = $middle;
                   7573:                     }
1.560     damieng  7574:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7575:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7576:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7577:                     my $showvalue = $value;
                   7578:                     if ($istype{$parmname} eq '') {
                   7579:                         my $type = &standard_parameter_types($parmname);
                   7580:                         if ($type ne '') {
                   7581:                             if (&isdateparm($type)) {
                   7582:                                 $showvalue =
                   7583:                                     &Apache::lonlocal::locallocaltime($value);
                   7584:                             }
                   7585:                         }
                   7586:                     } else {
1.560     damieng  7587:                         if (&isdateparm($istype{$parmname})) {
                   7588:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7589:                         }
1.469     raeburn  7590:                     }
                   7591:                     $output .= $showvalue;
1.560     damieng  7592:                     if ($value ne $all[$level]) {
                   7593:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7594:                     } else {
                   7595:                         $stillactive=1;
                   7596:                     }
                   7597:                 }
1.473     amueller 7598:             }
1.568     raeburn  7599:             $output .= '</td>';
                   7600: 
                   7601:             unless ($readonly) { 
                   7602:                 $output .= '<td>';
                   7603:                 if ($stillactive) {
                   7604:                     my $parmitem = &standard_parameter_names($parmname);
                   7605:                     $parmitem = &mt($parmitem);
                   7606:                     my $title=&mt('Changed [_1]',$parmitem);
                   7607:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7608:                         $parmitem,$realmdescription,
                   7609:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7610:                     if (($uname) && ($udom)) {
                   7611:                         $output .=
                   7612:                         &Apache::loncommon::messagewrapper('Notify User',
                   7613:                                                            $uname,$udom,$title,
                   7614:                                                            $description);
                   7615:                     } else {
                   7616:                         $output .=
                   7617:                             &Apache::lonrss::course_blog_link($id,$title,
                   7618:                                                               $description);
                   7619:                     }
1.560     damieng  7620:                 }
1.568     raeburn  7621:                 $output .= '</td>';
1.560     damieng  7622:             }
1.568     raeburn  7623:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7624:         }
1.560     damieng  7625:         if ($env{'form.displayfilter'} eq 'containing') {
                   7626:             my $wholeentry=$about_me_link.':'.
                   7627:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7628:             $output;
                   7629:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7630:         }
1.349     www      7631:         if ($count) {
1.560     damieng  7632:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7633:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7634:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7635:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7636:             $send_msg_link.'</td>'.$output);
                   7637:             $shown++;
                   7638:         }
                   7639:         if (!($env{'form.show'} eq &mt('all')
                   7640:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7641:     }
1.301     www      7642:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7643:     &endSettingsScreen($r);
1.284     www      7644:     $r->print(&Apache::loncommon::end_page());
                   7645: }
                   7646: 
1.560     damieng  7647: ##################################################
                   7648: # MISC !
                   7649: ##################################################
                   7650: 
1.563     damieng  7651: # Stores slot information.
1.560     damieng  7652: # Used by table UI
1.563     damieng  7653: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7654: #
                   7655: # @param {string} $slot_name - slot name
                   7656: # @param {string} $cdom - course domain
                   7657: # @param {string} $cnum - course number
                   7658: # @param {string} $symb - resource symb
                   7659: # @param {string} $uname - user name
                   7660: # @param {string} $udom - user domain
                   7661: # @returns {string} - 'ok' or error name
1.437     raeburn  7662: sub update_slots {
                   7663:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7664:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7665:     if (!keys(%slot)) {
                   7666:         return 'error: slot does not exist';
                   7667:     }
                   7668:     my $max=$slot{'maxspace'};
                   7669:     if (!defined($max)) { $max=99999; }
                   7670: 
                   7671:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7672:                                        "^$slot_name\0");
                   7673:     my ($tmp)=%consumed;
                   7674:     if ($tmp=~/^error: 2 / ) {
                   7675:         return 'error: unable to determine current slot status';
                   7676:     }
                   7677:     my $last=0;
                   7678:     foreach my $key (keys(%consumed)) {
                   7679:         my $num=(split('\0',$key))[1];
                   7680:         if ($num > $last) { $last=$num; }
                   7681:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7682:             return 'ok';
                   7683:         }
                   7684:     }
                   7685: 
                   7686:     if (scalar(keys(%consumed)) >= $max) {
                   7687:         return 'error: no space left in slot';
                   7688:     }
                   7689:     my $wanted=$last+1;
                   7690: 
                   7691:     my %reservation=('name'      => $uname.':'.$udom,
                   7692:                      'timestamp' => time,
                   7693:                      'symb'      => $symb);
                   7694: 
                   7695:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7696:                                         {"$slot_name\0$wanted" =>
                   7697:                                              \%reservation},
                   7698:                                         $cdom, $cnum);
1.438     raeburn  7699:     if ($success eq 'ok') {
                   7700:         my %storehash = (
                   7701:                           symb    => $symb,
                   7702:                           slot    => $slot_name,
                   7703:                           action  => 'reserve',
                   7704:                           context => 'parameter',
                   7705:                         );
1.526     raeburn  7706:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7707:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7708: 
1.526     raeburn  7709:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7710:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7711:     }
1.437     raeburn  7712:     return $success;
                   7713: }
                   7714: 
1.563     damieng  7715: # Deletes a slot reservation.
1.560     damieng  7716: # Used by table UI
1.563     damieng  7717: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7718: #
                   7719: # @param {string} $slot_name - slot name
                   7720: # @param {string} $cdom - course domain
                   7721: # @param {string} $cnum - course number
                   7722: # @param {string} $uname - user name
                   7723: # @param {string} $udom - user domain
                   7724: # @param {string} $symb - resource symb
                   7725: # @returns {string} - 'ok' or error name
1.437     raeburn  7726: sub delete_slots {
                   7727:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7728:     my $delresult;
                   7729:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7730:                                          $cnum, "^$slot_name\0");
                   7731:     if (&Apache::lonnet::error(%consumed)) {
                   7732:         return 'error: unable to determine current slot status';
                   7733:     }
                   7734:     my ($tmp)=%consumed;
                   7735:     if ($tmp=~/^error: 2 /) {
                   7736:         return 'error: unable to determine current slot status';
                   7737:     }
                   7738:     foreach my $key (keys(%consumed)) {
                   7739:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7740:             my $num=(split('\0',$key))[1];
                   7741:             my $entry = $slot_name.'\0'.$num;
                   7742:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7743:                                               $cdom,$cnum);
                   7744:             if ($delresult eq 'ok') {
                   7745:                 my %storehash = (
                   7746:                                   symb    => $symb,
                   7747:                                   slot    => $slot_name,
                   7748:                                   action  => 'release',
                   7749:                                   context => 'parameter',
                   7750:                                 );
1.526     raeburn  7751:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7752:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7753:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7754:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7755:             }
                   7756:         }
                   7757:     }
                   7758:     return $delresult;
                   7759: }
                   7760: 
1.563     damieng  7761: # Returns true if there is a current course.
1.560     damieng  7762: # Used by handler
1.563     damieng  7763: #
                   7764: # @returns {boolean}
1.355     albertel 7765: sub check_for_course_info {
                   7766:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7767:     return 1 if ($navmap);
                   7768:     return 0;
                   7769: }
                   7770: 
1.563     damieng  7771: # Returns the current course host and host LON-CAPA version.
                   7772: #
                   7773: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7774: sub parameter_release_vars { 
1.504     raeburn  7775:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7776:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7777:    my $chostname = &Apache::lonnet::hostname($chome);
                   7778:    my ($cmajor,$cminor) = 
                   7779:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7780:    return ($chostname,$cmajor,$cminor);
                   7781: }
                   7782: 
1.563     damieng  7783: # Checks if the course host version can handle a parameter required version,
                   7784: # and if it does, stores the release needed for the course.
                   7785: #
                   7786: # @param {string} $name - parameter name
                   7787: # @param {string} $value - parameter value
                   7788: # @param {string} $valmatch - name of the test used for checking the value
                   7789: # @param {string} $namematch - name of the test used for checking the name
                   7790: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7791: # @param {integer} $cmajor - course major version number
                   7792: # @param {integer} $cminor - course minor version number
                   7793: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7794: sub parameter_releasecheck {
1.557     raeburn  7795:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7796:     my $needsnewer;
                   7797:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7798:     if (($cmajor < $needsmajor) || 
                   7799:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7800:         $needsnewer = 1;
1.557     raeburn  7801:     } elsif ($name) {
                   7802:         if ($valmatch) {
                   7803:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7804:         } elsif ($value) { 
                   7805:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7806:         }
                   7807:     } elsif ($namematch) {
                   7808:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7809:     }
                   7810:     return $needsnewer;
                   7811: }
                   7812: 
1.568     raeburn  7813: sub get_permission {
                   7814:     my %permission;
                   7815:     my $allowed = 0;
                   7816:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7817:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7818:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7819:                   $env{'request.course.sec'}))) {
                   7820:         %permission= (
                   7821:                        'edit'               => 1,
                   7822:                        'set'                => 1,
                   7823:                        'setoverview'        => 1,
                   7824:                        'addmetadata'        => 1,
                   7825:                        'ordermetadata'      => 1,
                   7826:                        'setrestrictmeta'    => 1,
                   7827:                        'newoverview'        => 1,
                   7828:                        'setdefaults'        => 1,
                   7829:                        'settable'           => 1,
                   7830:                        'parameterchangelog' => 1,
                   7831:                        'cleanparameters'    => 1,
                   7832:                        'dateshift1'         => 1,
                   7833:                        'dateshift2'         => 1,
                   7834:                        'helper'             => 1,
                   7835:          );
                   7836:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7837:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7838:                   $env{'request.course.sec'}))) {
                   7839:         %permission = (
                   7840:                        'set'                => 1,
                   7841:                        'settable'           => 1,
                   7842:                        'newoverview'        => 1,
                   7843:                        'setoverview'        => 1,
                   7844:                        'parameterchangelog' => 1,
                   7845:                       );
                   7846:     }
                   7847:     foreach my $perm (values(%permission)) {
                   7848:         if ($perm) { $allowed=1; last; }
                   7849:     }
                   7850:     return (\%permission,$allowed);
                   7851: }
                   7852: 
1.560     damieng  7853: ##################################################
                   7854: # HANDLER
                   7855: ##################################################
                   7856: 
                   7857: # Main handler for lonparmset.
                   7858: # Sub called based on request parameters action and command:
                   7859: # no command or action: print_main_menu
                   7860: # command 'set': assessparms (direct access to table mode for a resource)
                   7861: #                (this can also be accessed simply with the symb parameter)
                   7862: # action 'setoverview': overview (display all existing parameter settings)
                   7863: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7864: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7865: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7866: # action 'newoverview': newoverview (overview mode)
                   7867: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7868: # action 'settable': assessparms (table mode)
                   7869: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7870: #                              blog postings, user notification changes)
                   7871: # action 'cleanparameters': clean_parameters (unused)
                   7872: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7873: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7874: sub handler {
1.43      albertel 7875:     my $r=shift;
1.30      www      7876: 
1.376     albertel 7877:     &reset_caches();
                   7878: 
1.414     droeschl 7879:     &Apache::loncommon::content_type($r,'text/html');
                   7880:     $r->send_http_header;
                   7881:     return OK if $r->header_only;
                   7882: 
1.193     albertel 7883:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7884:                         ['action','state',
1.205     www      7885:                                              'pres_marker',
                   7886:                                              'pres_value',
1.206     www      7887:                                              'pres_type',
1.506     www      7888:                                              'filter','part',
1.390     www      7889:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7890: 
1.83      bowersj2 7891: 
1.193     albertel 7892:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7893:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7894:                         text=>"Content and Problem Settings",
1.473     amueller 7895:                         faq=>10,
                   7896:                         bug=>'Instructor Interface',
1.442     droeschl 7897:                                             help =>
                   7898:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7899: 
1.30      www      7900: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7901:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7902:     my $exists = &check_for_course_info();
                   7903: 
1.568     raeburn  7904:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7905:         #
                   7906:         # Main switch on form.action and form.state, as appropriate
                   7907:         #
                   7908:         # Check first if coming from someone else headed directly for
                   7909:         #  the table mode
1.568     raeburn  7910:         if (($parm_permission->{'set'}) && 
                   7911:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7912:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7913:             &assessparms($r,$parm_permission);
1.193     albertel 7914:         } elsif (! exists($env{'form.action'})) {
                   7915:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7916:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7917:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7918:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7919:             &overview($r,$parm_permission);
1.560     damieng  7920:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7921:             &addmetafield($r);
                   7922:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7923:             &order_meta_fields($r);
1.414     droeschl 7924:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7925:             &setrestrictmeta($r);
1.414     droeschl 7926:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7927:             &newoverview($r,$parm_permission);
1.414     droeschl 7928:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7929:             &defaultsetter($r);
                   7930:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7931:             &assessparms($r,$parm_permission);
1.414     droeschl 7932:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7933:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7934:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7935:             &clean_parameters($r);
1.414     droeschl 7936:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7937:             &date_shift_one($r);
1.414     droeschl 7938:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7939:             &date_shift_two($r);
1.446     bisitz   7940:         }
1.43      albertel 7941:     } else {
1.1       www      7942: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7943:         if ($exists) {
                   7944:             $env{'user.error.msg'}=
                   7945:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7946:         } else {
                   7947:             $env{'user.error.msg'}=
                   7948:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7949:         }
                   7950:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7951:     }
1.376     albertel 7952:     &reset_caches();
                   7953: 
1.43      albertel 7954:     return OK;
1.1       www      7955: }
                   7956: 
                   7957: 1;
                   7958: __END__
                   7959: 
                   7960: 

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