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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.603   ! raeburn     4: # $Id: lonparmset.pm,v 1.602 2021/08/12 20:43:26 raeburn Exp $
1.40      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.59      matthew    28: ###################################################################
                     29: ###################################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: lonparmset - Handler to set parameters for assessments and course
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
1.579     raeburn    39: lonparmset provides an interface to setting content parameters in a 
                     40: course.
1.560     damieng    41: 
                     42: It contains all the code for the "Content and Problem Settings" UI, except
                     43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
                     44: and lonblockingmenu.pm.
1.59      matthew    45: 
                     46: =head1 DESCRIPTION
                     47: 
                     48: This module sets coursewide and assessment parameters.
                     49: 
                     50: =head1 INTERNAL SUBROUTINES
                     51: 
1.416     jms        52: =over
1.59      matthew    53: 
1.416     jms        54: =item parmval()
1.59      matthew    55: 
                     56: Figure out a cascading parameter.
                     57: 
1.71      albertel   58: Inputs:  $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162     albertel   59:          $id   - a bighash Id number
1.71      albertel   60:          $def  - the resource's default value   'stupid emacs
                     61: 
1.556     raeburn    62: Returns:  A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71      albertel   63: 
1.556     raeburn    64: 18 - General Course
                     65: 17 - Map or Folder level in course (recursive) 
                     66: 16 - Map or Folder level in course (non-recursive)
                     67: 15 - resource default
                     68: 14 - map default
                     69: 13 - resource level in course
                     70: 12 - General for section
                     71: 11 - Map or Folder level for section (recursive)
                     72: 10 - Map or Folder level for section (non-recursive)
                     73: 9 - resource level in section
                     74: 8 - General for group
                     75: 7 - Map or Folder level for group (recursive)
                     76: 6 - Map or Folder level for group (non-recursive)
                     77: 5 - resource level in group
                     78: 4 - General for specific student
                     79: 3 - Map or Folder level for specific student (recursive)
                     80: 2 - Map or Folder level for specific student (non-recursive)
1.71      albertel   81: 1 - resource level for specific student
1.2       www        82: 
1.416     jms        83: =item parmval_by_symb()
                     84: 
                     85: =item reset_caches()
                     86: 
                     87: =item cacheparmhash() 
                     88: 
                     89: =item parmhash()
                     90: 
                     91: =item symbcache()
                     92: 
                     93: =item preset_defaults()
                     94: 
                     95: =item date_sanity_info()
                     96: 
                     97: =item storeparm()
                     98: 
                     99: Store a parameter by symb
                    100: 
                    101:     Takes
                    102:     - symb
                    103:     - name of parameter
                    104:     - level
                    105:     - new value
                    106:     - new type
                    107:     - username
                    108:     - userdomain
                    109: 
                    110: =item log_parmset()
                    111: 
                    112: =item storeparm_by_symb_inner()
                    113: 
                    114: =item valout()
                    115: 
                    116: Format a value for output.
                    117: 
                    118: Inputs:  $value, $type, $editable
                    119: 
                    120: Returns: $value, formatted for output.  If $type indicates it is a date,
                    121: localtime($value) is returned.
                    122: $editable will return an icon to click on
                    123: 
                    124: =item plink()
                    125: 
                    126: Produces a link anchor.
                    127: 
                    128: Inputs: $type,$dis,$value,$marker,$return,$call
                    129: 
                    130: Returns: scalar with html code for a link which will envoke the 
                    131: javascript function 'pjump'.
                    132: 
                    133: =item page_js()
                    134: 
                    135: =item startpage()
                    136: 
                    137: =item print_row()
                    138: 
                    139: =item print_td()
                    140: 
1.580     raeburn   141: =item check_other_groups()
1.416     jms       142: 
                    143: =item parm_control_group()
                    144: 
                    145: =item extractResourceInformation() : 
                    146: 
1.512     foxr      147:  extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416     jms       148: 
1.542     raeburn   149: Input: See list below
                    150: 
                    151: =over 4
1.416     jms       152: 
1.512     foxr      153: =item * B<env{'user.name'}> : Current username
1.416     jms       154: 
1.512     foxr      155: =item * B<env{'user.domain'}> : Domain of current user.
1.416     jms       156: 
1.542     raeburn   157: =item * B<env{"request.course.fn"}> : Course
                    158: 
                    159: =back
1.416     jms       160: 
1.512     foxr      161: Outputs: See list below:
1.416     jms       162: 
1.542     raeburn   163: =over 4
                    164: 
1.512     foxr      165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416     jms       166: 
1.512     foxr      167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416     jms       168: 
1.512     foxr      169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416     jms       170: 
1.512     foxr      171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416     jms       172: 
1.512     foxr      173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
                    174: 
                    175: =item * B<allmaps> (out) : hash, ???
1.416     jms       176: 
                    177: =item * B<mapp> : ??
                    178: 
                    179: =item * B<symbp> : hash, id->full sym?
                    180: 
1.512     foxr      181: =item * B<maptitles>
                    182: 
                    183: =item * B<uris>
1.416     jms       184: 
1.512     foxr      185: =item * B<keyorder>
                    186: 
                    187: =item * B<defkeytype>
1.416     jms       188: 
1.542     raeburn   189: =back
                    190: 
1.416     jms       191: =item isdateparm()
                    192: 
                    193: =item parmmenu()
                    194: 
                    195: =item partmenu()
                    196: 
                    197: =item usermenu()
                    198: 
                    199: =item displaymenu()
                    200: 
                    201: =item mapmenu()
                    202: 
                    203: =item levelmenu()
                    204: 
                    205: =item sectionmenu()
                    206: 
                    207: =item keysplit()
                    208: 
                    209: =item keysinorder()
                    210: 
                    211: =item keysinorder_bytype()
                    212: 
                    213: =item keysindisplayorder()
                    214: 
                    215: =item standardkeyorder()
                    216: 
                    217: =item assessparms() : 
                    218: 
                    219: Show assessment data and parameters.  This is a large routine that should
                    220: be simplified and shortened... someday.
                    221: 
1.513     foxr      222: Inputs: $r - the Apache request object.
                    223:   
1.416     jms       224: Returns: nothing
                    225: 
                    226: Variables used (guessed by Jeremy):
                    227: 
1.542     raeburn   228: =over
                    229: 
1.416     jms       230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
                    231: 
                    232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
                    233: 
                    234: =item * B<@catmarker> contains list of all possible parameters including part #s
                    235: 
                    236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
                    237: 
                    238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
                    239:         When storing information, store as part 0
                    240:         When requesting information, request from full part
                    241: 
1.542     raeburn   242: =back
                    243: 
1.416     jms       244: =item tablestart()
                    245: 
                    246: =item tableend()
                    247: 
                    248: =item extractuser()
                    249: 
                    250: =item parse_listdata_key()
                    251: 
                    252: =item listdata()
                    253: 
                    254: =item date_interval_selector()
                    255: 
                    256: =item get_date_interval_from_form()
                    257: 
                    258: =item default_selector()
                    259: 
                    260: =item string_selector()
                    261: 
                    262: =item dateshift()
                    263: 
                    264: =item newoverview()
                    265: 
                    266: =item secgroup_lister()
                    267: 
                    268: =item overview()
                    269: 
                    270: =item clean_parameters()
                    271: 
                    272: =item date_shift_one()
                    273: 
                    274: =item date_shift_two()
                    275: 
                    276: =item parse_key()
                    277: 
                    278: =item header()
                    279: 
                    280: Output html header for page
                    281: 
                    282: =item print_main_menu()
                    283: 
                    284: =item output_row()
                    285: 
                    286: Set portfolio metadata
                    287: 
                    288: =item order_meta_fields()
                    289: 
                    290: =item addmetafield()
                    291: 
                    292: =item setrestrictmeta()
                    293: 
                    294: =item get_added_meta_fieldnames()
                    295: 
                    296: =item get_deleted_meta_fieldnames()
                    297: 
                    298: =item defaultsetter()
                    299: 
                    300: =item components()
                    301: 
                    302: =item load_parameter_names()
                    303: 
                    304: =item parm_change_log()
                    305: 
                    306: =item handler() : 
                    307: 
1.450     raeburn   308: Main handler.  Calls &assessparms subroutine.
1.416     jms       309: 
                    310: =back
                    311: 
1.59      matthew   312: =cut
                    313: 
1.416     jms       314: ###################################################################
                    315: ###################################################################
                    316: 
                    317: package Apache::lonparmset;
                    318: 
                    319: use strict;
                    320: use Apache::lonnet;
                    321: use Apache::Constants qw(:common :http REDIRECT);
                    322: use Apache::lonhtmlcommon();
                    323: use Apache::loncommon;
                    324: use GDBM_File;
                    325: use Apache::lonhomework;
                    326: use Apache::lonxml;
                    327: use Apache::lonlocal;
                    328: use Apache::lonnavmaps;
                    329: use Apache::longroup;
                    330: use Apache::lonrss;
1.506     www       331: use HTML::Entities;
1.416     jms       332: use LONCAPA qw(:DEFAULT :match);
                    333: 
                    334: 
1.560     damieng   335: ##################################################
                    336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    337: ##################################################
                    338: 
                    339: # Page header
1.561     damieng   340: #
                    341: # @param {Apache2::RequestRec} $r - Apache request object
                    342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    343: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       344: sub startSettingsScreen {
1.531     raeburn   345:     my ($r,$mode,$crstype)=@_;
1.507     www       346: 
1.531     raeburn   347:     my $tabtext = &mt('Course Settings');
                    348:     if ($crstype eq 'Community') {
                    349:         $tabtext = &mt('Community Settings');
                    350:     } 
1.507     www       351:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    352:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   353:                                           $tabtext.
1.507     www       354:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    355: 
1.523     raeburn   356:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       357:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    358:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   359:     $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507     www       360: }
                    361: 
1.560     damieng   362: # Page footer
1.507     www       363: sub endSettingsScreen {
                    364:    my ($r)=@_;
                    365:    $r->print('</div></div></div>');
                    366: }
                    367: 
                    368: 
                    369: 
1.560     damieng   370: ##################################################
1.563     damieng   371: # (mostly) TABLE MODE
1.560     damieng   372: # (parmval is also used for the log of parameter changes)
                    373: ##################################################
                    374: 
1.566     damieng   375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   376: #
                    377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   378: # @param {string} $id - resource id or map pc
1.561     damieng   379: # @param {string} $def - the resource's default value for this parameter
                    380: # @param {string} $uname - user name
                    381: # @param {string} $udom - user domain
                    382: # @param {string} $csec - section name
                    383: # @param {string} $cgroup - group name
                    384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    385: # @returns {Array}
1.2       www       386: sub parmval {
1.275     raeburn   387:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    388:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    389:                                                            $cgroup,$courseopt);
1.201     www       390: }
                    391: 
1.561     damieng   392: # Returns an array containing
                    393: # - the most specific level that is defined for that parameter (integer)
                    394: # - an array with the level as index and the parameter value as value (when defined)
                    395: #   (level 1 is the most specific and will have precedence)
                    396: #
                    397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   398: # @param {string} $symb - resource symb or map src
1.561     damieng   399: # @param {string} $def - the resource's default value for this parameter
                    400: # @param {string} $uname - user name
                    401: # @param {string} $udom - user domain
                    402: # @param {string} $csec - section name
                    403: # @param {string} $cgroup - group name
                    404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    405: # @returns {Array}
1.201     www       406: sub parmval_by_symb {
1.275     raeburn   407:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       408: 
1.352     albertel  409:     my $useropt;
                    410:     if ($uname ne '' && $udom ne '') {
1.561     damieng   411:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  412:     }
1.200     www       413: 
1.8       www       414:     my $result='';
1.44      albertel  415:     my @outpar=();
1.2       www       416: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    417:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  418:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   419:     
                    420:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    421:     # any change should be reflected there.
                    422:     
1.201     www       423:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   424:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       425:     my $mapparm=$map.'___(all).'.$what;
1.10      www       426: 
1.269     raeburn   427:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    428:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   429:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   430:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    431: 
1.190     albertel  432:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    433:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   434:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  435:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    436: 
                    437:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    438:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   439:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  440:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       441: 
1.11      www       442: 
1.182     albertel  443: # --------------------------------------------------------- first, check course
1.11      www       444: 
1.561     damieng   445: # 18 - General Course
1.200     www       446:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   447:         $outpar[18]=$$courseopt{$courselevel};
                    448:         $result=18;
                    449:     }
                    450: 
1.561     damieng   451: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   452:     if (defined($$courseopt{$courseleveli})) {
                    453:         $outpar[17]=$$courseopt{$courseleveli};
                    454:         $result=17;
1.43      albertel  455:     }
1.11      www       456: 
1.561     damieng   457: # 16 - Map or Folder level in course (non-recursive)
1.200     www       458:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   459:         $outpar[16]=$$courseopt{$courselevelm};
                    460:         $result=16;
1.43      albertel  461:     }
1.11      www       462: 
1.182     albertel  463: # ------------------------------------------------------- second, check default
                    464: 
1.561     damieng   465: # 15 - resource default
1.556     raeburn   466:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  467: 
                    468: # ------------------------------------------------------ third, check map parms
                    469: 
1.556     raeburn   470:     
1.561     damieng   471: # 14 - map default
1.376     albertel  472:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   473:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  474: 
1.561     damieng   475: # 13 - resource level in course
1.200     www       476:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   477:         $outpar[13]=$$courseopt{$courselevelr};
                    478:         $result=13;
1.43      albertel  479:     }
1.11      www       480: 
1.182     albertel  481: # ------------------------------------------------------ fourth, back to course
1.352     albertel  482:     if ($csec ne '') {
1.561     damieng   483: # 12 - General for section
1.200     www       484:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   485:             $outpar[12]=$$courseopt{$seclevel};
                    486:             $result=12;
                    487:         }
1.561     damieng   488: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   489:         if (defined($$courseopt{$secleveli})) {
                    490:             $outpar[11]=$$courseopt{$secleveli};
                    491:             $result=11;
                    492:         }
1.561     damieng   493: # 10 - Map or Folder level for section (non-recursive)
1.200     www       494:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   495:             $outpar[10]=$$courseopt{$seclevelm};
                    496:             $result=10;
                    497:         }
1.561     damieng   498: # 9 - resource level in section
1.200     www       499:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   500:             $outpar[9]=$$courseopt{$seclevelr};
                    501:             $result=9;
                    502:         }
1.43      albertel  503:     }
1.275     raeburn   504: # ------------------------------------------------------ fifth, check course group
1.352     albertel  505:     if ($cgroup ne '') {
1.561     damieng   506: # 8 - General for group
1.269     raeburn   507:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   508:             $outpar[8]=$$courseopt{$grplevel};
                    509:             $result=8;
                    510:         }
1.561     damieng   511: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   512:         if (defined($$courseopt{$grpleveli})) {
                    513:             $outpar[7]=$$courseopt{$grpleveli};
                    514:             $result=7;
1.269     raeburn   515:         }
1.561     damieng   516: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   517:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   518:             $outpar[6]=$$courseopt{$grplevelm};
                    519:             $result=6;
1.269     raeburn   520:         }
1.561     damieng   521: # 5 - resource level in group
1.269     raeburn   522:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   523:             $outpar[5]=$$courseopt{$grplevelr};
                    524:             $result=5;
1.269     raeburn   525:         }
                    526:     }
1.11      www       527: 
1.556     raeburn   528: # ---------------------------------------------------------- sixth, check user
1.11      www       529: 
1.352     albertel  530:     if ($uname ne '') {
1.561     damieng   531: # 4 - General for specific student
                    532:         if (defined($$useropt{$courselevel})) {
                    533:             $outpar[4]=$$useropt{$courselevel};
                    534:             $result=4;
                    535:         }
1.556     raeburn   536: 
1.561     damieng   537: # 3 - Map or Folder level for specific student (recursive)
                    538:         if (defined($$useropt{$courseleveli})) {
                    539:             $outpar[3]=$$useropt{$courseleveli};
                    540:             $result=3;
                    541:         }
1.473     amueller  542: 
1.561     damieng   543: # 2 - Map or Folder level for specific student (non-recursive)
                    544:         if (defined($$useropt{$courselevelm})) {
                    545:             $outpar[2]=$$useropt{$courselevelm};
                    546:             $result=2;
                    547:         }
1.473     amueller  548: 
1.561     damieng   549: # 1 - resource level for specific student
                    550:         if (defined($$useropt{$courselevelr})) {
                    551:             $outpar[1]=$$useropt{$courselevelr};
                    552:             $result=1;
                    553:         }
1.43      albertel  554:     }
1.44      albertel  555:     return ($result,@outpar);
1.2       www       556: }
                    557: 
1.198     www       558: 
                    559: 
1.376     albertel  560: # --- Caches local to lonparmset
                    561: 
1.446     bisitz    562: 
1.561     damieng   563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  564: sub reset_caches {
                    565:     &resetparmhash();
                    566:     &resetsymbcache();
                    567:     &resetrulescache();
1.203     www       568: }
                    569: 
1.561     damieng   570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  572: {
1.561     damieng   573:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    574:     my %parmhash; # the parameter cache
                    575:     # reset map parameter hash
1.376     albertel  576:     sub resetparmhash {
1.560     damieng   577:         undef($parmhashid);
                    578:         undef(%parmhash);
1.376     albertel  579:     }
1.446     bisitz    580: 
1.561     damieng   581:     # dump the _parms.db database into %parmhash
1.376     albertel  582:     sub cacheparmhash {
1.560     damieng   583:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    584:         my %parmhashfile;
                    585:         if (tie(%parmhashfile,'GDBM_File',
                    586:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    587:             %parmhash=%parmhashfile;
                    588:             untie(%parmhashfile);
                    589:             $parmhashid=$env{'request.course.fn'};
                    590:         }
1.201     www       591:     }
1.446     bisitz    592: 
1.561     damieng   593:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  594:     sub parmhash {
1.560     damieng   595:         my ($id) = @_;
                    596:         &cacheparmhash();
                    597:         return $parmhash{$id};
1.376     albertel  598:     }
1.560     damieng   599: }
1.376     albertel  600: 
1.566     damieng   601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    602: {
1.561     damieng   603:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    604:     my %symbs; # hash id->symb
                    605:     # reset the id->symb cache
1.376     albertel  606:     sub resetsymbcache {
1.560     damieng   607:         undef($symbsid);
                    608:         undef(%symbs);
1.376     albertel  609:     }
1.446     bisitz    610: 
1.566     damieng   611:     # returns the resource symb or map src corresponding to a resource id or map pc
                    612:     # (using lonnavmaps and a cache)
1.376     albertel  613:     sub symbcache {
1.560     damieng   614:         my $id=shift;
                    615:         if ($symbsid ne $env{'request.course.id'}) {
                    616:             undef(%symbs);
                    617:         }
                    618:         if (!$symbs{$id}) {
                    619:             my $navmap = Apache::lonnavmaps::navmap->new();
                    620:             if ($id=~/\./) {
                    621:                 my $resource=$navmap->getById($id);
                    622:                 $symbs{$id}=$resource->symb();
                    623:             } else {
                    624:                 my $resource=$navmap->getByMapPc($id);
                    625:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    626:             }
                    627:             $symbsid=$env{'request.course.id'};
1.473     amueller  628:         }
1.560     damieng   629:         return $symbs{$id};
1.473     amueller  630:     }
1.560     damieng   631: }
1.201     www       632: 
1.561     damieng   633: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    634: {
1.561     damieng   635:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    636:     my %rules; # parameter default actions hash
1.376     albertel  637:     sub resetrulescache {
1.560     damieng   638:         undef($rulesid);
                    639:         undef(%rules);
1.376     albertel  640:     }
1.446     bisitz    641: 
1.561     damieng   642:     # returns the value for a given key in the parameter default action hash
1.376     albertel  643:     sub rulescache {
1.560     damieng   644:         my $id=shift;
                    645:         if ($rulesid ne $env{'request.course.id'}
                    646:             && !defined($rules{$id})) {
                    647:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    648:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    649:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    650:             $rulesid=$env{'request.course.id'};
                    651:         }
                    652:         return $rules{$id};
1.221     www       653:     }
                    654: }
                    655: 
1.416     jms       656: 
1.561     damieng   657: # Returns the values of the parameter type default action
                    658: # "default value when manually setting".
                    659: # If none is defined, ('','','','','') is returned.
                    660: #
                    661: # @param {string} $type - parameter type
                    662: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       663: sub preset_defaults {
                    664:     my $type=shift;
                    665:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   666:         # yes, there is something
                    667:         return (&rulescache($type.'_hours'),
                    668:             &rulescache($type.'_min'),
                    669:             &rulescache($type.'_sec'),
                    670:             &rulescache($type.'_value'));
1.229     www       671:     } else {
1.560     damieng   672:         # nothing there or something else
                    673:         return ('','','','','');
1.229     www       674:     }
                    675: }
                    676: 
1.416     jms       677: 
1.561     damieng   678: # Checks that a date is after enrollment start date and before
                    679: # enrollment end date.
                    680: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    681: # This is used by both overview and table modes.
                    682: #
                    683: # @param {integer} $checkdate - the date to check.
                    684: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       685: sub date_sanity_info {
                    686:    my $checkdate=shift;
                    687:    unless ($checkdate) { return ''; }
                    688:    my $result='';
                    689:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    690:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    691:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    692:          $result.='<div class="LC_warning">'
                    693:                  .&mt('After course enrollment end!')
                    694:                  .'</div>';
1.277     www       695:       }
                    696:    }
                    697:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    698:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    699:          $result.='<div class="LC_warning">'
                    700:                  .&mt('Before course enrollment start!')
                    701:                  .'</div>';
1.277     www       702:       }
                    703:    }
1.413     bisitz    704: # Preparation for additional warnings about dates in the past/future.
                    705: # An improved, more context sensitive version is recommended,
                    706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    707: #   if ($checkdate<time) {
                    708: #      $result.='<div class="LC_info">'
                    709: #              .'('.&mt('in the past').')'
                    710: #              .'</div>';
                    711: #      }
                    712: #   if ($checkdate>time) {
                    713: #      $result.='<div class="LC_info">'
                    714: #              .'('.&mt('in the future').')'
                    715: #              .'</div>';
                    716: #      }
1.277     www       717:    return $result;
                    718: }
1.561     damieng   719: 
                    720: 
                    721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       722: #
1.566     damieng   723: # @param {string} $sresid - resource id or map pc
1.565     damieng   724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   725: # @param {integer} $snum - level
                    726: # @param {string} $nval - new value
                    727: # @param {string} $ntype - new type
                    728: # @param {string} $uname - username
                    729: # @param {string} $udom - userdomain
                    730: # @param {string} $csec - section name
                    731: # @param {string} $cgroup - group name
1.186     www       732: sub storeparm {
1.269     raeburn   733:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   734:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       735: }
                    736: 
1.561     damieng   737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    738: 
                    739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    741: #
1.566     damieng   742: # @param {string} $symb - resource symb or map src
1.565     damieng   743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   744: # @param {integer} $snum - level
                    745: # @param {string} $nval - new value
                    746: # @param {string} $ntype - new type
                    747: # @param {string} $uname - username
                    748: # @param {string} $udom - userdomain
                    749: # @param {string} $csec - section name
                    750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    751: # @param {string} $cgroup - group name
1.197     www       752: sub storeparm_by_symb {
1.275     raeburn   753:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       754:     unless ($recflag) {
1.560     damieng   755:         # first time call
                    756:         %recstack=();
                    757:         $recflag=1;
1.226     www       758:     }
1.560     damieng   759:     # store parameter
1.226     www       760:     &storeparm_by_symb_inner
1.473     amueller  761:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   762:     # don't do anything if parameter was reset
1.266     www       763:     unless ($nval) { return; }
1.226     www       764:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   765:     # remember that this was set
1.226     www       766:     $recstack{$parm}=1;
1.560     damieng   767:     # what does this trigger?
1.226     www       768:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   769:         # don't backfire
                    770:         unless ((!$triggered) || ($recstack{$triggered})) {
                    771:             my $action=&rulescache($triggered.'_action');
                    772:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    773:             # set triggered parameter on same level
                    774:             my $newspnam=$prefix.$triggered;
                    775:             my $newvalue='';
                    776:             my $active=1;
                    777:             if ($action=~/^when\_setting/) {
                    778:             # are there restrictions?
                    779:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    780:                     $active=0;
1.565     damieng   781:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   782:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    783:                     }
                    784:                 }
                    785:                 $newvalue=&rulescache($triggered.'_value');
                    786:             } else {
                    787:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    788:                 if ($action=~/^later\_than/) {
                    789:                     $newvalue=$nval+$totalsecs;
                    790:                 } else {
                    791:                     $newvalue=$nval-$totalsecs;
                    792:                 }
                    793:             }
                    794:             if ($active) {
                    795:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    796:                         $uname,$udom,$csec,$recflag,$cgroup);
                    797:             }
                    798:         }
1.226     www       799:     }
                    800:     return '';
                    801: }
                    802: 
1.561     damieng   803: # Adds all given arguments to the course parameter log.
                    804: # @returns {string} - the answer to the lonnet query.
1.293     www       805: sub log_parmset {
1.525     raeburn   806:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       807: }
                    808: 
1.561     damieng   809: # Store a parameter value and type by symb, without using the parameter default actions.
                    810: # Expire related sheets.
                    811: #
1.566     damieng   812: # @param {string} $symb - resource symb or map src
1.561     damieng   813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    814: # @param {integer} $snum - level
                    815: # @param {string} $nval - new value
                    816: # @param {string} $ntype - new type
                    817: # @param {string} $uname - username
                    818: # @param {string} $udom - userdomain
                    819: # @param {string} $csec - section name
                    820: # @param {string} $cgroup - group name
                    821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       822: sub storeparm_by_symb_inner {
1.197     www       823: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   824:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       825: # ---------------------------------------------------------- Construct prefixes
1.186     www       826:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    827:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  828:     $map = &Apache::lonnet::deversion($map);
                    829: 
1.197     www       830:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   831:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       832:     my $mapparm=$map.'___(all).'.$spnam;
                    833: 
1.269     raeburn   834:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    835:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   836:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   837:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    838: 
1.190     albertel  839:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    840:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   841:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  842:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    843: 
1.190     albertel  844:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    845:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   846:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  847:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    848: 
1.186     www       849:     my $storeunder='';
1.578     raeburn   850:     my $possreplace='';
1.556     raeburn   851:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   852:     if (($snum==17) || ($snum==3)) { 
                    853:         $storeunder=$courseleveli;
                    854:         $possreplace=$courselevelm; 
                    855:     } 
                    856:     if (($snum==16) || ($snum==2)) { 
                    857:         $storeunder=$courselevelm;
                    858:         $possreplace=$courseleveli;
                    859:     }
1.556     raeburn   860:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    861:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   862:     if ($snum==11) { 
                    863:         $storeunder=$secleveli;
                    864:         $possreplace=$seclevelm; 
                    865:     }
                    866:     if ($snum==10) { 
                    867:         $storeunder=$seclevelm;
                    868:         $possreplace=$secleveli;
                    869:     }
1.556     raeburn   870:     if ($snum==9) { $storeunder=$seclevelr; }
                    871:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   872:     if ($snum==7) { 
                    873:         $storeunder=$grpleveli;
                    874:         $possreplace=$grplevelm;
                    875:     }
                    876:     if ($snum==6) {
                    877:         $storeunder=$grplevelm;
                    878:         $possreplace=$grpleveli;
                    879:     }
1.556     raeburn   880:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   881: 
1.446     bisitz    882: 
1.186     www       883:     my $delete;
                    884:     if ($nval eq '') { $delete=1;}
                    885:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  886:             $storeunder.'.type' => $ntype);
1.186     www       887:     my $reply='';
1.560     damieng   888:     
1.556     raeburn   889:     if ($snum>4) {
1.186     www       890: # ---------------------------------------------------------------- Store Course
                    891: #
1.560     damieng   892:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    893:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    894:         # Expire sheets
                    895:         &Apache::lonnet::expirespread('','','studentcalc');
                    896:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    897:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   898:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   899:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    900:         } else {
                    901:             &Apache::lonnet::expirespread('','','assesscalc');
                    902:         }
                    903:         # Store parameter
                    904:         if ($delete) {
                    905:             $reply=&Apache::lonnet::del
                    906:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    907:                 &log_parmset(\%storecontent,1);
                    908:         } else {
                    909:             $reply=&Apache::lonnet::cput
                    910:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    911:             &log_parmset(\%storecontent);
1.578     raeburn   912:             if ($possreplace) {
                    913:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    914:                 if (ref($resdata) eq 'HASH') {
                    915:                     if (exists($resdata->{$possreplace})) {
                    916:                         if (&Apache::lonnet::del
                    917:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    918:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    919:                         }
                    920:                     }
                    921:                 }
                    922:             }
1.560     damieng   923:         }
                    924:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       925:     } else {
                    926: # ------------------------------------------------------------------ Store User
                    927: #
1.560     damieng   928:         # Expire sheets
                    929:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    930:         if ($snum==1) {
                    931:             &Apache::lonnet::expirespread
                    932:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   933:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   934:             &Apache::lonnet::expirespread
                    935:             ($uname,$udom,'assesscalc',$map);
                    936:         } else {
                    937:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    938:         }
                    939:         # Store parameter
                    940:         if ($delete) {
                    941:             $reply=&Apache::lonnet::del
                    942:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    943:             &log_parmset(\%storecontent,1,$uname,$udom);
                    944:         } else {
                    945:             $reply=&Apache::lonnet::cput
                    946:             ('resourcedata',\%storecontent,$udom,$uname);
                    947:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   948:             if ($possreplace) {
                    949:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    950:                 if (ref($resdata) eq 'HASH') {
                    951:                     if (exists($resdata->{$possreplace})) {
                    952:                         if (&Apache::lonnet::del
                    953:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    954:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    955:                                           $uname,$udom);
                    956:                         }
                    957:                     }
                    958:                 }
                    959:             }
1.560     damieng   960:         }
                    961:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       962:     }
1.446     bisitz    963: 
1.186     www       964:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   965:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       966:     }
                    967:     return '';
                    968: }
                    969: 
1.9       www       970: 
1.561     damieng   971: # Returns HTML with the value of the given parameter,
                    972: # using a readable format for dates, and
                    973: # a warning if there is a problem with a date.
                    974: # Used by table mode.
                    975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    976: #
                    977: # @param {string} $value - the parameter value
                    978: # @param {string} $type - the parameter type
                    979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       980: sub valout {
1.600     raeburn   981:     my ($value,$type,$editable)=@_;
1.59      matthew   982:     my $result = '';
                    983:     # Values of zero are valid.
                    984:     if (! $value && $value ne '0') {
1.528     bisitz    985:         if ($editable) {
                    986:             $result =
                    987:                 '<img src="/res/adm/pages/editmap.png"'
                    988:                .' alt="'.&mt('Change').'"'
1.539     raeburn   989:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    990:         } else {
                    991:             $result='&nbsp;';
                    992:         }
1.59      matthew   993:     } else {
1.66      www       994:         if ($type eq 'date_interval') {
1.559     raeburn   995:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    996:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    997:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    998:                 $donebuttontext = $1;
                    999:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1000:                 $usesdone = 'done';
                   1001:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1002:                 $donebuttontext = &mt('Done');
                   1003:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1004:             }
1.554     raeburn  1005:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1006:             my @timer;
1.66      www      1007:             $year=$year-70;
                   1008:             $mday--;
                   1009:             if ($year) {
1.413     bisitz   1010: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1011:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1012:             }
                   1013:             if ($mon) {
1.413     bisitz   1014: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1015:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1016:             }
                   1017:             if ($mday) {
1.413     bisitz   1018: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1019:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1020:             }
                   1021:             if ($hour) {
1.413     bisitz   1022: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1023:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1024:             }
                   1025:             if ($min) {
1.413     bisitz   1026: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1027:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1028:             }
                   1029:             if ($sec) {
1.413     bisitz   1030: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1031:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1032:             }
1.413     bisitz   1033: #           $result=~s/\s+$//;
                   1034:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1035:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1036:             }
                   1037:             $result.=join(", ",@timer);
1.559     raeburn  1038:             if ($usesdone eq 'done') {
1.558     raeburn  1039:                 if ($secretkey) {
1.559     raeburn  1040:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1041:                 } else {
1.559     raeburn  1042:                     $result .= ' + "'.$donebuttontext.'"';
                   1043:                 }
1.554     raeburn  1044:             }
1.213     www      1045:         } elsif (&isdateparm($type)) {
1.361     albertel 1046:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1047:                 &date_sanity_info($value);
1.59      matthew  1048:         } else {
                   1049:             $result = $value;
1.517     www      1050:             $result=~s/\,/\, /gs;
1.560     damieng  1051:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1052:         }
                   1053:     }
                   1054:     return $result;
1.9       www      1055: }
                   1056: 
1.59      matthew  1057: 
1.561     damieng  1058: # Returns HTML containing a link on a parameter value, for table mode.
                   1059: # The link uses the javascript function 'pjump'.
                   1060: #
                   1061: # @param {string} $type - parameter type
                   1062: # @param {string} $dis - dialog title for editing the parameter value and type
                   1063: # @param {string} $value - parameter value
                   1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
                   1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1069: sub plink {
1.588     raeburn  1070:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1071:     my $winvalue=$value;
                   1072:     unless ($winvalue) {
1.592     raeburn  1073:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1074:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1075:         } elsif ($type eq 'string_yesno') {
                   1076:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1077:                 $winvalue=$env{'form.recent_string'};
                   1078:             }
1.23      www      1079:         } else {
1.190     albertel 1080:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1081:         }
                   1082:     }
1.229     www      1083:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1084:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1085:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1086:     my $valout = &valout($value,$type,1);
1.429     raeburn  1087:     my $unencmarker = $marker;
1.378     albertel 1088:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1089:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1090:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1091:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1092:     }
1.429     raeburn  1093:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1094:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1095:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1096:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1097:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1098: 
1.5       www      1099: }
                   1100: 
1.561     damieng  1101: # Javascript for table mode.
1.280     albertel 1102: sub page_js {
                   1103: 
1.81      www      1104:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1105:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1106: 
                   1107:     return(<<ENDJS);
                   1108: <script type="text/javascript">
1.454     bisitz   1109: // <![CDATA[
1.44      albertel 1110: 
1.88      matthew  1111:     $pjump_def
1.44      albertel 1112: 
                   1113:     function psub() {
1.591     raeburn  1114:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1115:         if (document.parmform.pres_marker.value!='') {
                   1116:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1117:             var typedef=new Array();
                   1118:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1119:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1120:                 if ((typedef[0]=='date') || 
1.591     raeburn  1121:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1122:                     eval('document.parmform.recent_'+
                   1123:                         document.parmform.pres_type.value+
                   1124:                         '.value=document.parmform.pres_value.value;');
                   1125:                 } else {
                   1126:                     eval('document.parmform.recent_'+typedef[0]+
                   1127:                         '.value=document.parmform.pres_value.value;');
                   1128:                 }
1.44      albertel 1129:             }
                   1130:             document.parmform.submit();
                   1131:         } else {
                   1132:             document.parmform.pres_value.value='';
                   1133:             document.parmform.pres_marker.value='';
                   1134:         }
                   1135:     }
                   1136: 
1.57      albertel 1137:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1138:         var options = "width=" + w + ",height=" + h + ",";
                   1139:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1140:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1141:         var newWin = window.open(url, wdwName, options);
                   1142:         newWin.focus();
                   1143:     }
1.523     raeburn  1144: 
1.454     bisitz   1145: // ]]>
1.523     raeburn  1146: 
1.44      albertel 1147: </script>
1.81      www      1148: $selscript
1.280     albertel 1149: ENDJS
                   1150: 
                   1151: }
1.507     www      1152: 
1.561     damieng  1153: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1154: # for table and overview modes.
1.523     raeburn  1155: sub showhide_js {
                   1156:     return <<"COURSECONTENTSCRIPT";
                   1157: 
                   1158: function showHide_courseContent() {
                   1159:     var parmlevValue=document.getElementById("parmlev").value;
                   1160:     if (parmlevValue == 'general') {
                   1161:         document.getElementById('mapmenu').style.display="none";
                   1162:     } else {
                   1163:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1164:             document.getElementById('mapmenu').style.display ="";
                   1165:         } else {
                   1166:             document.getElementById('mapmenu').style.display="none";
                   1167:         }
                   1168:     }
                   1169:     return;
                   1170: }
                   1171: 
                   1172: COURSECONTENTSCRIPT
                   1173: }
                   1174: 
1.561     damieng  1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1176: sub toggleparmtextbox_js {
                   1177:     return <<"ENDSCRIPT";
                   1178: 
                   1179: if (!document.getElementsByClassName) {
                   1180:     function getElementsByClassName(node, classname) {
                   1181:         var a = [];
                   1182:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1183:         var els = node.getElementsByTagName("*");
                   1184:         for(var i=0,j=els.length; i<j; i++)
                   1185:             if(re.test(els[i].className))a.push(els[i]);
                   1186:         return a;
                   1187:     }
                   1188: }
                   1189: 
                   1190: function showHideLenient() {
                   1191:     var lenients;
                   1192:     var setRegExp = /^set_/;
                   1193:     if (document.getElementsByClassName) {
                   1194:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1195:     } else {
                   1196:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1197:     }
                   1198:     if (lenients != 'undefined') {
                   1199:         for (var i=0; i<lenients.length; i++) {
                   1200:             if (lenients[i].checked) {
                   1201:                 if (lenients[i].value == 'weighted') {
                   1202:                     if (setRegExp.test(lenients[i].name)) {
                   1203:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1204:                         toggleParmTextbox(document.parmform,identifier);
                   1205:                     }
                   1206:                 }
                   1207:             }
                   1208:         }
                   1209:     }
                   1210:     return;
                   1211: }
                   1212: 
                   1213: function toggleParmTextbox(form,key) {
                   1214:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1215:     if (divfortext) {
                   1216:         var caller = form.elements['set_'+key];
                   1217:         if (caller.length) {
                   1218:             for (i=0; i<caller.length; i++) {
                   1219:                 if (caller[i].checked) {
                   1220:                     if (caller[i].value == 'weighted') {
                   1221:                         divfortext.style.display = 'inline';
                   1222:                     } else {
                   1223:                         divfortext.style.display = 'none';
                   1224:                     }
                   1225:                 }
                   1226:             }
                   1227:         }
                   1228:     }
                   1229:     return;
                   1230: }
                   1231: 
                   1232: ENDSCRIPT
                   1233: }
                   1234: 
1.561     damieng  1235: # Javascript function validateParms, for overview mode
1.549     raeburn  1236: sub validateparms_js {
                   1237:     return <<'ENDSCRIPT';
                   1238: 
                   1239: function validateParms() {
                   1240:     var textRegExp = /^settext_/;
                   1241:     var tailLenient = /\.lenient$/;
                   1242:     var patternRelWeight = /^\-?[\d.]+$/;
                   1243:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1244:     var ipRegExp = /^setip/;
1.549     raeburn  1245:     var ipallowRegExp = /^setipallow_/;
                   1246:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1247:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1248:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1249:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1250:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1251:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1252:     var dlKeyRegExp = /^deeplink_key_/;
                   1253:     var dlMenusRegExp = /^deeplink_menus_/;
                   1254:     var dlCollsRegExp = /^deeplink_colls_/;
1.549     raeburn  1255:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1256:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1257:         if (document.parmform.elements.length) {
                   1258:             for (i=0; i<document.parmform.elements.length; i++) {
                   1259:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1260:                 if (textRegExp.test(name)) {
1.549     raeburn  1261:                     var identifier = name.replace(textRegExp,'');
                   1262:                     if (tailLenient.test(identifier)) {
                   1263:                         if (document.parmform.elements['set_'+identifier].length) {
                   1264:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1265:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1266:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1267:                                         var relweight = document.parmform.elements[i].value;
                   1268:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1269:                                         if (!patternRelWeight.test(relweight)) {
                   1270:                                             relweight = '0.0';
                   1271:                                         }
                   1272:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1273:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1274:                                         } else {
                   1275:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1276:                                         }
                   1277:                                     }
                   1278:                                     break;
                   1279:                                 }
                   1280:                             }
                   1281:                         }
                   1282:                     }
1.597     raeburn  1283:                 } else if (ipRegExp.test(name)) {
                   1284:                     if (ipallowRegExp.test(name)) {
                   1285:                         var identifier = name.replace(ipallowRegExp,'');
                   1286:                         var possallow = document.parmform.elements[i].value;
                   1287:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1288:                         if (patternIP.test(possallow)) {
                   1289:                             if (document.parmform.elements['set_'+identifier].value) {
                   1290:                                 possallow = ','+possallow;
                   1291:                             }
                   1292:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1293:                         }
                   1294:                     } else if (ipdenyRegExp.test(name)) {
                   1295:                         var identifier = name.replace(ipdenyRegExp,'');
                   1296:                         var possdeny = document.parmform.elements[i].value;
                   1297:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1298:                         if (patternIP.test(possdeny)) {
                   1299:                             possdeny = '!'+possdeny;
                   1300:                             if (document.parmform.elements['set_'+identifier].value) {
                   1301:                                 possdeny = ','+possdeny;
                   1302:                             }
                   1303:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1304:                         }
                   1305:                     }
                   1306:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1307:                     if (dlListScopeRegExp.test(name)) {
                   1308:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1309:                         var idx = document.parmform.elements[i].selectedIndex;
                   1310:                         if (idx > 0) { 
                   1311:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1312:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1313:                             if (document.parmform.elements['set_'+identifier].value) {
                   1314:                                 possdeeplink = ','+possdeeplink;
                   1315:                             }
                   1316:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1317:                         }
1.601     raeburn  1318:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1319:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1320:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1321:                             var posslinkurl = document.parmform.elements[i].value;
                   1322:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1323:                             if (document.parmform.elements['set_'+identifier].value) {
                   1324:                                 posslinkurl = ','+posslinkurl;
                   1325:                             }
                   1326:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1327:                         }
1.601     raeburn  1328:                     } else if (dlLtidRegExp.test(name)) {
                   1329:                         var identifier = name.replace(dlLtidRegExp,'');
                   1330:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1331:                             var possltid = document.parmform.elements[i].value;
                   1332:                             possltid = possltid.replace(/\D+/g,'');
                   1333:                             if (possltid.length) {
1.597     raeburn  1334:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1335:                                     possltid = ':'+possltid;
1.597     raeburn  1336:                                 }
1.601     raeburn  1337:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1338:                             } else {
                   1339:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1340:                                 alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597     raeburn  1341:                                 return false;  
                   1342:                             }
                   1343:                         }
1.601     raeburn  1344:                     } else if (dlLticRegExp.test(name)) {
                   1345:                         var identifier = name.replace(dlLticRegExp,'');
                   1346:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1347:                             var possltic = document.parmform.elements[i].value;
                   1348:                             possltic = possltic.replace(/\D+/g,'');
                   1349:                             if (possltic.length) {
                   1350:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1351:                                     possltic = ':'+possltic;
                   1352:                                 }
                   1353:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1354:                             } else {
                   1355:                                 document.parmform.elements['set_'+identifier].value = '';
                   1356:                                 alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                   1357:                                 return false;
                   1358:                             }
                   1359:                         }
1.597     raeburn  1360:                     } else if (dlKeyRegExp.test(name)) {
                   1361:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1362:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1363:                             var posskey = document.parmform.elements[i].value;
                   1364:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1365:                             var origlength = posskey.length;
                   1366:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1367:                             var newlength = posskey.length;
                   1368:                             if (newlength > 0) {
                   1369:                                 var change = origlength - newlength;
                   1370:                                 if (change) {
                   1371:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1372:                                 }
                   1373:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1374:                                     posskey = ':'+posskey;
                   1375:                                 }
                   1376:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1377:                             } else {
                   1378:                                 document.parmform.elements['set_'+identifier].value = '';
                   1379:                                 if (newlength < origlength) {
                   1380:                                     alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
                   1381:                                 } else {
                   1382:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1383:                                 }
                   1384:                                 return false;
                   1385:                             }
                   1386:                         }
                   1387:                     } else if (dlMenusRegExp.test(name)) {
                   1388:                         if (document.parmform.elements[i].checked) {
                   1389:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1390:                             var posslinkmenu = document.parmform.elements[i].value;
                   1391:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1392:                             if (posslinkmenu == 'std') {
                   1393:                                 posslinkmenu = '0';
                   1394:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1395:                                     posslinkmenu = ','+posslinkmenu;
                   1396:                                 }
                   1397:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1398:                             }
                   1399:                         }
                   1400:                     } else if (dlCollsRegExp.test(name)) {
                   1401:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1402:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1403:                             var posslinkmenu = document.parmform.elements[i].value;
                   1404:                             if (document.parmform.elements['set_'+identifier].value) {
                   1405:                                 posslinkmenu = ','+posslinkmenu;
                   1406:                             }
                   1407:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1408:                         }
1.549     raeburn  1409:                     }
                   1410:                 }
                   1411:             }
                   1412:         }
                   1413:     }
                   1414:     return true;
                   1415: }
                   1416: 
1.597     raeburn  1417: function isRadioSet(name,expected) {
                   1418:     var menuitems = document.getElementsByName(name);
                   1419:     var radioLength = menuitems.length;
                   1420:     result = false;
                   1421:     if (radioLength  > 1) {
                   1422:         for (var j=0; j<radioLength; j++) {
                   1423:             if (menuitems[j].checked) {
                   1424:                 if (menuitems[j].value == expected) {
                   1425:                     result = true;
                   1426:                     break;
                   1427:                 }
                   1428:             }
                   1429:         }
                   1430:     }
                   1431:     return result;
                   1432: }
                   1433: 
1.549     raeburn  1434: ENDSCRIPT
                   1435: }
                   1436: 
1.561     damieng  1437: # Javascript initialization, for overview mode
1.549     raeburn  1438: sub ipacc_boxes_js  {
                   1439:     my $remove = &mt('Remove');
                   1440:     return <<"END";
                   1441: \$(document).ready(function() {
                   1442:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1443:     var add_button      = \$(".LC_add_ipacc_button");
                   1444:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1445: 
                   1446:     \$(add_button).click(function(e){
                   1447:         e.preventDefault();
                   1448:         var identifier = \$(this).closest("div").attr("id");
                   1449:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1450:         \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');
1.549     raeburn  1451:     });
                   1452: 
                   1453:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1454:         e.preventDefault(); \$(this).closest("div").remove();
                   1455:     })
                   1456: });
                   1457: 
                   1458: 
                   1459: END
                   1460: }
                   1461: 
1.561     damieng  1462: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1463: sub done_proctor_js {
                   1464:     return <<"END";
                   1465: function toggleSecret(form,radio,key) {
                   1466:     var radios = form[radio+key];
                   1467:     if (radios.length) {
                   1468:         for (var i=0; i<radios.length; i++) {
                   1469:             if (radios[i].checked) {
                   1470:                 if (radios[i].value == '_done_proctor') {
                   1471:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1472:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1473:                     }
                   1474:                 } else {
                   1475:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1476:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1477:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1478:                     }
                   1479:                 }
                   1480:             }
                   1481:         }
                   1482:     }
                   1483: }
                   1484: END
                   1485: 
                   1486: }
                   1487: 
1.588     raeburn  1488: # Javascript function toggle
                   1489: sub deeplink_js {
                   1490:     return <<"END";
                   1491: function toggleDeepLink(form,item,key) {
                   1492:     var radios = form['deeplink_'+item+'_'+key];
                   1493:     if (radios.length) {
                   1494:         var keybox;
                   1495:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1496:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1497:         }
1.601     raeburn  1498:         var divoptions = new Array();
                   1499:         if (item == 'protect') {
                   1500:             divoptions = ['ltic','ltid'];
1.597     raeburn  1501:         } else {
                   1502:             if (item == 'menus') {
1.601     raeburn  1503:                 divoptions = ['colls'];
1.597     raeburn  1504:             }
                   1505:         }
1.601     raeburn  1506:         var seldivs = new Array();
                   1507:         if ((item == 'protect') || (item == 'menus')) {
                   1508:             for (var i=0; i<divoptions.length; i++) {
                   1509:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1510:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1511:                 } else {
                   1512:                     seldivs[i] = '';
                   1513:                 }
                   1514:             }
1.588     raeburn  1515:         }
                   1516:         for (var i=0; i<radios.length; i++) {
                   1517:             if (radios[i].checked) {
1.601     raeburn  1518:                 if ((item == 'protect') || (item == 'menus')) {
                   1519:                     for (var j=0; j<seldivs.length; j++) {
                   1520:                         if (radios[i].value == divoptions[j]) {
                   1521:                             if (seldivs[j] != '') {
                   1522:                                 seldivs[j].style.display = 'inline-block';
                   1523:                             }
                   1524:                             if (item == 'protect') {
                   1525:                                 keybox.type = 'hidden';
                   1526:                                 keybox.value = '';
                   1527:                             }
                   1528:                         } else {
                   1529:                             if (seldivs[j] != '') {
                   1530:                                 seldivs[j].style.display = 'none';
                   1531:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1532:                             }
                   1533:                         }
1.597     raeburn  1534:                     }
1.601     raeburn  1535:                     if (item == 'protect') {
1.597     raeburn  1536:                         if (radios[i].value == 'key') {
                   1537:                             keybox.type = 'text';
                   1538:                         } else {
                   1539:                             keybox.type = 'hidden';
                   1540:                         }
1.588     raeburn  1541:                     }
                   1542:                 }
                   1543:             }
                   1544:         }
                   1545:     }
                   1546: }
                   1547: END
                   1548: 
                   1549: }
                   1550: 
1.561     damieng  1551: # Prints HTML page start for table mode.
                   1552: # @param {Apache2::RequestRec} $r - the Apache request
                   1553: # @param {string} $psymb - resource symb
                   1554: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1555: sub startpage {
1.531     raeburn  1556:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1557: 
1.515     raeburn  1558:     my %loaditems = (
                   1559:                       'onload'   => "group_or_section('cgroup')",
                   1560:                     );
                   1561:     if (!$psymb) {
1.523     raeburn  1562:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1563:     }
1.280     albertel 1564: 
1.560     damieng  1565:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1566:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1567:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1568:             text=>"Problem Parameters"});
1.414     droeschl 1569:     } else {
1.560     damieng  1570:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1571:             text=>"Table Mode",
                   1572:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1573:     }
1.523     raeburn  1574:     my $js = &page_js().'
                   1575: <script type="text/javascript">
                   1576: // <![CDATA[
                   1577: '.
                   1578:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1579: // ]]>
                   1580: </script>
                   1581: ';
1.446     bisitz   1582:     my $start_page =
1.523     raeburn  1583:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1584:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1585:     my $breadcrumbs =
1.473     amueller 1586:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1587:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1588:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1589:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1590:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1591:     $r->print(<<ENDHEAD);
1.193     albertel 1592: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1593: <input type="hidden" value="" name="pres_value" />
                   1594: <input type="hidden" value="" name="pres_type" />
                   1595: <input type="hidden" value="" name="pres_marker" />
                   1596: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1597: <input type="hidden" value="$escfilter" name="filter" />
                   1598: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1599: ENDHEAD
                   1600: }
                   1601: 
1.209     www      1602: 
1.561     damieng  1603: # Prints a row for table mode (except for the tr start).
                   1604: # Every time a hash reference is passed, a single entry is used, so print_row
                   1605: # could just use these values, but why make it simple when it can be complicated ?
                   1606: #
                   1607: # @param {Apache2::RequestRec} $r - the Apache request
                   1608: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1609: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1610: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1611: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1612: # @param {string} $rid - resource id
                   1613: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1614: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1615: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1616: # @param {string} $defbgone - user level and other levels background color
                   1617: # @param {string} $defbgtwo - section level background color, also used for part number
                   1618: # @param {string} $defbgthree - group level background color
                   1619: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1620: # @param {string} $uname - user name
                   1621: # @param {string} $udom - user domain
                   1622: # @param {string} $csec - section name
                   1623: # @param {string} $cgroup - group name
                   1624: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1625: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1626: # @param {boolean} $readonly - true if no editing allowed.
                   1627: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1628: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1629: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1630: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1631: sub print_row {
1.201     www      1632:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1633:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1634:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1635:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1636:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1637:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1638:     my $numlinks = 0;
1.553     raeburn  1639: 
1.560     damieng  1640:     # get the values for the parameter in cascading order
                   1641:     # empty levels will remain empty
1.44      albertel 1642:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1643:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1644:     # get the type for the parameters
                   1645:     # problem: these may not be set for all levels
1.66      www      1646:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1647:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1648:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1649:     # cascade down manually
1.182     albertel 1650:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1651:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1652:         if ($typeoutpar[$i]) {
1.66      www      1653:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1654:         } else {
1.66      www      1655:             $typeoutpar[$i]=$cascadetype;
                   1656:         }
                   1657:     }
1.57      albertel 1658:     my $parm=$$display{$which};
                   1659: 
1.203     www      1660:     if ($parmlev eq 'full') {
1.419     bisitz   1661:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1662:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1663:     } else {
1.57      albertel 1664:         $parm=~s|\[.*\]\s||g;
                   1665:     }
1.231     www      1666:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1667:     if ($automatic) {
1.560     damieng  1668:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1669:     }
1.427     bisitz   1670:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1671: 
1.44      albertel 1672:     my $thismarker=$which;
                   1673:     $thismarker=~s/^parameter\_//;
                   1674:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1675:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1676:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1677:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1678:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1679:         if ($result eq '') {
                   1680:             $recurse_check = 1;
                   1681:         } elsif (($uname ne '') && ($result > 3)) {
                   1682:             $recurse_check = 1;
                   1683:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1684:             $recurse_check = 1;
                   1685:         } elsif (($csec ne '') && ($result > 11)) {
                   1686:             $recurse_check = 1;
                   1687:         } elsif ($result > 17) {
                   1688:             $recurse_check = 1;
                   1689:         }
                   1690:         if ($recurse_check) {
                   1691:             my $what = $$part{$which}.'.'.$$name{$which};
                   1692:             my $prefix;
                   1693:             if (($uname ne '') && ($udom ne '')) {
                   1694:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1695:                 $prefix = $env{'request.course.id'};
                   1696:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1697:                 if (ref($recursinfo) eq 'ARRAY') {
                   1698:                     $effparm_rec = 1;
                   1699:                     $effparm_level = &mt('user: [_1]',$uname);
                   1700:                 }
                   1701:             }
                   1702:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1703:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1704:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1705:                 if (ref($recursinfo) eq 'ARRAY') {
                   1706:                     $effparm_rec = 1;
                   1707:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1708:                 }
                   1709:             }
                   1710:             if (($csec ne '') && (!$effparm_rec)) {
                   1711:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1712:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1713:                 if (ref($recursinfo) eq 'ARRAY') {
                   1714:                     $effparm_rec = 1;
                   1715:                     $effparm_level = &mt('section: [_1]',$csec);
                   1716:                 }
                   1717:             }
                   1718:             if (!$effparm_rec) {
                   1719:                 $prefix = $env{'request.course.id'};
                   1720:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1721:                 if (ref($recursinfo) eq 'ARRAY') {
                   1722:                     $effparm_rec = 1;
                   1723:                 }
                   1724:             }
                   1725:         }
                   1726:     }
                   1727:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1728:         $effparm_rec = 1;
                   1729:     }
                   1730:     if ((!$effparm_rec) && 
                   1731:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1732:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1733:         $effparm_rec = 1;
                   1734:     }
1.588     raeburn  1735:     if ($parmname eq 'deeplink') {
1.601     raeburn  1736:         my ($domltistr,$crsltistr);
1.588     raeburn  1737:         my %lti =
                   1738:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
                   1739:                                             'provider');
1.601     raeburn  1740:         if (keys(%lti)) {
                   1741:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
                   1742:                 if (ref($lti{$item}) eq 'HASH') {
                   1743:                     unless ($lti{$item}{'requser'}) {
                   1744:                         $domltistr .= $item.':'.&escape(&escape($lti{$item}{'consumer'})).',';
                   1745:                     }
1.588     raeburn  1746:                 }
                   1747:             }
1.601     raeburn  1748:             $domltistr =~ s/,$//;
                   1749:             if ($domltistr) {
                   1750:                 $extra = 'ltid_'.$domltistr;
                   1751:             }
1.588     raeburn  1752:         }
1.601     raeburn  1753:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1754:         if (keys(%courselti)) {
                   1755:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1756:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1757:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1758:                 }
                   1759:             }
                   1760:             $crsltistr =~ s/,$//;
                   1761:             if ($crsltistr) {
                   1762:                 if ($extra) {
                   1763:                     $extra .= '&';
                   1764:                 }
                   1765:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1766:             }
                   1767:         }
1.597     raeburn  1768:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1769:             my @colls;
                   1770:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1771:                 my ($num,$value) = split(/\%/,$item);
                   1772:                 if ($num =~ /^\d+$/) {
                   1773:                     push(@colls,$num);
                   1774:                 }
                   1775:             }
                   1776:             if (@colls) {
                   1777:                 if ($extra) {
                   1778:                     $extra .= '&';
                   1779:                 }
                   1780:                 $extra .= 'menus_'.join(',',@colls);
                   1781:             }
                   1782:         }
1.588     raeburn  1783:     }
1.57      albertel 1784:     if ($parmlev eq 'general') {
                   1785:         if ($uname) {
1.588     raeburn  1786:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1787:         } elsif ($cgroup) {
1.588     raeburn  1788:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1789:         } elsif ($csec) {
1.588     raeburn  1790:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1791:         } else {
1.588     raeburn  1792:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1793:         }
                   1794:     } elsif ($parmlev eq 'map') {
                   1795:         if ($uname) {
1.588     raeburn  1796:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1797:         } elsif ($cgroup) {
1.588     raeburn  1798:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1799:         } elsif ($csec) {
1.588     raeburn  1800:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1801:         } else {
1.588     raeburn  1802:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1803:         }
                   1804:     } else {
1.275     raeburn  1805:         if ($uname) {
                   1806:             if (@{$usersgroups} > 1) {
1.582     raeburn  1807:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1808:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1809:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1810:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1811:                     if (defined($controlgrp)) {
                   1812:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1813:                             $eff_groupparm = $grp_parm;
                   1814:                             undef($result);
                   1815:                             undef($effparm_rec);
                   1816:                             if ($grp_is_rec) {
                   1817:                                  $effparm_rec = 1;
                   1818:                             }
1.275     raeburn  1819:                         }
                   1820:                     }
                   1821:                 }
                   1822:             }
                   1823:         }
1.57      albertel 1824: 
1.588     raeburn  1825:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1826:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1827:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1828:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1829:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1830: 
                   1831:         if ($csec) {
1.588     raeburn  1832:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1833:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1834:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1835:         }
1.269     raeburn  1836: 
                   1837:         if ($cgroup) {
1.588     raeburn  1838:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1839:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1840:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1841:         }
1.446     bisitz   1842: 
1.548     raeburn  1843:         if ($uname) {
1.275     raeburn  1844:             if ($othergrp) {
                   1845:                 $r->print($othergrp);
                   1846:             }
1.588     raeburn  1847:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1848:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1849:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1850:         }
1.57      albertel 1851:     } # end of $parmlev if/else
1.582     raeburn  1852:     if (ref($recursinfo) eq 'ARRAY') {
                   1853:         my $rectitle = &mt('recursive');
                   1854:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1855:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1856:                 $rectitle = &mt('set in: [_1]','"'.
                   1857:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1858:                                                               "'$parmname','$$part{$which}'".');">'.
                   1859:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1860:               
                   1861:                 $numlinks ++;
                   1862:             }
                   1863:         }
                   1864:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1865:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1866:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1867:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1868:                   $effparm_level.'</span></td>');
                   1869:     } else {
                   1870:         if ($result) {
1.593     raeburn  1871:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1872:         }
                   1873:         if ($eff_groupparm) {
                   1874:             $effective_parm = $eff_groupparm;
                   1875:         }
                   1876:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1877:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1878:                                 '</span>':'').'</td>');
                   1879:     }
1.203     www      1880:     if ($parmlev eq 'full') {
1.136     albertel 1881:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1882:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1883:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1884:         if (!defined($sessionvaltype)) {
                   1885:             $sessionvaltype=$$defaulttype{$which};
                   1886:         }
1.419     bisitz   1887:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1888:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1889:                   '</font></td>');
1.136     albertel 1890:     }
1.44      albertel 1891:     $r->print('</tr>');
1.57      albertel 1892:     $r->print("\n");
1.582     raeburn  1893:     if (($numlinks) && (ref($reclinks))) {
                   1894:         $$reclinks = $numlinks;
                   1895:     }
1.44      albertel 1896: }
1.59      matthew  1897: 
1.561     damieng  1898: # Prints a cell for table mode.
                   1899: #
                   1900: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1901: # Also, it would make more sense to pass the display for this cell rather
                   1902: # than the full display hash and the key to use.
                   1903: #
                   1904: # @param {Apache2::RequestRec} $r - the Apache request
                   1905: # @param {integer} $which - level
                   1906: # @param {string} $defbg - cell background color
                   1907: # @param {integer} $result - the most specific level that is defined for that parameter
                   1908: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1909: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1910: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1911: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1912: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1913: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1914: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1915: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1916: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1917: sub print_td {
1.578     raeburn  1918:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  1919:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  1920:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   1921:     $ineffect = 0;
                   1922:     $currval = $$outpar[$which];
                   1923:     $currtype = $$typeoutpar[$which];
                   1924:     $currlevel = $which;
                   1925:     if (($result) && ($result == $which)) {
                   1926:         $ineffect = 1;
                   1927:     } 
                   1928:     if ($ismaplevel) {
                   1929:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   1930:             if (($result) && ($result == $which)) {
                   1931:                 $recursive = 1;
                   1932:             }
                   1933:         } elsif ($$outpar[$which+1] ne '') {
                   1934:             $recursive = 1;
                   1935:             $currlevel = $which+1;
                   1936:             $currval = $$outpar[$currlevel];
                   1937:             $currtype = $$typeoutpar[$currlevel];
                   1938:             if (($result) && ($result == $currlevel)) {
                   1939:                 $ineffect = 1;
                   1940:             }
                   1941:         }
                   1942:     }
                   1943:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   1944:               ';" align="center">');
1.437     raeburn  1945:     my $nolink = 0;
1.568     raeburn  1946:     if ($readonly) {
1.552     raeburn  1947:         $nolink = 1;
1.568     raeburn  1948:     } else { 
1.578     raeburn  1949:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  1950:             $nolink = 1;
1.568     raeburn  1951:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1952:             $nolink = 1;
1.568     raeburn  1953:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1954:             if ($noeditgrp) {
                   1955:                 $nolink = 1;
                   1956:             }
                   1957:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  1958:             $nolink = 1;
1.568     raeburn  1959:         } elsif ($mprefix =~ /examcode\&$/) {
                   1960:             unless ($which == 2) {
                   1961:                 $nolink = 1;
                   1962:             }
1.533     raeburn  1963:         }
1.437     raeburn  1964:     }
                   1965:     if ($nolink) {
1.577     raeburn  1966:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  1967:         $r->print(&valout($currval,$currtype));
1.114     www      1968:     } else {
1.578     raeburn  1969:         $r->print(&plink($currtype,
                   1970:                          $$display{$value},$currval,
1.588     raeburn  1971:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   1972:                          $extra));
1.114     www      1973:     }
                   1974:     $r->print('</td>'."\n");
1.57      albertel 1975: }
                   1976: 
1.561     damieng  1977: # Returns HTML and other info for the cell added when a user is selected
                   1978: # and that user is in several groups. This is the cell with the title "Control by other group".
                   1979: #
                   1980: # @param {string} $what - parameter part.'.'.parameter name
                   1981: # @param {string} $rid - resource id
                   1982: # @param {string} $cgroup - group name
                   1983: # @param {string} $defbg - cell background color
                   1984: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1985: # @param {integer} $result - level
                   1986: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  1987: # @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  1988: sub check_other_groups {
                   1989:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  1990:     my $courseid = $env{'request.course.id'};
                   1991:     my $output;
                   1992:     my $symb = &symbcache($rid);
                   1993:     my $symbparm=$symb.'.'.$what;
                   1994:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  1995:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  1996:     my $mapparm=$map.'___(all).'.$what;
                   1997:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  1998:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   1999:                               $recurseparm,$what,$courseopt);
1.275     raeburn  2000:     my $bgcolor = $defbg;
1.582     raeburn  2001:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2002:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2003:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2004:         if ($result > 3) {
1.419     bisitz   2005:             $bgcolor = '#AAFFAA';
1.275     raeburn  2006:         }
1.593     raeburn  2007:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2008:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2009:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2010:             if ($resultlevel eq 'recursive') {
                   2011:                 $resultlevel = 'map/folder';
                   2012:                 $grp_is_rec = 1;
                   2013:             }
                   2014:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2015:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2016:              
1.275     raeburn  2017:         } else {
                   2018:             $output .= '&nbsp;';
                   2019:         }
                   2020:         $output .= '</td>';
                   2021:     } else {
1.419     bisitz   2022:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2023:     }
1.582     raeburn  2024:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2025: }
                   2026: 
1.561     damieng  2027: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2028: # Used by check_other_groups.
1.561     damieng  2029: #
                   2030: # @param {string} $courseid - the course id
                   2031: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2032: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2033: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2034: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2035: # @param {string} $what - parameter part.'.'.parameter name
                   2036: # @param {hash reference} $courseopt - course parameters hash
                   2037: # @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  2038: sub parm_control_group {
1.556     raeburn  2039:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2040:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2041:     my $grpfound = 0;
1.556     raeburn  2042:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2043:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2044:     foreach my $group (@{$usersgroups}) {
                   2045:         if ($grpfound) { last; }
                   2046:         for (my $i=0; $i<@levels; $i++) {
                   2047:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2048:             if (defined($$courseopt{$item})) {
                   2049:                 $coursereply = $$courseopt{$item};
                   2050:                 $resultitem = $item;
                   2051:                 $resultgroup = $group;
                   2052:                 $resultlevel = $levelnames[$i];
                   2053:                 $resulttype = $$courseopt{$item.'.type'};
                   2054:                 $grpfound = 1;
                   2055:                 last;
                   2056:             }
                   2057:         }
                   2058:     }
                   2059:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2060: }
1.201     www      2061: 
1.63      bowersj2 2062: 
                   2063: 
1.562     damieng  2064: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2065: # All the parameters are references and are filled by the sub.
                   2066: #
1.566     damieng  2067: # @param {array reference} $ids - resource and map ids
                   2068: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2069: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2070: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2071: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2072: # @param {hash reference} $allmaps - hash map pc -> map src
                   2073: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2074: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2075: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2076: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2077: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2078: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.63      bowersj2 2079: sub extractResourceInformation {
                   2080:     my $ids = shift;
                   2081:     my $typep = shift;
                   2082:     my $keyp = shift;
                   2083:     my $allparms = shift;
                   2084:     my $allparts = shift;
                   2085:     my $allmaps = shift;
                   2086:     my $mapp = shift;
                   2087:     my $symbp = shift;
1.82      www      2088:     my $maptitles=shift;
1.196     www      2089:     my $uris=shift;
1.210     www      2090:     my $keyorder=shift;
1.211     www      2091:     my $defkeytype=shift;
1.603   ! raeburn  2092:     my $pssymb=shift;
1.196     www      2093: 
1.210     www      2094:     my $keyordercnt=100;
1.63      bowersj2 2095: 
1.196     www      2096:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603   ! raeburn  2097:     return unless(ref($navmap));
        !          2098:     my @allres;
        !          2099:     if ($pssymb ne '') {
        !          2100:         my $res = $navmap->getBySymb($pssymb);
        !          2101:         if (ref($res)) {
        !          2102:             @allres = ($res);
        !          2103:         }
        !          2104:     }
        !          2105:     if (!@allres) { 
        !          2106:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
        !          2107:     }
1.196     www      2108:     foreach my $resource (@allres) {
1.480     amueller 2109:         my $id=$resource->id();
1.196     www      2110:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2111:         if ($mapid eq '0') { next; }
                   2112:         $$ids[$#$ids+1]=$id;
                   2113:         my $srcf=$resource->src();
                   2114:         $srcf=~/\.(\w+)$/;
                   2115:         $$typep{$id}=$1;
1.584     raeburn  2116:         my $toolsymb;
                   2117:         if ($srcf =~ /ext\.tool$/) {
                   2118:             $toolsymb = $resource->symb();
                   2119:         }
1.480     amueller 2120:         $$keyp{$id}='';
1.196     www      2121:         $$uris{$id}=$srcf;
1.512     foxr     2122: 
1.584     raeburn  2123:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2124:             next if ($key!~/^parameter_/);
1.363     albertel 2125: 
1.209     www      2126: # Hidden parameters
1.584     raeburn  2127:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2128: #
                   2129: # allparms is a hash of parameter names
                   2130: #
1.584     raeburn  2131:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2132:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2133:                 my ($display,$parmdis);
                   2134:                 $display = &standard_parameter_names($name);
                   2135:                 if ($display eq '') {
1.584     raeburn  2136:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2137:                     $parmdis = $display;
                   2138:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2139:                 } else {
                   2140:                     $parmdis = &mt($display);
                   2141:                 }
                   2142:                 $$allparms{$name}=$parmdis;
                   2143:                 if (ref($defkeytype)) {
                   2144:                     $$defkeytype{$name}=
1.584     raeburn  2145:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2146:                 }
                   2147:             }
1.363     albertel 2148: 
1.209     www      2149: #
                   2150: # allparts is a hash of all parts
                   2151: #
1.584     raeburn  2152:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2153:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2154: #
                   2155: # Remember all keys going with this resource
                   2156: #
1.480     amueller 2157:             if ($$keyp{$id}) {
                   2158:                 $$keyp{$id}.=','.$key;
                   2159:             } else {
                   2160:                 $$keyp{$id}=$key;
                   2161:             }   
1.210     www      2162: #
                   2163: # Put in order
1.446     bisitz   2164: #
1.480     amueller 2165:             unless ($$keyorder{$key}) {
                   2166:                 $$keyorder{$key}=$keyordercnt;
                   2167:                 $keyordercnt++;
                   2168:             }
1.473     amueller 2169:         }
                   2170: 
                   2171: 
1.480     amueller 2172:         if (!exists($$mapp{$mapid})) {
                   2173:             $$mapp{$id}=
                   2174:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2175:             $$mapp{$mapid}=$$mapp{$id};
                   2176:             $$allmaps{$mapid}=$$mapp{$id};
                   2177:             if ($mapid eq '1') {
1.532     raeburn  2178:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2179:             } else {
                   2180:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2181:             }
                   2182:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2183:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2184:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2185:                                                      # are commented out in rev. 1.57
1.473     amueller 2186:         } else {
1.480     amueller 2187:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2188:         }
1.480     amueller 2189:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2190:     }
                   2191: }
                   2192: 
1.582     raeburn  2193: sub get_recursive {
                   2194:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2195:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2196:         foreach my $item (@{$recurseup}) {
                   2197:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2198:             if (defined($resdata->{$norecursechk})) {
                   2199:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2200:                     my $type = $resdata->{$norecursechk.'.type'};
                   2201:                     return [$resdata->{$norecursechk},$type,$item];
                   2202:                 } else {
                   2203:                     last;
                   2204:                 }
                   2205:             }
                   2206:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2207:             if (defined($resdata->{$recursechk})) {
                   2208:                 my $type = $resdata->{$recursechk.'.type'};
                   2209:                 return [$resdata->{$recursechk},$type,$item];
                   2210:             }
                   2211:         }
                   2212:     }
                   2213:     return;
                   2214: }
                   2215: 
1.208     www      2216: 
1.562     damieng  2217: # Tells if a parameter type is a date.
                   2218: #
                   2219: # @param {string} type - parameter type
                   2220: # @returns{boolean} - true if it is a date
1.213     www      2221: sub isdateparm {
                   2222:     my $type=shift;
                   2223:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2224: }
                   2225: 
1.589     raeburn  2226: # Determine if parameter type is specialized string type (i.e.,
                   2227: # not just string or string_yesno.  
                   2228: 
                   2229: sub is_specialstring {
                   2230:     my $type=shift;
1.603   ! raeburn  2231:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2232: }
                   2233: 
1.562     damieng  2234: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2235: #
1.581     raeburn  2236: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2237: sub parmmenu {
1.581     raeburn  2238:     my ($r)=@_;
1.208     www      2239:     $r->print(<<ENDSCRIPT);
                   2240: <script type="text/javascript">
1.454     bisitz   2241: // <![CDATA[
1.208     www      2242:     function checkall(value, checkName) {
1.453     schualex 2243: 
                   2244:         var li = "_li";
                   2245:         var displayOverview = "";
                   2246:         
                   2247:         if (value == false) {
                   2248:             displayOverview = "none"
                   2249:         }
                   2250: 
1.562     damieng  2251:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2252:             ele = document.forms.parmform.elements[i];
                   2253:             if (ele.name == checkName) {
                   2254:                 document.forms.parmform.elements[i].checked=value;
                   2255:             }
                   2256:         }
                   2257:     }
1.210     www      2258: 
                   2259:     function checkthis(thisvalue, checkName) {
1.562     damieng  2260:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2261:             ele = document.forms.parmform.elements[i];
                   2262:             if (ele.name == checkName) {
1.562     damieng  2263:                 if (ele.value == thisvalue) {
                   2264:                     document.forms.parmform.elements[i].checked=true;
                   2265:                 }
1.210     www      2266:             }
                   2267:         }
                   2268:     }
                   2269: 
                   2270:     function checkdates() {
1.562     damieng  2271:         checkthis('duedate','pscat');
                   2272:         checkthis('opendate','pscat');
                   2273:         checkthis('answerdate','pscat');
1.218     www      2274:     }
                   2275: 
                   2276:     function checkdisset() {
1.562     damieng  2277:         checkthis('discussend','pscat');
                   2278:         checkthis('discusshide','pscat');
                   2279:         checkthis('discussvote','pscat');
1.218     www      2280:     }
                   2281: 
                   2282:     function checkcontdates() {
1.562     damieng  2283:         checkthis('contentopen','pscat');
                   2284:         checkthis('contentclose','pscat');
1.218     www      2285:     }
1.446     bisitz   2286: 
1.210     www      2287:     function checkvisi() {
1.562     damieng  2288:         checkthis('hiddenresource','pscat');
                   2289:         checkthis('encrypturl','pscat');
                   2290:         checkthis('problemstatus','pscat');
                   2291:         checkthis('contentopen','pscat');
                   2292:         checkthis('opendate','pscat');
1.210     www      2293:     }
                   2294: 
                   2295:     function checkparts() {
1.562     damieng  2296:         checkthis('hiddenparts','pscat');
                   2297:         checkthis('display','pscat');
                   2298:         checkthis('ordered','pscat');
1.210     www      2299:     }
                   2300: 
                   2301:     function checkstandard() {
                   2302:         checkall(false,'pscat');
1.562     damieng  2303:         checkdates();
                   2304:         checkthis('weight','pscat');
                   2305:         checkthis('maxtries','pscat');
                   2306:         checkthis('type','pscat');
                   2307:         checkthis('problemstatus','pscat');
1.210     www      2308:     }
                   2309: 
1.454     bisitz   2310: // ]]>
1.208     www      2311: </script>
                   2312: ENDSCRIPT
1.453     schualex 2313: 
1.491     bisitz   2314:     $r->print('<hr />');
1.581     raeburn  2315:     &shortCuts($r);
1.491     bisitz   2316:     $r->print('<hr />');
1.453     schualex 2317: }
1.562     damieng  2318: 
                   2319: # Returns parameter categories.
                   2320: #
                   2321: # @returns {hash} - category name -> title in English
1.465     amueller 2322: sub categories {
                   2323:     return ('time_settings' => 'Time Settings',
                   2324:     'grading' => 'Grading',
                   2325:     'tries' => 'Tries',
                   2326:     'problem_appearance' => 'Problem Appearance',
                   2327:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2328:     'hiding' => 'Hiding',
                   2329:     'high_level_randomization' => 'High Level Randomization',
                   2330:     'slots' => 'Slots',
                   2331:     'file_submission' => 'File Submission',
                   2332:     'misc' => 'Miscellaneous' ); 
                   2333: }
                   2334: 
1.562     damieng  2335: # Returns the category for each parameter.
                   2336: #
                   2337: # @returns {hash} - parameter name -> category name
1.465     amueller 2338: sub lookUpTableParameter {
                   2339:  
                   2340:     return ( 
                   2341:         'opendate' => 'time_settings',
                   2342:         'duedate' => 'time_settings',
                   2343:         'answerdate' => 'time_settings',
                   2344:         'interval' => 'time_settings',
                   2345:         'contentopen' => 'time_settings',
                   2346:         'contentclose' => 'time_settings',
                   2347:         'discussend' => 'time_settings',
1.560     damieng  2348:         'printstartdate' => 'time_settings',
                   2349:         'printenddate' => 'time_settings',
1.465     amueller 2350:         'weight' => 'grading',
                   2351:         'handgrade' => 'grading',
                   2352:         'maxtries' => 'tries',
                   2353:         'hinttries' => 'tries',
1.503     raeburn  2354:         'randomizeontries' => 'tries',
1.465     amueller 2355:         'type' => 'problem_appearance',
                   2356:         'problemstatus' => 'problem_appearance',
                   2357:         'display' => 'problem_appearance',
                   2358:         'ordered' => 'problem_appearance',
                   2359:         'numbubbles' => 'problem_appearance',
                   2360:         'tol' => 'behaviour_of_input_fields',
                   2361:         'sig' => 'behaviour_of_input_fields',
                   2362:         'turnoffunit' => 'behaviour_of_input_fields',
                   2363:         'hiddenresource' => 'hiding',
                   2364:         'hiddenparts' => 'hiding',
                   2365:         'discusshide' => 'hiding',
                   2366:         'buttonshide' => 'hiding',
                   2367:         'turnoffeditor' => 'hiding',
                   2368:         'encrypturl' => 'hiding',
1.587     raeburn  2369:         'deeplink' => 'hiding',
1.465     amueller 2370:         'randomorder' => 'high_level_randomization',
                   2371:         'randompick' => 'high_level_randomization',
                   2372:         'available' => 'slots',
                   2373:         'useslots' => 'slots',
                   2374:         'availablestudent' => 'slots',
                   2375:         'uploadedfiletypes' => 'file_submission',
                   2376:         'maxfilesize' => 'file_submission',
                   2377:         'cssfile' => 'misc',
                   2378:         'mapalias' => 'misc',
                   2379:         'acc' => 'misc',
                   2380:         'maxcollaborators' => 'misc',
                   2381:         'scoreformat' => 'misc',
1.514     raeburn  2382:         'lenient' => 'grading',
1.519     raeburn  2383:         'retrypartial' => 'tries',
1.521     raeburn  2384:         'discussvote'  => 'misc',
1.584     raeburn  2385:         'examcode' => 'high_level_randomization',
1.575     raeburn  2386:     );
1.465     amueller 2387: }
                   2388: 
1.562     damieng  2389: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2390: #
                   2391: # @param {string} $name - parameter name
                   2392: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2393: sub whatIsMyCategory {
                   2394:     my $name = shift;
                   2395:     my $catList = shift;
                   2396:     my @list;
                   2397:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2398:     my $cat = $lookUpList{$name};
                   2399:     if (defined($cat)) {
                   2400:         if (!defined($$catList{$cat})){
                   2401:             push @list, ($name);
                   2402:             $$catList{$cat} = \@list;
                   2403:         } else {
                   2404:             push @{${$catList}{$cat}}, ($name);     
                   2405:         }
                   2406:     } else {
                   2407:         if (!defined($$catList{'misc'})){
                   2408:             push @list, ($name);
                   2409:             $$catList{'misc'} = \@list;
                   2410:         } else {
                   2411:             push @{${$catList}{'misc'}}, ($name);     
                   2412:         }
                   2413:     }        
                   2414: }
                   2415: 
1.562     damieng  2416: # Sorts parameter names based on appearance order.
                   2417: #
                   2418: # @param {array reference} name - array reference of parameter names
                   2419: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2420: # @returns {Array} - array of parameter names
1.465     amueller 2421: sub keysindisplayorderCategory {
                   2422:     my ($name,$keyorder)=@_;
                   2423:     return sort {
1.473     amueller 2424:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2425:     } ( @{$name});
                   2426: }
                   2427: 
1.562     damieng  2428: # Returns a hash category name -> order, starting at 1 (integer)
                   2429: #
                   2430: # @returns {hash}
1.467     amueller 2431: sub category_order {
                   2432:     return (
                   2433:         'time_settings' => 1,
                   2434:         'grading' => 2,
                   2435:         'tries' => 3,
                   2436:         'problem_appearance' => 4,
                   2437:         'hiding' => 5,
                   2438:         'behaviour_of_input_fields' => 6,
                   2439:         'high_level_randomization'  => 7,
                   2440:         'slots' => 8,
                   2441:         'file_submission' => 9,
                   2442:         'misc' => 10
                   2443:     );
                   2444: 
                   2445: }
1.453     schualex 2446: 
1.562     damieng  2447: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2448: #
                   2449: # @param {Apache2::RequestRec} $r - the Apache request
                   2450: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2451: # @param {array reference} $pscat - list of selected parameter names
                   2452: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2453: sub parmboxes {
                   2454:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2455:     my %categories = &categories();
1.467     amueller 2456:     my %category_order = &category_order();
1.465     amueller 2457:     my %categoryList = (
                   2458:         'time_settings' => [],
                   2459:         'grading' => [],
                   2460:         'tries' => [],
                   2461:         'problem_appearance' => [],
                   2462:         'behaviour_of_input_fields' => [],
                   2463:         'hiding' => [],
                   2464:         'high_level_randomization' => [],
                   2465:         'slots' => [],
                   2466:         'file_submission' => [],
                   2467:         'misc' => [],
1.489     bisitz   2468:     );
1.510     www      2469: 
1.548     raeburn  2470:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2471:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2472:     }
1.453     schualex 2473:     #part to print the parm-list
1.536     raeburn  2474:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2475:         next if (@{$categoryList{$key}} == 0);
                   2476:         next if ($key eq '');
                   2477:         $r->print('<div class="LC_Box LC_400Box">'
                   2478:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2479:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2480:             next if ($tempkey eq '');
1.536     raeburn  2481:             $r->print('<span class="LC_nobreak">'
                   2482:                      .'<label><input type="checkbox" name="pscat" '
                   2483:                      .'value="'.$tempkey.'" ');
                   2484:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2485:                 $r->print( ' checked="checked"');
                   2486:             }
                   2487:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2488:                                                       : $tempkey)
1.536     raeburn  2489:                      .'</label></span><br />'."\n");
1.465     amueller 2490:         }
1.536     raeburn  2491:         $r->print('</div>');
1.465     amueller 2492:     }
1.536     raeburn  2493:     $r->print("\n");
1.453     schualex 2494: }
1.562     damieng  2495: 
                   2496: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2497: #
1.562     damieng  2498: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2499: sub shortCuts {
1.581     raeburn  2500:     my ($r)=@_;
1.453     schualex 2501: 
1.491     bisitz   2502:     # Parameter Selection
                   2503:     $r->print(
                   2504:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2505:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2506:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2507:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2508:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2509:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2510:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2511:        .&Apache::lonhtmlcommon::end_funclist()
                   2512:     );
                   2513: 
                   2514:     # Add Selection for...
                   2515:     $r->print(
                   2516:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2517:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2518:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2519:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2520:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2521:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2522:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2523:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2524:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2525:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2526:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2527:        .&Apache::lonhtmlcommon::end_funclist()
                   2528:     );
1.208     www      2529: }
                   2530: 
1.562     damieng  2531: # Prints HTML to select parts to view (except for the title).
                   2532: # Used by table and overview modes.
                   2533: #
                   2534: # @param {Apache2::RequestRec} $r - the Apache request
                   2535: # @param {hash reference} $allparts - hash parameter part -> part title
                   2536: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2537: sub partmenu {
1.446     bisitz   2538:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2539:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2540:     if ($selsize > 8) {
                   2541:         $selsize = 8;
                   2542:     }
1.446     bisitz   2543: 
1.523     raeburn  2544:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2545:     $r->print('<option value="all"');
1.562     damieng  2546:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2547:     $r->print('>'.&mt('All Parts').'</option>');
                   2548:     my %temphash=();
                   2549:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2550:     foreach my $tempkey (sort {
1.560     damieng  2551:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2552:             } keys(%{$allparts})) {
                   2553:         unless ($tempkey =~ /\./) {
                   2554:             $r->print('<option value="'.$tempkey.'"');
                   2555:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2556:                 $r->print(' selected="selected"');
                   2557:             }
                   2558:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2559:         }
1.208     www      2560:     }
1.446     bisitz   2561:     $r->print('</select>');
1.209     www      2562: }
                   2563: 
1.562     damieng  2564: # Prints HTML to select a user and/or a group.
                   2565: # Used by table mode.
                   2566: #
                   2567: # @param {Apache2::RequestRec} $r - the Apache request
                   2568: # @param {string} $uname - selected user name
                   2569: # @param {string} $id - selected Student/Employee ID
                   2570: # @param {string} $udom - selected user domain
                   2571: # @param {string} $csec - selected section name
                   2572: # @param {string} $cgroup - selected group name
                   2573: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2574: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2575: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2576: sub usermenu {
1.553     raeburn  2577:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2578:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2579:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2580:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2581: function setCourseadv(form,caller) {
                   2582:     if (caller.value == 'st') {
                   2583:         form.courseadv.value = 'none';
                   2584:     } else {
                   2585:         form.courseadv.value = '';
                   2586:     }
                   2587:     return;
                   2588: }
                   2589: ENDJS
1.412     bisitz   2590: 
1.596     raeburn  2591:     my (%chkroles,$stuonly,$courseadv);
                   2592:     if ($env{'form.userroles'} eq 'any') {
                   2593:         $chkroles{'any'} = ' checked="checked"';
                   2594:     } else {
                   2595:         $chkroles{'st'} = ' checked="checked"';
                   2596:         $courseadv = 'none';
                   2597:     }
                   2598:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2599:     if ($crstype eq 'Community') {
                   2600:         $stuonly = &mt('member only');
                   2601:     } else {
                   2602:         $stuonly = &mt('student only');
                   2603:     }
                   2604:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2605:                   &mt("User's role").':&nbsp;'.
                   2606:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2607:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2608:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2609:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2610:     my $sections='';
1.300     albertel 2611:     my %sectionhash = &Apache::loncommon::get_sections();
                   2612: 
1.269     raeburn  2613:     my $groups;
1.553     raeburn  2614:     my %grouphash;
                   2615:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2616:         %grouphash = &Apache::longroup::coursegroups();
                   2617:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2618:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2619:     }
1.299     albertel 2620: 
1.412     bisitz   2621:     my $g_s_header='';
                   2622:     my $g_s_footer='';
1.446     bisitz   2623: 
1.552     raeburn  2624:     my $currsec = $env{'request.course.sec'};
                   2625:     if ($currsec) {
                   2626:         $sections=&mt('Section:').' '.$currsec;
                   2627:         if (%grouphash) {
                   2628:             $sections .= ';'.('&nbsp;' x2);
                   2629:         }
                   2630:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2631:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2632:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2633:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2634:         }
                   2635:         $sections .= '>';
1.548     raeburn  2636:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2637:         $sections.='<option value="'.$section.'" '.
                   2638:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2639:                                                               '</option>';
1.209     www      2640:         }
                   2641:         $sections.='</select>';
1.269     raeburn  2642:     }
1.412     bisitz   2643: 
1.552     raeburn  2644:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2645:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2646:         $sections .= qq|
                   2647: <script type="text/javascript">
1.454     bisitz   2648: // <![CDATA[
1.269     raeburn  2649: function group_or_section(caller) {
                   2650:    if (caller == "cgroup") {
                   2651:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2652:            document.parmform.csec.selectedIndex = 0;
                   2653:        }
                   2654:    } else {
                   2655:        if (document.parmform.csec.selectedIndex != 0) {
                   2656:            document.parmform.cgroup.selectedIndex = 0;
                   2657:        }
                   2658:    }
                   2659: }
1.454     bisitz   2660: // ]]>
1.269     raeburn  2661: </script>
                   2662: |;
1.554     raeburn  2663:     } else {
1.269     raeburn  2664:         $sections .= qq|
                   2665: <script type="text/javascript">
1.454     bisitz   2666: // <![CDATA[
1.269     raeburn  2667: function group_or_section(caller) {
                   2668:     return;
                   2669: }
1.454     bisitz   2670: // ]]>
1.269     raeburn  2671: </script>
                   2672: |;
1.446     bisitz   2673:     }
1.299     albertel 2674: 
                   2675:     if (%grouphash) {
1.597     raeburn  2676:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2677:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2678:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2679:         }
                   2680:         $groups .= '>';
1.548     raeburn  2681:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2682:             $groups.='<option value="'.$grp.'" ';
                   2683:             if ($grp eq $cgroup) {
                   2684:                 unless ((defined($uname)) && ($grp eq '')) {
                   2685:                     $groups .=  'selected="selected" ';
                   2686:                 }
                   2687:             } elsif (!defined($cgroup)) {
                   2688:                 if (@{$usersgroups} == 1) {
                   2689:                     if ($grp eq $$usersgroups[0]) {
                   2690:                         $groups .=  'selected="selected" ';
                   2691:                     }
                   2692:                 }
                   2693:             }
                   2694:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2695:         }
                   2696:         $groups.='</select>';
                   2697:     }
1.412     bisitz   2698: 
1.445     neumanie 2699:     if (%sectionhash || %grouphash) {
1.446     bisitz   2700:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2701:         $r->print($sections.$groups);
1.448     bisitz   2702:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2703:     } else {
                   2704:         $r->print($sections); 
1.445     neumanie 2705:     }
1.446     bisitz   2706: 
                   2707:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2708:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2709:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2710:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2711:                  ,$chooseopt));
1.209     www      2712: }
                   2713: 
1.562     damieng  2714: # Prints HTML to select parameters from a list of all parameters.
                   2715: # Uses parmmenu and parmboxes.
                   2716: # Used by table and overview modes.
1.468     amueller 2717: #
1.562     damieng  2718: # @param {Apache2::RequestRec} $r - the Apache request
                   2719: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2720: # @param {array reference} $pscat - list of selected parameter names
                   2721: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2722: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2723: sub displaymenu {
1.581     raeburn  2724:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2725: 
1.445     neumanie 2726:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2727:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2728: 
1.581     raeburn  2729:     &parmmenu($r);
1.536     raeburn  2730:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2731:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2732:     $r->print(&Apache::loncommon::end_scrollbox());
                   2733: 
                   2734:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2735:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2736:  
1.209     www      2737: }
                   2738: 
1.562     damieng  2739: # Prints HTML to select a map.
                   2740: # Used by table mode and overview mode.
                   2741: #
                   2742: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2743: # @param {hash reference} $allmaps - hash map pc -> map src
                   2744: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2745: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2746: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445     neumanie 2747: sub mapmenu {
1.499     raeburn  2748:     my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468     amueller 2749:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2750:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2751:     my $tree=[];
                   2752:     my $treeinfo={};
                   2753:     if (defined($navmap)) {
1.499     raeburn  2754:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2755:         my $curRes;
                   2756:         my $depth = 0;
1.468     amueller 2757:         my %parent = ();
                   2758:         my $startcount = 5;
                   2759:         my $lastcontainer = $startcount;
                   2760: # preparing what is to show ...
1.461     neumanie 2761:         while ($curRes = $it->next()) {
                   2762:             if ($curRes == $it->BEGIN_MAP()) {
                   2763:                 $depth++;
1.468     amueller 2764:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2765:             }
                   2766:             if ($curRes == $it->END_MAP()) {
                   2767:                 $depth--;
1.468     amueller 2768:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2769:             }
                   2770:             if (ref($curRes)) {
1.468     amueller 2771:                 my $symb = $curRes->symb();
                   2772:                 my $ressymb = $symb;
1.461     neumanie 2773:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2774:                     my $type = 'sequence';
                   2775:                     if ($curRes->is_page()) {
                   2776:                         $type = 'page';
                   2777:                     }
                   2778:                     my $id= $curRes->id();
1.468     amueller 2779:                     my $srcf = $curRes->src();
                   2780:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2781:                     if(!exists($treeinfo->{$id})) {
                   2782:                         push(@$tree,$id);
1.473     amueller 2783:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2784:                         $treeinfo->{$id} = {
1.461     neumanie 2785:                                     depth => $depth,
                   2786:                                     type  => $type,
1.468     amueller 2787:                                     name  => $resource_name,
                   2788:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2789:                                     };
1.462     neumanie 2790:                     }
1.461     neumanie 2791:                 }
                   2792:             }
                   2793:         }
1.462     neumanie 2794:     }
1.473     amueller 2795: # Show it ...    
1.484     amueller 2796:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461     neumanie 2797:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2798:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2799:         my $whitespace =
                   2800:             '<img src="'
                   2801:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2802:            .'" alt="" />';
                   2803: 
1.498     bisitz   2804:         # Info about selectable folders/maps
                   2805:         $r->print(
                   2806:             '<div class="LC_info">'
1.508     www      2807:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2808:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2809:            .'</div>'
                   2810:         );
                   2811: 
1.536     raeburn  2812:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2813:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2814: 
1.498     bisitz   2815:         # Display row: "All Maps or Folders"
                   2816:         $r->print(
1.523     raeburn  2817:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2818:            .'<td>'
                   2819:            .'<label>'
                   2820:            .'<input type="radio" name="pschp"'
1.497     bisitz   2821:         );
                   2822:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2823:         $r->print(
                   2824:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2825:            .&mt('All Maps or Folders')
                   2826:            .'</label>'
                   2827:            .'<hr /></td>'
                   2828:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2829:         );
1.497     bisitz   2830: 
1.532     raeburn  2831:         # Display row: "Main Content"
1.468     amueller 2832:         if (exists($$allmaps{1})) {
1.498     bisitz   2833:             $r->print(
                   2834:                 &Apache::loncommon::start_data_table_row()
                   2835:                .'<td>'
                   2836:                .'<label>'
                   2837:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2838:             );
1.497     bisitz   2839:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2840:             $r->print(
                   2841:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2842:                .$$maptitles{1}
                   2843:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2844:                .'</label>'
                   2845:                .'</td>'
                   2846:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2847:             );
                   2848:         }
1.497     bisitz   2849: 
                   2850:         # Display rows for all course maps and folders
1.468     amueller 2851:         foreach my $id (@{$tree}) {
                   2852:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2853:             # Indentation
1.468     amueller 2854:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2855:             my $indent;
                   2856:             for (my $i = 0; $i < $depth; $i++) {
                   2857:                 $indent.= $whitespace;
                   2858:             }
1.461     neumanie 2859:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2860:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2861:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2862:             }
1.468     amueller 2863:             my $symb_name = $$symbp{$id};
                   2864:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2865:             $symb_name = $tail;
1.498     bisitz   2866:             $r->print(
                   2867:                 &Apache::loncommon::start_data_table_row()
                   2868:                .'<td>'
                   2869:                .'<label>'
1.463     bisitz   2870:             );
1.498     bisitz   2871:             # Only offer radio button for folders/maps which can be parameterized
                   2872:             if ($allmaps_inverted{$symb_name}) {
                   2873:                 $r->print(
                   2874:                     '<input type ="radio" name="pschp"'
                   2875:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2876:                 );
                   2877:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2878:                 $r->print('/>');
                   2879:             } else {
                   2880:                 $r->print($whitespace);
1.461     neumanie 2881:             }
1.498     bisitz   2882:             $r->print(
                   2883:                 $indent.$icon.'&nbsp;'
                   2884:                .$treeinfo->{$id}->{name}
                   2885:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2886:                .'</label>'
                   2887:                .'</td>'
                   2888:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2889:             );
1.461     neumanie 2890:         }
1.497     bisitz   2891: 
1.523     raeburn  2892:         $r->print(&Apache::loncommon::end_data_table().
                   2893:                   '<br style="line-height:2px;" />'.
                   2894:                   &Apache::loncommon::end_scrollbox());
1.209     www      2895:     }
                   2896: }
                   2897: 
1.563     damieng  2898: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2899: # Used by table and overview modes.
                   2900: #
                   2901: # @param {Apache2::RequestRec} $r - the Apache request
                   2902: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2903: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2904: sub levelmenu {
1.446     bisitz   2905:     my ($r,$alllevs,$parmlev)=@_;
                   2906: 
1.548     raeburn  2907:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2908:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2909:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2910:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2911:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2912:         if ($parmlev eq $$alllevs{$lev}) {
                   2913:             $r->print(' selected="selected"');
                   2914:         }
                   2915:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2916:     }
1.446     bisitz   2917:     $r->print("</select>");
1.208     www      2918: }
                   2919: 
1.211     www      2920: 
1.563     damieng  2921: # Returns HTML to select a section (with a select HTML element).
                   2922: # Used by overview mode.
                   2923: #
                   2924: # @param {array reference} $selectedsections - list of selected section ids
                   2925: # @returns {string}
1.211     www      2926: sub sectionmenu {
1.553     raeburn  2927:     my ($selectedsections)=@_;
1.300     albertel 2928:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2929:     return '' if (!%sectionhash);
1.300     albertel 2930: 
1.552     raeburn  2931:     my (@possibles,$disabled);
                   2932:     if ($env{'request.course.sec'} ne '') {
                   2933:         @possibles = ($env{'request.course.sec'});
                   2934:         $selectedsections = [$env{'request.course.sec'}];
                   2935:         $disabled = ' disabled="disabled"';
                   2936:     } else {
                   2937:         @possibles = ('all',sort(keys(%sectionhash)));
                   2938:     }
1.553     raeburn  2939:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2940:     foreach my $s (@possibles) {
1.553     raeburn  2941:         $output .= '    <option value="'.$s.'"';
                   2942:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2943:             $output .= ' selected="selected"';
1.473     amueller 2944:         }
1.553     raeburn  2945:         $output .= '>'."$s</option>\n";
1.300     albertel 2946:     }
1.553     raeburn  2947:     $output .= "</select>\n";
                   2948:     return $output;
1.269     raeburn  2949: }
                   2950: 
1.563     damieng  2951: # Returns HTML to select a group (with a select HTML element).
                   2952: # Used by overview mode.
                   2953: #
                   2954: # @param {array reference} $selectedgroups - list of selected group names
                   2955: # @returns {string}
1.269     raeburn  2956: sub groupmenu {
1.553     raeburn  2957:     my ($selectedgroups)=@_;
                   2958:     my %grouphash;
                   2959:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2960:         %grouphash = &Apache::longroup::coursegroups();
                   2961:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2962:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2963:     }
                   2964:     return '' if (!%grouphash);
1.299     albertel 2965: 
1.553     raeburn  2966:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2967:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2968:         $output .= '    <option value="'.$group.'"';
                   2969:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2970:             $output .=  ' selected="selected"';
1.473     amueller 2971:         }
1.553     raeburn  2972:         $output .= '>'."$group</option>\n";
1.211     www      2973:     }
1.553     raeburn  2974:     $output .= "</select>\n";
                   2975:     return $output;
1.211     www      2976: }
                   2977: 
1.563     damieng  2978: # Returns an array with the given parameter split by comma.
                   2979: # Used by assessparms (table mode).
                   2980: #
                   2981: # @param {string} $keyp - the string to split
                   2982: # @returns {Array<string>}
1.210     www      2983: sub keysplit {
                   2984:     my $keyp=shift;
                   2985:     return (split(/\,/,$keyp));
                   2986: }
                   2987: 
1.563     damieng  2988: # Returns the keys in $name, sorted using $keyorder.
                   2989: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   2990: # Used by assessparms (table mode) for resource level.
                   2991: #
                   2992: # @param {hash reference} $name - parameter key -> parameter name
                   2993: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2994: # @returns {Array<string>}
1.210     www      2995: sub keysinorder {
                   2996:     my ($name,$keyorder)=@_;
                   2997:     return sort {
1.560     damieng  2998:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  2999:     } (keys(%{$name}));
1.210     www      3000: }
                   3001: 
1.563     damieng  3002: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3003: # Used by assessparms (table mode) for map and general levels.
                   3004: #
                   3005: # @param {hash reference} $name - parameter key -> parameter name
                   3006: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3007: # @returns {Array<string>}
1.236     albertel 3008: sub keysinorder_bytype {
                   3009:     my ($name,$keyorder)=@_;
                   3010:     return sort {
1.563     damieng  3011:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3012:         my $tb=(split('_',$b))[-1];
                   3013:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3014:             return ($a cmp $b);
                   3015:         }
                   3016:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3017:     } (keys(%{$name}));
1.236     albertel 3018: }
                   3019: 
1.563     damieng  3020: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3021: # Used by defaultsetter (parameter settings default actions).
                   3022: #
                   3023: # @param {hash reference} $name - hash parameter name -> parameter title
                   3024: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3025: # @returns {Array<string>}
1.211     www      3026: sub keysindisplayorder {
                   3027:     my ($name,$keyorder)=@_;
                   3028:     return sort {
1.560     damieng  3029:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3030:     } (keys(%{$name}));
1.211     www      3031: }
                   3032: 
1.563     damieng  3033: # Prints HTML with a choice to sort results by realm or student first.
                   3034: # Used by overview mode.
                   3035: #
                   3036: # @param {Apache2::RequestRec} $r - the Apache request
                   3037: # @param {string} $sortorder - realmstudent|studentrealm
1.214     www      3038: sub sortmenu {
                   3039:     my ($r,$sortorder)=@_;
1.236     albertel 3040:     $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214     www      3041:     if ($sortorder eq 'realmstudent') {
1.422     bisitz   3042:        $r->print(' checked="checked"');
1.214     www      3043:     }
                   3044:     $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236     albertel 3045:     $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214     www      3046:     if ($sortorder eq 'studentrealm') {
1.422     bisitz   3047:        $r->print(' checked="checked"');
1.214     www      3048:     }
1.236     albertel 3049:     $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473     amueller 3050:           '</label>');
1.214     www      3051: }
                   3052: 
1.563     damieng  3053: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3054: #
                   3055: # @returns {hash}
1.211     www      3056: sub standardkeyorder {
                   3057:     return ('parameter_0_opendate' => 1,
1.473     amueller 3058:         'parameter_0_duedate' => 2,
                   3059:         'parameter_0_answerdate' => 3,
                   3060:         'parameter_0_interval' => 4,
                   3061:         'parameter_0_weight' => 5,
                   3062:         'parameter_0_maxtries' => 6,
                   3063:         'parameter_0_hinttries' => 7,
                   3064:         'parameter_0_contentopen' => 8,
                   3065:         'parameter_0_contentclose' => 9,
                   3066:         'parameter_0_type' => 10,
                   3067:         'parameter_0_problemstatus' => 11,
                   3068:         'parameter_0_hiddenresource' => 12,
                   3069:         'parameter_0_hiddenparts' => 13,
                   3070:         'parameter_0_display' => 14,
                   3071:         'parameter_0_ordered' => 15,
                   3072:         'parameter_0_tol' => 16,
                   3073:         'parameter_0_sig' => 17,
                   3074:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3075:         'parameter_0_discussend' => 19,
                   3076:         'parameter_0_discusshide' => 20,
                   3077:         'parameter_0_discussvote' => 21,
1.560     damieng  3078:         'parameter_0_printstartdate'  =>  22,
                   3079:         'parameter_0_printenddate' =>  23);
1.211     www      3080: }
                   3081: 
1.59      matthew  3082: 
1.560     damieng  3083: # Table mode UI.
1.563     damieng  3084: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3085: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3086: #
                   3087: # Parameters used from the request:
                   3088: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3089: # cgroup - selected group
                   3090: # command - 'set': direct access to table mode for a resource
                   3091: # csec - selected section
                   3092: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3093: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3094: # id - student/employee ID
                   3095: # parmlev - selected level (full|map|general)
                   3096: # part - selected part (unused ?)
                   3097: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3098: # pres_type - &&&-separated parameter types
                   3099: # pres_value - &&&-separated parameter values
                   3100: # prevvisit - '1' if the user has submitted the form before
                   3101: # pscat (multiple values) - selected parameter names
1.566     damieng  3102: # pschp - selected map pc, or 'all'
1.563     damieng  3103: # psprt (multiple values) - list of selected parameter parts
                   3104: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3105: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3106: # symb - resource symb (when a single resource is selected)
                   3107: # udom - selected user domain
                   3108: # uname - selected user name
                   3109: # url - used only with command 'set', the resource url
                   3110: #
                   3111: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3112: # @param $parm_permission - ref to hash of permissions
                   3113: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3114: sub assessparms {
1.1       www      3115: 
1.568     raeburn  3116:     my ($r,$parm_permission) = @_;
1.201     www      3117: 
1.512     foxr     3118: 
                   3119: # -------------------------------------------------------- Variable declaration
1.566     damieng  3120:     my @ids=(); # resource and map ids
                   3121:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3122:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3123:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3124:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3125:     my %uris=(); # hash resource/map id -> resource src
                   3126:     my %maptitles=(); # hash map pc or src -> map title
                   3127:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3128:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3129:     my %alllevs=(); # hash English level title -> value
                   3130: 
                   3131:     my $uname; # selected user name
                   3132:     my $udom; # selected user domain
                   3133:     my $uhome; # server with the user's files, or 'no_host'
                   3134:     my $csec; # selected section name
                   3135:     my $cgroup; # selected group name
                   3136:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3137:     my $numreclinks = 0;
1.446     bisitz   3138: 
1.190     albertel 3139:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3140: 
1.57      albertel 3141:     $alllevs{'Resource Level'}='full';
1.215     www      3142:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3143:     $alllevs{'Course Level'}='general';
                   3144: 
1.563     damieng  3145:     my %allparms; # hash parameter name -> parameter title
                   3146:     my %allparts; # hash parameter part -> part title
1.512     foxr     3147: # ------------------------------------------------------------------------------
                   3148: 
1.210     www      3149: #
                   3150: # Order in which these parameters will be displayed
                   3151: #
1.211     www      3152:     my %keyorder=&standardkeyorder();
                   3153: 
1.512     foxr     3154: #    @ids=();
                   3155: #    %symbp=();       # These seem defined above already.
                   3156: #    %typep=();
1.43      albertel 3157: 
                   3158:     my $message='';
                   3159: 
1.190     albertel 3160:     $csec=$env{'form.csec'};
1.552     raeburn  3161:     if ($env{'request.course.sec'} ne '') {
                   3162:         $csec = $env{'request.course.sec'};    
                   3163:     }
                   3164: 
1.553     raeburn  3165: # Check group privs.
1.269     raeburn  3166:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3167:     my $noeditgrp; 
                   3168:     if ($cgroup ne '') {
                   3169:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3170:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3171:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3172:                 $noeditgrp = 1;
                   3173:             }
                   3174:         }
                   3175:     }
1.188     www      3176: 
1.190     albertel 3177:     if      ($udom=$env{'form.udom'}) {
                   3178:     } elsif ($udom=$env{'request.role.domain'}) {
                   3179:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3180:     } else {
1.473     amueller 3181:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3182:     }
1.468     amueller 3183:     
1.43      albertel 3184: 
1.134     albertel 3185:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3186:     my $pschp=$env{'form.pschp'};
1.506     www      3187: 
                   3188: 
1.134     albertel 3189:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3190:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3191:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3192: 
1.43      albertel 3193:     my $pssymb='';
1.57      albertel 3194:     my $parmlev='';
1.446     bisitz   3195: 
1.190     albertel 3196:     unless ($env{'form.parmlev'}) {
1.57      albertel 3197:         $parmlev = 'map';
                   3198:     } else {
1.190     albertel 3199:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3200:     }
1.26      www      3201: 
1.29      www      3202: # ----------------------------------------------- Was this started from grades?
                   3203: 
1.560     damieng  3204:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3205:             (!$env{'form.dis'})) {
1.473     amueller 3206:         my $url=$env{'form.url'};
                   3207:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3208:         $pssymb=&Apache::lonnet::symbread($url);
                   3209:         if (!@pscat) { @pscat=('all'); }
                   3210:         $pschp='';
1.57      albertel 3211:         $parmlev = 'full';
1.190     albertel 3212:     } elsif ($env{'form.symb'}) {
1.473     amueller 3213:         $pssymb=$env{'form.symb'};
                   3214:         if (!@pscat) { @pscat=('all'); }
                   3215:         $pschp='';
1.57      albertel 3216:         $parmlev = 'full';
1.43      albertel 3217:     } else {
1.473     amueller 3218:         $env{'form.url'}='';
1.43      albertel 3219:     }
                   3220: 
1.190     albertel 3221:     my $id=$env{'form.id'};
1.43      albertel 3222:     if (($id) && ($udom)) {
1.555     raeburn  3223:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3224:         if ($uname) {
                   3225:             $id='';
                   3226:         } else {
                   3227:             $message=
1.540     bisitz   3228:                 '<p class="LC_warning">'.
                   3229:                 &mt('Unknown ID [_1] at domain [_2]',
                   3230:                     "'".$id."'","'".$udom."'").
                   3231:                 '</p>';
1.473     amueller 3232:         }
1.43      albertel 3233:     } else {
1.473     amueller 3234:         $uname=$env{'form.uname'};
1.43      albertel 3235:     }
                   3236:     unless ($udom) { $uname=''; }
                   3237:     $uhome='';
                   3238:     if ($uname) {
1.473     amueller 3239:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3240:         if ($uhome eq 'no_host') {
1.473     amueller 3241:             $message=
1.540     bisitz   3242:                 '<p class="LC_warning">'.
                   3243:                 &mt('Unknown user [_1] at domain [_2]',
                   3244:                     "'".$uname."'","'".$udom."'").
                   3245:                 '</p>';
1.473     amueller 3246:             $uname='';
1.12      www      3247:         } else {
1.473     amueller 3248:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3249:                           $env{'request.course.id'});
                   3250:             if ($csec eq '-1') {
1.596     raeburn  3251:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3252:                 if ($env{'form.userroles'} eq 'any') {
                   3253:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3254:                         $csec = $env{'request.course.sec'};
                   3255:                         $message = '<span class="LC_info">';
                   3256:                         if ($crstype eq 'Community') {
                   3257:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3258:                                             $uname,$udom);
                   3259:                         } else {
                   3260:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3261:                                             $uname,$udom);
                   3262:                         }
                   3263:                         $message .= '</span>';
                   3264:                     } else {
                   3265:                         my @possroles = ('in','ep','ta','cr');
                   3266:                         if ($crstype eq 'Community') {
                   3267:                             unshift(@possroles,'co');
                   3268:                         } else {
                   3269:                             unshift(@possroles,'cc');
                   3270:                         }
                   3271:                         my %not_student_roles =
                   3272:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3273:                                                           \@possroles,[$udom],1,1);
                   3274:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3275:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3276:                         my %sections_by_role;
                   3277:                         foreach my $role (keys(%not_student_roles)) {
                   3278:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3279:                                 my ($rolename,$sec) = ($1,$2);
                   3280:                                 if ($rolename =~ m{^cr/}) {
                   3281:                                     $rolename = 'cr';
                   3282:                                 }
                   3283:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3284:                             }
                   3285:                         }
                   3286:                         my $numroles = scalar(keys(%sections_by_role));
                   3287:                         if ($numroles) {
                   3288:                             foreach my $role (@possroles) {
                   3289:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3290:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3291:                                     $csec = $secs[0];
                   3292:                                     last;
                   3293:                                 }
                   3294:                             }
                   3295:                         }
                   3296:                         if ($csec eq '-1') {
                   3297:                             $message = '<span class="LC_warning">';
                   3298:                             if ($crstype eq 'Community') {
                   3299:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3300:                                                 $uname,$udom);
                   3301:                             } else {
                   3302:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3303:                                                 $uname,$udom);
                   3304:                             }
                   3305:                             $message .= '</span>';
                   3306:                             $uname='';
                   3307:                             if ($env{'request.course.sec'} ne '') {
                   3308:                                 $csec=$env{'request.course.sec'};
                   3309:                             } else {
                   3310:                                 $csec=$env{'form.csec'};
                   3311:                             }
                   3312:                             $cgroup=$env{'form.cgroup'};
                   3313:                         } else {
                   3314:                             $message = '<span class="LC_info">';
                   3315:                             if ($crstype eq 'Community') {
                   3316:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3317:                                          $uname,$udom);
                   3318:                             } else {
                   3319:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3320:                                                 $uname,$udom);
                   3321:                             }
                   3322:                             $message .= '</span>';
                   3323:                         }
                   3324:                     }
1.594     raeburn  3325:                 } else {
1.596     raeburn  3326:                     $message = '<span class="LC_warning">';
                   3327:                     if ($crstype eq 'Community') {
                   3328:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3329:                                          $uname,$udom);
                   3330:                     } else {
                   3331:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3332:                                          $uname,$udom);
                   3333:                     }
                   3334:                     $message .= '</span>';
                   3335:                     $uname='';
                   3336:                     if ($env{'request.course.sec'} ne '') {
                   3337:                         $csec=$env{'request.course.sec'};
                   3338:                     } else {
                   3339:                         $csec=$env{'form.csec'};
                   3340:                     }
                   3341:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3342:                 }
                   3343:             } elsif ($env{'request.course.sec'} ne '') {
                   3344:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3345:                     $message='<span class="LC_warning">'.
1.594     raeburn  3346:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3347:                                   $uname,$udom,$env{'request.course.sec'}).
                   3348:                               '</span>';
                   3349:                     $uname='';
                   3350:                     $csec=$env{'request.course.sec'};
                   3351:                 }
1.269     raeburn  3352:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3353:             }
                   3354:             if ($uname ne '') {
1.473     amueller 3355:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3356:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3357:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3358:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3359:                             .$name{'lastname'}.' '.$name{'generation'}
                   3360:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3361:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3362:                                    $udom,$uname,$env{'request.course.id'});
                   3363:                 if (@usersgroups > 0) {
                   3364:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3365:                         $cgroup = $usersgroups[0];
                   3366:                     }
                   3367:                 } else {
                   3368:                     $cgroup = '';
1.297     raeburn  3369:                 }
1.269     raeburn  3370:             }
1.12      www      3371:         }
1.43      albertel 3372:     }
1.2       www      3373: 
1.43      albertel 3374:     unless ($csec) { $csec=''; }
1.269     raeburn  3375:     unless ($cgroup) { $cgroup=''; }
1.12      www      3376: 
1.14      www      3377: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3378:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3379:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603   ! raeburn  3380:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3381: 
1.582     raeburn  3382:     %allmaps_inverted = reverse(%allmaps);
                   3383: 
1.57      albertel 3384:     $mapp{'0.0'} = '';
                   3385:     $symbp{'0.0'} = '';
1.99      albertel 3386: 
1.14      www      3387: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3388:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3389:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3390:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3391:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3392:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3393:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3394:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3395:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3396:         my $totalstored = 0;
1.546     raeburn  3397:         my $now = time;
1.473     amueller 3398:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3399:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3400:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3401:                 next if ($csec ne $env{'request.course.sec'});
                   3402:             }
1.556     raeburn  3403:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3404:                 next if ($noeditgrp);
1.557     raeburn  3405:             }
                   3406:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3407:                 $namematch = 'maplevelrecurse';
                   3408:             }
1.556     raeburn  3409:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3410:                 my (@ok_slots,@fail_slots,@del_slots);
                   3411:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3412:                 my ($level,@all) =
                   3413:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3414:                                      $csec,$cgroup,$courseopt);
                   3415:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3416:                     next if ($slot_name eq '');
                   3417:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3418:                         push(@ok_slots,$slot_name);
                   3419: 
                   3420:                     } else {
                   3421:                         push(@fail_slots,$slot_name);
                   3422:                     }
                   3423:                 }
                   3424:                 if (@ok_slots) {
                   3425:                     $values[$i] = join(':',@ok_slots);
                   3426:                 } else {
                   3427:                     $values[$i] = '';
                   3428:                 }
                   3429:                 if ($all[$level] ne '') {
                   3430:                     my @existing = split(/:/,$all[$level]);
                   3431:                     foreach my $slot_name (@existing) {
                   3432:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3433:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3434:                                 push(@del_slots,$slot_name);
                   3435:                             }
                   3436:                         }
                   3437:                     }
                   3438:                 }
1.554     raeburn  3439:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3440:                 $name = $1;
1.533     raeburn  3441:                 my $val = $values[$i];
1.549     raeburn  3442:                 my $valmatch = '';
1.533     raeburn  3443:                 if ($name eq 'examcode') {
1.544     raeburn  3444:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3445:                         $val = 'valid';
                   3446:                     }
1.546     raeburn  3447:                 } elsif ($name eq 'printstartdate') {
                   3448:                     if ($val =~ /^\d+$/) {
                   3449:                         if ($val > $now) {
                   3450:                             $val = 'future';
                   3451:                         }
                   3452:                     } 
                   3453:                 } elsif ($name eq 'printenddate') {
                   3454:                     if ($val =~ /^\d+$/) {
                   3455:                         if ($val < $now) {
                   3456:                             $val = 'past';
                   3457:                         }
                   3458:                     }
1.549     raeburn  3459:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3460:                     my $stringtype = &get_stringtype($name);
                   3461:                     my $stringmatch = &standard_string_matches($stringtype);
                   3462:                     if (ref($stringmatch) eq 'ARRAY') {
                   3463:                         foreach my $item (@{$stringmatch}) {
                   3464:                             if (ref($item) eq 'ARRAY') {
                   3465:                                 my ($regexpname,$pattern) = @{$item};
                   3466:                                 if ($pattern ne '') {
                   3467:                                     if ($val =~ /$pattern/) {
                   3468:                                         $valmatch = $regexpname;
                   3469:                                         $val = '';
                   3470:                                         last;
                   3471:                                     }
                   3472:                                 }
                   3473:                             }
                   3474:                         }
                   3475:                     }
1.554     raeburn  3476:                 } elsif ($name eq 'interval') {
                   3477:                     my $intervaltype = &get_intervaltype($name);
                   3478:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3479:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3480:                         foreach my $item (@{$intervalmatch}) {
                   3481:                             if (ref($item) eq 'ARRAY') {
                   3482:                                 my ($regexpname,$pattern) = @{$item};
                   3483:                                 if ($pattern ne '') {
                   3484:                                     if ($val =~ /$pattern/) {
                   3485:                                         $valmatch = $regexpname;
                   3486:                                         $val = '';
                   3487:                                         last;
                   3488:                                     }
                   3489:                                 }
                   3490:                             }
                   3491:                         }
                   3492:                     }
1.533     raeburn  3493:                 }
1.504     raeburn  3494:                 $needsrelease =
1.557     raeburn  3495:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3496:                 if ($needsrelease) {
1.505     raeburn  3497:                     unless ($got_chostname) {
1.514     raeburn  3498:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3499:                         $got_chostname = 1;
1.546     raeburn  3500:                     } 
1.557     raeburn  3501:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3502:                                                           $needsrelease,
                   3503:                                                           $cmajor,$cminor);
1.500     raeburn  3504:                 }
1.437     raeburn  3505:             }
1.504     raeburn  3506:             if ($needsnewer) {
1.557     raeburn  3507:                 undef($namematch);
                   3508:             } else {
                   3509:                 my $currneeded;
                   3510:                 if ($needsrelease) {
                   3511:                     $currneeded = $needsrelease;
                   3512:                 }
                   3513:                 if ($namematch) {
                   3514:                     $needsrelease =
                   3515:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3516:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3517:                         unless ($got_chostname) {
                   3518:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3519:                             $got_chostname = 1;
                   3520:                         }
                   3521:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3522:                                                               $needsrelease,
                   3523:                                                               $cmajor,$cminor);
                   3524:                     } else {
                   3525:                         undef($namematch);
                   3526:                     }
                   3527:                 }
                   3528:             }
                   3529:             if ($needsnewer) {
                   3530:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3531:                                                 $cminor,$needsrelease);
                   3532:             } else {
                   3533:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3534:                                      $values[$i],
                   3535:                                      $types[$i],
                   3536:                                      $uname,$udom,$csec,$cgroup);
                   3537:                 $totalstored ++;
                   3538:             }
1.473     amueller 3539:         }
1.68      www      3540: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3541:         if ($totalstored) {
                   3542:             $message.='<p class="LC_warning">'
                   3543:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3544:                      .&Apache::loncommon::help_open_topic('Caching')
                   3545:                      .'</p>';
                   3546:         }
1.68      www      3547:     }
1.584     raeburn  3548: 
1.57      albertel 3549: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3550:     if ($pscat[0] eq "all") {
                   3551:         @pscat = (keys(%allparms));
                   3552:     }
                   3553:     if (!@pscat) {
                   3554:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3555:     };
                   3556:     if ($psprt[0] eq "all" || !@psprt) {
                   3557:         @psprt = (keys(%allparts));
                   3558:     }
1.2       www      3559: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3560: 
1.531     raeburn  3561:     my $crstype = &Apache::loncommon::course_type();
                   3562:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3563: 
1.548     raeburn  3564:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3565:             'date_interval','int','float','string','string_lenient',
                   3566:             'string_examcode','string_deeplink','string_discussvote',
                   3567:             'string_useslots','string_problemstatus','string_ip',
                   3568:             'string_questiontype') {
1.473     amueller 3569:         $r->print('<input type="hidden" value="'.
1.563     damieng  3570:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3571:             '" name="recent_'.$item.'" />');
1.44      albertel 3572:     }
1.446     bisitz   3573: 
1.459     bisitz   3574:     # ----- Start Parameter Selection
                   3575: 
                   3576:     # Hide parm selection?
                   3577:     $r->print(<<ENDPARMSELSCRIPT);
                   3578: <script type="text/javascript">
                   3579: // <![CDATA[
                   3580: function parmsel_show() {
1.562     damieng  3581:     document.getElementById('parmsel').style.display = "";
                   3582:     document.getElementById('parmsellink').style.display = "none";
1.459     bisitz   3583: }
                   3584: // ]]>
                   3585: </script>
                   3586: ENDPARMSELSCRIPT
1.474     amueller 3587:     
1.445     neumanie 3588:     if (!$pssymb) {
1.563     damieng  3589:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3590:         my $parmselhiddenstyle=' style="display:none"';
                   3591:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3592:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3593:         } else  {
                   3594:            $r->print('<div id="parmsel">');
                   3595:         }
                   3596: 
1.491     bisitz   3597:         # Step 1
1.523     raeburn  3598:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3599:         $r->print('
1.474     amueller 3600: <script type="text/javascript">
1.523     raeburn  3601: // <![CDATA['.
                   3602:                  &showhide_js().'
1.474     amueller 3603: // ]]>
                   3604: </script>
1.523     raeburn  3605: ');
                   3606:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3607:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3608:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.474     amueller 3609:         &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491     bisitz   3610:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3611:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3612:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3613:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3614:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3615: 
                   3616:         # Step 2
1.523     raeburn  3617:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3618:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3619: 
                   3620:         # Step 3
1.523     raeburn  3621:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3622:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3623:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3624:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3625:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3626: 
                   3627:         # Update Display Button
1.486     www      3628:         $r->print('<p>'
                   3629:              .'<input type="submit" name="dis"'
1.511     www      3630:              .' value="'.&mt('Update Display').'" />'
1.486     www      3631:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3632:              .'</p>');
                   3633:         $r->print('</div>');
1.491     bisitz   3634: 
1.486     www      3635:         # Offer link to display parameter selection again
                   3636:         $r->print('<p id="parmsellink"');
                   3637:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3638:            $r->print($parmselhiddenstyle);
                   3639:         }
                   3640:         $r->print('>'
                   3641:              .'<a href="javascript:parmsel_show()">'
                   3642:              .&mt('Change Parameter Selection')
                   3643:              .'</a>'
                   3644:              .'</p>');
1.44      albertel 3645:     } else {
1.478     amueller 3646:         # parameter screen for a single resource. 
1.486     www      3647:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3648:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3649:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3650:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3651:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3652:                   '<br />');
                   3653:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3654:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3655:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3656:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3657:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3658:         $r->print('<p>'
1.459     bisitz   3659:              .'<input type="submit" name="dis"'
1.511     www      3660:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3661:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3662:              .'</p>');
1.459     bisitz   3663:     }
1.478     amueller 3664:     
1.486     www      3665:     # ----- End Parameter Selection
1.57      albertel 3666: 
1.459     bisitz   3667:     # Display Messages
                   3668:     $r->print('<div>'.$message.'</div>');
1.210     www      3669: 
1.57      albertel 3670: 
                   3671:     my @temp_pscat;
                   3672:     map {
                   3673:         my $cat = $_;
                   3674:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3675:     } @pscat;
                   3676: 
                   3677:     @pscat = @temp_pscat;
                   3678: 
1.548     raeburn  3679: 
1.209     www      3680:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3681: # ----------------------------------------------------------------- Start Table
1.57      albertel 3682:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3683:         my $csuname=$env{'user.name'};
                   3684:         my $csudom=$env{'user.domain'};
1.568     raeburn  3685:         my $readonly = 1;
                   3686:         if ($parm_permission->{'edit'}) {
                   3687:             undef($readonly); 
                   3688:         }
1.57      albertel 3689: 
1.203     www      3690:         if ($parmlev eq 'full') {
1.506     www      3691: #
                   3692: # This produces the cascading table output of parameters
                   3693: #
1.578     raeburn  3694:             my $coursespan=$csec?8:5;
                   3695:             my $userspan=3;
1.560     damieng  3696:             if ($cgroup ne '') {
1.578     raeburn  3697:                 $coursespan += 3;
1.560     damieng  3698:             }
1.473     amueller 3699: 
1.560     damieng  3700:             $r->print(&Apache::loncommon::start_data_table());
                   3701:             #
                   3702:             # This produces the headers
                   3703:             #
                   3704:             $r->print('<tr><td colspan="5"></td>');
                   3705:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3706:             if ($uname) {
1.473     amueller 3707:                 if (@usersgroups > 1) {
1.560     damieng  3708:                     $userspan ++;
                   3709:                 }
                   3710:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3711:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3712:             }
                   3713:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3714:                 'pie'    => "Parameter in Effect",
                   3715:                 'csv'    => "Current Session Value",
1.472     amueller 3716:                 'rl'     => "Resource Level",
1.473     amueller 3717:                 'ic'     => 'in Course',
                   3718:                 'aut'    => "Assessment URL and Title",
                   3719:                 'type'   => 'Type',
                   3720:                 'emof'   => "Enclosing Map or Folder",
                   3721:                 'part'   => 'Part',
1.472     amueller 3722:                 'pn'     => 'Parameter Name',
1.473     amueller 3723:                 'def'    => 'default',
                   3724:                 'femof'  => 'from Enclosing Map or Folder',
                   3725:                 'gen'    => 'general',
                   3726:                 'foremf' => 'for Enclosing Map or Folder',
                   3727:                 'fr'     => 'for Resource'
                   3728:             );
1.560     damieng  3729:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3730: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3731: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3732: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3733: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3734: 
1.10      www      3735: ENDTABLETWO
1.560     damieng  3736:             if ($csec) {
1.578     raeburn  3737:                 $r->print('<th colspan="3">'.
1.560     damieng  3738:                 &mt("in Section")." $csec</th>");
                   3739:             }
                   3740:             if ($cgroup) {
1.578     raeburn  3741:                 $r->print('<th colspan="3">'.
1.472     amueller 3742:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3743:             }
                   3744:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3745: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3746: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3747: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3748: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3749: ENDTABLEHEADFOUR
1.57      albertel 3750: 
1.560     damieng  3751:             if ($csec) {
1.578     raeburn  3752:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3753:             }
1.473     amueller 3754: 
1.560     damieng  3755:             if ($cgroup) {
1.578     raeburn  3756:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3757:             }
                   3758: 
                   3759:             if ($uname) {
                   3760:                 if (@usersgroups > 1) {
                   3761:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3762:                 }
1.578     raeburn  3763:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3764:             }
                   3765: 
                   3766:             $r->print('</tr>');
1.506     www      3767: #
                   3768: # Done with the headers
                   3769: # 
1.560     damieng  3770:             my $defbgone='';
                   3771:             my $defbgtwo='';
                   3772:             my $defbgthree = '';
1.57      albertel 3773: 
1.560     damieng  3774:             foreach my $rid (@ids) {
1.57      albertel 3775: 
                   3776:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3777:                 if ((!$pssymb &&
1.560     damieng  3778:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3779:                         ||
                   3780:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3781: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3782:                     if ($defbgone eq '#E0E099') {
                   3783:                         $defbgone='#E0E0DD';
1.57      albertel 3784:                     } else {
1.419     bisitz   3785:                         $defbgone='#E0E099';
1.57      albertel 3786:                     }
1.419     bisitz   3787:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3788:                         $defbgtwo='#FFFFDD';
1.57      albertel 3789:                     } else {
1.473     amueller 3790:                         $defbgtwo='#FFFF99';
1.57      albertel 3791:                     }
1.419     bisitz   3792:                     if ($defbgthree eq '#FFBB99') {
                   3793:                         $defbgthree='#FFBBDD';
1.269     raeburn  3794:                     } else {
1.419     bisitz   3795:                         $defbgthree='#FFBB99';
1.269     raeburn  3796:                     }
                   3797: 
1.57      albertel 3798:                     my $thistitle='';
                   3799:                     my %name=   ();
                   3800:                     undef %name;
                   3801:                     my %part=   ();
                   3802:                     my %display=();
                   3803:                     my %type=   ();
                   3804:                     my %default=();
1.196     www      3805:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3806:                     my $toolsymb;
                   3807:                     if ($uri =~ /ext\.tool$/) {
                   3808:                         $toolsymb = $symbp{$rid};
                   3809:                     }
1.57      albertel 3810: 
1.506     www      3811:                     my $filter=$env{'form.filter'};
1.548     raeburn  3812:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3813:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3814:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3815:     # We may only want certain parameters listed
                   3816:                             if ($filter) {
                   3817:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3818:                             }
                   3819:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3820:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3821: 
1.584     raeburn  3822:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3823:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3824:                                 my $identifier;
                   3825:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3826:                                     $identifier = $1;
                   3827:                                 }
                   3828:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3829:                             } else {
                   3830:                                 $display{$tempkeyp} = $parmdis;
                   3831:                             }
                   3832:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3833:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3834:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3835:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3836:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3837:                         }
                   3838:                     }
1.548     raeburn  3839:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3840:                     if ($totalparms>0) {
1.560     damieng  3841:                         my $firstrow=1;
1.473     amueller 3842:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3843:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3844:                         my @recurseup;
                   3845:                         if (ref($navmap) && $mapp{$rid}) {
                   3846:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3847:                         }
1.419     bisitz   3848:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3849:                              ' rowspan='.$totalparms.
1.419     bisitz   3850:                              '><tt><font size="-1">'.
1.57      albertel 3851:                              join(' / ',split(/\//,$uri)).
                   3852:                              '</font></tt><p><b>'.
1.154     albertel 3853:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3854:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3855:                           &escape($symbp{$rid}).
1.336     albertel 3856:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3857:                              " target=\"_self\">$title");
1.57      albertel 3858: 
                   3859:                         if ($thistitle) {
1.473     amueller 3860:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3861:                         }
                   3862:                         $r->print('</a></b></td>');
1.419     bisitz   3863:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3864:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3865:                                       '</td>');
                   3866: 
1.419     bisitz   3867:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3868:                                       ' rowspan='.$totalparms.
1.238     www      3869:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3870:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3871:                             unless ($firstrow) {
                   3872:                                 $r->print('<tr>');
                   3873:                             } else {
                   3874:                                 undef $firstrow;
                   3875:                             }
1.548     raeburn  3876:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3877:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3878:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  3879:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   3880:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   3881:                                        \$numreclinks);
1.57      albertel 3882:                         }
                   3883:                     }
                   3884:                 }
                   3885:             } # end foreach ids
1.43      albertel 3886: # -------------------------------------------------- End entry for one resource
1.517     www      3887:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3888:         } # end of  full
1.57      albertel 3889: #--------------------------------------------------- Entry for parm level map
                   3890:         if ($parmlev eq 'map') {
1.419     bisitz   3891:             my $defbgone = '#E0E099';
                   3892:             my $defbgtwo = '#FFFF99';
                   3893:             my $defbgthree = '#FFBB99';
1.57      albertel 3894: 
                   3895:             my %maplist;
                   3896: 
                   3897:             if ($pschp eq 'all') {
1.446     bisitz   3898:                 %maplist = %allmaps;
1.57      albertel 3899:             } else {
                   3900:                 %maplist = ($pschp => $mapp{$pschp});
                   3901:             }
                   3902: 
                   3903: #-------------------------------------------- for each map, gather information
                   3904:             my $mapid;
1.560     damieng  3905:             foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {
1.60      albertel 3906:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3907: 
                   3908: #-----------------------  loop through ids and get all parameter types for map
                   3909: #-----------------------------------------          and associated information
                   3910:                 my %name = ();
                   3911:                 my %part = ();
                   3912:                 my %display = ();
                   3913:                 my %type = ();
                   3914:                 my %default = ();
                   3915:                 my $map = 0;
                   3916: 
1.473     amueller 3917: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3918: 
1.548     raeburn  3919:                 foreach my $id (@ids) {
                   3920:                     ($map)=($id =~ /([\d]*?)\./);
                   3921:                     my $rid = $id;
1.446     bisitz   3922: 
1.57      albertel 3923: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3924: 
1.560     damieng  3925:                     if ($map eq $mapid) {
1.473     amueller 3926:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3927:                         my $toolsymb;
                   3928:                         if ($uri =~ /ext\.tool$/) {
                   3929:                             $toolsymb = $symbp{$rid};
                   3930:                         }
1.582     raeburn  3931: 
1.57      albertel 3932: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3933: 
                   3934: #--------------------------------------------------------------------
                   3935: # @catmarker contains list of all possible parameters including part #s
                   3936: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3937: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3938: # When storing information, store as part 0
                   3939: # When requesting information, request from full part
                   3940: #-------------------------------------------------------------------
1.548     raeburn  3941:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3942:                             my $tempkeyp = $fullkeyp;
                   3943:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 3944: 
1.548     raeburn  3945:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3946:                                 $part{$tempkeyp}="0";
1.584     raeburn  3947:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   3948:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 3949:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   3950:                                     my $identifier;
                   3951:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3952:                                         $identifier = $1;
                   3953:                                     }
                   3954:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3955:                                 } else {
                   3956:                                     $display{$tempkeyp} = $parmdis;
                   3957:                                 }
                   3958:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3959:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3960:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  3961:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   3962:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 3963:                               }
                   3964:                         } # end loop through keys
1.560     damieng  3965:                     }
1.57      albertel 3966:                 } # end loop through ids
1.446     bisitz   3967: 
1.57      albertel 3968: #---------------------------------------------------- print header information
1.133     www      3969:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      3970:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   3971:                 my $tmp="";
1.57      albertel 3972:                 if ($uname) {
1.473     amueller 3973:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   3974:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   3975:                         &mt('in')." \n";
1.57      albertel 3976:                 } else {
1.401     bisitz   3977:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 3978:                 }
1.269     raeburn  3979:                 if ($cgroup) {
1.401     bisitz   3980:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   3981:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3982:                     $csec = '';
                   3983:                 } elsif ($csec) {
1.401     bisitz   3984:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   3985:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3986:                 }
1.401     bisitz   3987:                 $r->print('<div align="center"><h4>'
                   3988:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   3989:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   3990:                              ,$tmp
                   3991:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   3992:                              )
                   3993:                          ."<br /></h4>\n"
1.422     bisitz   3994:                 );
1.57      albertel 3995: #---------------------------------------------------------------- print table
1.419     bisitz   3996:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3997:                          .&Apache::loncommon::start_data_table_header_row()
                   3998:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  3999:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4000:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4001:                          .&Apache::loncommon::end_data_table_header_row()
                   4002:                 );
1.57      albertel 4003: 
1.582     raeburn  4004:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4005:                 my @recurseup;
                   4006:                 if (ref($navmap)) {
                   4007:                      my $mapres = $navmap->getByMapPc($mapid);
                   4008:                      if (ref($mapres)) {
                   4009:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4010:                      }
                   4011:                 }
                   4012: 
                   4013: 
1.548     raeburn  4014:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4015:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4016:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4017:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4018:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4019:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4020:                            \$numreclinks);
1.57      albertel 4021:                 }
1.422     bisitz   4022:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4023:                          .'</div>'
                   4024:                 );
1.57      albertel 4025:             } # end each map
                   4026:         } # end of $parmlev eq map
                   4027: #--------------------------------- Entry for parm level general (Course level)
                   4028:         if ($parmlev eq 'general') {
1.473     amueller 4029:             my $defbgone = '#E0E099';
1.419     bisitz   4030:             my $defbgtwo = '#FFFF99';
                   4031:             my $defbgthree = '#FFBB99';
1.57      albertel 4032: 
                   4033: #-------------------------------------------- for each map, gather information
                   4034:             my $mapid="0.0";
                   4035: #-----------------------  loop through ids and get all parameter types for map
                   4036: #-----------------------------------------          and associated information
                   4037:             my %name = ();
                   4038:             my %part = ();
                   4039:             my %display = ();
                   4040:             my %type = ();
                   4041:             my %default = ();
1.446     bisitz   4042: 
1.548     raeburn  4043:             foreach $id (@ids) {
                   4044:                 my $rid = $id;
1.446     bisitz   4045: 
1.196     www      4046:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4047:                 my $toolsymb;
                   4048:                 if ($uri =~ /ext\.tool$/) {
                   4049:                     $toolsymb = $symbp{$rid};
                   4050:                 }
1.57      albertel 4051: 
                   4052: #--------------------------------------------------------------------
                   4053: # @catmarker contains list of all possible parameters including part #s
                   4054: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4055: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4056: # When storing information, store as part 0
                   4057: # When requesting information, request from full part
                   4058: #-------------------------------------------------------------------
1.548     raeburn  4059:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4060:                     my $tempkeyp = $fullkeyp;
                   4061:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4062:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4063:                         $part{$tempkeyp}="0";
1.584     raeburn  4064:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4065:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4066:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4067:                             my $identifier;
                   4068:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4069:                                 $identifier = $1;
                   4070:                             }
                   4071:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4072:                         } else {
                   4073:                             $display{$tempkeyp} = $parmdis;
                   4074:                         }
                   4075:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4076:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4077:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4078:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4079:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4080:                     }
1.57      albertel 4081:                 } # end loop through keys
                   4082:             } # end loop through ids
1.446     bisitz   4083: 
1.57      albertel 4084: #---------------------------------------------------- print header information
1.473     amueller 4085:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4086:             $r->print(<<ENDMAPONE);
1.419     bisitz   4087: <center>
                   4088: <h4>$setdef
1.135     albertel 4089: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4090: ENDMAPONE
                   4091:             if ($uname) {
1.473     amueller 4092:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4093:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4094:             } else {
1.135     albertel 4095:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4096:             }
1.446     bisitz   4097: 
1.135     albertel 4098:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4099:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4100:             $r->print("</h4>\n");
1.57      albertel 4101: #---------------------------------------------------------------- print table
1.419     bisitz   4102:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4103:                      .&Apache::loncommon::start_data_table_header_row()
                   4104:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4105:                      .'<th>'.&mt('Default Value').'</th>'
                   4106:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4107:                      .&Apache::loncommon::end_data_table_header_row()
                   4108:             );
1.57      albertel 4109: 
1.548     raeburn  4110:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4111:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4112:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4113:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4114:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4115:                            $readonly);
1.57      albertel 4116:             }
1.419     bisitz   4117:             $r->print(&Apache::loncommon::end_data_table()
                   4118:                      .'</p>'
                   4119:                      .'</center>'
                   4120:             );
1.57      albertel 4121:         } # end of $parmlev eq general
1.43      albertel 4122:     }
1.507     www      4123:     $r->print('</form>');
1.582     raeburn  4124:     if ($numreclinks) {
                   4125:         $r->print(<<"END");
                   4126: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4127: <input type="hidden" name="pschp" />
                   4128: <input type="hidden" name="pscat" />
                   4129: <input type="hidden" name="psprt" />
                   4130: <input type="hidden" name="hideparmsel" value="hidden" />
                   4131: </form>
                   4132: <script type="text/javascript">
                   4133: function pjumprec(rid,name,part) {
                   4134:     document.forms.recurseform.pschp.value = rid;
                   4135:     document.forms.recurseform.pscat.value = name;
                   4136:     document.forms.recurseform.psprt.value = part;
                   4137:     document.forms.recurseform.submit();
                   4138:     return false;
                   4139: }
                   4140: </script>
                   4141: END
                   4142:     }
1.507     www      4143:     &endSettingsScreen($r);
                   4144:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4145: } # end sub assessparms
1.30      www      4146: 
1.560     damieng  4147: 
                   4148: 
1.120     www      4149: ##################################################
1.560     damieng  4150: # OVERVIEW MODE
1.207     www      4151: ##################################################
1.124     www      4152: 
1.563     damieng  4153: my $tableopen; # boolean, true if HTML table is already opened
                   4154: 
                   4155: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4156: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4157: # @returns {string}
1.124     www      4158: sub tablestart {
1.576     raeburn  4159:     my ($readonly,$is_map) = @_;
1.124     www      4160:     if ($tableopen) {
1.552     raeburn  4161:         return '';
1.124     www      4162:     } else {
1.552     raeburn  4163:         $tableopen=1;
                   4164:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4165:         if ($readonly) {
                   4166:             $output .= '<th>'.&mt('Current value').'</th>';
                   4167:         } else {
1.576     raeburn  4168:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4169:                        '<th>'.&mt('Set to ...').'</th>';
                   4170:             if ($is_map) {
                   4171:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4172:             }
1.552     raeburn  4173:         }
                   4174:         $output .= '</tr>';
                   4175:         return $output;
1.124     www      4176:     }
                   4177: }
                   4178: 
1.563     damieng  4179: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4180: # @returns {string}
1.124     www      4181: sub tableend {
                   4182:     if ($tableopen) {
1.560     damieng  4183:         $tableopen=0;
                   4184:         return &Apache::loncommon::end_data_table();
1.124     www      4185:     } else {
1.560     damieng  4186:         return'';
1.124     www      4187:     }
                   4188: }
                   4189: 
1.563     damieng  4190: # Reads course and user information.
                   4191: # 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).
                   4192: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4193: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4194: # @param {string} $crs - course number
                   4195: # @param {string} $dom - course domain
                   4196: # @returns {hash reference|Array}
1.207     www      4197: sub readdata {
                   4198:     my ($crs,$dom)=@_;
                   4199: # Read coursedata
                   4200:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4201: # Read userdata
                   4202: 
                   4203:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4204:     foreach my $user (keys(%$classlist)) {
                   4205:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4206:             my ($tuname,$tudom)=($1,$2);
                   4207:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4208:             foreach my $userkey (keys(%{$useropt})) {
                   4209:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4210:                     my $newkey=$userkey;
1.548     raeburn  4211:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4212:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4213:                 }
                   4214:             }
1.473     amueller 4215:         }
                   4216:     }
1.552     raeburn  4217:     if (wantarray) {
                   4218:         return ($resourcedata,$classlist);
                   4219:     } else {
                   4220:         return $resourcedata;
                   4221:     }
1.207     www      4222: }
                   4223: 
                   4224: 
1.563     damieng  4225: # Stores parameter data, using form parameters directly.
                   4226: #
                   4227: # 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  4228: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4229: # del_* - remove a parameter
                   4230: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4231: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4232: # key_* - date values
                   4233: # days_* - for date intervals
                   4234: # hours_* - for date intervals
                   4235: # minutes_* - for date intervals
                   4236: # seconds_* - for date intervals
                   4237: # done_* - for date intervals
                   4238: # typeof_* - parameter type
                   4239: # 
                   4240: # @param {Apache2::RequestRec} $r - the Apache request
                   4241: # @param {string} $crs - course number
                   4242: # @param {string} $dom - course domain
1.208     www      4243: sub storedata {
                   4244:     my ($r,$crs,$dom)=@_;
1.207     www      4245: # Set userlevel immediately
                   4246: # Do an intermediate store of course level
                   4247:     my $olddata=&readdata($crs,$dom);
1.124     www      4248:     my %newdata=();
                   4249:     undef %newdata;
                   4250:     my @deldata=();
1.576     raeburn  4251:     my @delrec=();
                   4252:     my @delnonrec=();
1.124     www      4253:     undef @deldata;
1.504     raeburn  4254:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4255:     my $now = time;
1.560     damieng  4256:     foreach my $key (keys(%env)) {
                   4257:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4258:             my $cmd=$1;
                   4259:             my $thiskey=$2;
1.576     raeburn  4260:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4261:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4262:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4263:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4264:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4265:                     $altkey = $thiskey;
                   4266:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4267:                     if ($env{'form.rec_'.$thiskey}) {
                   4268:                         $recursive = 1;
                   4269:                     }
                   4270:                 }
                   4271:             }
1.560     damieng  4272:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4273:             if ($tuname) {
1.576     raeburn  4274:                 $tkey=$thiskey;
1.560     damieng  4275:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4276:                 if ($altkey) {
                   4277:                     $tkeynonrec = $tkey; 
                   4278:                     $tkeyrec = $altkey;
                   4279:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4280:                 }
1.560     damieng  4281:             }
                   4282:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4283:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4284:                 if ($cmd eq 'set') {
                   4285:                     $data=$env{$key};
                   4286:                     $valmatch = '';
                   4287:                     $valchk = $data;
                   4288:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4289:                     $text = &mt('Saved modified parameter for');
                   4290:                     if ($typeof eq 'string_questiontype') {
                   4291:                         $name = 'type';
1.588     raeburn  4292:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4293:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4294:                         my $stringmatch = &standard_string_matches($typeof);
                   4295:                         if (ref($stringmatch) eq 'ARRAY') {
                   4296:                             foreach my $item (@{$stringmatch}) {
                   4297:                                 if (ref($item) eq 'ARRAY') {
                   4298:                                     my ($regexpname,$pattern) = @{$item};
                   4299:                                     if ($pattern ne '') {
                   4300:                                         if ($data =~ /$pattern/) {
                   4301:                                             $valmatch = $regexpname;
                   4302:                                             $valchk = '';
                   4303:                                             last;
                   4304:                                         }
1.560     damieng  4305:                                     }
1.549     raeburn  4306:                                 }
                   4307:                             }
                   4308:                         }
1.563     damieng  4309:                     } elsif ($typeof eq 'string_discussvote') {
                   4310:                         $name = 'discussvote';
                   4311:                     } elsif ($typeof eq 'string_examcode') {
                   4312:                         $name = 'examcode';
                   4313:                         if (&Apache::lonnet::validCODE($data)) {
                   4314:                             $valchk = 'valid';
                   4315:                         }
                   4316:                     } elsif ($typeof eq 'string_yesno') {
                   4317:                         if ($thiskey =~ /\.retrypartial$/) {
                   4318:                             $name = 'retrypartial';
                   4319:                         }
1.549     raeburn  4320:                     }
1.563     damieng  4321:                 } elsif ($cmd eq 'datepointer') {
                   4322:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4323:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4324:                     $text = &mt('Saved modified date for');
                   4325:                     if ($typeof eq 'date_start') {
                   4326:                         if ($thiskey =~ /\.printstartdate$/) {
                   4327:                             $name = 'printstartdate';
                   4328:                             if (($data) && ($data > $now)) {
                   4329:                                 $valchk = 'future';
                   4330:                             }
1.560     damieng  4331:                         }
1.563     damieng  4332:                     } elsif ($typeof eq 'date_end') {
                   4333:                         if ($thiskey =~ /\.printenddate$/) {
                   4334:                             $name = 'printenddate';
                   4335:                             if (($data) && ($data < $now)) {
                   4336:                                 $valchk = 'past';
                   4337:                             }
1.560     damieng  4338:                         }
1.504     raeburn  4339:                     }
1.563     damieng  4340:                 } elsif ($cmd eq 'dateinterval') {
                   4341:                     $data=&get_date_interval_from_form($thiskey);
                   4342:                     if ($thiskey =~ /\.interval$/) {
                   4343:                         $name = 'interval';
                   4344:                         my $intervaltype = &get_intervaltype($name);
                   4345:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4346:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4347:                             foreach my $item (@{$intervalmatch}) {
                   4348:                                 if (ref($item) eq 'ARRAY') {
                   4349:                                     my ($regexpname,$pattern) = @{$item};
                   4350:                                     if ($pattern ne '') {
                   4351:                                         if ($data =~ /$pattern/) {
                   4352:                                             $valmatch = $regexpname;
                   4353:                                             $valchk = '';
                   4354:                                             last;
                   4355:                                         }
1.560     damieng  4356:                                     }
1.554     raeburn  4357:                                 }
                   4358:                             }
                   4359:                         }
                   4360:                     }
1.563     damieng  4361:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4362:                     $text = &mt('Saved modified date for');
1.554     raeburn  4363:                 }
1.576     raeburn  4364:                 if ($recursive) {
1.563     damieng  4365:                     $namematch = 'maplevelrecurse';
1.560     damieng  4366:                 }
1.563     damieng  4367:                 if (($name ne '') || ($namematch ne '')) {
                   4368:                     my ($needsrelease,$needsnewer);
                   4369:                     if ($name ne '') {
                   4370:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4371:                         if ($needsrelease) {
                   4372:                             unless ($got_chostname) {
1.563     damieng  4373:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4374:                                 $got_chostname = 1;
                   4375:                             }
1.563     damieng  4376:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4377:                                                                 $needsrelease,
                   4378:                                                                 $cmajor,$cminor);
                   4379:                         }
                   4380:                     }
                   4381:                     if ($namematch ne '') {
                   4382:                         if ($needsnewer) {
                   4383:                             undef($namematch);
1.560     damieng  4384:                         } else {
1.563     damieng  4385:                             my $currneeded;
                   4386:                             if ($needsrelease) {
                   4387:                                 $currneeded = $needsrelease;
                   4388:                             }
                   4389:                             $needsrelease =
                   4390:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4391:                             if (($needsrelease) &&
                   4392:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4393:                                 unless ($got_chostname) {
                   4394:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4395:                                     $got_chostname = 1;
                   4396:                                 }
                   4397:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4398:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4399:                             } else {
                   4400:                                 undef($namematch);
                   4401:                             }
1.560     damieng  4402:                         }
1.557     raeburn  4403:                     }
1.563     damieng  4404:                     if ($needsnewer) {
                   4405:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4406:                                                             $chostname,$cmajor,
                   4407:                                                             $cminor,$needsrelease));
                   4408:                         next;
                   4409:                     }
1.504     raeburn  4410:                 }
1.576     raeburn  4411:                 my ($reconlychg,$haschange,$storekey);
                   4412:                 if ($tuname) {
                   4413:                     my $ustorekey;
                   4414:                     if ($altkey) {
                   4415:                         if ($recursive) {
                   4416:                             if (exists($$olddata{$thiskey})) {
                   4417:                                 if ($$olddata{$thiskey} eq $data) {
                   4418:                                     $reconlychg = 1;
                   4419:                                 }
                   4420:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4421:                             }
                   4422:                             if (exists($$olddata{$altkey})) {
                   4423:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4424:                                     $haschange = 1;
                   4425:                                 }
                   4426:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4427:                                 $haschange = 1;
                   4428:                             }
                   4429:                             $ustorekey = $tkeyrec;
                   4430:                         } else {
                   4431:                             if (exists($$olddata{$altkey})) {
                   4432:                                 if ($$olddata{$altkey} eq $data) {
                   4433:                                     $reconlychg = 1;
                   4434:                                 }
                   4435:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4436:                             }
                   4437:                             if (exists($$olddata{$thiskey})) {
                   4438:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4439:                                     $haschange = 1;
                   4440:                                 }
                   4441:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4442:                                 $haschange = 1;
                   4443:                             }
                   4444:                             $ustorekey = $tkeynonrec;
                   4445:                         }
                   4446:                     } else {
                   4447:                         if (exists($$olddata{$tkey})) {
                   4448:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4449:                                 $haschange = 1;
                   4450:                             }
                   4451:                             $ustorekey = $tkey;
                   4452:                         }
                   4453:                     }
                   4454:                     if ($haschange || $reconlychg)  {
                   4455:                         unless ($env{'form.del_'.$thiskey}) {
                   4456:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4457:                                                                      $ustorekey.'.type' => $typeof},
                   4458:                                                                      $tudom,$tuname) eq 'ok') {
                   4459:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4460:                                 $r->print('<br />'.$text.' '.
                   4461:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4462:                             } else {
                   4463:                                 $r->print('<div class="LC_error">'.
                   4464:                                           &mt('Error saving parameters').'</div>');
                   4465:                             }
                   4466:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4467:                         }
                   4468:                     }
                   4469:                 } else {
                   4470:                     if ($altkey) {
                   4471:                         if ($recursive) {
                   4472:                             if (exists($$olddata{$thiskey})) {
                   4473:                                 if ($$olddata{$thiskey} eq $data) {
                   4474:                                     $reconlychg = 1;
                   4475:                                 }
                   4476:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4477:                             }
                   4478:                             if (exists($$olddata{$altkey})) {
                   4479:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4480:                                     $haschange = 1;
                   4481:                                 }
                   4482:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4483:                                 $haschange = 1;
                   4484:                             }
                   4485:                             $storekey = $altkey;
1.563     damieng  4486:                         } else {
1.576     raeburn  4487:                             if (exists($$olddata{$altkey})) {
                   4488:                                 if ($$olddata{$altkey} eq $data) {
                   4489:                                     $reconlychg = 1;
                   4490:                                 }
                   4491:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4492:                             } 
                   4493:                             if (exists($$olddata{$thiskey})) {
                   4494:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4495:                                     $haschange = 1;
                   4496:                                 }
                   4497:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4498:                                 $haschange = 1;
                   4499:                             }
                   4500:                             $storekey = $thiskey;
1.563     damieng  4501:                         }
1.560     damieng  4502:                     } else {
1.576     raeburn  4503:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4504:                             $haschange = 1;
                   4505:                             $storekey = $thiskey;
                   4506:                         }
                   4507:                     }
                   4508:                 }
                   4509:                 if ($reconlychg || $haschange) {
                   4510:                     unless ($env{'form.del_'.$thiskey}) {
                   4511:                         $newdata{$storekey}=$data;
                   4512:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4513:                     }
                   4514:                 }
                   4515:             } elsif ($cmd eq 'del') {
                   4516:                 if ($tuname) {
1.576     raeburn  4517:                     my $error;
                   4518:                     if ($altkey) {  
                   4519:                         if (exists($$olddata{$altkey})) {
                   4520:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4521:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4522:                                 if ($recursive) {
                   4523:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4524:                                 }
                   4525:                             } elsif ($recursive) {
                   4526:                                 $error = 1;
                   4527:                             }
                   4528:                         }
                   4529:                         if (exists($$olddata{$thiskey})) {
                   4530:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4531:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4532:                                 unless ($recursive) {
                   4533:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4534:                                 }
                   4535:                             } elsif (!$recursive) {
                   4536:                                 $error = 1;
                   4537:                             }
                   4538:                         }
1.560     damieng  4539:                     } else {
1.576     raeburn  4540:                         if (exists($$olddata{$thiskey})) {
                   4541:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4542:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4543:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4544:                             } else {
                   4545:                                 $error = 1;
                   4546:                             }
                   4547:                         }
                   4548:                     }
                   4549:                     if ($error) { 
1.560     damieng  4550:                         $r->print('<div class="LC_error">'.
                   4551:                             &mt('Error deleting parameters').'</div>');
                   4552:                     }
                   4553:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4554:                 } else {
1.576     raeburn  4555:                     if ($altkey) {
                   4556:                         if (exists($$olddata{$altkey})) {
                   4557:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4558:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4559:                             }
                   4560:                         }
                   4561:                         if (exists($$olddata{$thiskey})) {
                   4562:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4563:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4564:                             }
                   4565:                         }
                   4566:                     } elsif (exists($$olddata{$thiskey})) {
                   4567:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4568:                     }
1.560     damieng  4569:                 }
1.473     amueller 4570:             }
                   4571:         }
                   4572:     }
1.207     www      4573: # Store all course level
1.144     www      4574:     my $delentries=$#deldata+1;
1.576     raeburn  4575:     my @alldels;
                   4576:     if (@delrec) {
                   4577:         push(@alldels,@delrec);
                   4578:     }
                   4579:     if (@delnonrec) {
                   4580:         push(@alldels,@delnonrec);
                   4581:     }
                   4582:     if (@deldata) {
                   4583:         push(@alldels,@deldata);
                   4584:     }
1.548     raeburn  4585:     my @newdatakeys=keys(%newdata);
1.144     www      4586:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4587:     my ($delresult,$devalidate);
                   4588:     if (@alldels) {
                   4589:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4590:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4591:             &log_parmset(\%loghash,1);
1.576     raeburn  4592:             if ($delentries) {
                   4593:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4594:             }
                   4595:         } elsif ($delentries) {
1.560     damieng  4596:             $r->print('<div class="LC_error">'.
                   4597:                 &mt('Error deleting parameters').'</div>');
                   4598:         }
1.576     raeburn  4599:         $devalidate = 1; 
1.144     www      4600:     }
                   4601:     if ($putentries) {
1.560     damieng  4602:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4603:                     &log_parmset(\%newdata,0);
                   4604:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4605:         } else {
                   4606:             $r->print('<div class="LC_error">'.
                   4607:                 &mt('Error saving parameters').'</div>');
                   4608:         }
1.576     raeburn  4609:         $devalidate = 1; 
                   4610:     }
                   4611:     if ($devalidate) {
1.560     damieng  4612:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4613:     }
1.208     www      4614: }
1.207     www      4615: 
1.563     damieng  4616: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4617: #
                   4618: # @param {string} $key - the key
                   4619: # @returns {Array}
1.208     www      4620: sub extractuser {
                   4621:     my $key=shift;
1.350     albertel 4622:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4623: }
1.206     www      4624: 
1.563     damieng  4625: # Parses a parameter key and returns the components.
                   4626: #
                   4627: # @param {string} $key - 
                   4628: # @param {hash reference} $listdata - 
                   4629: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4630: sub parse_listdata_key {
                   4631:     my ($key,$listdata) = @_;
                   4632:     # split into student/section affected, and
                   4633:     # the realm (folder/resource part and parameter
1.446     bisitz   4634:     my ($student,$realm) =
1.473     amueller 4635:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4636:     # if course wide student would be undefined
                   4637:     if (!defined($student)) {
1.560     damieng  4638:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4639:     }
                   4640:     # strip off the .type if it's not the Question type parameter
                   4641:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4642:         $realm=~s/\.type//;
1.381     albertel 4643:     }
                   4644:     # split into resource+part and parameter name
1.388     albertel 4645:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4646:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4647:     return ($student,$res,$part,$parm);
                   4648: }
                   4649: 
1.563     damieng  4650: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4651: #
                   4652: # @param {Apache2::RequestRec} $r - the Apache request
                   4653: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4654: # @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
                   4655: # @param {string} $sortorder - realmstudent|studentrealm
                   4656: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4657: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4658: # @param {boolean} $readonly - true if editing not allowed
1.563     damieng  4659: # @returns{integer} - number of $listdata parameters processed
1.208     www      4660: sub listdata {
1.568     raeburn  4661:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552     raeburn  4662:     
1.207     www      4663: # Start list output
1.206     www      4664: 
1.122     www      4665:     my $oldsection='';
                   4666:     my $oldrealm='';
                   4667:     my $oldpart='';
1.123     www      4668:     my $pointer=0;
1.124     www      4669:     $tableopen=0;
1.145     www      4670:     my $foundkeys=0;
1.248     albertel 4671:     my %keyorder=&standardkeyorder();
1.594     raeburn  4672:     my $readonlyall = $readonly;
1.381     albertel 4673: 
1.552     raeburn  4674:     my ($secidx,%grouphash);
                   4675:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4676:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4677:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4678:             %grouphash = &Apache::longroup::coursegroups();
                   4679:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4680:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4681:         }
1.552     raeburn  4682:     }
                   4683: 
1.576     raeburn  4684:     foreach my $key (sort {
1.560     damieng  4685:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4686:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381     albertel 4687: 
1.560     damieng  4688:         # get the numerical order for the param
                   4689:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4690:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4691: 
1.560     damieng  4692:         my $result=0;
1.381     albertel 4693: 
1.560     damieng  4694:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4695:             if ($ares     ne $bres    ) {
1.560     damieng  4696:                 $result = ($ares     cmp $bres);
1.446     bisitz   4697:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4698:                 $result = ($astudent cmp $bstudent);
                   4699:             } elsif ($apart    ne $bpart   ) {
                   4700:                 $result = ($apart    cmp $bpart);
                   4701:             }
                   4702:         } else {
                   4703:             if      ($astudent ne $bstudent) {
                   4704:                 $result = ($astudent cmp $bstudent);
                   4705:             } elsif ($ares     ne $bres    ) {
                   4706:                 $result = ($ares     cmp $bres);
                   4707:             } elsif ($apart    ne $bpart   ) {
                   4708:                 $result = ($apart    cmp $bpart);
                   4709:             }
1.473     amueller 4710:         }
1.446     bisitz   4711: 
1.560     damieng  4712:         if (!$result) {
1.381     albertel 4713:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4714:                 $result = ($aparm <=> $bparm);
1.381     albertel 4715:             } elsif (defined($aparm)) {
1.560     damieng  4716:                 $result = -1;
1.381     albertel 4717:             } elsif (defined($bparm)) {
1.560     damieng  4718:                 $result = 1;
                   4719:             }
1.473     amueller 4720:         }
1.381     albertel 4721: 
1.560     damieng  4722:         $result;
                   4723:         
1.576     raeburn  4724:     } keys(%{$listdata})) { # foreach my $key
                   4725:         my $thiskey = $key;
1.560     damieng  4726:         if ($$listdata{$thiskey.'.type'}) {
                   4727:             my $thistype=$$listdata{$thiskey.'.type'};
                   4728:             if ($$resourcedata{$thiskey.'.type'}) {
                   4729:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4730:             }
                   4731:             my ($middle,$part,$name)=
1.572     damieng  4732:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4733:             my $section=&mt('All Students');
1.594     raeburn  4734:             $readonly = $readonlyall;
1.599     raeburn  4735:             my $userscope;
1.576     raeburn  4736:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4737:             if ($middle=~/^\[(.*)\]/) {
                   4738:                 my $issection=$1;
                   4739:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4740:                     my ($stuname,$studom) = ($1,$2);
                   4741:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4742:                         if (ref($classlist) eq 'HASH') {
                   4743:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4744:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4745:                             }
                   4746:                         }
                   4747:                     }
                   4748:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4749:                     $userscope = 1;
1.560     damieng  4750:                 } else {
                   4751:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4752:                         if (exists($grouphash{$issection})) {
                   4753:                             $section=&mt('Group').': '.$issection;
                   4754:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4755:                             $section = &mt('Section').': '.$issection;
                   4756:                         } else {
                   4757:                             next; 
1.552     raeburn  4758:                         }
1.560     damieng  4759:                     } else {
                   4760:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4761:                     }
                   4762:                 }
1.560     damieng  4763:                 $middle=~s/^\[(.*)\]//;
                   4764:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4765:                 $readonly = 1;
                   4766:             }
                   4767:             $middle=~s/\.+$//;
                   4768:             $middle=~s/^\.+//;
                   4769:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4770:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4771:             if ($caller eq 'overview') {
                   4772:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4773:                     $mapurl = $1;
                   4774:                     $maplevel = $2;
                   4775:                     $is_map = 1;
                   4776:                 }
                   4777:             } elsif ($caller eq 'newoverview') {
                   4778:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4779:                     $mapurl = $1;
                   4780:                     $maplevel = $2;
                   4781:                     $is_map = 1;
                   4782:                 }
                   4783:             }
                   4784:             if ($is_map) {
1.560     damieng  4785:                 my $leveltitle = &mt('Folder/Map');
1.576     raeburn  4786:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4787:                     if ($caller eq 'newoverview') {
                   4788:                         my $altkey = $thiskey;
                   4789:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4790:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4791:                             $is_recursive = 1;
                   4792:                             if ($$resourcedata{$altkey.'.type'}) {
                   4793:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4794:                             }
                   4795:                             $showval = $$resourcedata{$altkey};
                   4796:                         }
                   4797:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4798:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4799:                         $is_recursive = 1;
                   4800:                     }
1.560     damieng  4801:                 }
                   4802:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
                   4803:             } elsif ($middle) {
                   4804:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   4805:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4806:                     ': '.&Apache::lonnet::gettitle($middle).
                   4807:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4808:                     $id.')</span></span>';
                   4809:             }
                   4810:             if ($sortorder eq 'realmstudent') {
                   4811:                 if ($realm ne $oldrealm) {
                   4812:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4813:                     $oldrealm=$realm;
                   4814:                     $oldsection='';
                   4815:                 }
                   4816:                 if ($section ne $oldsection) {
                   4817:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4818:                     $oldsection=$section;
                   4819:                     $oldpart='';
                   4820:                 }
1.552     raeburn  4821:             } else {
1.560     damieng  4822:                 if ($section ne $oldsection) {
                   4823:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4824:                     $oldsection=$section;
                   4825:                     $oldrealm='';
                   4826:                 }
                   4827:                 if ($realm ne $oldrealm) {
                   4828:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4829:                     $oldrealm=$realm;
                   4830:                     $oldpart='';
1.552     raeburn  4831:                 }
                   4832:             }
1.560     damieng  4833:             if ($part ne $oldpart) {
                   4834:                 $r->print(&tableend().
                   4835:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4836:                 $oldpart=$part;
1.556     raeburn  4837:             }
1.560     damieng  4838:     #
                   4839:     # Ready to print
                   4840:     #
1.470     raeburn  4841:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  4842:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  4843:                 &Apache::loncommon::start_data_table_row().
                   4844:                 '<td><b>'.&mt($parmitem).
                   4845:                 '</b></td>');
                   4846:             unless ($readonly) {
1.599     raeburn  4847:                 my $disabled;
                   4848:                 if (($name eq 'availablestudent') &&
                   4849:                     (($showval eq '') || ($userscope))) {
                   4850:                     $disabled = ' disabled="disabled"';
                   4851:                 }
1.560     damieng  4852:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  4853:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  4854:             }
                   4855:             $r->print('<td>');
                   4856:             $foundkeys++;
                   4857:             if (&isdateparm($thistype)) {
                   4858:                 my $jskey='key_'.$pointer;
                   4859:                 my $state;
                   4860:                 $pointer++;
                   4861:                 if ($readonly) {
                   4862:                     $state = 'disabled';
                   4863:                 }
                   4864:                 $r->print(
                   4865:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4866:                                                         $jskey,
1.576     raeburn  4867:                                                         $showval,
1.560     damieng  4868:                                                         '',1,$state));
                   4869:                 unless  ($readonly) {
                   4870:                     $r->print(
                   4871:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  4872:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  4873:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  4874:     &date_sanity_info($showval)
1.560     damieng  4875:                     );
                   4876:                 }
                   4877:             } elsif ($thistype eq 'date_interval') {
                   4878:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  4879:                           $showval,$readonly));
1.560     damieng  4880:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  4881:                 if ($name eq 'availablestudent') {
                   4882:                     $readonly = 1;
                   4883:                 }
1.560     damieng  4884:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  4885:                           $showval,$name,$readonly));
1.560     damieng  4886:             } else {
1.576     raeburn  4887:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  4888:             }
1.560     damieng  4889:             unless ($readonly) {
                   4890:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   4891:                         $thistype.'" />');
1.552     raeburn  4892:             }
1.576     raeburn  4893:             $r->print('</td>');
                   4894:             if ($is_map) {
                   4895:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   4896:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   4897:                 } else {
                   4898:                     my ($disabled,$recon,$recoff);
                   4899:                     if ($readonly) {
                   4900:                         $disabled = ' disabled="disabled"';
                   4901:                     }
                   4902:                     if ($is_recursive) {
                   4903:                         $recon = ' checked="checked"';
                   4904:                     } else {
                   4905:                         $recoff = ' checked="checked"';
                   4906:                     }
                   4907:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   4908:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   4909:                 }
                   4910:             }
                   4911:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 4912:         }
1.121     www      4913:     }
1.208     www      4914:     return $foundkeys;
                   4915: }
                   4916: 
1.563     damieng  4917: # Returns a string representing the interval, directly using form data matching the given key.
                   4918: # The returned string may also include information related to proctored exams.
                   4919: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   4920: #
                   4921: # @param {string} $key - suffix for form fields related to the interval
                   4922: # @returns {string}
1.385     albertel 4923: sub get_date_interval_from_form {
                   4924:     my ($key) = @_;
                   4925:     my $seconds = 0;
                   4926:     foreach my $which (['days', 86400],
1.473     amueller 4927:                ['hours', 3600],
                   4928:                ['minutes', 60],
                   4929:                ['seconds',  1]) {
1.560     damieng  4930:         my ($name, $factor) = @{ $which };
                   4931:         if (defined($env{'form.'.$name.'_'.$key})) {
                   4932:             $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   4933:         }
1.473     amueller 4934:     }
1.560     damieng  4935:     if (($key =~ /\.interval$/) &&
                   4936:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  4937:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   4938:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   4939:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   4940:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   4941:                 $seconds .= '_proctor';
                   4942:             }
                   4943:         } else {
                   4944:             $seconds .= $env{'form.done_'.$key}; 
                   4945:         }
                   4946:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  4947:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  4948:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   4949:         }
1.554     raeburn  4950:     }
1.385     albertel 4951:     return $seconds;
                   4952: }
                   4953: 
                   4954: 
1.563     damieng  4955: # Returns HTML to enter a text value for a parameter.
                   4956: #
                   4957: # @param {string} $thiskey - parameter key
                   4958: # @param {string} $showval - the current value
                   4959: # @param {boolean} $readonly - true if the field should not be made editable
                   4960: # @returns {string}
1.383     albertel 4961: sub default_selector {
1.552     raeburn  4962:     my ($thiskey, $showval, $readonly) = @_;
                   4963:     my $disabled;
                   4964:     if ($readonly) {
                   4965:         $disabled = ' disabled="disabled"';
                   4966:     }
                   4967:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 4968: }
                   4969: 
1.563     damieng  4970: # Returns HTML to enter allow/deny rules related to IP addresses.
                   4971: #
                   4972: # @param {string} $thiskey - parameter key
                   4973: # @param {string} $showval - the current value
                   4974: # @param {boolean} $readonly - true if the fields should not be made editable
                   4975: # @returns {string}
1.549     raeburn  4976: sub string_ip_selector {
1.552     raeburn  4977:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  4978:     my %access = (
                   4979:                    allow => [],
                   4980:                    deny  => [],
                   4981:                  );
                   4982:     if ($showval ne '') {
                   4983:         my @current;
                   4984:         if ($showval =~ /,/) {
                   4985:             @current = split(/,/,$showval);
                   4986:         } else {
                   4987:             @current = ($showval);
                   4988:         }
                   4989:         foreach my $item (@current) {
                   4990:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4991:                 push(@{$access{'deny'}},$1);
                   4992:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4993:                 push(@{$access{'allow'}},$item);
                   4994:             }
                   4995:         }
                   4996:     }
                   4997:     if (!@{$access{'allow'}}) {
                   4998:         @{$access{'allow'}} = ('');
                   4999:     }
                   5000:     if (!@{$access{'deny'}}) {
                   5001:         @{$access{'deny'}} = ('');
                   5002:     }
1.552     raeburn  5003:     my ($disabled,$addmore);
1.567     raeburn  5004:     if ($readonly) {
1.552     raeburn  5005:         $disabled=' disabled="disabled"';
                   5006:     } else {
                   5007:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5008:     }
1.549     raeburn  5009:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5010: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5011:     foreach my $acctype ('allow','deny') {
                   5012:         $output .= '
                   5013: <td valign="top">
                   5014: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5015:   <div class="LC_string_ipacc_inner">'."\n";
                   5016:         my $num = 0;
                   5017:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5018:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5019:             if ($num > 0) {
                   5020:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5021:             }
                   5022:             $output .= '</div>'."\n";
                   5023:             $num ++;
                   5024:         }
                   5025:         $output .= '
1.552     raeburn  5026:   </div>'.$addmore.'
1.549     raeburn  5027: </div>
                   5028: </td>';
                   5029:    }
                   5030:    $output .= '
                   5031: </tr>
                   5032: </table>'."\n";
                   5033:     return $output;
                   5034: }
                   5035: 
1.588     raeburn  5036: sub string_deeplink_selector {
                   5037:     my ($thiskey, $showval, $readonly) = @_;
1.597     raeburn  5038:     my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601     raeburn  5039:         %selectnull,%domlti,%crslti,@possmenus);
                   5040:     @components = ('state','others','listing','scope','protect','menus');
1.588     raeburn  5041:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5042:                   state   => 'Access status',
                   5043:                   others  => 'Hide other resources',
1.588     raeburn  5044:                   listing => 'In Contents and/or Gradebook',
                   5045:                   scope   => 'Access scope for link',
1.601     raeburn  5046:                   protect => 'Link protection',
1.597     raeburn  5047:                   menus   => 'Menu Items Displayed',
1.588     raeburn  5048:               );
                   5049:     %options = (
1.601     raeburn  5050:                    state   => ['only','off','both'],
                   5051:                    others  => ['hide','unhide'],
1.588     raeburn  5052:                    listing => ['full','absent','grades','details','datestatus'],
                   5053:                    scope   => ['res','map','rec'],
1.601     raeburn  5054:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5055:                    menus   => ['std','colls'],
1.588     raeburn  5056:                );
                   5057:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5058:                     only       => 'deep only',
                   5059:                     off        => 'deeplink off',
                   5060:                     both       => 'regular + deep',
                   5061:                     hide       => 'Hidden',
                   5062:                     unhide     => 'Unhidden',
1.588     raeburn  5063:                     full       => 'Listed (linked) in both',
                   5064:                     absent     => 'Not listed',
                   5065:                     grades     => 'Listed in grades only',
                   5066:                     details    => 'Listed (unlinked) in both',
                   5067:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5068:                     res        => 'resource only',
                   5069:                     map        => 'enclosing map/folder',
                   5070:                     rec        => 'recursive map/folder',
1.601     raeburn  5071:                     none       => 'not in use',
                   5072:                     key        => 'key access',
                   5073:                     ltic       => 'LTI access (course)',
                   5074:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5075:                     std        => 'Standard (all menus)',
                   5076:                     colls      => 'Numbered collection',
                   5077:                   );
                   5078:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5079:                     ltic => 'Select Launcher',
                   5080:                     ltid => 'Select Launcher', 
1.597     raeburn  5081:                     colls => 'Select',
1.588     raeburn  5082:                   );
                   5083:     if ($showval =~ /,/) {
1.597     raeburn  5084:         %values=();
1.588     raeburn  5085:         @current = split(/,/,$showval);
1.601     raeburn  5086:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5087:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5088:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5089:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5090:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5091:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.588     raeburn  5092:     } else {
1.601     raeburn  5093:         $defaults{'state'} = 'off',
                   5094:         $defaults{'others'} = 'unhide',
1.588     raeburn  5095:         $defaults{'listing'} = 'full';
                   5096:         $defaults{'scope'} = 'res';
1.601     raeburn  5097:         $defaults{'protect'} = 'none';
1.597     raeburn  5098:         $defaults{'menus'} = '0';
1.588     raeburn  5099:     }
                   5100:     my $disabled;
                   5101:     if ($readonly) {
                   5102:         $disabled=' disabled="disabled"';
                   5103:     }
1.601     raeburn  5104:     my %courselti =
                   5105:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5106:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5107:     foreach my $item (keys(%courselti)) {
                   5108:         if (ref($courselti{$item}) eq 'HASH') {
                   5109:             $crslti{$item} = $courselti{$item}{'name'};
                   5110:         }
                   5111:     }
                   5112:     my %lti =
1.588     raeburn  5113:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
                   5114:                                         'provider');
                   5115:     foreach my $item (keys(%lti)) {
                   5116:         if (ref($lti{$item}) eq 'HASH') {
                   5117:             unless ($lti{$item}{'requser'}) {
1.601     raeburn  5118:                 $domlti{$item} = $lti{$item}{'consumer'};
1.588     raeburn  5119:             }
                   5120:         }
                   5121:     }
1.597     raeburn  5122:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5123:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5124:             my ($num,$value) = split(/\%/,$item);
                   5125:             if ($num =~ /^\d+$/) {
                   5126:                 push(@possmenus,$num);
                   5127:             }
                   5128:         }
                   5129:     }
                   5130: 
1.588     raeburn  5131:     my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597     raeburn  5132:     foreach my $item (@components) {
1.588     raeburn  5133:         $output .= '<th>'.$titles{$item}.'</th>';
                   5134:     }
                   5135:     $output .= '</tr><tr>';
                   5136:     foreach my $item (@components) {
                   5137:         $output .= '<td>';
1.601     raeburn  5138:         if (($item eq 'protect') || ($item eq 'menus')) {
1.588     raeburn  5139:             my $selected = $values{$item};
                   5140:             foreach my $option (@{$options{$item}}) {
1.601     raeburn  5141:                 if ($item eq 'protect') { 
                   5142:                     if ($option eq 'ltid') {
                   5143:                         next unless (keys(%domlti));
                   5144:                     } elsif ($option eq 'ltic') {
                   5145:                         next unless (keys(%crslti));
                   5146:                     }
1.597     raeburn  5147:                 } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5148:                     next unless (@possmenus);
1.588     raeburn  5149:                 }
                   5150:                 my $checked;
1.597     raeburn  5151:                 if ($item eq 'menus') {
                   5152:                     if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5153:                         (grep(/^\Q$selected\E$/,@possmenus))) {
                   5154:                         if ($option eq 'colls') {
                   5155:                             $checked = ' checked="checked"';
                   5156:                         }
                   5157:                     } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
                   5158:                         $checked = ' checked="checked"';
                   5159:                     }
                   5160:                 } elsif ($selected =~ /^\Q$option\E/) {
1.588     raeburn  5161:                     $checked = ' checked="checked"';
                   5162:                 }
                   5163:                 my $onclick;
                   5164:                 unless ($readonly) {
                   5165:                     my $esc_key = &js_escape($thiskey);
                   5166:                     $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5167:                 }
                   5168:                 $output .= '<span class="LC_nobreak"><label>'.
                   5169:                            '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5170:                            $optiontext{$option}.'</label>';
1.601     raeburn  5171:                 if (($item eq 'protect') && ($option eq 'key')) {
1.588     raeburn  5172:                     my $visibility="hidden";
                   5173:                     my $currkey;
                   5174:                     if ($checked) {
                   5175:                         $visibility = "text";
                   5176:                         $currkey = (split(/\:/,$values{$item}))[1];
                   5177:                     }
                   5178:                     $output .= '&nbsp;'.
1.597     raeburn  5179:                         '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601     raeburn  5180:                 } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588     raeburn  5181:                     my $display="none";
1.597     raeburn  5182:                     my ($current,$blankcheck,@possibles);
1.588     raeburn  5183:                     if ($checked) {
                   5184:                         $display = 'inline-block';
1.601     raeburn  5185:                         if (($option eq 'ltic') || ($option eq 'ltid'))  {
1.597     raeburn  5186:                             $current = (split(/\:/,$selected))[1];
                   5187:                         } else {
                   5188:                             $current = $selected;
                   5189:                         }
1.588     raeburn  5190:                     } else {
                   5191:                         $blankcheck = ' selected="selected"';
                   5192:                     }
1.601     raeburn  5193:                     if ($option eq 'ltid') {
                   5194:                         @possibles = keys(%domlti);
                   5195:                     } elsif ($option eq 'ltic') {
                   5196:                         @possibles = keys(%crslti); 
1.597     raeburn  5197:                     } else {
                   5198:                         @possibles = @possmenus;
                   5199:                     }
1.588     raeburn  5200:                     $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5201:                                ' style="display: '.$display.'">&nbsp;<select name="'.
1.597     raeburn  5202:                                'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5203:                     if (@possibles > 1) {
                   5204:                         $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5205:                                    '</option>'."\n";
                   5206:                     }
                   5207:                     foreach my $poss (sort { $a <=> $b } @possibles) {
1.588     raeburn  5208:                         my $selected;
1.597     raeburn  5209:                         if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588     raeburn  5210:                             $selected = ' selected="selected"';
                   5211:                         }
1.597     raeburn  5212:                         my $shown = $poss;
1.601     raeburn  5213:                         if ($option eq 'ltid') {
                   5214:                             $shown = $domlti{$poss};
                   5215:                         } elsif ($option eq 'ltic') {
                   5216:                             $shown = $crslti{$poss};
1.597     raeburn  5217:                         }
                   5218:                         $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588     raeburn  5219:                     }
                   5220:                     $output .= '</select></div>';
                   5221:                 }
                   5222:                 $output .= '</span> ';
                   5223:             }
                   5224:         } else {
                   5225:             my $selected = $values{$item};
                   5226:             my $defsel;
                   5227:             if ($selected eq '') {
                   5228:                 $defsel = ' selected="selected"';
                   5229:             }
                   5230:             $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5231:                        '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5232:             foreach my $option (@{$options{$item}}) {
                   5233:                 $output .= '<option value="'.$option.'"';
                   5234:                 if ($option eq $selected) {
                   5235:                     $output .= ' selected="selected"';
                   5236:                 }
                   5237:                 $output .= '>'.$optiontext{$option}.'</option>';
                   5238:             }
                   5239:             $output .= '</select>';
                   5240:         }
                   5241:         $output .= '</td>';
                   5242:     }
                   5243:     $output .= '</tr></table>'."\n";
                   5244:     return $output;
                   5245: }
                   5246: 
1.560     damieng  5247: 
                   5248: { # block using some constants related to parameter types (overview mode)
                   5249: 
1.446     bisitz   5250: my %strings =
1.383     albertel 5251:     (
                   5252:      'string_yesno'
                   5253:              => [[ 'yes', 'Yes' ],
1.560     damieng  5254:                  [ 'no', 'No' ]],
1.383     albertel 5255:      'string_problemstatus'
                   5256:              => [[ 'yes', 'Yes' ],
1.473     amueller 5257:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5258:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5259:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5260:      'string_questiontype'
                   5261:              => [[ 'problem', 'Standard Problem'],
                   5262:                  [ 'survey', 'Survey'],
                   5263:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5264:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5265:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5266:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5267:                  [ 'practice', 'Practice'],
                   5268:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5269:      'string_lenient'
                   5270:              => [['yes', 'Yes' ],
                   5271:                  [ 'no', 'No' ],
1.549     raeburn  5272:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5273:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5274:      'string_discussvote'
                   5275:              => [['yes','Yes'],
                   5276:                  ['notended','Yes, unless discussion ended'],
                   5277:                  ['no','No']],
1.549     raeburn  5278:      'string_ip'
                   5279:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5280:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5281:      'string_deeplink'
1.597     raeburn  5282:              => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
1.587     raeburn  5283:     );
                   5284:    
1.383     albertel 5285: 
1.549     raeburn  5286: my %stringmatches = (
                   5287:          'string_lenient'
                   5288:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5289:          'string_ip'
                   5290:               => [['_allowfrom_','[^\!]+'],
                   5291:                   ['_denyfrom_','\!']],
1.588     raeburn  5292:          'string_deeplink'
1.602     raeburn  5293:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)$']],
1.549     raeburn  5294:     );
                   5295: 
                   5296: my %stringtypes = (
                   5297:                     type         => 'string_questiontype',
                   5298:                     lenient      => 'string_lenient',
                   5299:                     retrypartial => 'string_yesno',
                   5300:                     discussvote  => 'string_discussvote',
                   5301:                     examcode     => 'string_examcode',
                   5302:                     acc          => 'string_ip',
1.587     raeburn  5303:                     deeplink     => 'string_deeplink',
1.549     raeburn  5304:                   );
                   5305: 
1.563     damieng  5306: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5307: # Used by courseprefs.
                   5308: #
                   5309: # @param {string} $string_type - a parameter type for strings
                   5310: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5311: sub standard_string_options {
                   5312:     my ($string_type) = @_;
                   5313:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5314:         return $strings{$string_type};
                   5315:     }
                   5316:     return;
                   5317: }
1.383     albertel 5318: 
1.563     damieng  5319: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5320: #
                   5321: # @param {string} $string_type - a parameter type for strings
                   5322: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5323: sub standard_string_matches {
                   5324:     my ($string_type) = @_;
                   5325:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5326:         return $stringmatches{$string_type};
                   5327:     }
                   5328:     return;
                   5329: }
                   5330: 
1.563     damieng  5331: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5332: #
                   5333: # @param {string} $name - parameter name
                   5334: # @returns {string}
1.549     raeburn  5335: sub get_stringtype {
                   5336:     my ($name) = @_;
                   5337:     if (exists($stringtypes{$name})) {
                   5338:         return $stringtypes{$name};
                   5339:     }
                   5340:     return;
                   5341: }
                   5342: 
1.563     damieng  5343: # Returns HTML to edit a string parameter.
                   5344: #
                   5345: # @param {string} $thistype - parameter type
                   5346: # @param {string} $thiskey - parameter key
                   5347: # @param {string} $showval - parameter current value
                   5348: # @param {string} $name - parameter name
                   5349: # @param {boolean} $readonly - true if the values should not be made editable
                   5350: # @returns {string}
1.383     albertel 5351: sub string_selector {
1.552     raeburn  5352:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5353: 
1.383     albertel 5354:     if (!exists($strings{$thistype})) {
1.552     raeburn  5355:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5356:     }
                   5357: 
1.504     raeburn  5358:     my %skiptype;
1.514     raeburn  5359:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5360:             ($thistype eq 'string_lenient') ||
                   5361:             ($thistype eq 'string_discussvote') ||
                   5362:             ($thistype eq 'string_ip') ||
1.588     raeburn  5363:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5364:             ($name eq 'retrypartial')) {
1.504     raeburn  5365:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5366:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5367:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5368:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5369:             my $parmmatch;
                   5370:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5371:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5372:                     if (ref($item) eq 'ARRAY') {
                   5373:                         if ($parmval eq $item->[0]) {
                   5374:                             $parmmatch = $parmval;
                   5375:                             $parmval = '';
                   5376:                             last;
                   5377:                         }
                   5378:                     }
                   5379:                 }
                   5380:             }
                   5381:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5382:             if ($needsrelease) {
                   5383:                 unless ($got_chostname) {
1.514     raeburn  5384:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5385:                     $got_chostname = 1;
                   5386:                 }
1.557     raeburn  5387:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5388:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5389:                 if ($needsnewer) {
1.549     raeburn  5390:                     if ($parmmatch ne '') {
                   5391:                         $skiptype{$parmmatch} = 1;
                   5392:                     } elsif ($parmval ne '') {
                   5393:                         $skiptype{$parmval} = 1;
                   5394:                     }
1.504     raeburn  5395:                 }
                   5396:             }
                   5397:         }
                   5398:     }
1.549     raeburn  5399: 
                   5400:     if ($thistype eq 'string_ip') {
1.552     raeburn  5401:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5402:     } elsif ($thistype eq 'string_deeplink') {
                   5403:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5404:     }
1.504     raeburn  5405: 
1.552     raeburn  5406:     my ($result,$disabled);
                   5407: 
                   5408:     if ($readonly) {
                   5409:         $disabled = ' disabled="disabled"';
                   5410:     }
1.504     raeburn  5411:     my $numinrow = 3;
                   5412:     if ($thistype eq 'string_problemstatus') {
                   5413:         $numinrow = 2;
                   5414:     } elsif ($thistype eq 'string_questiontype') {
                   5415:         if (keys(%skiptype) > 0) {
                   5416:              $numinrow = 4;
                   5417:         }
                   5418:     }
                   5419:     my $rem;
                   5420:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5421:         my $i=0;
                   5422:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5423:             next unless (ref($possibilities) eq 'ARRAY');
                   5424:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5425:             next if ($skiptype{$name});
1.504     raeburn  5426:             $rem = $i%($numinrow);
                   5427:             if ($rem == 0) {
                   5428:                 if ($i > 0) {
                   5429:                     $result .= '</tr>';
                   5430:                 }
                   5431:                 $result .= '<tr>';
                   5432:             }
1.549     raeburn  5433:             my $colspan;
                   5434:             if ($i == @{ $strings{$thistype} }-1) {
                   5435:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5436:                 if ($rem) {
                   5437:                     my $colsleft = $numinrow - $rem;
                   5438:                     if ($colsleft) {
                   5439:                         $colspan = $colsleft+1;
                   5440:                         $colspan = ' colspan="'.$colspan.'"';
                   5441:                     }
                   5442:                 }
                   5443:             }
                   5444:             my ($add,$onchange,$css_class);
                   5445:             if ($thistype eq 'string_lenient') {
                   5446:                 if ($name eq 'weighted') {
                   5447:                     my $display;
                   5448:                     my %relatives = &Apache::lonlocal::texthash(
                   5449:                                         corrchkd     => 'Correct (checked)',
                   5450:                                         corrunchkd   => 'Correct (unchecked)',
                   5451:                                         incorrchkd   => 'Incorrect (checked)',
                   5452:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5453:                     );
                   5454:                     my %textval = (
                   5455:                                     corrchkd     => '1.0',
                   5456:                                     corrunchkd   => '1.0',
                   5457:                                     incorrchkd   => '0.0',
                   5458:                                     incorrunchkd => '0.0',
                   5459:                     );
                   5460:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5461:                         $textval{'corrchkd'} = $1;
                   5462:                         $textval{'corrunchkd'} = $2;
                   5463:                         $textval{'incorrchkd'} = $3;
                   5464:                         $textval{'incorrunchkd'} = $4;
                   5465:                         $display = 'inline';
                   5466:                         $showval = $name;
                   5467:                     } else {
                   5468:                         $display = 'none';
                   5469:                     }
                   5470:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5471:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5472:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5473:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5474:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5475:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5476:                                 '</td></tr>';
                   5477:                     }
                   5478:                     $add .= '</table></div>'."\n";
                   5479:                 }
                   5480:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5481:                 $css_class = ' class="LC_lenient_radio"';
                   5482:             }
                   5483:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5484:                        '<span class="LC_nobreak"><label>'.
                   5485:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5486:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5487:             if ($showval eq $name) {
                   5488:                 $result .= ' checked="checked"';
                   5489:             }
1.549     raeburn  5490:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5491:             $i++;
                   5492:         }
                   5493:         $result .= '</tr>';
1.473     amueller 5494:     }
1.504     raeburn  5495:     if ($result) {
                   5496:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5497:     }
                   5498:     return $result;
                   5499: }
                   5500: 
1.554     raeburn  5501: my %intervals =
                   5502:     (
                   5503:      'date_interval'
                   5504:              => [[ 'done', 'Yes' ],
1.558     raeburn  5505:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5506:                  [ '', 'No' ]],
                   5507:     );
                   5508: 
                   5509: my %intervalmatches = (
                   5510:          'date_interval'
1.559     raeburn  5511:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5512:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5513:     );
                   5514: 
                   5515: my %intervaltypes = (
                   5516:                       interval => 'date_interval',
                   5517:     );
                   5518: 
1.563     damieng  5519: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5520: #
                   5521: # @param {string} $interval_type - a parameter type for intervals
                   5522: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5523: sub standard_interval_matches {
                   5524:     my ($interval_type) = @_;
                   5525:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5526:         return $intervalmatches{$interval_type};
                   5527:     }
                   5528:     return;
                   5529: }
                   5530: 
1.563     damieng  5531: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5532: #
                   5533: # @param {string} $name - parameter name
                   5534: # @returns {string}
1.554     raeburn  5535: sub get_intervaltype {
                   5536:     my ($name) = @_;
                   5537:     if (exists($intervaltypes{$name})) {
                   5538:         return $intervaltypes{$name};
                   5539:     }
                   5540:     return;
                   5541: }
                   5542: 
1.563     damieng  5543: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5544: # Used by courseprefs.
                   5545: #
                   5546: # @param {string} $interval_type - a parameter type for intervals
                   5547: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5548: sub standard_interval_options {
                   5549:     my ($interval_type) = @_;
                   5550:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5551:         return $intervals{$interval_type};
                   5552:     }
                   5553:     return;
                   5554: }
                   5555: 
1.563     damieng  5556: # Returns HTML to edit a date interval parameter.
                   5557: #
                   5558: # @param {string} $thiskey - parameter key
                   5559: # @param {string} $name - parameter name
                   5560: # @param {string} $showval - parameter current value
                   5561: # @param {boolean} $readonly - true if the values should not be made editable
                   5562: # @returns {string}
1.554     raeburn  5563: sub date_interval_selector {
                   5564:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5565:     my ($result,%skipval);
                   5566:     if ($name eq 'interval') {
                   5567:         my $intervaltype = &get_intervaltype($name);
                   5568:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5569:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5570:             next unless (ref($possibilities) eq 'ARRAY');
                   5571:             my ($parmval, $description) = @{ $possibilities };
                   5572:             my $parmmatch;
                   5573:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5574:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5575:                     if (ref($item) eq 'ARRAY') {
                   5576:                         if ($parmval eq $item->[0]) {
                   5577:                             $parmmatch = $parmval;
                   5578:                             $parmval = '';
                   5579:                             last;
                   5580:                         }
                   5581:                     }
                   5582:                 }
                   5583:             }
                   5584:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5585:             if ($needsrelease) {
                   5586:                 unless ($got_chostname) {
                   5587:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5588:                     $got_chostname = 1;
                   5589:                 }
1.557     raeburn  5590:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5591:                                                        $needsrelease,$cmajor,$cminor);
                   5592:                 if ($needsnewer) {
                   5593:                     if ($parmmatch ne '') {
                   5594:                         $skipval{$parmmatch} = 1;
                   5595:                     } elsif ($parmval ne '') {
                   5596:                         $skipval{$parmval} = 1;
                   5597:                     }
                   5598:                 }
                   5599:             }
                   5600:         }
                   5601:     }
                   5602: 
                   5603:     my $currval = $showval;
                   5604:     foreach my $which (['days', 86400, 31],
                   5605:                ['hours', 3600, 23],
                   5606:                ['minutes', 60, 59],
                   5607:                ['seconds',  1, 59]) {
1.560     damieng  5608:         my ($name, $factor, $max) = @{ $which };
                   5609:         my $amount = int($showval/$factor);
                   5610:         $showval  %= $factor;
                   5611:         my %select = ((map {$_ => $_} (0..$max)),
                   5612:                 'select_form_order' => [0..$max]);
                   5613:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5614:                             \%select,'',$readonly);
                   5615:         $result .= ' '.&mt($name);
1.554     raeburn  5616:     }
                   5617:     if ($name eq 'interval') {
                   5618:         unless ($skipval{'done'}) {
                   5619:             my $checkedon = '';
1.558     raeburn  5620:             my $checkedproc = '';
                   5621:             my $currproctorkey = '';
                   5622:             my $currprocdisplay = 'hidden';
1.559     raeburn  5623:             my $currdonetext = &mt('Done');
1.554     raeburn  5624:             my $checkedoff = ' checked="checked"';
1.559     raeburn  5625:             if ($currval =~ /^(?:\d+)_done$/) {
                   5626:                 $checkedon = ' checked="checked"';
                   5627:                 $checkedoff = '';
                   5628:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5629:                 $currdonetext = $1;
1.554     raeburn  5630:                 $checkedon = ' checked="checked"';
                   5631:                 $checkedoff = '';
1.558     raeburn  5632:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5633:                 $currproctorkey = $1;
                   5634:                 $checkedproc = ' checked="checked"';
                   5635:                 $checkedoff = '';
                   5636:                 $currprocdisplay = 'text';
1.559     raeburn  5637:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5638:                 $currdonetext = $1;
                   5639:                 $currproctorkey = $2;
                   5640:                 $checkedproc = ' checked="checked"';
                   5641:                 $checkedoff = '';
                   5642:                 $currprocdisplay = 'text';
1.554     raeburn  5643:             }
1.558     raeburn  5644:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5645:             my $disabled;
                   5646:             if ($readonly) {
                   5647:                 $disabled = ' disabled="disabled"';
                   5648:             }
1.558     raeburn  5649:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5650:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5651:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5652:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5653:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5654:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5655:                        &mt('Yes, with proctor key').'</label>'.
                   5656:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5657:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5658:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567     raeburn  5659:                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5660:         }
                   5661:     }
                   5662:     unless ($readonly) {
                   5663:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5664:     }
                   5665:     return $result;
                   5666: }
                   5667: 
1.563     damieng  5668: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5669: #
                   5670: # @param {string} $name - parameter name
                   5671: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5672: # @param {string} $value - parameter value
                   5673: # @param {string} $chostname - course server name
                   5674: # @param {integer} $cmajor - major version number
                   5675: # @param {integer} $cminor - minor version number
                   5676: # @param {string} $needsrelease - release version needed (major.minor)
                   5677: # @returns {string}
1.549     raeburn  5678: sub oldversion_warning {
1.557     raeburn  5679:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5680:     my $standard_name = &standard_parameter_names($name);
                   5681:     if ($namematch) {
                   5682:         my $level = &standard_parameter_levels($namematch);
                   5683:         my $msg = '';
                   5684:         if ($level) {
                   5685:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5686:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5687:         } else {
                   5688:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5689:                       $standard_name,'<b>','</b>');
                   5690:         }
                   5691:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5692:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5693:                    $cmajor.'.'.$cminor,$chostname,
                   5694:                    $needsrelease).
                   5695:                    '</p>';
                   5696:     }
1.549     raeburn  5697:     my $desc;
                   5698:     my $stringtype = &get_stringtype($name);
                   5699:     if ($stringtype ne '') {
                   5700:         if ($name eq 'examcode') {
                   5701:             $desc = $value;
                   5702:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5703:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5704:                 next unless (ref($possibilities) eq 'ARRAY');
                   5705:                 my ($parmval, $description) = @{ $possibilities };
                   5706:                 my $parmmatch;
                   5707:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5708:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5709:                         if (ref($item) eq 'ARRAY') {
                   5710:                             my ($regexpname,$pattern) = @{$item};
                   5711:                             if ($parmval eq $regexpname) {
                   5712:                                 if ($value =~ /$pattern/) {
                   5713:                                     $desc = $description; 
                   5714:                                     $parmmatch = 1;
                   5715:                                     last;
                   5716:                                 }
                   5717:                             }
                   5718:                         }
                   5719:                     }
                   5720:                     last if ($parmmatch);
                   5721:                 } elsif ($parmval eq $value) {
                   5722:                     $desc = $description;
                   5723:                     last;
                   5724:                 }
                   5725:             }
                   5726:         }
                   5727:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5728:         my $now = time;
                   5729:         if ($value =~ /^\d+$/) {
                   5730:             if ($name eq 'printstartdate') {
                   5731:                 if ($value > $now) {
                   5732:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5733:                 }
                   5734:             } elsif ($name eq 'printenddate') {
                   5735:                 if ($value < $now) {
                   5736:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5737:                 }
                   5738:             }
                   5739:         }
                   5740:     }
                   5741:     return '<p class="LC_warning">'.
1.557     raeburn  5742:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5743:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5744:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5745:        $cmajor.'.'.$cminor,$chostname,
                   5746:        $needsrelease).
                   5747:        '</p>';
1.549     raeburn  5748: }
                   5749: 
1.560     damieng  5750: } # end of block using some constants related to parameter types
                   5751: 
1.549     raeburn  5752: 
1.563     damieng  5753: 
                   5754: # Shifts all start and end dates in the current course by $shift.
1.389     www      5755: #
1.563     damieng  5756: # @param {integer} $shift - time to shift, in seconds
                   5757: # @returns {string} - error name or 'ok'
1.389     www      5758: sub dateshift {
1.594     raeburn  5759:     my ($shift,$numchanges)=@_;
1.389     www      5760:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5761:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  5762:     my $sec = $env{'request.course.sec'};
1.595     raeburn  5763:     my $secgrpregex;
                   5764:     if ($sec ne '') {
                   5765:         my @groups;
                   5766:         if ($env{'request.course.groups'} ne '') {
                   5767:             @groups = split(/:/,$env{'request.course.groups'});
                   5768:         }
                   5769:         if (@groups) {
                   5770:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   5771:         } else {
                   5772:             $secgrpregex = $sec;
                   5773:         }
                   5774:     }
1.389     www      5775:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   5776: # ugly retro fix for broken version of types
1.548     raeburn  5777:     foreach my $key (keys(%data)) {
1.389     www      5778:         if ($key=~/\wtype$/) {
                   5779:             my $newkey=$key;
                   5780:             $newkey=~s/type$/\.type/;
                   5781:             $data{$newkey}=$data{$key};
                   5782:             delete $data{$key};
                   5783:         }
                   5784:     }
1.391     www      5785:     my %storecontent=();
1.389     www      5786: # go through all parameters and look for dates
1.548     raeburn  5787:     foreach my $key (keys(%data)) {
1.389     www      5788:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  5789:           if ($sec ne '') {
1.595     raeburn  5790:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  5791:           }
1.389     www      5792:           my $newdate=$data{$key}+$shift;
1.594     raeburn  5793:           $$numchanges ++;
1.391     www      5794:           $storecontent{$key}=$newdate;
1.389     www      5795:        }
                   5796:     }
1.391     www      5797:     my $reply=&Apache::lonnet::cput
                   5798:                 ('resourcedata',\%storecontent,$dom,$crs);
                   5799:     if ($reply eq 'ok') {
                   5800:        &log_parmset(\%storecontent);
                   5801:     }
                   5802:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   5803:     return $reply;
1.389     www      5804: }
                   5805: 
1.563     damieng  5806: # Overview mode UI to edit course parameters.
                   5807: #
                   5808: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5809: sub newoverview {
1.568     raeburn  5810:     my ($r,$parm_permission) = @_;
1.280     albertel 5811: 
1.208     www      5812:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5813:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5814:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5815:     my $readonly = 1;
                   5816:     if ($parm_permission->{'edit'}) {
                   5817:         undef($readonly);
                   5818:     }
1.414     droeschl 5819:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5820:         text=>"Overview Mode"});
1.523     raeburn  5821: 
                   5822:     my %loaditems = (
1.549     raeburn  5823:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  5824:                     );
                   5825:     my $js = '
                   5826: <script type="text/javascript">
                   5827: // <![CDATA[
                   5828: '.
                   5829:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   5830:             &showhide_js()."\n".
1.549     raeburn  5831:             &toggleparmtextbox_js()."\n".
                   5832:             &validateparms_js()."\n".
                   5833:             &ipacc_boxes_js()."\n".
1.558     raeburn  5834:             &done_proctor_js()."\n".
1.588     raeburn  5835:             &deeplink_js()."\n".
1.523     raeburn  5836: '// ]]>
                   5837: </script>
                   5838: ';
1.549     raeburn  5839: 
1.523     raeburn  5840:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   5841:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 5842:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5843:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5844:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      5845:     $r->print(<<ENDOVER);
1.549     raeburn  5846: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      5847: ENDOVER
1.211     www      5848:     my @ids=();
                   5849:     my %typep=();
                   5850:     my %keyp=();
                   5851:     my %allparms=();
                   5852:     my %allparts=();
                   5853:     my %allmaps=();
                   5854:     my %mapp=();
                   5855:     my %symbp=();
                   5856:     my %maptitles=();
                   5857:     my %uris=();
                   5858:     my %keyorder=&standardkeyorder();
                   5859:     my %defkeytype=();
                   5860: 
                   5861:     my %alllevs=();
                   5862:     $alllevs{'Resource Level'}='full';
1.215     www      5863:     $alllevs{'Map/Folder Level'}='map';
1.211     www      5864:     $alllevs{'Course Level'}='general';
                   5865: 
                   5866:     my $csec=$env{'form.csec'};
1.269     raeburn  5867:     my $cgroup=$env{'form.cgroup'};
1.211     www      5868: 
                   5869:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   5870:     my $pschp=$env{'form.pschp'};
1.506     www      5871: 
1.211     www      5872:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      5873:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      5874: 
1.446     bisitz   5875:     my @selected_sections =
1.473     amueller 5876:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      5877:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 5878:     foreach my $sec (@selected_sections) {
                   5879:         if ($sec eq 'all') {
1.211     www      5880:             @selected_sections = ('all');
                   5881:         }
                   5882:     }
1.552     raeburn  5883:     if ($env{'request.course.sec'} ne '') {
                   5884:         @selected_sections = ($env{'request.course.sec'});
                   5885:     }
1.269     raeburn  5886:     my @selected_groups =
                   5887:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      5888: 
                   5889:     my $pssymb='';
                   5890:     my $parmlev='';
1.446     bisitz   5891: 
1.211     www      5892:     unless ($env{'form.parmlev'}) {
                   5893:         $parmlev = 'map';
                   5894:     } else {
                   5895:         $parmlev = $env{'form.parmlev'};
                   5896:     }
                   5897: 
1.446     bisitz   5898:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 5899:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603   ! raeburn  5900:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      5901: 
1.374     albertel 5902:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 5903:         @psprt = keys(%allparts);
1.374     albertel 5904:     }
1.211     www      5905: # Menu to select levels, etc
                   5906: 
1.456     bisitz   5907:     $r->print('<div class="LC_Box">');
1.445     neumanie 5908:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   5909:     $r->print('<div>');
1.523     raeburn  5910:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      5911:     &levelmenu($r,\%alllevs,$parmlev);
                   5912:     if ($parmlev ne 'general') {
1.447     bisitz   5913:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.483     amueller 5914:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211     www      5915:     }
1.447     bisitz   5916:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5917:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5918:     $r->print('</div></div>');
1.446     bisitz   5919: 
1.456     bisitz   5920:     $r->print('<div class="LC_Box">');
1.452     bisitz   5921:     $r->print('<div>');
1.581     raeburn  5922:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 5923:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   5924:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  5925:     my $sectionselector = &sectionmenu(\@selected_sections);
                   5926:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 5927:     $r->print('<table>'.
1.553     raeburn  5928:               '<tr><th>'.&mt('Parts').'</th>');
                   5929:     if ($sectionselector) {
                   5930:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   5931:     }
                   5932:     if ($groupselector) {
                   5933:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   5934:     }
                   5935:     $r->print('</tr><tr><td>');
1.211     www      5936:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  5937:     $r->print('</td>');
                   5938:     if ($sectionselector) { 
                   5939:         $r->print('<td>'.$sectionselector.'</td>');
                   5940:     }
                   5941:     if ($groupselector) {
                   5942:         $r->print('<td>'.$groupselector.'</td>');
                   5943:     }
                   5944:     $r->print('</tr></table>');
1.447     bisitz   5945:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5946:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5947:     $r->print('</div></div>');
                   5948: 
1.456     bisitz   5949:     $r->print('<div class="LC_Box">');
1.452     bisitz   5950:     $r->print('<div>');
1.214     www      5951:     my $sortorder=$env{'form.sortorder'};
                   5952:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5953:     &sortmenu($r,$sortorder);
1.445     neumanie 5954:     $r->print('</div></div>');
1.446     bisitz   5955: 
1.214     www      5956:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   5957: 
1.211     www      5958: # Build the list data hash from the specified parms
                   5959: 
                   5960:     my $listdata;
                   5961:     %{$listdata}=();
                   5962: 
                   5963:     foreach my $cat (@pscat) {
1.269     raeburn  5964:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   5965:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      5966:     }
                   5967: 
1.212     www      5968:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      5969: 
1.481     amueller 5970:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      5971: 
                   5972: # Read modified data
                   5973: 
1.481     amueller 5974:         my $resourcedata=&readdata($crs,$dom);
1.211     www      5975: 
                   5976: # List data
                   5977: 
1.568     raeburn  5978:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
                   5979:     }
                   5980:     $r->print(&tableend());
                   5981:     unless ($readonly) {
                   5982:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      5983:     }
1.568     raeburn  5984:     $r->print('</form>');
1.507     www      5985:     &endSettingsScreen($r);
                   5986:     $r->print(&Apache::loncommon::end_page());
1.208     www      5987: }
                   5988: 
1.563     damieng  5989: # Fills $listdata with parameter information.
                   5990: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   5991: # The non-type value is always 1.
                   5992: #
                   5993: # @param {string} $cat - parameter name
1.566     damieng  5994: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  5995: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   5996: # @param {hash reference} $listdata - the parameter data that will be modified
                   5997: # @param {array reference} $psprt - selected parts
                   5998: # @param {array reference} $selections - selected sections
                   5999: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6000: # @param {hash reference} $allmaps - hash map pc -> map src
                   6001: # @param {array reference} $ids - resource and map ids
                   6002: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6003: sub secgroup_lister {
                   6004:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6005:     foreach my $item (@{$selections}) {
                   6006:         foreach my $part (@{$psprt}) {
                   6007:             my $rootparmkey=$env{'request.course.id'};
                   6008:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6009:                 $rootparmkey.='.['.$item.']';
                   6010:             }
                   6011:             if ($parmlev eq 'general') {
                   6012: # course-level parameter
                   6013:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6014:                 $$listdata{$newparmkey}=1;
                   6015:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6016:             } elsif ($parmlev eq 'map') {
                   6017: # map-level parameter
1.548     raeburn  6018:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6019:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6020:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6021:                     $$listdata{$newparmkey}=1;
                   6022:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6023:                 }
                   6024:             } else {
                   6025: # resource-level parameter
                   6026:                 foreach my $rid (@{$ids}) {
                   6027:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6028:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6029:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6030:                     $$listdata{$newparmkey}=1;
                   6031:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6032:                 }
                   6033:             }
                   6034:         }
                   6035:     }
                   6036: }
                   6037: 
1.563     damieng  6038: # UI to edit parameter settings starting with a list of all existing parameters.
                   6039: # (called by setoverview action)
                   6040: #
                   6041: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6042: sub overview {
1.568     raeburn  6043:     my ($r,$parm_permission) = @_;
1.208     www      6044:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6045:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6046:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6047:     my $readonly = 1;
                   6048:     if ($parm_permission->{'edit'}) {
                   6049:         undef($readonly);
                   6050:     }
1.549     raeburn  6051:     my $js = '<script type="text/javascript">'."\n".
                   6052:              '// <![CDATA['."\n".
                   6053:              &toggleparmtextbox_js()."\n".
                   6054:              &validateparms_js()."\n".
                   6055:              &ipacc_boxes_js()."\n".
1.558     raeburn  6056:              &done_proctor_js()."\n".
1.588     raeburn  6057:              &deeplink_js()."\n".
1.549     raeburn  6058:              '// ]]>'."\n".
                   6059:              '</script>'."\n";
1.414     droeschl 6060:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6061:     text=>"Overview Mode"});
1.549     raeburn  6062:     my %loaditems = (
                   6063:                       'onload'   => "showHideLenient();",
                   6064:                     );
                   6065: 
                   6066:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6067:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6068:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6069:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6070:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6071: 
1.208     www      6072: # Store modified
                   6073: 
1.568     raeburn  6074:     unless ($readonly) {
                   6075:         &storedata($r,$crs,$dom);
                   6076:     }
1.208     www      6077: 
                   6078: # Read modified data
                   6079: 
1.552     raeburn  6080:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6081: 
1.214     www      6082: 
                   6083:     my $sortorder=$env{'form.sortorder'};
                   6084:     unless ($sortorder) { $sortorder='realmstudent'; }
                   6085:     &sortmenu($r,$sortorder);
                   6086: 
1.568     raeburn  6087:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6088: 
                   6089:     if ($readonly) {
                   6090:         $r->print('<p>'.$submitbutton.'</p>');
                   6091:     }
                   6092: 
1.208     www      6093: # List data
                   6094: 
1.568     raeburn  6095:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6096:     $r->print(&tableend().'<p>');
                   6097:     if ($foundkeys) {
                   6098:         unless ($readonly) {
                   6099:             $r->print('<p>'.$submitbutton.'</p>');
                   6100:         }
                   6101:     } else {
                   6102:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6103:     }
                   6104:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6105: }
1.121     www      6106: 
1.560     damieng  6107: # Unused sub.
1.563     damieng  6108: #
                   6109: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6110: sub clean_parameters {
                   6111:     my ($r) = @_;
                   6112:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6113:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6114: 
1.414     droeschl 6115:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6116:         text=>"Clean Parameters"});
1.333     albertel 6117:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6118:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6119:     $r->print(<<ENDOVER);
                   6120: $start_page
                   6121: $breadcrumbs
                   6122: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6123: ENDOVER
                   6124: # Store modified
                   6125: 
                   6126:     &storedata($r,$crs,$dom);
                   6127: 
                   6128: # Read modified data
                   6129: 
                   6130:     my $resourcedata=&readdata($crs,$dom);
                   6131: 
                   6132: # List data
                   6133: 
                   6134:     $r->print('<h3>'.
1.473     amueller 6135:           &mt('These parameters refer to resources that do not exist.').
                   6136:           '</h3>'.
                   6137:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6138:           '<br />');
1.333     albertel 6139:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6140:           '<tr>'.
                   6141:           '<th>'.&mt('Delete').'</th>'.
                   6142:           '<th>'.&mt('Parameter').'</th>'.
                   6143:           '</tr>');
1.333     albertel 6144:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6145:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6146:             && $thiskey=~/\.type$/);
                   6147:         my %data = &parse_key($thiskey);
                   6148:         if (1) { #exists($data{'realm_exists'})
                   6149:             #&& !$data{'realm_exists'}) {
                   6150:             $r->print(&Apache::loncommon::start_data_table_row().
                   6151:                 '<tr>'.
                   6152:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6153: 
                   6154:             $r->print('<td>');
                   6155:             my $display_value = $resourcedata->{$thiskey};
                   6156:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6157:             $display_value =
                   6158:                 &Apache::lonlocal::locallocaltime($display_value);
                   6159:             }
1.470     raeburn  6160:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6161:             $parmitem = &mt($parmitem);
1.560     damieng  6162:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6163:                 $parmitem,$resourcedata->{$thiskey}));
                   6164:             $r->print('<br />');
                   6165:             if ($data{'scope_type'} eq 'all') {
                   6166:                 $r->print(&mt('All users'));
                   6167:             } elsif ($data{'scope_type'} eq 'user') {
                   6168:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6169:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6170:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6171:             }
                   6172:             $r->print('<br />');
                   6173:             if ($data{'realm_type'} eq 'all') {
                   6174:                 $r->print(&mt('All Resources'));
                   6175:             } elsif ($data{'realm_type'} eq 'folder') {
                   6176:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6177:             } elsif ($data{'realm_type'} eq 'symb') {
                   6178:             my ($map,$resid,$url) =
                   6179:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6180:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6181:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6182:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6183:             }
                   6184:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6185:             $r->print('</td></tr>');
                   6186: 
1.473     amueller 6187:         }
1.333     albertel 6188:     }
                   6189:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6190:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6191:           '</p></form>');
                   6192:     &endSettingsScreen($r);
                   6193:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6194: }
                   6195: 
1.563     damieng  6196: # UI to shift all dates (called by dateshift1 action).
                   6197: # Used by overview mode.
                   6198: #
                   6199: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6200: sub date_shift_one {
                   6201:     my ($r) = @_;
                   6202:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6203:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6204:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6205:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6206:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6207:         text=>"Shifting Dates"});
1.594     raeburn  6208:     my $submit_text = &mt('Shift all dates accordingly');
                   6209:     if ($sec ne '') {
1.595     raeburn  6210:         my @groups;
                   6211:         if ($env{'request.course.groups'} ne '') {
                   6212:             @groups = split(/:/,$env{'request.course.groups'});
                   6213:         }
                   6214:         if (@groups) {
                   6215:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6216:         } else {
                   6217:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6218:         }
1.594     raeburn  6219:     }
1.390     www      6220:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6221:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6222:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6223:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6224:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6225:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6226:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6227:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6228:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6229:                                                         'timeshifted',
                   6230:                                                         $env{'form.timebase'},,
                   6231:                                                         '').
                   6232:               '</td></tr></table>'.
                   6233:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6234:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6235:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6236:     &endSettingsScreen($r);
1.390     www      6237:     $r->print(&Apache::loncommon::end_page());
                   6238: }
                   6239: 
1.563     damieng  6240: # UI to shift all dates (second form).
                   6241: #
                   6242: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6243: sub date_shift_two {
                   6244:     my ($r) = @_;
                   6245:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6246:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6247:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6248:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6249:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6250:         text=>"Shifting Dates"});
1.390     www      6251:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6252:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6253:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6254:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6255:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6256:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6257:     if ($sec ne '') {
1.595     raeburn  6258:         my @groups;
                   6259:         if ($env{'request.course.groups'} ne '') {
                   6260:             @groups = split(/:/,$env{'request.course.groups'});
                   6261:         }
                   6262:         if (@groups) {
                   6263:             $r->print('<p>'.
                   6264:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6265:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6266:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6267:                       '</p>');
                   6268:         } else {
                   6269:             $r->print('<p>'.
                   6270:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6271:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6272:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6273:                       '</p>');
                   6274:         }
1.594     raeburn  6275:     } else {
                   6276:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6277:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6278:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6279:                   '</p>');
                   6280:     }
1.390     www      6281:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6282:     my $numchanges = 0;
                   6283:     my $result = &dateshift($delta,\$numchanges);
                   6284:     if ($result eq 'ok') {
                   6285:         $r->print(
                   6286:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6287:                                                     $numchanges)));
                   6288:     } elsif ($result eq 'con_delayed') {
                   6289:         $r->print(
                   6290:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6291:                                                         $numchanges)));
                   6292:     } else {
                   6293:         $r->print(
                   6294:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6295:     }
1.543     bisitz   6296:     $r->print(
                   6297:         '<br /><br />'.
                   6298:         &Apache::lonhtmlcommon::actionbox(
                   6299:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6300:     &endSettingsScreen($r);
1.390     www      6301:     $r->print(&Apache::loncommon::end_page());
                   6302: }
                   6303: 
1.563     damieng  6304: # Returns the different components of a resourcedata key.
                   6305: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6306: #       realm_exists, parameter_part, parameter_name.
                   6307: # Was used by clean_parameters (which is unused).
                   6308: #
                   6309: # @param {string} $key - the parameter key
                   6310: # @returns {hash}
1.333     albertel 6311: sub parse_key {
                   6312:     my ($key) = @_;
                   6313:     my %data;
                   6314:     my ($middle,$part,$name)=
1.572     damieng  6315:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6316:     $data{'scope_type'} = 'all';
                   6317:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6318:         $data{'scope'} = $1;
                   6319:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6320:             $data{'scope_type'} = 'user';
                   6321:             $data{'scope'} = [$1,$2];
                   6322:         } else {
1.581     raeburn  6323:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6324:         }
                   6325:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6326:     }
                   6327:     $middle=~s/\.+$//;
                   6328:     $middle=~s/^\.+//;
                   6329:     $data{'realm_type'}='all';
                   6330:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6331:         $data{'realm'} = $1;
                   6332:         $data{'realm_type'} = 'folder';
                   6333:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6334:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6335:     } elsif ($middle) {
1.560     damieng  6336:         $data{'realm'} = $middle;
                   6337:         $data{'realm_type'} = 'symb';
                   6338:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6339:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6340:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6341:     }
1.446     bisitz   6342: 
1.333     albertel 6343:     $data{'parameter_part'} = $part;
                   6344:     $data{'parameter_name'} = $name;
                   6345: 
                   6346:     return %data;
                   6347: }
                   6348: 
1.239     raeburn  6349: 
1.563     damieng  6350: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6351: sub header {
1.507     www      6352:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6353: }
1.193     albertel 6354: 
                   6355: 
                   6356: 
1.560     damieng  6357: ##################################################
                   6358: # MAIN MENU
                   6359: ##################################################
                   6360: 
1.563     damieng  6361: # Content and problem settings main menu.
                   6362: #
                   6363: # @param {Apache2::RequestRec} $r - the Apache request
                   6364: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6365: sub print_main_menu {
                   6366:     my ($r,$parm_permission)=@_;
                   6367:     #
1.414     droeschl 6368:     $r->print(&header());
1.507     www      6369:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6370:     my $crstype = &Apache::loncommon::course_type();
                   6371:     my $lc_crstype = lc($crstype);
                   6372: 
                   6373:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6374:     $r->print(<<ENDMAINFORMHEAD);
                   6375: <form method="post" enctype="multipart/form-data"
                   6376:       action="/adm/parmset" name="studentform">
                   6377: ENDMAINFORMHEAD
                   6378: #
1.195     albertel 6379:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6380:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6381:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6382:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6383:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6384:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6385:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6386:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6387:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6388:                                         '/'.$env{'request.course.sec'});
                   6389:     }
1.568     raeburn  6390:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6391:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6392:                                         '/'.$env{'request.course.sec'});
                   6393:     }
                   6394:     my (%linktext,%linktitle,%url);
                   6395:     if ($parm_permission->{'edit'}) {
                   6396:         %linktext = (
                   6397:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6398:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6399:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6400:                     );
                   6401:         %linktitle = (
                   6402:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6403:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6404:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6405:                      );
                   6406:     } else {
                   6407:         %linktext = (
                   6408:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6409:                      settable        => 'View Resource Parameters - Table Mode',
                   6410:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6411:                    );
                   6412:         %linktitle = (
                   6413:                      newoverview     => 'Display resource parameters in overview mode.',
                   6414:                      settable        => 'Display resource parameters in table mode.',
                   6415:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6416:                      );
                   6417:     }
                   6418:     if ($mgr) {
                   6419:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6420:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6421:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6422:     } elsif ($vgr) {
                   6423:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6424:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6425:         $url{'resettimes'} = '/adm/accesstimes';
                   6426:     }
1.193     albertel 6427:     my @menu =
1.507     www      6428:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6429:         items => [
                   6430:           { linktext => 'Portfolio Metadata',
                   6431:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6432:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6433:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6434:             icon =>'contact-new.png'   ,
                   6435:             },
1.568     raeburn  6436:           { linktext => $linktext{'resettimes'},
                   6437:             url => $url{'resettimes'},
                   6438:             permission => ($vgr || $mgr),
                   6439:             linktitle => $linktitle{'resettimes'},
                   6440:             icon => 'start-here.png',
1.473     amueller 6441:             },
1.520     raeburn  6442:           { linktext => 'Blocking Communication/Resource Access',
                   6443:             url => '/adm/setblock',
1.568     raeburn  6444:             permission => ($vcb || $dcm),
1.520     raeburn  6445:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6446:             icon => 'comblock.png',
                   6447:             },
1.473     amueller 6448:           { linktext => 'Set Parameter Setting Default Actions',
                   6449:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6450:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6451:             linktitle =>'Set default actions for parameters.'  ,
                   6452:             icon => 'folder-new.png'  ,
                   6453:             }]},
                   6454:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6455:         items => [
                   6456:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6457:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6458:             permission => $parm_permission->{'helper'},
1.473     amueller 6459:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6460:             icon => 'dialog-information.png'  ,
                   6461:             #help => 'Parameter_Helper',
                   6462:             },
1.568     raeburn  6463:           { linktext => $linktext{'newoverview'},
1.473     amueller 6464:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6465:             permission => $parm_permission->{'newoverview'},
                   6466:             linktitle => $linktitle{'newoverview'},
                   6467:             icon => 'edit-find.png',
1.473     amueller 6468:             #help => 'Parameter_Overview',
                   6469:             },
1.568     raeburn  6470:           { linktext => $linktext{'settable'},
1.473     amueller 6471:             url => '/adm/parmset?action=settable',
1.568     raeburn  6472:             permission => $parm_permission->{'settable'},
                   6473:             linktitle => $linktitle{'settable'},
                   6474:             icon => 'edit-copy.png',
1.473     amueller 6475:             #help => 'Table_Mode',
                   6476:             }]},
1.417     droeschl 6477:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6478:          items => [
1.570     raeburn  6479:           { linktext => $linktext{'setoverview'},
1.473     amueller 6480:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6481:             permission => $parm_permission->{'setoverview'},
                   6482:             linktitle => $linktitle{'setoverview'},
                   6483:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6484:             #help => 'Parameter_Overview',
                   6485:             },
                   6486:           { linktext => 'Change Log',
                   6487:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6488:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6489:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6490:             icon => 'document-properties.png',
1.473     amueller 6491:             }]}
1.193     albertel 6492:           );
1.414     droeschl 6493:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6494:     $r->print('</form>');
1.507     www      6495:     &endSettingsScreen($r);
1.539     raeburn  6496:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6497:     return;
                   6498: }
1.414     droeschl 6499: 
1.416     jms      6500: 
                   6501: 
1.560     damieng  6502: ##################################################
                   6503: # PORTFOLIO METADATA
                   6504: ##################################################
                   6505: 
1.563     damieng  6506: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6507: # It looks like field titles are not localized.
                   6508: #
                   6509: # @param {Apache2::RequestRec} $r - the Apache request
                   6510: # @param {string} $field_name - metadata field name
                   6511: # @param {string} $field_text - metadata field title, in English unless manually added
                   6512: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6513: sub output_row {
1.347     banghart 6514:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6515:     my $output;
1.263     banghart 6516:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6517:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6518:     if (!defined($options)) {
1.254     banghart 6519:         $options = 'active,stuadd';
1.261     banghart 6520:         $values = '';
1.252     banghart 6521:     }
1.337     banghart 6522:     if (!($options =~ /deleted/)) {
                   6523:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6524:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6525:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6526: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6527:         if ($added_flag) {
                   6528:             push @options,['deleted', 'Delete Metadata Field'];
                   6529:         }
1.351     banghart 6530:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6531:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6532:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6533:         foreach my $opt (@options) {
1.560     damieng  6534:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6535:             $output .= &Apache::loncommon::continue_data_table_row();
                   6536:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6537:                     <input type="checkbox" name="'.
                   6538:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6539:                     &mt($opt->[1]).'</label></td>';
                   6540:             $output .= &Apache::loncommon::end_data_table_row();
                   6541:         }
1.351     banghart 6542:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6543:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6544:         $output .= &Apache::loncommon::end_data_table_row();
                   6545:         my $multiple_checked;
                   6546:         my $single_checked;
                   6547:         if ($options =~ m/onlyone/) {
1.422     bisitz   6548:             $multiple_checked = '';
1.423     bisitz   6549:             $single_checked = ' checked="checked"';
1.351     banghart 6550:         } else {
1.423     bisitz   6551:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6552:             $single_checked = '';
1.351     banghart 6553:         }
1.560     damieng  6554:         $output .= &Apache::loncommon::continue_data_table_row();
                   6555:         $output .= '<td>'.('&nbsp;' x 10).'
                   6556:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6557:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6558:         $output .= &Apache::loncommon::end_data_table_row();
                   6559:         $output .= &Apache::loncommon::continue_data_table_row();
                   6560:         $output .= '<td>'.('&nbsp;' x 10).'
                   6561:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6562:                     '.&mt('Student may select only one choice from list').'</td>';
                   6563:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6564:     }
                   6565:     return ($output);
                   6566: }
1.416     jms      6567: 
                   6568: 
1.560     damieng  6569: # UI to order portfolio metadata fields.
1.563     damieng  6570: # Currently useless because addmetafield does not work.
                   6571: #
                   6572: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6573: sub order_meta_fields {
                   6574:     my ($r)=@_;
                   6575:     my $idx = 1;
                   6576:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6577:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6578:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6579:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6580:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6581:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6582:         text=>"Add Metadata Field"});
1.560     damieng  6583:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6584:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6585:         text=>"Restrict Metadata"},
                   6586:         {text=>"Order Metadata"});
1.345     banghart 6587:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6588:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6589:     if ($env{'form.storeorder'}) {
                   6590:         my $newpos = $env{'form.newpos'} - 1;
                   6591:         my $currentpos = $env{'form.currentpos'} - 1;
                   6592:         my @neworder = ();
1.548     raeburn  6593:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6594:         my $i;
1.341     banghart 6595:         if ($newpos > $currentpos) {
1.340     banghart 6596:         # moving stuff up
                   6597:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6598:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6599:             }
                   6600:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6601:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6602:             }
                   6603:             $neworder[$newpos]=$oldorder[$currentpos];
                   6604:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6605:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6606:             }
                   6607:         } else {
                   6608:         # moving stuff down
1.473     amueller 6609:             for ($i=0;$i<$newpos;$i++) {
                   6610:                 $neworder[$i]=$oldorder[$i];
                   6611:             }
                   6612:             $neworder[$newpos]=$oldorder[$currentpos];
                   6613:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6614:                 $neworder[$i]=$oldorder[$i-1];
                   6615:             }
                   6616:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6617:                 $neworder[$i]=$oldorder[$i];
                   6618:             }
1.340     banghart 6619:         }
1.560     damieng  6620:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6621:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6622:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6623:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6624:     }
1.357     raeburn  6625:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6626:     my $ordered_fields;
1.548     raeburn  6627:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6628:     if (!@fields_in_order) {
                   6629:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6630:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6631:             push @fields_in_order, $key;
1.341     banghart 6632:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6633:         }
1.341     banghart 6634:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6635:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6636:     }
1.340     banghart 6637:     $r->print('<table>');
                   6638:     my $num_fields = scalar(@fields_in_order);
                   6639:     foreach my $key (@fields_in_order) {
                   6640:         $r->print('<tr><td>');
                   6641:         $r->print('<form method="post" action="">');
1.537     bisitz   6642:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6643:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6644:             if ($i eq $idx) {
                   6645:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6646:             } else {
                   6647:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6648:             }
                   6649:         }
                   6650:         $r->print('</select></td><td>');
                   6651:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6652:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6653:         $r->print('</form>');
                   6654:         $r->print($$fields{$key}.'</td></tr>');
                   6655:         $idx ++;
                   6656:     }
                   6657:     $r->print('</table>');
1.507     www      6658:     &endSettingsScreen($r);
1.340     banghart 6659:     return 'ok';
                   6660: }
1.416     jms      6661: 
                   6662: 
1.563     damieng  6663: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6664: # @returns {string}
1.359     banghart 6665: sub continue {
                   6666:     my $output;
                   6667:     $output .= '<form action="" method="post">';
                   6668:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6669:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6670:     return ($output);
                   6671: }
1.416     jms      6672: 
                   6673: 
1.563     damieng  6674: # UI to add a metadata field.
                   6675: # Currenly does not work because of an HTML error (the field is not visible).
                   6676: #
                   6677: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6678: sub addmetafield {
                   6679:     my ($r)=@_;
1.414     droeschl 6680:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6681:         text=>"Add Metadata Field"});
1.334     banghart 6682:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6683:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6684:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6685:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6686:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6687:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6688:     if (exists($env{'form.undelete'})) {
1.358     banghart 6689:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6690:         foreach my $meta_field(@meta_fields) {
                   6691:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6692:             $options =~ s/deleted//;
                   6693:             $options =~ s/,,/,/;
                   6694:             my $put_result = &Apache::lonnet::put('environment',
                   6695:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6696: 
1.586     raeburn  6697:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6698:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6699:                           '</strong>',$put_result).
                   6700:                       '<br />');
1.339     banghart 6701:         }
1.359     banghart 6702:         $r->print(&continue());
1.339     banghart 6703:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6704:         my $meta_field = $env{'form.fieldname'};
                   6705:         my $display_field = $env{'form.fieldname'};
                   6706:         $meta_field =~ s/\W/_/g;
1.338     banghart 6707:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6708:         my $put_result = &Apache::lonnet::put('environment',
                   6709:                             {'metadata.'.$meta_field.'.values'=>"",
                   6710:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6711:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6712:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6713:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6714:                   '<br />');
1.359     banghart 6715:         $r->print(&continue());
1.335     banghart 6716:     } else {
1.357     raeburn  6717:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6718:         if ($fields) {
1.586     raeburn  6719:             $r->print(&mt('You may undelete previously deleted fields.').
                   6720:                       '<br />'.
                   6721:                       &mt('Check those you wish to undelete and click Undelete.').
                   6722:                       '<br />');
1.339     banghart 6723:             $r->print('<form method="post" action="">');
                   6724:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6725:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6726:             }
1.586     raeburn  6727:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6728:             $r->print('</form>');
                   6729:         }
1.586     raeburn  6730:         $r->print('<hr />'.
                   6731:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6732:                       '<strong>','</strong>').
1.581     raeburn  6733:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6734:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6735:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6736:         $r->print('</form>');
1.334     banghart 6737:     }
1.507     www      6738:     &endSettingsScreen($r);
1.334     banghart 6739: }
1.416     jms      6740: 
                   6741: 
                   6742: 
1.560     damieng  6743: # Display or save portfolio metadata.
1.563     damieng  6744: #
                   6745: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6746: sub setrestrictmeta {
1.240     banghart 6747:     my ($r)=@_;
1.242     banghart 6748:     my $next_meta;
1.244     banghart 6749:     my $output;
1.245     banghart 6750:     my $item_num;
1.246     banghart 6751:     my $put_result;
1.414     droeschl 6752:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6753:         text=>"Restrict Metadata"});
1.280     albertel 6754:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6755:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6756:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6757:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6758:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6759:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 6760:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 6761:     my $save_field = '';
1.586     raeburn  6762:     my %lt = &Apache::lonlocal::texthash(
                   6763:                                            addm => 'Add Metadata Field',
                   6764:                                            ordm => 'Order Metadata Fields',
                   6765:                                            save => 'Save',
                   6766:                                         );
1.259     banghart 6767:     if ($env{'form.restrictmeta'}) {
1.254     banghart 6768:         foreach my $field (sort(keys(%env))) {
1.252     banghart 6769:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 6770:                 my $options;
1.252     banghart 6771:                 my $meta_field = $1;
                   6772:                 my $meta_key = $2;
1.253     banghart 6773:                 if ($save_field ne $meta_field) {
1.252     banghart 6774:                     $save_field = $meta_field;
1.473     amueller 6775:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   6776:                         $options.='stuadd,';
                   6777:                     }
                   6778:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   6779:                         $options.='choices,';
                   6780:                     }
                   6781:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   6782:                         $options.='onlyone,';
                   6783:                     }
                   6784:                     if ($env{'form.'.$meta_field.'_active'}) {
                   6785:                         $options.='active,';
                   6786:                     }
                   6787:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   6788:                         $options.='deleted,';
                   6789:                     }
1.259     banghart 6790:                     my $name = $save_field;
1.560     damieng  6791:                     $put_result = &Apache::lonnet::put('environment',
                   6792:                         {'metadata.'.$meta_field.'.options'=>$options,
                   6793:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   6794:                         },$dom,$crs);
1.252     banghart 6795:                 }
                   6796:             }
                   6797:         }
                   6798:     }
1.296     albertel 6799:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 6800:                        {'freshen_cache' => 1});
1.335     banghart 6801:     # Get the default metadata fields
1.258     albertel 6802:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 6803:     # Now get possible added metadata fields
1.357     raeburn  6804:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 6805:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 6806:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 6807:         if ($field ne 'courserestricted') {
1.586     raeburn  6808:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  6809:         }
1.255     banghart 6810:     }
1.351     banghart 6811:     my $buttons = (<<ENDButtons);
1.586     raeburn  6812:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 6813:         </form><br />
                   6814:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  6815:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 6816:         </form>
                   6817:         <br />
                   6818:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  6819:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 6820: ENDButtons
1.337     banghart 6821:     my $added_flag = 1;
1.335     banghart 6822:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  6823:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 6824:     }
1.347     banghart 6825:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   6826:     $r->print(<<ENDenv);
1.259     banghart 6827:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 6828:         $output
1.351     banghart 6829:         $buttons
1.340     banghart 6830:         </form>
1.244     banghart 6831: ENDenv
1.507     www      6832:     &endSettingsScreen($r);
1.280     albertel 6833:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 6834:     return 'ok';
                   6835: }
1.416     jms      6836: 
                   6837: 
1.563     damieng  6838: # Returns metadata fields that have been manually added.
                   6839: #
                   6840: # @param {string} $cid - course id
                   6841: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 6842: sub get_added_meta_fieldnames {
1.357     raeburn  6843:     my ($cid) = @_;
1.335     banghart 6844:     my %fields;
                   6845:     foreach my $key(%env) {
1.357     raeburn  6846:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 6847:             my $field_name = $1;
                   6848:             my ($display_field_name) = $env{$key};
                   6849:             $fields{$field_name} = $display_field_name;
                   6850:         }
                   6851:     }
                   6852:     return \%fields;
                   6853: }
1.416     jms      6854: 
                   6855: 
1.563     damieng  6856: # Returns metadata fields that have been manually added and deleted.
                   6857: #
                   6858: # @param {string} $cid - course id
                   6859: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 6860: sub get_deleted_meta_fieldnames {
1.357     raeburn  6861:     my ($cid) = @_;
1.339     banghart 6862:     my %fields;
                   6863:     foreach my $key(%env) {
1.357     raeburn  6864:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 6865:             my $field_name = $1;
                   6866:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   6867:                 my ($display_field_name) = $env{$key};
                   6868:                 $fields{$field_name} = $display_field_name;
                   6869:             }
                   6870:         }
                   6871:     }
                   6872:     return \%fields;
                   6873: }
1.560     damieng  6874: 
                   6875: 
                   6876: ##################################################
                   6877: # PARAMETER SETTINGS DEFAULT ACTIONS
                   6878: ##################################################
                   6879: 
                   6880: # UI to change parameter setting default actions
1.563     damieng  6881: #
                   6882: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      6883: sub defaultsetter {
1.280     albertel 6884:     my ($r) = @_;
                   6885: 
1.414     droeschl 6886:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 6887:         text=>"Set Defaults"});
1.531     raeburn  6888:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6889:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6890:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   6891:     my $start_page =
1.531     raeburn  6892:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 6893:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      6894:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6895:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      6896:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 6897: 
1.221     www      6898:     my @ids=();
                   6899:     my %typep=();
                   6900:     my %keyp=();
                   6901:     my %allparms=();
                   6902:     my %allparts=();
                   6903:     my %allmaps=();
                   6904:     my %mapp=();
                   6905:     my %symbp=();
                   6906:     my %maptitles=();
                   6907:     my %uris=();
                   6908:     my %keyorder=&standardkeyorder();
                   6909:     my %defkeytype=();
                   6910: 
1.446     bisitz   6911:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6912:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   6913:                 \%keyorder,\%defkeytype);
1.224     www      6914:     if ($env{'form.storerules'}) {
1.560     damieng  6915:         my %newrules=();
                   6916:         my @delrules=();
                   6917:         my %triggers=();
                   6918:         foreach my $key (keys(%env)) {
1.225     albertel 6919:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  6920:                 my $tempkey=$1;
                   6921:                 my $action=$env{$key};
1.226     www      6922:                 if ($action) {
1.560     damieng  6923:                     $newrules{$tempkey.'_action'}=$action;
                   6924:                     if ($action ne 'default') {
                   6925:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   6926:                         $triggers{$whichparm}.=$tempkey.':';
                   6927:                     }
                   6928:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   6929:                     if (&isdateparm($defkeytype{$tempkey})) {
                   6930:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   6931:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   6932:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   6933:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   6934:                     } else {
                   6935:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   6936:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   6937:                     }
                   6938:                 } else {
                   6939:                     push(@delrules,$tempkey.'_action');
                   6940:                     push(@delrules,$tempkey.'_type');
                   6941:                     push(@delrules,$tempkey.'_hours');
                   6942:                     push(@delrules,$tempkey.'_min');
                   6943:                     push(@delrules,$tempkey.'_sec');
                   6944:                     push(@delrules,$tempkey.'_value');
                   6945:                 }
1.473     amueller 6946:             }
                   6947:         }
1.560     damieng  6948:         foreach my $key (keys(%allparms)) {
                   6949:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 6950:         }
1.560     damieng  6951:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   6952:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   6953:         &resetrulescache();
1.224     www      6954:     }
1.227     www      6955:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 6956:                        'hours' => 'Hours',
                   6957:                        'min' => 'Minutes',
                   6958:                        'sec' => 'Seconds',
                   6959:                        'yes' => 'Yes',
                   6960:                        'no' => 'No');
1.222     www      6961:     my @standardoptions=('','default');
                   6962:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   6963:     my @dateoptions=('','default');
                   6964:     my @datedisplay=('',&mt('Default value when manually setting'));
                   6965:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  6966:         unless ($tempkey) { next; }
                   6967:         push @standardoptions,'when_setting_'.$tempkey;
                   6968:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   6969:         if (&isdateparm($defkeytype{$tempkey})) {
                   6970:             push @dateoptions,'later_than_'.$tempkey;
                   6971:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   6972:             push @dateoptions,'earlier_than_'.$tempkey;
                   6973:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   6974:         }
1.222     www      6975:     }
1.563     damieng  6976:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   6977:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 6978:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 6979:           &Apache::loncommon::start_data_table_header_row().
                   6980:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   6981:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   6982:           &Apache::loncommon::end_data_table_header_row());
1.221     www      6983:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  6984:         unless ($tempkey) { next; }
                   6985:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   6986:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   6987:         my $action=&rulescache($tempkey.'_action');
                   6988:         $r->print('<select name="'.$tempkey.'_action">');
                   6989:         if (&isdateparm($defkeytype{$tempkey})) {
                   6990:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   6991:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   6992:             $r->print("\n<option value='$dateoptions[$i]'".
                   6993:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   6994:                 ">$datedisplay[$i]</option>");
                   6995:             }
                   6996:         } else {
                   6997:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   6998:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   6999:             $r->print("\n<option value='$standardoptions[$i]'".
                   7000:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7001:                 ">$standarddisplay[$i]</option>");
                   7002:             }
1.473     amueller 7003:         }
1.560     damieng  7004:         $r->print('</select>');
                   7005:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7006:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7007:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7008:         }
1.560     damieng  7009:         $r->print("\n</td><td>\n");
1.222     www      7010: 
1.221     www      7011:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7012:             my $days=&rulescache($tempkey.'_days');
                   7013:             my $hours=&rulescache($tempkey.'_hours');
                   7014:             my $min=&rulescache($tempkey.'_min');
                   7015:             my $sec=&rulescache($tempkey.'_sec');
                   7016:             $r->print(<<ENDINPUTDATE);
                   7017:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7018:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7019:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7020:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7021: ENDINPUTDATE
1.560     damieng  7022:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7023:                 my $yeschecked='';
                   7024:                 my $nochecked='';
                   7025:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7026:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7027: 
                   7028:             $r->print(<<ENDYESNO);
                   7029:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7030:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7031: ENDYESNO
1.221     www      7032:         } else {
1.560     damieng  7033:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7034:         }
1.318     albertel 7035:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7036:     }
1.318     albertel 7037:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7038:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7039:           &mt('Save').'" /></form>'."\n");
                   7040:     &endSettingsScreen($r);
                   7041:     $r->print(&Apache::loncommon::end_page());
1.220     www      7042:     return;
                   7043: }
1.193     albertel 7044: 
1.560     damieng  7045: ##################################################
                   7046: # PARAMETER CHANGES LOG
                   7047: ##################################################
                   7048: 
1.563     damieng  7049: # Returns some info for a parameter log entry.
                   7050: # Returned entries:
                   7051: # $realm - HTML title for the parameter level and resource
                   7052: # $section - parameter section
                   7053: # $name - parameter name
                   7054: # $part - parameter part
                   7055: # $what - $part.'.'.$name
                   7056: # $middle - resource symb ?
                   7057: # $uname - user name (same as given)
                   7058: # $udom - user domain (same as given)
                   7059: # $issection - section or group name
                   7060: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7061: #
                   7062: # @param {string} $key - parameter log key
                   7063: # @param {string} $uname - user name
                   7064: # @param {string} $udom - user domain
                   7065: # @param {boolean} $typeflag - .type log entry
                   7066: # @returns {Array}
1.290     www      7067: sub components {
1.581     raeburn  7068:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7069: 
                   7070:     if ($typeflag) {
1.560     damieng  7071:         $key=~s/\.type$//;
1.290     www      7072:     }
1.330     albertel 7073: 
                   7074:     my ($middle,$part,$name)=
1.572     damieng  7075:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7076:     my $issection;
1.330     albertel 7077: 
1.290     www      7078:     my $section=&mt('All Students');
                   7079:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7080:         $issection=$1;
                   7081:         $section=&mt('Group/Section').': '.$issection;
                   7082:         $middle=~s/^\[(.*)\]//;
1.290     www      7083:     }
                   7084:     $middle=~s/\.+$//;
                   7085:     $middle=~s/^\.+//;
1.291     www      7086:     if ($uname) {
1.560     damieng  7087:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7088:         $issection='';
1.291     www      7089:     }
1.316     albertel 7090:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7091:     my $realmdescription=&mt('all resources');
1.556     raeburn  7092:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7093:         my $mapurl = $1;
                   7094:         my $maplevel = $2;
                   7095:         my $leveltitle = &mt('Folder/Map');
                   7096:         if ($maplevel eq 'rec') {
                   7097:             $leveltitle = &mt('Recursive');
                   7098:         }
1.560     damieng  7099:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7100:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7101:             $mapurl.')</span></span>';
                   7102:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7103:     } elsif ($middle) {
                   7104:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7105:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7106:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7107:             ' in '.$map.' id: '.$id.')</span></span>';
                   7108:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7109:     }
1.291     www      7110:     my $what=$part.'.'.$name;
1.330     albertel 7111:     return ($realm,$section,$name,$part,
1.473     amueller 7112:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7113: }
1.293     www      7114: 
1.563     damieng  7115: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7116: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7117: 
1.563     damieng  7118: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7119: sub load_parameter_names {
1.583     raeburn  7120:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7121:     while (my $configline=<$config>) {
1.560     damieng  7122:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7123:         chomp($configline);
                   7124:         my ($short,$plain)=split(/:/,$configline);
                   7125:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7126:         if ($type eq 'display') {
                   7127:             $standard_parms{$name} = $plain;
1.469     raeburn  7128:         } elsif ($type eq 'type') {
1.560     damieng  7129:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7130:         }
1.328     albertel 7131:     }
                   7132:     close($config);
                   7133:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7134:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7135:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7136: }
                   7137: 
1.563     damieng  7138: # Returns a parameter title for standard parameters, the name for others.
                   7139: #
                   7140: # @param {string} $name - parameter name
                   7141: # @returns {string}
1.292     www      7142: sub standard_parameter_names {
                   7143:     my ($name)=@_;
1.328     albertel 7144:     if (!%standard_parms) {
1.560     damieng  7145:         &load_parameter_names();
1.328     albertel 7146:     }
1.292     www      7147:     if ($standard_parms{$name}) {
1.560     damieng  7148:         return $standard_parms{$name};
1.446     bisitz   7149:     } else {
1.560     damieng  7150:         return $name;
1.292     www      7151:     }
                   7152: }
1.290     www      7153: 
1.563     damieng  7154: # Returns a parameter type for standard parameters, undef for others.
                   7155: #
                   7156: # @param {string} $name - parameter name
                   7157: # @returns {string}
1.469     raeburn  7158: sub standard_parameter_types {
                   7159:     my ($name)=@_;
                   7160:     if (!%standard_parms_types) {
                   7161:         &load_parameter_names();
                   7162:     }
                   7163:     if ($standard_parms_types{$name}) {
                   7164:         return $standard_parms_types{$name};
                   7165:     }
                   7166:     return;
                   7167: }
1.309     www      7168: 
1.563     damieng  7169: # Returns a parameter level title (not localized) from the parameter level name.
                   7170: #
                   7171: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7172: # @returns {string}
1.557     raeburn  7173: sub standard_parameter_levels {
                   7174:     my ($name)=@_;
                   7175:     my %levels = (
                   7176:                     'resourcelevel'   => 'a single resource',
                   7177:                     'maplevel'        => 'the enclosing map/folder', 
                   7178:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7179:                     'courselevel'     => 'the general (course) level',
                   7180:                  );
                   7181:     if ($levels{$name}) {
                   7182:         return $levels{$name};
                   7183:     }
                   7184:     return;
                   7185: }
                   7186: 
1.560     damieng  7187: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7188: #
                   7189: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7190: sub parm_change_log {
1.568     raeburn  7191:     my ($r,$parm_permission)=@_;
1.531     raeburn  7192:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7193:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7194:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7195:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7196:     text=>"Parameter Change Log"});
1.522     raeburn  7197:     my $js = '<script type="text/javascript">'."\n".
                   7198:              '// <![CDATA['."\n".
                   7199:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7200:              '// ]]>'."\n".
                   7201:              '</script>'."\n";
                   7202:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7203:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7204:     &startSettingsScreen($r,'parmset',$crstype);
                   7205:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7206: 
1.301     www      7207:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7208: 
1.522     raeburn  7209:     $r->print('<div class="LC_left_float">'.
                   7210:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7211:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7212:                      method="post" name="parameterlog">');
1.446     bisitz   7213: 
1.311     albertel 7214:     my %saveable_parameters = ('show' => 'scalar',);
                   7215:     &Apache::loncommon::store_course_settings('parameter_log',
                   7216:                                               \%saveable_parameters);
                   7217:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7218:                                                 \%saveable_parameters);
1.522     raeburn  7219:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7220:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7221:               '</form></fieldset></div><br clear="all" />');
1.301     www      7222: 
1.568     raeburn  7223:     my $readonly = 1;
                   7224:     if ($parm_permission->{'edit'}) {
                   7225:         undef($readonly);
                   7226:     }
1.531     raeburn  7227:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7228:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7229:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7230:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7231:     unless ($readonly) {
                   7232:         $r->print('<th>'.&mt('Announce').'</th>');
                   7233:     }
                   7234:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7235:     my $shown=0;
1.349     www      7236:     my $folder='';
                   7237:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7238:         my $last='';
                   7239:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7240:                 &GDBM_READER(),0640)) {
                   7241:             $last=$hash{'last_known'};
                   7242:             untie(%hash);
                   7243:         }
                   7244:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7245:     }
1.595     raeburn  7246:     my $numgroups = 0;
                   7247:     my @groups;
                   7248:     if ($env{'request.course.groups'} ne '') {
                   7249:         @groups = split(/:/,$env{'request.course.groups'});
                   7250:         $numgroups = scalar(@groups);
                   7251:     }
1.560     damieng  7252:     foreach my $id (sort {
                   7253:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7254:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7255:                 }
                   7256:                 my $aid = (split('00000',$a))[-1];
                   7257:                 my $bid = (split('00000',$b))[-1];
                   7258:                 return $bid<=>$aid;
1.473     amueller 7259:             } (keys(%parmlog))) {
1.294     www      7260:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7261:         my $count = 0;
                   7262:         my $time =
                   7263:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7264:         my $plainname =
                   7265:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7266:                         $parmlog{$id}{'exe_udom'});
                   7267:         my $about_me_link =
                   7268:             &Apache::loncommon::aboutmewrapper($plainname,
                   7269:                             $parmlog{$id}{'exe_uname'},
                   7270:                             $parmlog{$id}{'exe_udom'});
                   7271:         my $send_msg_link='';
1.568     raeburn  7272:         if ((!$readonly) && 
                   7273:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7274:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7275:             $send_msg_link ='<br />'.
                   7276:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7277:                             $parmlog{$id}{'exe_uname'},
                   7278:                             $parmlog{$id}{'exe_udom'});
                   7279:         }
                   7280:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7281:         my $makenewrow=0;
                   7282:         my %istype=();
                   7283:         my $output;
                   7284:         foreach my $changed (reverse(sort(@changes))) {
                   7285:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7286:             my $typeflag = ($changed =~/\.type$/ &&
                   7287:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7288:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7289:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7290:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7291:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7292:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7293:                 if ($uname ne '') {
                   7294:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7295:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7296:                 }
                   7297:             }
                   7298:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7299:                 if ($folder) {
                   7300:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7301:                 }
                   7302:             }
                   7303:             if ($typeflag) {
                   7304:                 $istype{$parmname}=$value;
                   7305:                 if (!$env{'form.includetypes'}) { next; }
                   7306:             }
                   7307:             $count++;
                   7308:             if ($makenewrow) {
                   7309:                 $output .= $row_start;
                   7310:             } else {
                   7311:                 $makenewrow=1;
                   7312:             }
1.470     raeburn  7313:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7314:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7315:                 &mt($parmitem).'</td><td>'.
                   7316:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7317:             my $stillactive=0;
                   7318:             if ($parmlog{$id}{'delflag'}) {
                   7319:                 $output .= &mt('Deleted');
                   7320:             } else {
                   7321:                 if ($typeflag) {
1.470     raeburn  7322:                     my $parmitem = &standard_parameter_names($value); 
                   7323:                     $parmitem = &mt($parmitem);
1.560     damieng  7324:                     $output .= &mt('Type: [_1]',$parmitem);
                   7325:                 } else {
1.584     raeburn  7326:                     my $toolsymb;
                   7327:                     if ($middle =~ /ext\.tool$/) {
                   7328:                         $toolsymb = $middle;
                   7329:                     }
1.560     damieng  7330:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7331:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7332:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7333:                     my $showvalue = $value;
                   7334:                     if ($istype{$parmname} eq '') {
                   7335:                         my $type = &standard_parameter_types($parmname);
                   7336:                         if ($type ne '') {
                   7337:                             if (&isdateparm($type)) {
                   7338:                                 $showvalue =
                   7339:                                     &Apache::lonlocal::locallocaltime($value);
                   7340:                             }
                   7341:                         }
                   7342:                     } else {
1.560     damieng  7343:                         if (&isdateparm($istype{$parmname})) {
                   7344:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7345:                         }
1.469     raeburn  7346:                     }
                   7347:                     $output .= $showvalue;
1.560     damieng  7348:                     if ($value ne $all[$level]) {
                   7349:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7350:                     } else {
                   7351:                         $stillactive=1;
                   7352:                     }
                   7353:                 }
1.473     amueller 7354:             }
1.568     raeburn  7355:             $output .= '</td>';
                   7356: 
                   7357:             unless ($readonly) { 
                   7358:                 $output .= '<td>';
                   7359:                 if ($stillactive) {
                   7360:                     my $parmitem = &standard_parameter_names($parmname);
                   7361:                     $parmitem = &mt($parmitem);
                   7362:                     my $title=&mt('Changed [_1]',$parmitem);
                   7363:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7364:                         $parmitem,$realmdescription,
                   7365:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7366:                     if (($uname) && ($udom)) {
                   7367:                         $output .=
                   7368:                         &Apache::loncommon::messagewrapper('Notify User',
                   7369:                                                            $uname,$udom,$title,
                   7370:                                                            $description);
                   7371:                     } else {
                   7372:                         $output .=
                   7373:                             &Apache::lonrss::course_blog_link($id,$title,
                   7374:                                                               $description);
                   7375:                     }
1.560     damieng  7376:                 }
1.568     raeburn  7377:                 $output .= '</td>';
1.560     damieng  7378:             }
1.568     raeburn  7379:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7380:         }
1.560     damieng  7381:         if ($env{'form.displayfilter'} eq 'containing') {
                   7382:             my $wholeentry=$about_me_link.':'.
                   7383:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7384:             $output;
                   7385:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7386:         }
1.349     www      7387:         if ($count) {
1.560     damieng  7388:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7389:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7390:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7391:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7392:             $send_msg_link.'</td>'.$output);
                   7393:             $shown++;
                   7394:         }
                   7395:         if (!($env{'form.show'} eq &mt('all')
                   7396:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7397:     }
1.301     www      7398:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7399:     &endSettingsScreen($r);
1.284     www      7400:     $r->print(&Apache::loncommon::end_page());
                   7401: }
                   7402: 
1.560     damieng  7403: ##################################################
                   7404: # MISC !
                   7405: ##################################################
                   7406: 
1.563     damieng  7407: # Stores slot information.
1.560     damieng  7408: # Used by table UI
1.563     damieng  7409: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7410: #
                   7411: # @param {string} $slot_name - slot name
                   7412: # @param {string} $cdom - course domain
                   7413: # @param {string} $cnum - course number
                   7414: # @param {string} $symb - resource symb
                   7415: # @param {string} $uname - user name
                   7416: # @param {string} $udom - user domain
                   7417: # @returns {string} - 'ok' or error name
1.437     raeburn  7418: sub update_slots {
                   7419:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7420:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7421:     if (!keys(%slot)) {
                   7422:         return 'error: slot does not exist';
                   7423:     }
                   7424:     my $max=$slot{'maxspace'};
                   7425:     if (!defined($max)) { $max=99999; }
                   7426: 
                   7427:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7428:                                        "^$slot_name\0");
                   7429:     my ($tmp)=%consumed;
                   7430:     if ($tmp=~/^error: 2 / ) {
                   7431:         return 'error: unable to determine current slot status';
                   7432:     }
                   7433:     my $last=0;
                   7434:     foreach my $key (keys(%consumed)) {
                   7435:         my $num=(split('\0',$key))[1];
                   7436:         if ($num > $last) { $last=$num; }
                   7437:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7438:             return 'ok';
                   7439:         }
                   7440:     }
                   7441: 
                   7442:     if (scalar(keys(%consumed)) >= $max) {
                   7443:         return 'error: no space left in slot';
                   7444:     }
                   7445:     my $wanted=$last+1;
                   7446: 
                   7447:     my %reservation=('name'      => $uname.':'.$udom,
                   7448:                      'timestamp' => time,
                   7449:                      'symb'      => $symb);
                   7450: 
                   7451:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7452:                                         {"$slot_name\0$wanted" =>
                   7453:                                              \%reservation},
                   7454:                                         $cdom, $cnum);
1.438     raeburn  7455:     if ($success eq 'ok') {
                   7456:         my %storehash = (
                   7457:                           symb    => $symb,
                   7458:                           slot    => $slot_name,
                   7459:                           action  => 'reserve',
                   7460:                           context => 'parameter',
                   7461:                         );
1.526     raeburn  7462:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7463:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7464: 
1.526     raeburn  7465:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7466:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7467:     }
1.437     raeburn  7468:     return $success;
                   7469: }
                   7470: 
1.563     damieng  7471: # Deletes a slot reservation.
1.560     damieng  7472: # Used by table UI
1.563     damieng  7473: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7474: #
                   7475: # @param {string} $slot_name - slot name
                   7476: # @param {string} $cdom - course domain
                   7477: # @param {string} $cnum - course number
                   7478: # @param {string} $uname - user name
                   7479: # @param {string} $udom - user domain
                   7480: # @param {string} $symb - resource symb
                   7481: # @returns {string} - 'ok' or error name
1.437     raeburn  7482: sub delete_slots {
                   7483:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7484:     my $delresult;
                   7485:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7486:                                          $cnum, "^$slot_name\0");
                   7487:     if (&Apache::lonnet::error(%consumed)) {
                   7488:         return 'error: unable to determine current slot status';
                   7489:     }
                   7490:     my ($tmp)=%consumed;
                   7491:     if ($tmp=~/^error: 2 /) {
                   7492:         return 'error: unable to determine current slot status';
                   7493:     }
                   7494:     foreach my $key (keys(%consumed)) {
                   7495:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7496:             my $num=(split('\0',$key))[1];
                   7497:             my $entry = $slot_name.'\0'.$num;
                   7498:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7499:                                               $cdom,$cnum);
                   7500:             if ($delresult eq 'ok') {
                   7501:                 my %storehash = (
                   7502:                                   symb    => $symb,
                   7503:                                   slot    => $slot_name,
                   7504:                                   action  => 'release',
                   7505:                                   context => 'parameter',
                   7506:                                 );
1.526     raeburn  7507:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7508:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7509:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7510:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7511:             }
                   7512:         }
                   7513:     }
                   7514:     return $delresult;
                   7515: }
                   7516: 
1.563     damieng  7517: # Returns true if there is a current course.
1.560     damieng  7518: # Used by handler
1.563     damieng  7519: #
                   7520: # @returns {boolean}
1.355     albertel 7521: sub check_for_course_info {
                   7522:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7523:     return 1 if ($navmap);
                   7524:     return 0;
                   7525: }
                   7526: 
1.563     damieng  7527: # Returns the current course host and host LON-CAPA version.
                   7528: #
                   7529: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7530: sub parameter_release_vars { 
1.504     raeburn  7531:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7532:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7533:    my $chostname = &Apache::lonnet::hostname($chome);
                   7534:    my ($cmajor,$cminor) = 
                   7535:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7536:    return ($chostname,$cmajor,$cminor);
                   7537: }
                   7538: 
1.563     damieng  7539: # Checks if the course host version can handle a parameter required version,
                   7540: # and if it does, stores the release needed for the course.
                   7541: #
                   7542: # @param {string} $name - parameter name
                   7543: # @param {string} $value - parameter value
                   7544: # @param {string} $valmatch - name of the test used for checking the value
                   7545: # @param {string} $namematch - name of the test used for checking the name
                   7546: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7547: # @param {integer} $cmajor - course major version number
                   7548: # @param {integer} $cminor - course minor version number
                   7549: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7550: sub parameter_releasecheck {
1.557     raeburn  7551:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7552:     my $needsnewer;
                   7553:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7554:     if (($cmajor < $needsmajor) || 
                   7555:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7556:         $needsnewer = 1;
1.557     raeburn  7557:     } elsif ($name) {
                   7558:         if ($valmatch) {
                   7559:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7560:         } elsif ($value) { 
                   7561:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7562:         }
                   7563:     } elsif ($namematch) {
                   7564:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7565:     }
                   7566:     return $needsnewer;
                   7567: }
                   7568: 
1.568     raeburn  7569: sub get_permission {
                   7570:     my %permission;
                   7571:     my $allowed = 0;
                   7572:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7573:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7574:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7575:                   $env{'request.course.sec'}))) {
                   7576:         %permission= (
                   7577:                        'edit'               => 1,
                   7578:                        'set'                => 1,
                   7579:                        'setoverview'        => 1,
                   7580:                        'addmetadata'        => 1,
                   7581:                        'ordermetadata'      => 1,
                   7582:                        'setrestrictmeta'    => 1,
                   7583:                        'newoverview'        => 1,
                   7584:                        'setdefaults'        => 1,
                   7585:                        'settable'           => 1,
                   7586:                        'parameterchangelog' => 1,
                   7587:                        'cleanparameters'    => 1,
                   7588:                        'dateshift1'         => 1,
                   7589:                        'dateshift2'         => 1,
                   7590:                        'helper'             => 1,
                   7591:          );
                   7592:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7593:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7594:                   $env{'request.course.sec'}))) {
                   7595:         %permission = (
                   7596:                        'set'                => 1,
                   7597:                        'settable'           => 1,
                   7598:                        'newoverview'        => 1,
                   7599:                        'setoverview'        => 1,
                   7600:                        'parameterchangelog' => 1,
                   7601:                       );
                   7602:     }
                   7603:     foreach my $perm (values(%permission)) {
                   7604:         if ($perm) { $allowed=1; last; }
                   7605:     }
                   7606:     return (\%permission,$allowed);
                   7607: }
                   7608: 
1.560     damieng  7609: ##################################################
                   7610: # HANDLER
                   7611: ##################################################
                   7612: 
                   7613: # Main handler for lonparmset.
                   7614: # Sub called based on request parameters action and command:
                   7615: # no command or action: print_main_menu
                   7616: # command 'set': assessparms (direct access to table mode for a resource)
                   7617: #                (this can also be accessed simply with the symb parameter)
                   7618: # action 'setoverview': overview (display all existing parameter settings)
                   7619: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7620: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7621: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7622: # action 'newoverview': newoverview (overview mode)
                   7623: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7624: # action 'settable': assessparms (table mode)
                   7625: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7626: #                              blog postings, user notification changes)
                   7627: # action 'cleanparameters': clean_parameters (unused)
                   7628: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7629: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7630: sub handler {
1.43      albertel 7631:     my $r=shift;
1.30      www      7632: 
1.376     albertel 7633:     &reset_caches();
                   7634: 
1.414     droeschl 7635:     &Apache::loncommon::content_type($r,'text/html');
                   7636:     $r->send_http_header;
                   7637:     return OK if $r->header_only;
                   7638: 
1.193     albertel 7639:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7640:                         ['action','state',
1.205     www      7641:                                              'pres_marker',
                   7642:                                              'pres_value',
1.206     www      7643:                                              'pres_type',
1.506     www      7644:                                              'filter','part',
1.390     www      7645:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7646: 
1.83      bowersj2 7647: 
1.193     albertel 7648:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7649:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7650:                         text=>"Content and Problem Settings",
1.473     amueller 7651:                         faq=>10,
                   7652:                         bug=>'Instructor Interface',
1.442     droeschl 7653:                                             help =>
                   7654:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7655: 
1.30      www      7656: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7657:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7658:     my $exists = &check_for_course_info();
                   7659: 
1.568     raeburn  7660:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7661:         #
                   7662:         # Main switch on form.action and form.state, as appropriate
                   7663:         #
                   7664:         # Check first if coming from someone else headed directly for
                   7665:         #  the table mode
1.568     raeburn  7666:         if (($parm_permission->{'set'}) && 
                   7667:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7668:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7669:             &assessparms($r,$parm_permission);
1.193     albertel 7670:         } elsif (! exists($env{'form.action'})) {
                   7671:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7672:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7673:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7674:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7675:             &overview($r,$parm_permission);
1.560     damieng  7676:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7677:             &addmetafield($r);
                   7678:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7679:             &order_meta_fields($r);
1.414     droeschl 7680:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7681:             &setrestrictmeta($r);
1.414     droeschl 7682:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7683:             &newoverview($r,$parm_permission);
1.414     droeschl 7684:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7685:             &defaultsetter($r);
                   7686:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7687:             &assessparms($r,$parm_permission);
1.414     droeschl 7688:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7689:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7690:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7691:             &clean_parameters($r);
1.414     droeschl 7692:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7693:             &date_shift_one($r);
1.414     droeschl 7694:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7695:             &date_shift_two($r);
1.446     bisitz   7696:         }
1.43      albertel 7697:     } else {
1.1       www      7698: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7699:         if ($exists) {
                   7700:             $env{'user.error.msg'}=
                   7701:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7702:         } else {
                   7703:             $env{'user.error.msg'}=
                   7704:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7705:         }
                   7706:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7707:     }
1.376     albertel 7708:     &reset_caches();
                   7709: 
1.43      albertel 7710:     return OK;
1.1       www      7711: }
                   7712: 
                   7713: 1;
                   7714: __END__
                   7715: 
                   7716: 

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