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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.575   ! raeburn     4: # $Id: lonparmset.pm,v 1.574 2017/07/10 12:48:41 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.560     damieng    39: lonparmset provides an interface to setting course parameters.
                     40: 
                     41: It contains all the code for the "Content and Problem Settings" UI, except
                     42: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
                     43: and lonblockingmenu.pm.
1.59      matthew    44: 
                     45: =head1 DESCRIPTION
                     46: 
                     47: This module sets coursewide and assessment parameters.
                     48: 
                     49: =head1 INTERNAL SUBROUTINES
                     50: 
1.416     jms        51: =over
1.59      matthew    52: 
1.416     jms        53: =item parmval()
1.59      matthew    54: 
                     55: Figure out a cascading parameter.
                     56: 
1.71      albertel   57: Inputs:  $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162     albertel   58:          $id   - a bighash Id number
1.71      albertel   59:          $def  - the resource's default value   'stupid emacs
                     60: 
1.556     raeburn    61: 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   62: 
1.556     raeburn    63: 18 - General Course
                     64: 17 - Map or Folder level in course (recursive) 
                     65: 16 - Map or Folder level in course (non-recursive)
                     66: 15 - resource default
                     67: 14 - map default
                     68: 13 - resource level in course
                     69: 12 - General for section
                     70: 11 - Map or Folder level for section (recursive)
                     71: 10 - Map or Folder level for section (non-recursive)
                     72: 9 - resource level in section
                     73: 8 - General for group
                     74: 7 - Map or Folder level for group (recursive)
                     75: 6 - Map or Folder level for group (non-recursive)
                     76: 5 - resource level in group
                     77: 4 - General for specific student
                     78: 3 - Map or Folder level for specific student (recursive)
                     79: 2 - Map or Folder level for specific student (non-recursive)
1.71      albertel   80: 1 - resource level for specific student
1.2       www        81: 
1.416     jms        82: =item parmval_by_symb()
                     83: 
                     84: =item reset_caches()
                     85: 
                     86: =item cacheparmhash() 
                     87: 
                     88: =item parmhash()
                     89: 
                     90: =item symbcache()
                     91: 
                     92: =item preset_defaults()
                     93: 
                     94: =item date_sanity_info()
                     95: 
                     96: =item storeparm()
                     97: 
                     98: Store a parameter by symb
                     99: 
                    100:     Takes
                    101:     - symb
                    102:     - name of parameter
                    103:     - level
                    104:     - new value
                    105:     - new type
                    106:     - username
                    107:     - userdomain
                    108: 
                    109: =item log_parmset()
                    110: 
                    111: =item storeparm_by_symb_inner()
                    112: 
                    113: =item valout()
                    114: 
                    115: Format a value for output.
                    116: 
                    117: Inputs:  $value, $type, $editable
                    118: 
                    119: Returns: $value, formatted for output.  If $type indicates it is a date,
                    120: localtime($value) is returned.
                    121: $editable will return an icon to click on
                    122: 
                    123: =item plink()
                    124: 
                    125: Produces a link anchor.
                    126: 
                    127: Inputs: $type,$dis,$value,$marker,$return,$call
                    128: 
                    129: Returns: scalar with html code for a link which will envoke the 
                    130: javascript function 'pjump'.
                    131: 
                    132: =item page_js()
                    133: 
                    134: =item startpage()
                    135: 
                    136: =item print_row()
                    137: 
                    138: =item print_td()
                    139: 
                    140: =item print_usergroups()
                    141: 
                    142: =item parm_control_group()
                    143: 
                    144: =item extractResourceInformation() : 
                    145: 
1.512     foxr      146:  extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416     jms       147: 
1.542     raeburn   148: Input: See list below
                    149: 
                    150: =over 4
1.416     jms       151: 
1.512     foxr      152: =item * B<env{'user.name'}> : Current username
1.416     jms       153: 
1.512     foxr      154: =item * B<env{'user.domain'}> : Domain of current user.
1.416     jms       155: 
1.542     raeburn   156: =item * B<env{"request.course.fn"}> : Course
                    157: 
                    158: =back
1.416     jms       159: 
1.512     foxr      160: Outputs: See list below:
1.416     jms       161: 
1.542     raeburn   162: =over 4
                    163: 
1.512     foxr      164: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416     jms       165: 
1.512     foxr      166: =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       167: 
1.512     foxr      168: =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       169: 
1.512     foxr      170: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416     jms       171: 
1.512     foxr      172: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
                    173: 
                    174: =item * B<allmaps> (out) : hash, ???
1.416     jms       175: 
                    176: =item * B<mapp> : ??
                    177: 
                    178: =item * B<symbp> : hash, id->full sym?
                    179: 
1.512     foxr      180: =item * B<maptitles>
                    181: 
                    182: =item * B<uris>
1.416     jms       183: 
1.512     foxr      184: =item * B<keyorder>
                    185: 
                    186: =item * B<defkeytype>
1.416     jms       187: 
1.542     raeburn   188: =back
                    189: 
1.416     jms       190: =item isdateparm()
                    191: 
                    192: =item parmmenu()
                    193: 
                    194: =item partmenu()
                    195: 
                    196: =item usermenu()
                    197: 
                    198: =item displaymenu()
                    199: 
                    200: =item mapmenu()
                    201: 
                    202: =item levelmenu()
                    203: 
                    204: =item sectionmenu()
                    205: 
                    206: =item keysplit()
                    207: 
                    208: =item keysinorder()
                    209: 
                    210: =item keysinorder_bytype()
                    211: 
                    212: =item keysindisplayorder()
                    213: 
                    214: =item standardkeyorder()
                    215: 
                    216: =item assessparms() : 
                    217: 
                    218: Show assessment data and parameters.  This is a large routine that should
                    219: be simplified and shortened... someday.
                    220: 
1.513     foxr      221: Inputs: $r - the Apache request object.
                    222:   
1.416     jms       223: Returns: nothing
                    224: 
                    225: Variables used (guessed by Jeremy):
                    226: 
1.542     raeburn   227: =over
                    228: 
1.416     jms       229: =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.
                    230: 
                    231: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
                    232: 
                    233: =item * B<@catmarker> contains list of all possible parameters including part #s
                    234: 
                    235: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
                    236: 
                    237: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
                    238:         When storing information, store as part 0
                    239:         When requesting information, request from full part
                    240: 
1.542     raeburn   241: =back
                    242: 
1.416     jms       243: =item tablestart()
                    244: 
                    245: =item tableend()
                    246: 
                    247: =item extractuser()
                    248: 
                    249: =item parse_listdata_key()
                    250: 
                    251: =item listdata()
                    252: 
                    253: =item date_interval_selector()
                    254: 
                    255: =item get_date_interval_from_form()
                    256: 
                    257: =item default_selector()
                    258: 
                    259: =item string_selector()
                    260: 
                    261: =item dateshift()
                    262: 
                    263: =item newoverview()
                    264: 
                    265: =item secgroup_lister()
                    266: 
                    267: =item overview()
                    268: 
                    269: =item clean_parameters()
                    270: 
                    271: =item date_shift_one()
                    272: 
                    273: =item date_shift_two()
                    274: 
                    275: =item parse_key()
                    276: 
                    277: =item header()
                    278: 
                    279: Output html header for page
                    280: 
                    281: =item print_main_menu()
                    282: 
                    283: =item output_row()
                    284: 
                    285: Set portfolio metadata
                    286: 
                    287: =item order_meta_fields()
                    288: 
                    289: =item addmetafield()
                    290: 
                    291: =item setrestrictmeta()
                    292: 
                    293: =item get_added_meta_fieldnames()
                    294: 
                    295: =item get_deleted_meta_fieldnames()
                    296: 
                    297: =item defaultsetter()
                    298: 
                    299: =item components()
                    300: 
                    301: =item load_parameter_names()
                    302: 
                    303: =item parm_change_log()
                    304: 
                    305: =item handler() : 
                    306: 
1.450     raeburn   307: Main handler.  Calls &assessparms subroutine.
1.416     jms       308: 
                    309: =back
                    310: 
1.59      matthew   311: =cut
                    312: 
1.416     jms       313: ###################################################################
                    314: ###################################################################
                    315: 
                    316: package Apache::lonparmset;
                    317: 
                    318: use strict;
                    319: use Apache::lonnet;
                    320: use Apache::Constants qw(:common :http REDIRECT);
                    321: use Apache::lonhtmlcommon();
                    322: use Apache::loncommon;
                    323: use GDBM_File;
                    324: use Apache::lonhomework;
                    325: use Apache::lonxml;
                    326: use Apache::lonlocal;
                    327: use Apache::lonnavmaps;
                    328: use Apache::longroup;
                    329: use Apache::lonrss;
1.506     www       330: use HTML::Entities;
1.416     jms       331: use LONCAPA qw(:DEFAULT :match);
                    332: 
                    333: 
1.560     damieng   334: ##################################################
                    335: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    336: ##################################################
                    337: 
                    338: # Page header
1.561     damieng   339: #
                    340: # @param {Apache2::RequestRec} $r - Apache request object
                    341: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    342: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       343: sub startSettingsScreen {
1.531     raeburn   344:     my ($r,$mode,$crstype)=@_;
1.507     www       345: 
1.531     raeburn   346:     my $tabtext = &mt('Course Settings');
                    347:     if ($crstype eq 'Community') {
                    348:         $tabtext = &mt('Community Settings');
                    349:     } 
1.507     www       350:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    351:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   352:                                           $tabtext.
1.507     www       353:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    354: 
1.523     raeburn   355:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       356:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    357:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   358:     $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       359: }
                    360: 
1.560     damieng   361: # Page footer
1.507     www       362: sub endSettingsScreen {
                    363:    my ($r)=@_;
                    364:    $r->print('</div></div></div>');
                    365: }
                    366: 
                    367: 
                    368: 
1.560     damieng   369: ##################################################
1.563     damieng   370: # (mostly) TABLE MODE
1.560     damieng   371: # (parmval is also used for the log of parameter changes)
                    372: ##################################################
                    373: 
1.566     damieng   374: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   375: #
                    376: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   377: # @param {string} $id - resource id or map pc
1.561     damieng   378: # @param {string} $def - the resource's default value for this parameter
                    379: # @param {string} $uname - user name
                    380: # @param {string} $udom - user domain
                    381: # @param {string} $csec - section name
                    382: # @param {string} $cgroup - group name
                    383: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    384: # @returns {Array}
1.2       www       385: sub parmval {
1.275     raeburn   386:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    387:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    388:                                                            $cgroup,$courseopt);
1.201     www       389: }
                    390: 
1.561     damieng   391: # Returns an array containing
                    392: # - the most specific level that is defined for that parameter (integer)
                    393: # - an array with the level as index and the parameter value as value (when defined)
                    394: #   (level 1 is the most specific and will have precedence)
                    395: #
                    396: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   397: # @param {string} $symb - resource symb or map src
1.561     damieng   398: # @param {string} $def - the resource's default value for this parameter
                    399: # @param {string} $uname - user name
                    400: # @param {string} $udom - user domain
                    401: # @param {string} $csec - section name
                    402: # @param {string} $cgroup - group name
                    403: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    404: # @returns {Array}
1.201     www       405: sub parmval_by_symb {
1.275     raeburn   406:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       407: 
1.352     albertel  408:     my $useropt;
                    409:     if ($uname ne '' && $udom ne '') {
1.561     damieng   410:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  411:     }
1.200     www       412: 
1.8       www       413:     my $result='';
1.44      albertel  414:     my @outpar=();
1.2       www       415: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    416:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  417:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   418:     
                    419:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    420:     # any change should be reflected there.
                    421:     
1.201     www       422:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   423:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       424:     my $mapparm=$map.'___(all).'.$what;
1.10      www       425: 
1.269     raeburn   426:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    427:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   428:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   429:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    430: 
1.190     albertel  431:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    432:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   433:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  434:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    435: 
                    436:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    437:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   438:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  439:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       440: 
1.11      www       441: 
1.182     albertel  442: # --------------------------------------------------------- first, check course
1.11      www       443: 
1.561     damieng   444: # 18 - General Course
1.200     www       445:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   446:         $outpar[18]=$$courseopt{$courselevel};
                    447:         $result=18;
                    448:     }
                    449: 
1.561     damieng   450: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   451:     if (defined($$courseopt{$courseleveli})) {
                    452:         $outpar[17]=$$courseopt{$courseleveli};
                    453:         $result=17;
1.43      albertel  454:     }
1.11      www       455: 
1.561     damieng   456: # 16 - Map or Folder level in course (non-recursive)
1.200     www       457:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   458:         $outpar[16]=$$courseopt{$courselevelm};
                    459:         $result=16;
1.43      albertel  460:     }
1.11      www       461: 
1.182     albertel  462: # ------------------------------------------------------- second, check default
                    463: 
1.561     damieng   464: # 15 - resource default
1.556     raeburn   465:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  466: 
                    467: # ------------------------------------------------------ third, check map parms
                    468: 
1.556     raeburn   469:     
1.561     damieng   470: # 14 - map default
1.376     albertel  471:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   472:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  473: 
1.561     damieng   474: # 13 - resource level in course
1.200     www       475:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   476:         $outpar[13]=$$courseopt{$courselevelr};
                    477:         $result=13;
1.43      albertel  478:     }
1.11      www       479: 
1.182     albertel  480: # ------------------------------------------------------ fourth, back to course
1.352     albertel  481:     if ($csec ne '') {
1.561     damieng   482: # 12 - General for section
1.200     www       483:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   484:             $outpar[12]=$$courseopt{$seclevel};
                    485:             $result=12;
                    486:         }
1.561     damieng   487: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   488:         if (defined($$courseopt{$secleveli})) {
                    489:             $outpar[11]=$$courseopt{$secleveli};
                    490:             $result=11;
                    491:         }
1.561     damieng   492: # 10 - Map or Folder level for section (non-recursive)
1.200     www       493:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   494:             $outpar[10]=$$courseopt{$seclevelm};
                    495:             $result=10;
                    496:         }
1.561     damieng   497: # 9 - resource level in section
1.200     www       498:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   499:             $outpar[9]=$$courseopt{$seclevelr};
                    500:             $result=9;
                    501:         }
1.43      albertel  502:     }
1.275     raeburn   503: # ------------------------------------------------------ fifth, check course group
1.352     albertel  504:     if ($cgroup ne '') {
1.561     damieng   505: # 8 - General for group
1.269     raeburn   506:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   507:             $outpar[8]=$$courseopt{$grplevel};
                    508:             $result=8;
                    509:         }
1.561     damieng   510: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   511:         if (defined($$courseopt{$grpleveli})) {
                    512:             $outpar[7]=$$courseopt{$grpleveli};
                    513:             $result=7;
1.269     raeburn   514:         }
1.561     damieng   515: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   516:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   517:             $outpar[6]=$$courseopt{$grplevelm};
                    518:             $result=6;
1.269     raeburn   519:         }
1.561     damieng   520: # 5 - resource level in group
1.269     raeburn   521:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   522:             $outpar[5]=$$courseopt{$grplevelr};
                    523:             $result=5;
1.269     raeburn   524:         }
                    525:     }
1.11      www       526: 
1.556     raeburn   527: # ---------------------------------------------------------- sixth, check user
1.11      www       528: 
1.352     albertel  529:     if ($uname ne '') {
1.561     damieng   530: # 4 - General for specific student
                    531:         if (defined($$useropt{$courselevel})) {
                    532:             $outpar[4]=$$useropt{$courselevel};
                    533:             $result=4;
                    534:         }
1.556     raeburn   535: 
1.561     damieng   536: # 3 - Map or Folder level for specific student (recursive)
                    537:         if (defined($$useropt{$courseleveli})) {
                    538:             $outpar[3]=$$useropt{$courseleveli};
                    539:             $result=3;
                    540:         }
1.473     amueller  541: 
1.561     damieng   542: # 2 - Map or Folder level for specific student (non-recursive)
                    543:         if (defined($$useropt{$courselevelm})) {
                    544:             $outpar[2]=$$useropt{$courselevelm};
                    545:             $result=2;
                    546:         }
1.473     amueller  547: 
1.561     damieng   548: # 1 - resource level for specific student
                    549:         if (defined($$useropt{$courselevelr})) {
                    550:             $outpar[1]=$$useropt{$courselevelr};
                    551:             $result=1;
                    552:         }
1.43      albertel  553:     }
1.44      albertel  554:     return ($result,@outpar);
1.2       www       555: }
                    556: 
1.198     www       557: 
                    558: 
1.376     albertel  559: # --- Caches local to lonparmset
                    560: 
1.446     bisitz    561: 
1.561     damieng   562: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  563: sub reset_caches {
                    564:     &resetparmhash();
                    565:     &resetsymbcache();
                    566:     &resetrulescache();
1.203     www       567: }
                    568: 
1.561     damieng   569: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    570: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  571: {
1.561     damieng   572:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    573:     my %parmhash; # the parameter cache
                    574:     # reset map parameter hash
1.376     albertel  575:     sub resetparmhash {
1.560     damieng   576:         undef($parmhashid);
                    577:         undef(%parmhash);
1.376     albertel  578:     }
1.446     bisitz    579: 
1.561     damieng   580:     # dump the _parms.db database into %parmhash
1.376     albertel  581:     sub cacheparmhash {
1.560     damieng   582:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    583:         my %parmhashfile;
                    584:         if (tie(%parmhashfile,'GDBM_File',
                    585:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    586:             %parmhash=%parmhashfile;
                    587:             untie(%parmhashfile);
                    588:             $parmhashid=$env{'request.course.fn'};
                    589:         }
1.201     www       590:     }
1.446     bisitz    591: 
1.561     damieng   592:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  593:     sub parmhash {
1.560     damieng   594:         my ($id) = @_;
                    595:         &cacheparmhash();
                    596:         return $parmhash{$id};
1.376     albertel  597:     }
1.560     damieng   598: }
1.376     albertel  599: 
1.566     damieng   600: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    601: {
1.561     damieng   602:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    603:     my %symbs; # hash id->symb
                    604:     # reset the id->symb cache
1.376     albertel  605:     sub resetsymbcache {
1.560     damieng   606:         undef($symbsid);
                    607:         undef(%symbs);
1.376     albertel  608:     }
1.446     bisitz    609: 
1.566     damieng   610:     # returns the resource symb or map src corresponding to a resource id or map pc
                    611:     # (using lonnavmaps and a cache)
1.376     albertel  612:     sub symbcache {
1.560     damieng   613:         my $id=shift;
                    614:         if ($symbsid ne $env{'request.course.id'}) {
                    615:             undef(%symbs);
                    616:         }
                    617:         if (!$symbs{$id}) {
                    618:             my $navmap = Apache::lonnavmaps::navmap->new();
                    619:             if ($id=~/\./) {
                    620:                 my $resource=$navmap->getById($id);
                    621:                 $symbs{$id}=$resource->symb();
                    622:             } else {
                    623:                 my $resource=$navmap->getByMapPc($id);
                    624:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    625:             }
                    626:             $symbsid=$env{'request.course.id'};
1.473     amueller  627:         }
1.560     damieng   628:         return $symbs{$id};
1.473     amueller  629:     }
1.560     damieng   630: }
1.201     www       631: 
1.561     damieng   632: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    633: {
1.561     damieng   634:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    635:     my %rules; # parameter default actions hash
1.376     albertel  636:     sub resetrulescache {
1.560     damieng   637:         undef($rulesid);
                    638:         undef(%rules);
1.376     albertel  639:     }
1.446     bisitz    640: 
1.561     damieng   641:     # returns the value for a given key in the parameter default action hash
1.376     albertel  642:     sub rulescache {
1.560     damieng   643:         my $id=shift;
                    644:         if ($rulesid ne $env{'request.course.id'}
                    645:             && !defined($rules{$id})) {
                    646:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    647:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    648:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    649:             $rulesid=$env{'request.course.id'};
                    650:         }
                    651:         return $rules{$id};
1.221     www       652:     }
                    653: }
                    654: 
1.416     jms       655: 
1.561     damieng   656: # Returns the values of the parameter type default action
                    657: # "default value when manually setting".
                    658: # If none is defined, ('','','','','') is returned.
                    659: #
                    660: # @param {string} $type - parameter type
                    661: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       662: sub preset_defaults {
                    663:     my $type=shift;
                    664:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   665:         # yes, there is something
                    666:         return (&rulescache($type.'_hours'),
                    667:             &rulescache($type.'_min'),
                    668:             &rulescache($type.'_sec'),
                    669:             &rulescache($type.'_value'));
1.229     www       670:     } else {
1.560     damieng   671:         # nothing there or something else
                    672:         return ('','','','','');
1.229     www       673:     }
                    674: }
                    675: 
1.416     jms       676: 
1.561     damieng   677: # Checks that a date is after enrollment start date and before
                    678: # enrollment end date.
                    679: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    680: # This is used by both overview and table modes.
                    681: #
                    682: # @param {integer} $checkdate - the date to check.
                    683: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       684: sub date_sanity_info {
                    685:    my $checkdate=shift;
                    686:    unless ($checkdate) { return ''; }
                    687:    my $result='';
                    688:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    689:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    690:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    691:          $result.='<div class="LC_warning">'
                    692:                  .&mt('After course enrollment end!')
                    693:                  .'</div>';
1.277     www       694:       }
                    695:    }
                    696:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    697:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    698:          $result.='<div class="LC_warning">'
                    699:                  .&mt('Before course enrollment start!')
                    700:                  .'</div>';
1.277     www       701:       }
                    702:    }
1.413     bisitz    703: # Preparation for additional warnings about dates in the past/future.
                    704: # An improved, more context sensitive version is recommended,
                    705: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    706: #   if ($checkdate<time) {
                    707: #      $result.='<div class="LC_info">'
                    708: #              .'('.&mt('in the past').')'
                    709: #              .'</div>';
                    710: #      }
                    711: #   if ($checkdate>time) {
                    712: #      $result.='<div class="LC_info">'
                    713: #              .'('.&mt('in the future').')'
                    714: #              .'</div>';
                    715: #      }
1.277     www       716:    return $result;
                    717: }
1.561     damieng   718: 
                    719: 
                    720: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       721: #
1.566     damieng   722: # @param {string} $sresid - resource id or map pc
1.565     damieng   723: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   724: # @param {integer} $snum - level
                    725: # @param {string} $nval - new value
                    726: # @param {string} $ntype - new type
                    727: # @param {string} $uname - username
                    728: # @param {string} $udom - userdomain
                    729: # @param {string} $csec - section name
                    730: # @param {string} $cgroup - group name
1.186     www       731: sub storeparm {
1.269     raeburn   732:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   733:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       734: }
                    735: 
1.561     damieng   736: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    737: 
                    738: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    739: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    740: #
1.566     damieng   741: # @param {string} $symb - resource symb or map src
1.565     damieng   742: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   743: # @param {integer} $snum - level
                    744: # @param {string} $nval - new value
                    745: # @param {string} $ntype - new type
                    746: # @param {string} $uname - username
                    747: # @param {string} $udom - userdomain
                    748: # @param {string} $csec - section name
                    749: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    750: # @param {string} $cgroup - group name
1.197     www       751: sub storeparm_by_symb {
1.275     raeburn   752:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       753:     unless ($recflag) {
1.560     damieng   754:         # first time call
                    755:         %recstack=();
                    756:         $recflag=1;
1.226     www       757:     }
1.560     damieng   758:     # store parameter
1.226     www       759:     &storeparm_by_symb_inner
1.473     amueller  760:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   761:     # don't do anything if parameter was reset
1.266     www       762:     unless ($nval) { return; }
1.226     www       763:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   764:     # remember that this was set
1.226     www       765:     $recstack{$parm}=1;
1.560     damieng   766:     # what does this trigger?
1.226     www       767:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   768:         # don't backfire
                    769:         unless ((!$triggered) || ($recstack{$triggered})) {
                    770:             my $action=&rulescache($triggered.'_action');
                    771:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    772:             # set triggered parameter on same level
                    773:             my $newspnam=$prefix.$triggered;
                    774:             my $newvalue='';
                    775:             my $active=1;
                    776:             if ($action=~/^when\_setting/) {
                    777:             # are there restrictions?
                    778:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    779:                     $active=0;
1.565     damieng   780:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   781:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    782:                     }
                    783:                 }
                    784:                 $newvalue=&rulescache($triggered.'_value');
                    785:             } else {
                    786:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    787:                 if ($action=~/^later\_than/) {
                    788:                     $newvalue=$nval+$totalsecs;
                    789:                 } else {
                    790:                     $newvalue=$nval-$totalsecs;
                    791:                 }
                    792:             }
                    793:             if ($active) {
                    794:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    795:                         $uname,$udom,$csec,$recflag,$cgroup);
                    796:             }
                    797:         }
1.226     www       798:     }
                    799:     return '';
                    800: }
                    801: 
1.561     damieng   802: # Adds all given arguments to the course parameter log.
                    803: # @returns {string} - the answer to the lonnet query.
1.293     www       804: sub log_parmset {
1.525     raeburn   805:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       806: }
                    807: 
1.561     damieng   808: # Store a parameter value and type by symb, without using the parameter default actions.
                    809: # Expire related sheets.
                    810: #
1.566     damieng   811: # @param {string} $symb - resource symb or map src
1.561     damieng   812: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    813: # @param {integer} $snum - level
                    814: # @param {string} $nval - new value
                    815: # @param {string} $ntype - new type
                    816: # @param {string} $uname - username
                    817: # @param {string} $udom - userdomain
                    818: # @param {string} $csec - section name
                    819: # @param {string} $cgroup - group name
                    820: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       821: sub storeparm_by_symb_inner {
1.197     www       822: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   823:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       824: # ---------------------------------------------------------- Construct prefixes
1.186     www       825:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    826:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  827:     $map = &Apache::lonnet::deversion($map);
                    828: 
1.197     www       829:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   830:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       831:     my $mapparm=$map.'___(all).'.$spnam;
                    832: 
1.269     raeburn   833:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    834:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   835:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   836:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    837: 
1.190     albertel  838:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    839:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   840:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  841:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    842: 
1.190     albertel  843:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    844:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   845:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  846:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    847: 
1.186     www       848:     my $storeunder='';
1.556     raeburn   849:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
                    850:     if (($snum==17) || ($snum==3)) { $storeunder=$courseleveli; } 
                    851:     if (($snum==16) || ($snum==2)) { $storeunder=$courselevelm; }
                    852:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    853:     if ($snum==12) { $storeunder=$seclevel; }
                    854:     if ($snum==11) { $storeunder=$secleveli; }
                    855:     if ($snum==10) { $storeunder=$seclevelm; }
                    856:     if ($snum==9) { $storeunder=$seclevelr; }
                    857:     if ($snum==8) { $storeunder=$grplevel; }
                    858:     if ($snum==7) { $storeunder=$grpleveli; }
                    859:     if ($snum==6) { $storeunder=$grplevelm; }
                    860:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   861: 
1.446     bisitz    862: 
1.186     www       863:     my $delete;
                    864:     if ($nval eq '') { $delete=1;}
                    865:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  866:             $storeunder.'.type' => $ntype);
1.186     www       867:     my $reply='';
1.560     damieng   868:     
1.556     raeburn   869:     if ($snum>4) {
1.186     www       870: # ---------------------------------------------------------------- Store Course
                    871: #
1.560     damieng   872:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    873:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    874:         # Expire sheets
                    875:         &Apache::lonnet::expirespread('','','studentcalc');
                    876:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    877:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
                    878:         } elsif (($snum==14) || ($snum==10) || ($snum==6)) {
                    879:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    880:         } else {
                    881:             &Apache::lonnet::expirespread('','','assesscalc');
                    882:         }
                    883:         # Store parameter
                    884:         if ($delete) {
                    885:             $reply=&Apache::lonnet::del
                    886:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    887:                 &log_parmset(\%storecontent,1);
                    888:         } else {
                    889:             $reply=&Apache::lonnet::cput
                    890:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    891:             &log_parmset(\%storecontent);
                    892:         }
                    893:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       894:     } else {
                    895: # ------------------------------------------------------------------ Store User
                    896: #
1.560     damieng   897:         # Expire sheets
                    898:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    899:         if ($snum==1) {
                    900:             &Apache::lonnet::expirespread
                    901:             ($uname,$udom,'assesscalc',$symb);
                    902:         } elsif ($snum==2) {
                    903:             &Apache::lonnet::expirespread
                    904:             ($uname,$udom,'assesscalc',$map);
                    905:         } else {
                    906:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    907:         }
                    908:         # Store parameter
                    909:         if ($delete) {
                    910:             $reply=&Apache::lonnet::del
                    911:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    912:             &log_parmset(\%storecontent,1,$uname,$udom);
                    913:         } else {
                    914:             $reply=&Apache::lonnet::cput
                    915:             ('resourcedata',\%storecontent,$udom,$uname);
                    916:             &log_parmset(\%storecontent,0,$uname,$udom);
                    917:         }
                    918:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       919:     }
1.446     bisitz    920: 
1.186     www       921:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   922:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       923:     }
                    924:     return '';
                    925: }
                    926: 
1.9       www       927: 
1.561     damieng   928: # Returns HTML with the value of the given parameter,
                    929: # using a readable format for dates, and
                    930: # a warning if there is a problem with a date.
                    931: # Used by table mode.
                    932: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    933: #
                    934: # @param {string} $value - the parameter value
                    935: # @param {string} $type - the parameter type
                    936: # @param {string} $name - the parameter name (unused)
                    937: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       938: sub valout {
1.554     raeburn   939:     my ($value,$type,$name,$editable)=@_;
1.59      matthew   940:     my $result = '';
                    941:     # Values of zero are valid.
                    942:     if (! $value && $value ne '0') {
1.528     bisitz    943:         if ($editable) {
                    944:             $result =
                    945:                 '<img src="/res/adm/pages/editmap.png"'
                    946:                .' alt="'.&mt('Change').'"'
1.539     raeburn   947:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    948:         } else {
                    949:             $result='&nbsp;';
                    950:         }
1.59      matthew   951:     } else {
1.66      www       952:         if ($type eq 'date_interval') {
1.559     raeburn   953:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    954:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    955:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    956:                 $donebuttontext = $1;
                    957:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                    958:                 $usesdone = 'done';
                    959:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                    960:                 $donebuttontext = &mt('Done');
                    961:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                    962:             }
1.554     raeburn   963:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz    964:             my @timer;
1.66      www       965:             $year=$year-70;
                    966:             $mday--;
                    967:             if ($year) {
1.413     bisitz    968: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                    969:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www       970:             }
                    971:             if ($mon) {
1.413     bisitz    972: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                    973:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www       974:             }
                    975:             if ($mday) {
1.413     bisitz    976: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                    977:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www       978:             }
                    979:             if ($hour) {
1.413     bisitz    980: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                    981:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www       982:             }
                    983:             if ($min) {
1.413     bisitz    984: #               $result.=&mt('[quant,_1,min]',$min).' ';
                    985:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www       986:             }
                    987:             if ($sec) {
1.413     bisitz    988: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                    989:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www       990:             }
1.413     bisitz    991: #           $result=~s/\s+$//;
                    992:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                    993:                 push(@timer,&mt('[quant,_1,sec]',0));
                    994:             }
                    995:             $result.=join(", ",@timer);
1.559     raeburn   996:             if ($usesdone eq 'done') {
1.558     raeburn   997:                 if ($secretkey) {
1.559     raeburn   998:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn   999:                 } else {
1.559     raeburn  1000:                     $result .= ' + "'.$donebuttontext.'"';
                   1001:                 }
1.554     raeburn  1002:             }
1.213     www      1003:         } elsif (&isdateparm($type)) {
1.361     albertel 1004:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1005:                 &date_sanity_info($value);
1.59      matthew  1006:         } else {
                   1007:             $result = $value;
1.517     www      1008:             $result=~s/\,/\, /gs;
1.560     damieng  1009:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1010:         }
                   1011:     }
                   1012:     return $result;
1.9       www      1013: }
                   1014: 
1.59      matthew  1015: 
1.561     damieng  1016: # Returns HTML containing a link on a parameter value, for table mode.
                   1017: # The link uses the javascript function 'pjump'.
                   1018: #
                   1019: # @param {string} $type - parameter type
                   1020: # @param {string} $dis - dialog title for editing the parameter value and type
                   1021: # @param {string} $value - parameter value
                   1022: # @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.
                   1023: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1024: # @param {string} $call - javascript function to call to submit the form ('psub')
1.5       www      1025: sub plink {
                   1026:     my ($type,$dis,$value,$marker,$return,$call)=@_;
1.23      www      1027:     my $winvalue=$value;
                   1028:     unless ($winvalue) {
1.560     damieng  1029:         if (&isdateparm($type)) {
1.190     albertel 1030:             $winvalue=$env{'form.recent_'.$type};
1.23      www      1031:         } else {
1.190     albertel 1032:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1033:         }
                   1034:     }
1.229     www      1035:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1036:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1037:     unless (defined($winvalue)) { $winvalue=$val; }
1.554     raeburn  1038:     my $valout = &valout($value,$type,$parmname,1);
1.429     raeburn  1039:     my $unencmarker = $marker;
1.378     albertel 1040:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.473     amueller 1041:               \$hour, \$min, \$sec) {
1.560     damieng  1042:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1043:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1044:     }
1.429     raeburn  1045:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1046:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
                   1047:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."'".');">'.
                   1048:         $valout.'</a></td></tr></table>';
1.5       www      1049: }
                   1050: 
1.561     damieng  1051: # Javascript for table mode.
1.280     albertel 1052: sub page_js {
                   1053: 
1.81      www      1054:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1055:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1056: 
                   1057:     return(<<ENDJS);
                   1058: <script type="text/javascript">
1.454     bisitz   1059: // <![CDATA[
1.44      albertel 1060: 
1.88      matthew  1061:     $pjump_def
1.44      albertel 1062: 
                   1063:     function psub() {
                   1064:         if (document.parmform.pres_marker.value!='') {
                   1065:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1066:             var typedef=new Array();
                   1067:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1068:             if (document.parmform.pres_type.value!='') {
                   1069:                 if (typedef[0]=='date') {
                   1070:                     eval('document.parmform.recent_'+
                   1071:                         document.parmform.pres_type.value+
                   1072:                         '.value=document.parmform.pres_value.value;');
                   1073:                 } else {
                   1074:                     eval('document.parmform.recent_'+typedef[0]+
                   1075:                         '.value=document.parmform.pres_value.value;');
                   1076:                 }
1.44      albertel 1077:             }
                   1078:             document.parmform.submit();
                   1079:         } else {
                   1080:             document.parmform.pres_value.value='';
                   1081:             document.parmform.pres_marker.value='';
                   1082:         }
                   1083:     }
                   1084: 
1.57      albertel 1085:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1086:         var options = "width=" + w + ",height=" + h + ",";
                   1087:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1088:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1089:         var newWin = window.open(url, wdwName, options);
                   1090:         newWin.focus();
                   1091:     }
1.523     raeburn  1092: 
1.454     bisitz   1093: // ]]>
1.523     raeburn  1094: 
1.44      albertel 1095: </script>
1.81      www      1096: $selscript
1.280     albertel 1097: ENDJS
                   1098: 
                   1099: }
1.507     www      1100: 
1.561     damieng  1101: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1102: # for table and overview modes.
1.523     raeburn  1103: sub showhide_js {
                   1104:     return <<"COURSECONTENTSCRIPT";
                   1105: 
                   1106: function showHide_courseContent() {
                   1107:     var parmlevValue=document.getElementById("parmlev").value;
                   1108:     if (parmlevValue == 'general') {
                   1109:         document.getElementById('mapmenu').style.display="none";
                   1110:     } else {
                   1111:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1112:             document.getElementById('mapmenu').style.display ="";
                   1113:         } else {
                   1114:             document.getElementById('mapmenu').style.display="none";
                   1115:         }
                   1116:     }
                   1117:     return;
                   1118: }
                   1119: 
                   1120: COURSECONTENTSCRIPT
                   1121: }
                   1122: 
1.561     damieng  1123: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1124: sub toggleparmtextbox_js {
                   1125:     return <<"ENDSCRIPT";
                   1126: 
                   1127: if (!document.getElementsByClassName) {
                   1128:     function getElementsByClassName(node, classname) {
                   1129:         var a = [];
                   1130:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1131:         var els = node.getElementsByTagName("*");
                   1132:         for(var i=0,j=els.length; i<j; i++)
                   1133:             if(re.test(els[i].className))a.push(els[i]);
                   1134:         return a;
                   1135:     }
                   1136: }
                   1137: 
                   1138: function showHideLenient() {
                   1139:     var lenients;
                   1140:     var setRegExp = /^set_/;
                   1141:     if (document.getElementsByClassName) {
                   1142:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1143:     } else {
                   1144:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1145:     }
                   1146:     if (lenients != 'undefined') {
                   1147:         for (var i=0; i<lenients.length; i++) {
                   1148:             if (lenients[i].checked) {
                   1149:                 if (lenients[i].value == 'weighted') {
                   1150:                     if (setRegExp.test(lenients[i].name)) {
                   1151:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1152:                         toggleParmTextbox(document.parmform,identifier);
                   1153:                     }
                   1154:                 }
                   1155:             }
                   1156:         }
                   1157:     }
                   1158:     return;
                   1159: }
                   1160: 
                   1161: function toggleParmTextbox(form,key) {
                   1162:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1163:     if (divfortext) {
                   1164:         var caller = form.elements['set_'+key];
                   1165:         if (caller.length) {
                   1166:             for (i=0; i<caller.length; i++) {
                   1167:                 if (caller[i].checked) {
                   1168:                     if (caller[i].value == 'weighted') {
                   1169:                         divfortext.style.display = 'inline';
                   1170:                     } else {
                   1171:                         divfortext.style.display = 'none';
                   1172:                     }
                   1173:                 }
                   1174:             }
                   1175:         }
                   1176:     }
                   1177:     return;
                   1178: }
                   1179: 
                   1180: ENDSCRIPT
                   1181: }
                   1182: 
1.561     damieng  1183: # Javascript function validateParms, for overview mode
1.549     raeburn  1184: sub validateparms_js {
                   1185:     return <<'ENDSCRIPT';
                   1186: 
                   1187: function validateParms() {
                   1188:     var textRegExp = /^settext_/;
                   1189:     var tailLenient = /\.lenient$/;
                   1190:     var patternRelWeight = /^\-?[\d.]+$/;
                   1191:     var patternLenientStd = /^(yes|no|default)$/;
                   1192:     var ipallowRegExp = /^setipallow_/;
                   1193:     var ipdenyRegExp = /^setipdeny_/; 
                   1194:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1195:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1196:         if (document.parmform.elements.length) {
                   1197:             for (i=0; i<document.parmform.elements.length; i++) {
                   1198:                 var name=document.parmform.elements[i].name;
                   1199:                 if (textRegExp.test(name)) { 
                   1200:                     var identifier = name.replace(textRegExp,'');
                   1201:                     if (tailLenient.test(identifier)) {
                   1202:                         if (document.parmform.elements['set_'+identifier].length) {
                   1203:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1204:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1205:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1206:                                         var relweight = document.parmform.elements[i].value;
                   1207:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1208:                                         if (!patternRelWeight.test(relweight)) {
                   1209:                                             relweight = '0.0';
                   1210:                                         }
                   1211:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1212:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1213:                                         } else {
                   1214:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1215:                                         }
                   1216:                                     }
                   1217:                                     break;
                   1218:                                 }
                   1219:                             }
                   1220:                         }
                   1221:                     }
                   1222:                 } else {
                   1223:                     if (ipallowRegExp.test(name)) {
                   1224:                         var identifier = name.replace(ipallowRegExp,'');
                   1225:                         var possallow = document.parmform.elements[i].value;
                   1226:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1227:                         if (patternIP.test(possallow)) {
                   1228:                             if (document.parmform.elements['set_'+identifier].value) {
                   1229:                                 possallow = ','+possallow;
                   1230:                             }
                   1231:                             document.parmform.elements['set_'+identifier].value += possallow; 
                   1232:                         }
                   1233:                     } else {
                   1234:                         if (ipdenyRegExp.test(name)) {
                   1235:                             var identifier = name.replace(ipdenyRegExp,'');
                   1236:                             var possdeny = document.parmform.elements[i].value;
                   1237:                             possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1238:                             if (patternIP.test(possdeny)) {
                   1239:                                 possdeny = '!'+possdeny;
                   1240:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1241:                                     possdeny = ','+possdeny;
                   1242:                                 }
                   1243:                                 document.parmform.elements['set_'+identifier].value += possdeny;
                   1244:                             }
                   1245:                         }
                   1246:                     }
                   1247:                 }
                   1248:             }
                   1249:         }
                   1250:     }
                   1251:     return true;
                   1252: }
                   1253: 
                   1254: ENDSCRIPT
                   1255: }
                   1256: 
1.561     damieng  1257: # Javascript initialization, for overview mode
1.549     raeburn  1258: sub ipacc_boxes_js  {
                   1259:     my $remove = &mt('Remove');
                   1260:     return <<"END";
                   1261: \$(document).ready(function() {
                   1262:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1263:     var add_button      = \$(".LC_add_ipacc_button");
                   1264:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1265: 
                   1266:     \$(add_button).click(function(e){
                   1267:         e.preventDefault();
                   1268:         var identifier = \$(this).closest("div").attr("id");
                   1269:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1270:         \$(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  1271:     });
                   1272: 
                   1273:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1274:         e.preventDefault(); \$(this).closest("div").remove();
                   1275:     })
                   1276: });
                   1277: 
                   1278: 
                   1279: END
                   1280: }
                   1281: 
1.561     damieng  1282: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1283: sub done_proctor_js {
                   1284:     return <<"END";
                   1285: function toggleSecret(form,radio,key) {
                   1286:     var radios = form[radio+key];
                   1287:     if (radios.length) {
                   1288:         for (var i=0; i<radios.length; i++) {
                   1289:             if (radios[i].checked) {
                   1290:                 if (radios[i].value == '_done_proctor') {
                   1291:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1292:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1293:                     }
                   1294:                 } else {
                   1295:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1296:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1297:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1298:                     }
                   1299:                 }
                   1300:             }
                   1301:         }
                   1302:     }
                   1303: }
                   1304: END
                   1305: 
                   1306: }
                   1307: 
1.561     damieng  1308: # Prints HTML page start for table mode.
                   1309: # @param {Apache2::RequestRec} $r - the Apache request
                   1310: # @param {string} $psymb - resource symb
                   1311: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1312: sub startpage {
1.531     raeburn  1313:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1314: 
1.515     raeburn  1315:     my %loaditems = (
                   1316:                       'onload'   => "group_or_section('cgroup')",
                   1317:                     );
                   1318:     if (!$psymb) {
1.523     raeburn  1319:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1320:     }
1.280     albertel 1321: 
1.560     damieng  1322:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1323:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1324:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1325:             text=>"Problem Parameters"});
1.414     droeschl 1326:     } else {
1.560     damieng  1327:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1328:             text=>"Table Mode",
                   1329:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1330:     }
1.523     raeburn  1331:     my $js = &page_js().'
                   1332: <script type="text/javascript">
                   1333: // <![CDATA[
                   1334: '.
                   1335:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1336: // ]]>
                   1337: </script>
                   1338: ';
1.446     bisitz   1339:     my $start_page =
1.523     raeburn  1340:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1341:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1342:     my $breadcrumbs =
1.473     amueller 1343:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1344:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1345:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1346:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1347:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1348:     $r->print(<<ENDHEAD);
1.193     albertel 1349: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1350: <input type="hidden" value="" name="pres_value" />
                   1351: <input type="hidden" value="" name="pres_type" />
                   1352: <input type="hidden" value="" name="pres_marker" />
                   1353: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1354: <input type="hidden" value="$escfilter" name="filter" />
                   1355: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1356: ENDHEAD
                   1357: }
                   1358: 
1.209     www      1359: 
1.561     damieng  1360: # Prints a row for table mode (except for the tr start).
                   1361: # Every time a hash reference is passed, a single entry is used, so print_row
                   1362: # could just use these values, but why make it simple when it can be complicated ?
                   1363: #
                   1364: # @param {Apache2::RequestRec} $r - the Apache request
                   1365: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1366: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1367: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1368: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1369: # @param {string} $rid - resource id
                   1370: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1371: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1372: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1373: # @param {string} $defbgone - user level and other levels background color
                   1374: # @param {string} $defbgtwo - section level background color, also used for part number
                   1375: # @param {string} $defbgthree - group level background color
                   1376: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1377: # @param {string} $uname - user name
                   1378: # @param {string} $udom - user domain
                   1379: # @param {string} $csec - section name
                   1380: # @param {string} $cgroup - group name
                   1381: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1382: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1383: # @param {boolean} $readonly - true if no editing allowed. 
1.44      albertel 1384: sub print_row {
1.201     www      1385:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1386:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
                   1387:     $readonly)=@_;
1.275     raeburn  1388:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1389:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1390:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.553     raeburn  1391: 
1.560     damieng  1392:     # get the values for the parameter in cascading order
                   1393:     # empty levels will remain empty
1.44      albertel 1394:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1395:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1396:     # get the type for the parameters
                   1397:     # problem: these may not be set for all levels
1.66      www      1398:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1399:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1400:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1401:     # cascade down manually
1.182     albertel 1402:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1403:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1404:         if ($typeoutpar[$i]) {
1.66      www      1405:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1406:         } else {
1.66      www      1407:             $typeoutpar[$i]=$cascadetype;
                   1408:         }
                   1409:     }
1.57      albertel 1410:     my $parm=$$display{$which};
                   1411: 
1.203     www      1412:     if ($parmlev eq 'full') {
1.419     bisitz   1413:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1414:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1415:     } else {
1.57      albertel 1416:         $parm=~s|\[.*\]\s||g;
                   1417:     }
1.231     www      1418:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1419:     if ($automatic) {
1.560     damieng  1420:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1421:     }
1.427     bisitz   1422:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1423: 
1.44      albertel 1424:     my $thismarker=$which;
                   1425:     $thismarker=~s/^parameter\_//;
                   1426:     my $mprefix=$rid.'&'.$thismarker.'&';
1.554     raeburn  1427:     my $effective_parm = &valout($outpar[$result],$typeoutpar[$result],$thismarker);
1.275     raeburn  1428:     my ($othergrp,$grp_parm,$controlgrp);
1.44      albertel 1429: 
1.57      albertel 1430:     if ($parmlev eq 'general') {
                   1431:         if ($uname) {
1.568     raeburn  1432:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.269     raeburn  1433:         } elsif ($cgroup) {
1.568     raeburn  1434:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
1.57      albertel 1435:         } elsif ($csec) {
1.568     raeburn  1436:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.57      albertel 1437:         } else {
1.568     raeburn  1438:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.57      albertel 1439:         }
                   1440:     } elsif ($parmlev eq 'map') {
                   1441:         if ($uname) {
1.568     raeburn  1442:             &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1443:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly); 
1.269     raeburn  1444:         } elsif ($cgroup) {
1.568     raeburn  1445:             &print_td($r,7,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
                   1446:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
1.57      albertel 1447:         } elsif ($csec) {
1.568     raeburn  1448:             &print_td($r,11,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1449:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.57      albertel 1450:         } else {
1.568     raeburn  1451:             &print_td($r,17,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1452:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.57      albertel 1453:         }
                   1454:     } else {
1.275     raeburn  1455:         if ($uname) {
                   1456:             if (@{$usersgroups} > 1) {
                   1457:                 my ($coursereply,$grp_parm,$controlgrp);
                   1458:                 ($coursereply,$othergrp,$grp_parm,$controlgrp) =
                   1459:                     &print_usergroups($r,$$part{$which}.'.'.$$name{$which},
                   1460:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.556     raeburn  1461:                 if ($coursereply && $result > 4) {
1.275     raeburn  1462:                     if (defined($controlgrp)) {
                   1463:                         if ($cgroup ne $controlgrp) {
                   1464:                             $effective_parm = $grp_parm;
                   1465:                             $result = 0;
                   1466:                         }
                   1467:                     }
                   1468:                 }
                   1469:             }
                   1470:         }
1.57      albertel 1471: 
1.568     raeburn  1472:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1473:         &print_td($r,17,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1474:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1475:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1476:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1477:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.548     raeburn  1478: 
                   1479:         if ($csec) {
1.568     raeburn  1480:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1481:             &print_td($r,11,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1482:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1483:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.548     raeburn  1484:         }
1.269     raeburn  1485: 
                   1486:         if ($cgroup) {
1.569     raeburn  1487:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
                   1488:             &print_td($r,7,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
                   1489:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly);
                   1490:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly);
1.269     raeburn  1491:         }
1.446     bisitz   1492: 
1.548     raeburn  1493:         if ($uname) {
1.275     raeburn  1494:             if ($othergrp) {
                   1495:                 $r->print($othergrp);
                   1496:             }
1.568     raeburn  1497:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1498:             &print_td($r,3,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1499:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
                   1500:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly);
1.548     raeburn  1501:         }
1.57      albertel 1502: 
                   1503:     } # end of $parmlev if/else
1.419     bisitz   1504:     $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.'</td>');
1.136     albertel 1505: 
1.203     www      1506:     if ($parmlev eq 'full') {
1.136     albertel 1507:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1508:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1509:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1510:         if (!defined($sessionvaltype)) {
                   1511:             $sessionvaltype=$$defaulttype{$which};
                   1512:         }
1.419     bisitz   1513:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.554     raeburn  1514:                   &valout($sessionval,$sessionvaltype,$$name{$which}).'&nbsp;'.
1.57      albertel 1515:                   '</font></td>');
1.136     albertel 1516:     }
1.44      albertel 1517:     $r->print('</tr>');
1.57      albertel 1518:     $r->print("\n");
1.44      albertel 1519: }
1.59      matthew  1520: 
1.561     damieng  1521: # Prints a cell for table mode.
                   1522: #
                   1523: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1524: # Also, it would make more sense to pass the display for this cell rather
                   1525: # than the full display hash and the key to use.
                   1526: #
                   1527: # @param {Apache2::RequestRec} $r - the Apache request
                   1528: # @param {integer} $which - level
                   1529: # @param {string} $defbg - cell background color
                   1530: # @param {integer} $result - the most specific level that is defined for that parameter
                   1531: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1532: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1533: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1534: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1535: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1536: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1537: # @param {boolean} $readonly -true if editing not allowed.
1.44      albertel 1538: sub print_td {
1.568     raeburn  1539:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,$noeditgrp,$readonly)=@_;
1.419     bisitz   1540:     $r->print('<td style="background-color:'.(($result==$which)?'#AAFFAA':$defbg).
                   1541:               ';" align="center">');
1.437     raeburn  1542:     my $nolink = 0;
1.568     raeburn  1543:     if ($readonly) {
1.552     raeburn  1544:         $nolink = 1;
1.568     raeburn  1545:     } else { 
1.574     raeburn  1546:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&/) {
1.553     raeburn  1547:             $nolink = 1;
1.568     raeburn  1548:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1549:             $nolink = 1;
1.568     raeburn  1550:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1551:             if ($noeditgrp) {
                   1552:                 $nolink = 1;
                   1553:             }
                   1554:         } elsif ($mprefix =~ /availablestudent\&$/) {
                   1555:             if ($which > 4) {
                   1556:                 $nolink = 1;
                   1557:             }
                   1558:         } elsif ($mprefix =~ /examcode\&$/) {
                   1559:             unless ($which == 2) {
                   1560:                 $nolink = 1;
                   1561:             }
1.573     raeburn  1562:         } elsif ($mprefix =~ /(encrypturl|hiddenresource)/) {
                   1563:             if ($which == 16 || $which == 10 || $which == 6 || $which == 2) {
                   1564:                 $nolink = 1;
                   1565:             }
1.533     raeburn  1566:         }
1.437     raeburn  1567:     }
                   1568:     if ($nolink) {
1.554     raeburn  1569:         $r->print(&valout($$outpar[$which],$$typeoutpar[$which],$mprefix));
1.561     damieng  1570: # FIXME: probably a good thing that mprefix is not used in valout, because it does not look like a parameter name !
1.114     www      1571:     } else {
1.437     raeburn  1572:         $r->print(&plink($$typeoutpar[$which],
                   1573:                          $$display{$value},$$outpar[$which],
                   1574:                          $mprefix."$which",'parmform.pres','psub'));
1.114     www      1575:     }
                   1576:     $r->print('</td>'."\n");
1.57      albertel 1577: }
                   1578: 
1.561     damieng  1579: # FIXME: Despite the name, this does not print anything, the $r parameter is unused.
                   1580: # Returns HTML and other info for the cell added when a user is selected
                   1581: # and that user is in several groups. This is the cell with the title "Control by other group".
                   1582: #
                   1583: # @param {Apache2::RequestRec} $r - the Apache request (unused)
                   1584: # @param {string} $what - parameter part.'.'.parameter name
                   1585: # @param {string} $rid - resource id
                   1586: # @param {string} $cgroup - group name
                   1587: # @param {string} $defbg - cell background color
                   1588: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1589: # @param {integer} $result - level
                   1590: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                   1591: # @returns {Array} - array (parameter value for the other group, HTML for the cell, HTML with the value, name of the other group)
1.275     raeburn  1592: sub print_usergroups {
                   1593:     my ($r,$what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
                   1594:     my $courseid = $env{'request.course.id'};
                   1595:     my $output;
                   1596:     my $symb = &symbcache($rid);
                   1597:     my $symbparm=$symb.'.'.$what;
                   1598:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  1599:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  1600:     my $mapparm=$map.'___(all).'.$what;
                   1601:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  1602:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   1603:                               $recurseparm,$what,$courseopt);
1.275     raeburn  1604:     my $bgcolor = $defbg;
                   1605:     my $grp_parm;
1.446     bisitz   1606:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.275     raeburn  1607:         if ($result > 3) {
1.419     bisitz   1608:             $bgcolor = '#AAFFAA';
1.554     raeburn  1609:             $grp_parm = &valout($coursereply,$resulttype,$what);
1.275     raeburn  1610:         }
1.554     raeburn  1611:         $grp_parm = &valout($coursereply,$resulttype,$what);
1.419     bisitz   1612:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  1613:         if ($resultgroup && $resultlevel) {
                   1614:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm;
                   1615:         } else {
                   1616:             $output .= '&nbsp;';
                   1617:         }
                   1618:         $output .= '</td>';
                   1619:     } else {
1.419     bisitz   1620:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  1621:     }
                   1622:     return ($coursereply,$output,$grp_parm,$resultgroup);
                   1623: }
                   1624: 
1.561     damieng  1625: # Looks for a group with a defined parameter for given user and parameter.
                   1626: # Used by print_usergroups.
                   1627: #
                   1628: # @param {string} $courseid - the course id
                   1629: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1630: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   1631: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   1632: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   1633: # @param {string} $what - parameter part.'.'.parameter name
                   1634: # @param {hash reference} $courseopt - course parameters hash
                   1635: # @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  1636: sub parm_control_group {
1.556     raeburn  1637:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  1638:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   1639:     my $grpfound = 0;
1.556     raeburn  1640:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   1641:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  1642:     foreach my $group (@{$usersgroups}) {
                   1643:         if ($grpfound) { last; }
                   1644:         for (my $i=0; $i<@levels; $i++) {
                   1645:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   1646:             if (defined($$courseopt{$item})) {
                   1647:                 $coursereply = $$courseopt{$item};
                   1648:                 $resultitem = $item;
                   1649:                 $resultgroup = $group;
                   1650:                 $resultlevel = $levelnames[$i];
                   1651:                 $resulttype = $$courseopt{$item.'.type'};
                   1652:                 $grpfound = 1;
                   1653:                 last;
                   1654:             }
                   1655:         }
                   1656:     }
                   1657:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   1658: }
1.201     www      1659: 
1.63      bowersj2 1660: 
                   1661: 
1.562     damieng  1662: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   1663: # All the parameters are references and are filled by the sub.
                   1664: #
1.566     damieng  1665: # @param {array reference} $ids - resource and map ids
                   1666: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   1667: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  1668: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   1669: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  1670: # @param {hash reference} $allmaps - hash map pc -> map src
                   1671: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   1672: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   1673: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   1674: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  1675: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   1676: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.63      bowersj2 1677: sub extractResourceInformation {
                   1678:     my $ids = shift;
                   1679:     my $typep = shift;
                   1680:     my $keyp = shift;
                   1681:     my $allparms = shift;
                   1682:     my $allparts = shift;
                   1683:     my $allmaps = shift;
                   1684:     my $mapp = shift;
                   1685:     my $symbp = shift;
1.82      www      1686:     my $maptitles=shift;
1.196     www      1687:     my $uris=shift;
1.210     www      1688:     my $keyorder=shift;
1.211     www      1689:     my $defkeytype=shift;
1.196     www      1690: 
1.210     www      1691:     my $keyordercnt=100;
1.63      bowersj2 1692: 
1.196     www      1693:     my $navmap = Apache::lonnavmaps::navmap->new();
                   1694:     my @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   1695:     foreach my $resource (@allres) {
1.480     amueller 1696:         my $id=$resource->id();
1.196     www      1697:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 1698:         if ($mapid eq '0') { next; }
                   1699:         $$ids[$#$ids+1]=$id;
                   1700:         my $srcf=$resource->src();
                   1701:         $srcf=~/\.(\w+)$/;
                   1702:         $$typep{$id}=$1;
                   1703:         $$keyp{$id}='';
1.196     www      1704:         $$uris{$id}=$srcf;
1.512     foxr     1705: 
1.480     amueller 1706:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys'))) {
                   1707:             next if ($key!~/^parameter_/);
1.363     albertel 1708: 
1.209     www      1709: # Hidden parameters
1.480     amueller 1710:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden') eq 'parm');
1.209     www      1711: #
                   1712: # allparms is a hash of parameter names
                   1713: #
1.480     amueller 1714:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name');
                   1715:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   1716:                 my ($display,$parmdis);
                   1717:                 $display = &standard_parameter_names($name);
                   1718:                 if ($display eq '') {
                   1719:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display');
                   1720:                     $parmdis = $display;
                   1721:                     $parmdis =~ s/\s*\[Part.*$//g;
                   1722:                 } else {
                   1723:                     $parmdis = &mt($display);
                   1724:                 }
                   1725:                 $$allparms{$name}=$parmdis;
                   1726:                 if (ref($defkeytype)) {
                   1727:                     $$defkeytype{$name}=
                   1728:                     &Apache::lonnet::metadata($srcf,$key.'.type');
                   1729:                 }
                   1730:             }
1.363     albertel 1731: 
1.209     www      1732: #
                   1733: # allparts is a hash of all parts
                   1734: #
1.480     amueller 1735:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part');
                   1736:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      1737: #
                   1738: # Remember all keys going with this resource
                   1739: #
1.480     amueller 1740:             if ($$keyp{$id}) {
                   1741:                 $$keyp{$id}.=','.$key;
                   1742:             } else {
                   1743:                 $$keyp{$id}=$key;
                   1744:             }   
1.210     www      1745: #
                   1746: # Put in order
1.446     bisitz   1747: #
1.480     amueller 1748:             unless ($$keyorder{$key}) {
                   1749:                 $$keyorder{$key}=$keyordercnt;
                   1750:                 $keyordercnt++;
                   1751:             }
1.473     amueller 1752:         }
                   1753: 
                   1754: 
1.480     amueller 1755:         if (!exists($$mapp{$mapid})) {
                   1756:             $$mapp{$id}=
                   1757:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   1758:             $$mapp{$mapid}=$$mapp{$id};
                   1759:             $$allmaps{$mapid}=$$mapp{$id};
                   1760:             if ($mapid eq '1') {
1.532     raeburn  1761:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 1762:             } else {
                   1763:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   1764:             }
                   1765:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  1766:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   1767:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   1768:                                                      # are commented out in rev. 1.57
1.473     amueller 1769:         } else {
1.480     amueller 1770:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 1771:         }
1.480     amueller 1772:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 1773:     }
                   1774: }
                   1775: 
1.208     www      1776: 
1.562     damieng  1777: # Tells if a parameter type is a date.
                   1778: #
                   1779: # @param {string} type - parameter type
                   1780: # @returns{boolean} - true if it is a date
1.213     www      1781: sub isdateparm {
                   1782:     my $type=shift;
                   1783:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   1784: }
                   1785: 
1.562     damieng  1786: # Prints the HTML and Javascript to select parameters, with various shortcuts.
                   1787: # FIXME: remove unused parameters
1.468     amueller 1788: #
1.562     damieng  1789: # @param {Apache2::RequestRec} $r - the Apache request (unused)
                   1790: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   1791: # @param {array reference} $pscat - list of selected parameter names (unused)
                   1792: # @param {hash reference} $keyorder - hash parameter key -> appearance rank (unused)
1.208     www      1793: sub parmmenu {
1.211     www      1794:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.208     www      1795:     my $tempkey;
                   1796:     $r->print(<<ENDSCRIPT);
                   1797: <script type="text/javascript">
1.454     bisitz   1798: // <![CDATA[
1.208     www      1799:     function checkall(value, checkName) {
1.453     schualex 1800: 
                   1801:         var li = "_li";
                   1802:         var displayOverview = "";
                   1803:         
                   1804:         if (value == false) {
                   1805:             displayOverview = "none"
                   1806:         }
                   1807: 
1.562     damieng  1808:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      1809:             ele = document.forms.parmform.elements[i];
                   1810:             if (ele.name == checkName) {
                   1811:                 document.forms.parmform.elements[i].checked=value;
                   1812:             }
                   1813:         }
                   1814:     }
1.210     www      1815: 
                   1816:     function checkthis(thisvalue, checkName) {
1.562     damieng  1817:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      1818:             ele = document.forms.parmform.elements[i];
                   1819:             if (ele.name == checkName) {
1.562     damieng  1820:                 if (ele.value == thisvalue) {
                   1821:                     document.forms.parmform.elements[i].checked=true;
                   1822:                 }
1.210     www      1823:             }
                   1824:         }
                   1825:     }
                   1826: 
                   1827:     function checkdates() {
1.562     damieng  1828:         checkthis('duedate','pscat');
                   1829:         checkthis('opendate','pscat');
                   1830:         checkthis('answerdate','pscat');
1.218     www      1831:     }
                   1832: 
                   1833:     function checkdisset() {
1.562     damieng  1834:         checkthis('discussend','pscat');
                   1835:         checkthis('discusshide','pscat');
                   1836:         checkthis('discussvote','pscat');
1.218     www      1837:     }
                   1838: 
                   1839:     function checkcontdates() {
1.562     damieng  1840:         checkthis('contentopen','pscat');
                   1841:         checkthis('contentclose','pscat');
1.218     www      1842:     }
1.446     bisitz   1843: 
1.210     www      1844:     function checkvisi() {
1.562     damieng  1845:         checkthis('hiddenresource','pscat');
                   1846:         checkthis('encrypturl','pscat');
                   1847:         checkthis('problemstatus','pscat');
                   1848:         checkthis('contentopen','pscat');
                   1849:         checkthis('opendate','pscat');
1.210     www      1850:     }
                   1851: 
                   1852:     function checkparts() {
1.562     damieng  1853:         checkthis('hiddenparts','pscat');
                   1854:         checkthis('display','pscat');
                   1855:         checkthis('ordered','pscat');
1.210     www      1856:     }
                   1857: 
                   1858:     function checkstandard() {
                   1859:         checkall(false,'pscat');
1.562     damieng  1860:         checkdates();
                   1861:         checkthis('weight','pscat');
                   1862:         checkthis('maxtries','pscat');
                   1863:         checkthis('type','pscat');
                   1864:         checkthis('problemstatus','pscat');
1.210     www      1865:     }
                   1866: 
1.454     bisitz   1867: // ]]>
1.208     www      1868: </script>
                   1869: ENDSCRIPT
1.453     schualex 1870: 
1.491     bisitz   1871:     $r->print('<hr />');
1.453     schualex 1872:     &shortCuts($r,$allparms,$pscat,$keyorder);
1.491     bisitz   1873:     $r->print('<hr />');
1.453     schualex 1874: }
1.562     damieng  1875: 
                   1876: # Returns parameter categories.
                   1877: #
                   1878: # @returns {hash} - category name -> title in English
1.465     amueller 1879: sub categories {
                   1880:     return ('time_settings' => 'Time Settings',
                   1881:     'grading' => 'Grading',
                   1882:     'tries' => 'Tries',
                   1883:     'problem_appearance' => 'Problem Appearance',
                   1884:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   1885:     'hiding' => 'Hiding',
                   1886:     'high_level_randomization' => 'High Level Randomization',
                   1887:     'slots' => 'Slots',
                   1888:     'file_submission' => 'File Submission',
                   1889:     'misc' => 'Miscellaneous' ); 
                   1890: }
                   1891: 
1.562     damieng  1892: # Returns the category for each parameter.
                   1893: #
                   1894: # @returns {hash} - parameter name -> category name
1.465     amueller 1895: sub lookUpTableParameter {
                   1896:  
                   1897:     return ( 
                   1898:         'opendate' => 'time_settings',
                   1899:         'duedate' => 'time_settings',
                   1900:         'answerdate' => 'time_settings',
                   1901:         'interval' => 'time_settings',
                   1902:         'contentopen' => 'time_settings',
                   1903:         'contentclose' => 'time_settings',
                   1904:         'discussend' => 'time_settings',
1.560     damieng  1905:         'printstartdate' => 'time_settings',
                   1906:         'printenddate' => 'time_settings',
1.465     amueller 1907:         'weight' => 'grading',
                   1908:         'handgrade' => 'grading',
                   1909:         'maxtries' => 'tries',
                   1910:         'hinttries' => 'tries',
1.503     raeburn  1911:         'randomizeontries' => 'tries',
1.465     amueller 1912:         'type' => 'problem_appearance',
                   1913:         'problemstatus' => 'problem_appearance',
                   1914:         'display' => 'problem_appearance',
                   1915:         'ordered' => 'problem_appearance',
                   1916:         'numbubbles' => 'problem_appearance',
                   1917:         'tol' => 'behaviour_of_input_fields',
                   1918:         'sig' => 'behaviour_of_input_fields',
                   1919:         'turnoffunit' => 'behaviour_of_input_fields',
                   1920:         'hiddenresource' => 'hiding',
                   1921:         'hiddenparts' => 'hiding',
                   1922:         'discusshide' => 'hiding',
                   1923:         'buttonshide' => 'hiding',
                   1924:         'turnoffeditor' => 'hiding',
                   1925:         'encrypturl' => 'hiding',
                   1926:         'randomorder' => 'high_level_randomization',
                   1927:         'randompick' => 'high_level_randomization',
                   1928:         'available' => 'slots',
                   1929:         'useslots' => 'slots',
                   1930:         'availablestudent' => 'slots',
                   1931:         'uploadedfiletypes' => 'file_submission',
                   1932:         'maxfilesize' => 'file_submission',
                   1933:         'cssfile' => 'misc',
                   1934:         'mapalias' => 'misc',
                   1935:         'acc' => 'misc',
                   1936:         'maxcollaborators' => 'misc',
                   1937:         'scoreformat' => 'misc',
1.514     raeburn  1938:         'lenient' => 'grading',
1.519     raeburn  1939:         'retrypartial' => 'tries',
1.521     raeburn  1940:         'discussvote'  => 'misc',
1.533     raeburn  1941:         'examcode' => 'high_level_randomization', 
1.575   ! raeburn  1942:     );
1.465     amueller 1943: }
                   1944: 
1.562     damieng  1945: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   1946: #
                   1947: # @param {string} $name - parameter name
                   1948: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 1949: sub whatIsMyCategory {
                   1950:     my $name = shift;
                   1951:     my $catList = shift;
                   1952:     my @list;
                   1953:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   1954:     my $cat = $lookUpList{$name};
                   1955:     if (defined($cat)) {
                   1956:         if (!defined($$catList{$cat})){
                   1957:             push @list, ($name);
                   1958:             $$catList{$cat} = \@list;
                   1959:         } else {
                   1960:             push @{${$catList}{$cat}}, ($name);     
                   1961:         }
                   1962:     } else {
                   1963:         if (!defined($$catList{'misc'})){
                   1964:             push @list, ($name);
                   1965:             $$catList{'misc'} = \@list;
                   1966:         } else {
                   1967:             push @{${$catList}{'misc'}}, ($name);     
                   1968:         }
                   1969:     }        
                   1970: }
                   1971: 
1.562     damieng  1972: # Sorts parameter names based on appearance order.
                   1973: #
                   1974: # @param {array reference} name - array reference of parameter names
                   1975: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   1976: # @returns {Array} - array of parameter names
1.465     amueller 1977: sub keysindisplayorderCategory {
                   1978:     my ($name,$keyorder)=@_;
                   1979:     return sort {
1.473     amueller 1980:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 1981:     } ( @{$name});
                   1982: }
                   1983: 
1.562     damieng  1984: # Returns a hash category name -> order, starting at 1 (integer)
                   1985: #
                   1986: # @returns {hash}
1.467     amueller 1987: sub category_order {
                   1988:     return (
                   1989:         'time_settings' => 1,
                   1990:         'grading' => 2,
                   1991:         'tries' => 3,
                   1992:         'problem_appearance' => 4,
                   1993:         'hiding' => 5,
                   1994:         'behaviour_of_input_fields' => 6,
                   1995:         'high_level_randomization'  => 7,
                   1996:         'slots' => 8,
                   1997:         'file_submission' => 9,
                   1998:         'misc' => 10
                   1999:     );
                   2000: 
                   2001: }
1.453     schualex 2002: 
1.562     damieng  2003: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2004: #
                   2005: # @param {Apache2::RequestRec} $r - the Apache request
                   2006: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2007: # @param {array reference} $pscat - list of selected parameter names
                   2008: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2009: sub parmboxes {
                   2010:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2011:     my %categories = &categories();
1.467     amueller 2012:     my %category_order = &category_order();
1.465     amueller 2013:     my %categoryList = (
                   2014:         'time_settings' => [],
                   2015:         'grading' => [],
                   2016:         'tries' => [],
                   2017:         'problem_appearance' => [],
                   2018:         'behaviour_of_input_fields' => [],
                   2019:         'hiding' => [],
                   2020:         'high_level_randomization' => [],
                   2021:         'slots' => [],
                   2022:         'file_submission' => [],
                   2023:         'misc' => [],
1.489     bisitz   2024:     );
1.510     www      2025: 
1.548     raeburn  2026:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2027:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2028:     }
1.453     schualex 2029:     #part to print the parm-list
1.536     raeburn  2030:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2031:         next if (@{$categoryList{$key}} == 0);
                   2032:         next if ($key eq '');
                   2033:         $r->print('<div class="LC_Box LC_400Box">'
                   2034:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2035:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575   ! raeburn  2036:             next if ($tempkey eq '');
1.536     raeburn  2037:             $r->print('<span class="LC_nobreak">'
                   2038:                      .'<label><input type="checkbox" name="pscat" '
                   2039:                      .'value="'.$tempkey.'" ');
                   2040:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2041:                 $r->print( ' checked="checked"');
                   2042:             }
                   2043:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2044:                                                       : $tempkey)
1.536     raeburn  2045:                      .'</label></span><br />'."\n");
1.465     amueller 2046:         }
1.536     raeburn  2047:         $r->print('</div>');
1.465     amueller 2048:     }
1.536     raeburn  2049:     $r->print("\n");
1.453     schualex 2050: }
1.562     damieng  2051: 
                   2052: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
                   2053: # FIXME: remove unused parameters
1.468     amueller 2054: #
1.562     damieng  2055: # @param {Apache2::RequestRec} $r - the Apache request
                   2056: # @param {hash reference} $allparms - hash parameter name -> parameter title (unused)
                   2057: # @param {array reference} $pscat - list of selected parameter names (unused)
                   2058: # @param {hash reference} $keyorder - hash parameter key -> appearance rank (unused)
1.453     schualex 2059: sub shortCuts {
                   2060:     my ($r,$allparms,$pscat,$keyorder)=@_;
                   2061: 
1.491     bisitz   2062:     # Parameter Selection
                   2063:     $r->print(
                   2064:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2065:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2066:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2067:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2068:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2069:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2070:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2071:        .&Apache::lonhtmlcommon::end_funclist()
                   2072:     );
                   2073: 
                   2074:     # Add Selection for...
                   2075:     $r->print(
                   2076:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2077:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2078:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2079:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2080:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2081:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2082:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2083:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2084:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2085:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2086:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2087:        .&Apache::lonhtmlcommon::end_funclist()
                   2088:     );
1.208     www      2089: }
                   2090: 
1.562     damieng  2091: # Prints HTML to select parts to view (except for the title).
                   2092: # Used by table and overview modes.
                   2093: #
                   2094: # @param {Apache2::RequestRec} $r - the Apache request
                   2095: # @param {hash reference} $allparts - hash parameter part -> part title
                   2096: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2097: sub partmenu {
1.446     bisitz   2098:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2099:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2100:     if ($selsize > 8) {
                   2101:         $selsize = 8;
                   2102:     }
1.446     bisitz   2103: 
1.523     raeburn  2104:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2105:     $r->print('<option value="all"');
1.562     damieng  2106:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2107:     $r->print('>'.&mt('All Parts').'</option>');
                   2108:     my %temphash=();
                   2109:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2110:     foreach my $tempkey (sort {
1.560     damieng  2111:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2112:             } keys(%{$allparts})) {
                   2113:         unless ($tempkey =~ /\./) {
                   2114:             $r->print('<option value="'.$tempkey.'"');
                   2115:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2116:                 $r->print(' selected="selected"');
                   2117:             }
                   2118:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2119:         }
1.208     www      2120:     }
1.446     bisitz   2121:     $r->print('</select>');
1.209     www      2122: }
                   2123: 
1.562     damieng  2124: # Prints HTML to select a user and/or a group.
                   2125: # Used by table mode.
                   2126: #
                   2127: # @param {Apache2::RequestRec} $r - the Apache request
                   2128: # @param {string} $uname - selected user name
                   2129: # @param {string} $id - selected Student/Employee ID
                   2130: # @param {string} $udom - selected user domain
                   2131: # @param {string} $csec - selected section name
                   2132: # @param {string} $cgroup - selected group name
                   2133: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2134: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2135: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2136: sub usermenu {
1.553     raeburn  2137:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2138:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
                   2139:         &Apache::loncommon::selectstudent_link('parmform','uname','udom');
                   2140:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.412     bisitz   2141: 
1.209     www      2142:     my $sections='';
1.300     albertel 2143:     my %sectionhash = &Apache::loncommon::get_sections();
                   2144: 
1.269     raeburn  2145:     my $groups;
1.553     raeburn  2146:     my %grouphash;
                   2147:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2148:         %grouphash = &Apache::longroup::coursegroups();
                   2149:     } elsif ($env{'request.course.groups'} ne '') {
                   2150:         map { $grouphash{$_} = 1; } split(/,/,$env{'request.course.groups'});
                   2151:     }
1.299     albertel 2152: 
1.412     bisitz   2153:     my $g_s_header='';
                   2154:     my $g_s_footer='';
1.446     bisitz   2155: 
1.552     raeburn  2156:     my $currsec = $env{'request.course.sec'};
                   2157:     if ($currsec) {
                   2158:         $sections=&mt('Section:').' '.$currsec;
                   2159:         if (%grouphash) {
                   2160:             $sections .= ';'.('&nbsp;' x2);
                   2161:         }
                   2162:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2163:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2164:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2165:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2166:         }
                   2167:         $sections .= '>';
1.548     raeburn  2168:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2169:         $sections.='<option value="'.$section.'" '.
                   2170:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2171:                                                               '</option>';
1.209     www      2172:         }
                   2173:         $sections.='</select>';
1.269     raeburn  2174:     }
1.412     bisitz   2175: 
1.552     raeburn  2176:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2177:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2178:         $sections .= qq|
                   2179: <script type="text/javascript">
1.454     bisitz   2180: // <![CDATA[
1.269     raeburn  2181: function group_or_section(caller) {
                   2182:    if (caller == "cgroup") {
                   2183:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2184:            document.parmform.csec.selectedIndex = 0;
                   2185:        }
                   2186:    } else {
                   2187:        if (document.parmform.csec.selectedIndex != 0) {
                   2188:            document.parmform.cgroup.selectedIndex = 0;
                   2189:        }
                   2190:    }
                   2191: }
1.454     bisitz   2192: // ]]>
1.269     raeburn  2193: </script>
                   2194: |;
1.554     raeburn  2195:     } else {
1.269     raeburn  2196:         $sections .= qq|
                   2197: <script type="text/javascript">
1.454     bisitz   2198: // <![CDATA[
1.269     raeburn  2199: function group_or_section(caller) {
                   2200:     return;
                   2201: }
1.454     bisitz   2202: // ]]>
1.269     raeburn  2203: </script>
                   2204: |;
1.446     bisitz   2205:     }
1.299     albertel 2206: 
                   2207:     if (%grouphash) {
1.412     bisitz   2208:         $groups=&mt('Group:').' <select name="cgroup"';
1.552     raeburn  2209:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2210:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2211:         }
                   2212:         $groups .= '>';
1.548     raeburn  2213:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2214:             $groups.='<option value="'.$grp.'" ';
                   2215:             if ($grp eq $cgroup) {
                   2216:                 unless ((defined($uname)) && ($grp eq '')) {
                   2217:                     $groups .=  'selected="selected" ';
                   2218:                 }
                   2219:             } elsif (!defined($cgroup)) {
                   2220:                 if (@{$usersgroups} == 1) {
                   2221:                     if ($grp eq $$usersgroups[0]) {
                   2222:                         $groups .=  'selected="selected" ';
                   2223:                     }
                   2224:                 }
                   2225:             }
                   2226:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2227:         }
                   2228:         $groups.='</select>';
                   2229:     }
1.412     bisitz   2230: 
1.445     neumanie 2231:     if (%sectionhash || %grouphash) {
1.446     bisitz   2232:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2233:         $r->print($sections.$groups);
1.448     bisitz   2234:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2235:     } else {
                   2236:         $r->print($sections); 
1.445     neumanie 2237:     }
1.446     bisitz   2238: 
                   2239:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2240:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2241:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2242:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2243:                  ,$chooseopt));
1.209     www      2244: }
                   2245: 
1.562     damieng  2246: # Prints HTML to select parameters from a list of all parameters.
                   2247: # Uses parmmenu and parmboxes.
                   2248: # Used by table and overview modes.
1.468     amueller 2249: #
1.562     damieng  2250: # @param {Apache2::RequestRec} $r - the Apache request
                   2251: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2252: # @param {array reference} $pscat - list of selected parameter names
                   2253: # @param {array reference} $psprt - list of selected parameter parts (unused)
                   2254: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2255: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2256: sub displaymenu {
1.536     raeburn  2257:     my ($r,$allparms,$pscat,$psprt,$keyorder,$divid)=@_;
1.510     www      2258: 
1.445     neumanie 2259:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2260:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2261: 
1.562     damieng  2262:     &parmmenu($r,$allparms,$pscat,$keyorder); # only $allparms is used by parmmenu
1.536     raeburn  2263:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2264:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2265:     $r->print(&Apache::loncommon::end_scrollbox());
                   2266: 
                   2267:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2268:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2269:  
1.209     www      2270: }
                   2271: 
1.562     damieng  2272: # Prints HTML to select a map.
                   2273: # Used by table mode and overview mode.
                   2274: #
                   2275: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2276: # @param {hash reference} $allmaps - hash map pc -> map src
                   2277: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2278: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2279: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445     neumanie 2280: sub mapmenu {
1.499     raeburn  2281:     my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468     amueller 2282:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2283:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2284:     my $tree=[];
                   2285:     my $treeinfo={};
                   2286:     if (defined($navmap)) {
1.499     raeburn  2287:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2288:         my $curRes;
                   2289:         my $depth = 0;
1.468     amueller 2290:         my %parent = ();
                   2291:         my $startcount = 5;
                   2292:         my $lastcontainer = $startcount;
                   2293: # preparing what is to show ...
1.461     neumanie 2294:         while ($curRes = $it->next()) {
                   2295:             if ($curRes == $it->BEGIN_MAP()) {
                   2296:                 $depth++;
1.468     amueller 2297:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2298:             }
                   2299:             if ($curRes == $it->END_MAP()) {
                   2300:                 $depth--;
1.468     amueller 2301:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2302:             }
                   2303:             if (ref($curRes)) {
1.468     amueller 2304:                 my $symb = $curRes->symb();
                   2305:                 my $ressymb = $symb;
1.461     neumanie 2306:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2307:                     my $type = 'sequence';
                   2308:                     if ($curRes->is_page()) {
                   2309:                         $type = 'page';
                   2310:                     }
                   2311:                     my $id= $curRes->id();
1.468     amueller 2312:                     my $srcf = $curRes->src();
                   2313:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2314:                     if(!exists($treeinfo->{$id})) {
                   2315:                         push(@$tree,$id);
1.473     amueller 2316:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2317:                         $treeinfo->{$id} = {
1.461     neumanie 2318:                                     depth => $depth,
                   2319:                                     type  => $type,
1.468     amueller 2320:                                     name  => $resource_name,
                   2321:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2322:                                     };
1.462     neumanie 2323:                     }
1.461     neumanie 2324:                 }
                   2325:             }
                   2326:         }
1.462     neumanie 2327:     }
1.473     amueller 2328: # Show it ...    
1.484     amueller 2329:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461     neumanie 2330:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2331:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2332:         my $whitespace =
                   2333:             '<img src="'
                   2334:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2335:            .'" alt="" />';
                   2336: 
1.498     bisitz   2337:         # Info about selectable folders/maps
                   2338:         $r->print(
                   2339:             '<div class="LC_info">'
1.508     www      2340:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2341:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2342:            .'</div>'
                   2343:         );
                   2344: 
1.536     raeburn  2345:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2346:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2347: 
1.498     bisitz   2348:         # Display row: "All Maps or Folders"
                   2349:         $r->print(
1.523     raeburn  2350:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2351:            .'<td>'
                   2352:            .'<label>'
                   2353:            .'<input type="radio" name="pschp"'
1.497     bisitz   2354:         );
                   2355:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2356:         $r->print(
                   2357:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2358:            .&mt('All Maps or Folders')
                   2359:            .'</label>'
                   2360:            .'<hr /></td>'
                   2361:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2362:         );
1.497     bisitz   2363: 
1.532     raeburn  2364:         # Display row: "Main Content"
1.468     amueller 2365:         if (exists($$allmaps{1})) {
1.498     bisitz   2366:             $r->print(
                   2367:                 &Apache::loncommon::start_data_table_row()
                   2368:                .'<td>'
                   2369:                .'<label>'
                   2370:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2371:             );
1.497     bisitz   2372:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2373:             $r->print(
                   2374:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2375:                .$$maptitles{1}
                   2376:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2377:                .'</label>'
                   2378:                .'</td>'
                   2379:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2380:             );
                   2381:         }
1.497     bisitz   2382: 
                   2383:         # Display rows for all course maps and folders
1.468     amueller 2384:         foreach my $id (@{$tree}) {
                   2385:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2386:             # Indentation
1.468     amueller 2387:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2388:             my $indent;
                   2389:             for (my $i = 0; $i < $depth; $i++) {
                   2390:                 $indent.= $whitespace;
                   2391:             }
1.461     neumanie 2392:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2393:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2394:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2395:             }
1.468     amueller 2396:             my $symb_name = $$symbp{$id};
                   2397:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2398:             $symb_name = $tail;
1.498     bisitz   2399:             $r->print(
                   2400:                 &Apache::loncommon::start_data_table_row()
                   2401:                .'<td>'
                   2402:                .'<label>'
1.463     bisitz   2403:             );
1.498     bisitz   2404:             # Only offer radio button for folders/maps which can be parameterized
                   2405:             if ($allmaps_inverted{$symb_name}) {
                   2406:                 $r->print(
                   2407:                     '<input type ="radio" name="pschp"'
                   2408:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2409:                 );
                   2410:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2411:                 $r->print('/>');
                   2412:             } else {
                   2413:                 $r->print($whitespace);
1.461     neumanie 2414:             }
1.498     bisitz   2415:             $r->print(
                   2416:                 $indent.$icon.'&nbsp;'
                   2417:                .$treeinfo->{$id}->{name}
                   2418:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2419:                .'</label>'
                   2420:                .'</td>'
                   2421:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2422:             );
1.461     neumanie 2423:         }
1.497     bisitz   2424: 
1.523     raeburn  2425:         $r->print(&Apache::loncommon::end_data_table().
                   2426:                   '<br style="line-height:2px;" />'.
                   2427:                   &Apache::loncommon::end_scrollbox());
1.209     www      2428:     }
                   2429: }
                   2430: 
1.563     damieng  2431: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2432: # Used by table and overview modes.
                   2433: #
                   2434: # @param {Apache2::RequestRec} $r - the Apache request
                   2435: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2436: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2437: sub levelmenu {
1.446     bisitz   2438:     my ($r,$alllevs,$parmlev)=@_;
                   2439: 
1.548     raeburn  2440:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2441:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2442:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2443:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2444:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2445:         if ($parmlev eq $$alllevs{$lev}) {
                   2446:             $r->print(' selected="selected"');
                   2447:         }
                   2448:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2449:     }
1.446     bisitz   2450:     $r->print("</select>");
1.208     www      2451: }
                   2452: 
1.211     www      2453: 
1.563     damieng  2454: # Returns HTML to select a section (with a select HTML element).
                   2455: # Used by overview mode.
                   2456: #
                   2457: # @param {array reference} $selectedsections - list of selected section ids
                   2458: # @returns {string}
1.211     www      2459: sub sectionmenu {
1.553     raeburn  2460:     my ($selectedsections)=@_;
1.300     albertel 2461:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2462:     return '' if (!%sectionhash);
1.300     albertel 2463: 
1.552     raeburn  2464:     my (@possibles,$disabled);
                   2465:     if ($env{'request.course.sec'} ne '') {
                   2466:         @possibles = ($env{'request.course.sec'});
                   2467:         $selectedsections = [$env{'request.course.sec'}];
                   2468:         $disabled = ' disabled="disabled"';
                   2469:     } else {
                   2470:         @possibles = ('all',sort(keys(%sectionhash)));
                   2471:     }
1.553     raeburn  2472:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2473:     foreach my $s (@possibles) {
1.553     raeburn  2474:         $output .= '    <option value="'.$s.'"';
                   2475:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2476:             $output .= ' selected="selected"';
1.473     amueller 2477:         }
1.553     raeburn  2478:         $output .= '>'."$s</option>\n";
1.300     albertel 2479:     }
1.553     raeburn  2480:     $output .= "</select>\n";
                   2481:     return $output;
1.269     raeburn  2482: }
                   2483: 
1.563     damieng  2484: # Returns HTML to select a group (with a select HTML element).
                   2485: # Used by overview mode.
                   2486: #
                   2487: # @param {array reference} $selectedgroups - list of selected group names
                   2488: # @returns {string}
1.269     raeburn  2489: sub groupmenu {
1.553     raeburn  2490:     my ($selectedgroups)=@_;
                   2491:     my %grouphash;
                   2492:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2493:         %grouphash = &Apache::longroup::coursegroups();
                   2494:     } elsif ($env{'request.course.groups'} ne '') {
                   2495:          map { $grouphash{$_} = 1; } split(/,/,$env{'request.course.groups'});
                   2496:     }
                   2497:     return '' if (!%grouphash);
1.299     albertel 2498: 
1.553     raeburn  2499:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2500:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2501:         $output .= '    <option value="'.$group.'"';
                   2502:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2503:             $output .=  ' selected="selected"';
1.473     amueller 2504:         }
1.553     raeburn  2505:         $output .= '>'."$group</option>\n";
1.211     www      2506:     }
1.553     raeburn  2507:     $output .= "</select>\n";
                   2508:     return $output;
1.211     www      2509: }
                   2510: 
1.563     damieng  2511: # Returns an array with the given parameter split by comma.
                   2512: # Used by assessparms (table mode).
                   2513: #
                   2514: # @param {string} $keyp - the string to split
                   2515: # @returns {Array<string>}
1.210     www      2516: sub keysplit {
                   2517:     my $keyp=shift;
                   2518:     return (split(/\,/,$keyp));
                   2519: }
                   2520: 
1.563     damieng  2521: # Returns the keys in $name, sorted using $keyorder.
                   2522: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   2523: # Used by assessparms (table mode) for resource level.
                   2524: #
                   2525: # @param {hash reference} $name - parameter key -> parameter name
                   2526: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2527: # @returns {Array<string>}
1.210     www      2528: sub keysinorder {
                   2529:     my ($name,$keyorder)=@_;
                   2530:     return sort {
1.560     damieng  2531:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  2532:     } (keys(%{$name}));
1.210     www      2533: }
                   2534: 
1.563     damieng  2535: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   2536: # Used by assessparms (table mode) for map and general levels.
                   2537: #
                   2538: # @param {hash reference} $name - parameter key -> parameter name
                   2539: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2540: # @returns {Array<string>}
1.236     albertel 2541: sub keysinorder_bytype {
                   2542:     my ($name,$keyorder)=@_;
                   2543:     return sort {
1.563     damieng  2544:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  2545:         my $tb=(split('_',$b))[-1];
                   2546:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   2547:             return ($a cmp $b);
                   2548:         }
                   2549:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  2550:     } (keys(%{$name}));
1.236     albertel 2551: }
                   2552: 
1.563     damieng  2553: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   2554: # Used by defaultsetter (parameter settings default actions).
                   2555: #
                   2556: # @param {hash reference} $name - hash parameter name -> parameter title
                   2557: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2558: # @returns {Array<string>}
1.211     www      2559: sub keysindisplayorder {
                   2560:     my ($name,$keyorder)=@_;
                   2561:     return sort {
1.560     damieng  2562:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  2563:     } (keys(%{$name}));
1.211     www      2564: }
                   2565: 
1.563     damieng  2566: # Prints HTML with a choice to sort results by realm or student first.
                   2567: # Used by overview mode.
                   2568: #
                   2569: # @param {Apache2::RequestRec} $r - the Apache request
                   2570: # @param {string} $sortorder - realmstudent|studentrealm
1.214     www      2571: sub sortmenu {
                   2572:     my ($r,$sortorder)=@_;
1.236     albertel 2573:     $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214     www      2574:     if ($sortorder eq 'realmstudent') {
1.422     bisitz   2575:        $r->print(' checked="checked"');
1.214     www      2576:     }
                   2577:     $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236     albertel 2578:     $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214     www      2579:     if ($sortorder eq 'studentrealm') {
1.422     bisitz   2580:        $r->print(' checked="checked"');
1.214     www      2581:     }
1.236     albertel 2582:     $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473     amueller 2583:           '</label>');
1.214     www      2584: }
                   2585: 
1.563     damieng  2586: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   2587: #
                   2588: # @returns {hash}
1.211     www      2589: sub standardkeyorder {
                   2590:     return ('parameter_0_opendate' => 1,
1.473     amueller 2591:         'parameter_0_duedate' => 2,
                   2592:         'parameter_0_answerdate' => 3,
                   2593:         'parameter_0_interval' => 4,
                   2594:         'parameter_0_weight' => 5,
                   2595:         'parameter_0_maxtries' => 6,
                   2596:         'parameter_0_hinttries' => 7,
                   2597:         'parameter_0_contentopen' => 8,
                   2598:         'parameter_0_contentclose' => 9,
                   2599:         'parameter_0_type' => 10,
                   2600:         'parameter_0_problemstatus' => 11,
                   2601:         'parameter_0_hiddenresource' => 12,
                   2602:         'parameter_0_hiddenparts' => 13,
                   2603:         'parameter_0_display' => 14,
                   2604:         'parameter_0_ordered' => 15,
                   2605:         'parameter_0_tol' => 16,
                   2606:         'parameter_0_sig' => 17,
                   2607:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  2608:         'parameter_0_discussend' => 19,
                   2609:         'parameter_0_discusshide' => 20,
                   2610:         'parameter_0_discussvote' => 21,
1.560     damieng  2611:         'parameter_0_printstartdate'  =>  22,
                   2612:         'parameter_0_printenddate' =>  23);
1.211     www      2613: }
                   2614: 
1.59      matthew  2615: 
1.560     damieng  2616: # Table mode UI.
1.563     damieng  2617: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   2618: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   2619: #
                   2620: # Parameters used from the request:
                   2621: # action - handler action (see handler), usermenu is checking for value 'settable'
                   2622: # cgroup - selected group
                   2623: # command - 'set': direct access to table mode for a resource
                   2624: # csec - selected section
                   2625: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   2626: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   2627: # id - student/employee ID
                   2628: # parmlev - selected level (full|map|general)
                   2629: # part - selected part (unused ?)
                   2630: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   2631: # pres_type - &&&-separated parameter types
                   2632: # pres_value - &&&-separated parameter values
                   2633: # prevvisit - '1' if the user has submitted the form before
                   2634: # pscat (multiple values) - selected parameter names
1.566     damieng  2635: # pschp - selected map pc, or 'all'
1.563     damieng  2636: # psprt (multiple values) - list of selected parameter parts
                   2637: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   2638: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   2639: # symb - resource symb (when a single resource is selected)
                   2640: # udom - selected user domain
                   2641: # uname - selected user name
                   2642: # url - used only with command 'set', the resource url
                   2643: #
                   2644: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  2645: # @param $parm_permission - ref to hash of permissions
                   2646: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      2647: sub assessparms {
1.1       www      2648: 
1.568     raeburn  2649:     my ($r,$parm_permission) = @_;
1.201     www      2650: 
1.512     foxr     2651: 
                   2652: # -------------------------------------------------------- Variable declaration
1.566     damieng  2653:     my @ids=(); # resource and map ids
                   2654:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   2655:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   2656:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   2657:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   2658:     my %uris=(); # hash resource/map id -> resource src
                   2659:     my %maptitles=(); # hash map pc or src -> map title
                   2660:     my %allmaps=(); # hash map pc -> map src
1.563     damieng  2661:     my %alllevs=(); # hash English level title -> value
                   2662: 
                   2663:     my $uname; # selected user name
                   2664:     my $udom; # selected user domain
                   2665:     my $uhome; # server with the user's files, or 'no_host'
                   2666:     my $csec; # selected section name
                   2667:     my $cgroup; # selected group name
                   2668:     my @usersgroups = (); # list of the user groups
1.446     bisitz   2669: 
1.190     albertel 2670:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      2671: 
1.57      albertel 2672:     $alllevs{'Resource Level'}='full';
1.215     www      2673:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 2674:     $alllevs{'Course Level'}='general';
                   2675: 
1.563     damieng  2676:     my %allparms; # hash parameter name -> parameter title
                   2677:     my %allparts; # hash parameter part -> part title
1.512     foxr     2678: # ------------------------------------------------------------------------------
                   2679: 
1.210     www      2680: #
                   2681: # Order in which these parameters will be displayed
                   2682: #
1.211     www      2683:     my %keyorder=&standardkeyorder();
                   2684: 
1.512     foxr     2685: #    @ids=();
                   2686: #    %symbp=();       # These seem defined above already.
                   2687: #    %typep=();
1.43      albertel 2688: 
                   2689:     my $message='';
                   2690: 
1.190     albertel 2691:     $csec=$env{'form.csec'};
1.552     raeburn  2692:     if ($env{'request.course.sec'} ne '') {
                   2693:         $csec = $env{'request.course.sec'};    
                   2694:     }
                   2695: 
1.553     raeburn  2696: # Check group privs.
1.269     raeburn  2697:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  2698:     my $noeditgrp; 
                   2699:     if ($cgroup ne '') {
                   2700:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2701:             if (($env{'request.course.groups'} eq '') || 
                   2702:                 (!grep(/^\Q$cgroup\E$/,split(/,/,$env{'request.course.groups'})))) {
                   2703:                 $noeditgrp = 1;
                   2704:             }
                   2705:         }
                   2706:     }
1.188     www      2707: 
1.190     albertel 2708:     if      ($udom=$env{'form.udom'}) {
                   2709:     } elsif ($udom=$env{'request.role.domain'}) {
                   2710:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 2711:     } else {
1.473     amueller 2712:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 2713:     }
1.468     amueller 2714:     
1.43      albertel 2715: 
1.134     albertel 2716:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 2717:     my $pschp=$env{'form.pschp'};
1.506     www      2718: 
                   2719: 
1.134     albertel 2720:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      2721:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      2722:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 2723: 
1.43      albertel 2724:     my $pssymb='';
1.57      albertel 2725:     my $parmlev='';
1.446     bisitz   2726: 
1.190     albertel 2727:     unless ($env{'form.parmlev'}) {
1.57      albertel 2728:         $parmlev = 'map';
                   2729:     } else {
1.190     albertel 2730:         $parmlev = $env{'form.parmlev'};
1.57      albertel 2731:     }
1.26      www      2732: 
1.29      www      2733: # ----------------------------------------------- Was this started from grades?
                   2734: 
1.560     damieng  2735:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   2736:             (!$env{'form.dis'})) {
1.473     amueller 2737:         my $url=$env{'form.url'};
                   2738:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   2739:         $pssymb=&Apache::lonnet::symbread($url);
                   2740:         if (!@pscat) { @pscat=('all'); }
                   2741:         $pschp='';
1.57      albertel 2742:         $parmlev = 'full';
1.190     albertel 2743:     } elsif ($env{'form.symb'}) {
1.473     amueller 2744:         $pssymb=$env{'form.symb'};
                   2745:         if (!@pscat) { @pscat=('all'); }
                   2746:         $pschp='';
1.57      albertel 2747:         $parmlev = 'full';
1.43      albertel 2748:     } else {
1.473     amueller 2749:         $env{'form.url'}='';
1.43      albertel 2750:     }
                   2751: 
1.190     albertel 2752:     my $id=$env{'form.id'};
1.43      albertel 2753:     if (($id) && ($udom)) {
1.555     raeburn  2754:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 2755:         if ($uname) {
                   2756:             $id='';
                   2757:         } else {
                   2758:             $message=
1.540     bisitz   2759:                 '<p class="LC_warning">'.
                   2760:                 &mt('Unknown ID [_1] at domain [_2]',
                   2761:                     "'".$id."'","'".$udom."'").
                   2762:                 '</p>';
1.473     amueller 2763:         }
1.43      albertel 2764:     } else {
1.473     amueller 2765:         $uname=$env{'form.uname'};
1.43      albertel 2766:     }
                   2767:     unless ($udom) { $uname=''; }
                   2768:     $uhome='';
                   2769:     if ($uname) {
1.473     amueller 2770:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 2771:         if ($uhome eq 'no_host') {
1.473     amueller 2772:             $message=
1.540     bisitz   2773:                 '<p class="LC_warning">'.
                   2774:                 &mt('Unknown user [_1] at domain [_2]',
                   2775:                     "'".$uname."'","'".$udom."'").
                   2776:                 '</p>';
1.473     amueller 2777:             $uname='';
1.12      www      2778:         } else {
1.473     amueller 2779:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   2780:                           $env{'request.course.id'});
                   2781:             if ($csec eq '-1') {
1.540     bisitz   2782:                 $message=
                   2783:                     '<p class="LC_warning">'.
                   2784:                     &mt('User [_1] at domain [_2] not in this course',
                   2785:                         "'".$uname."'","'".$udom."'").
                   2786:                     '</p>';
1.473     amueller 2787:                 $uname='';
                   2788:                 $csec=$env{'form.csec'};
1.269     raeburn  2789:                 $cgroup=$env{'form.cgroup'};
1.473     amueller 2790:             } else {
                   2791:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   2792:                   ('firstname','middlename','lastname','generation','id'));
                   2793:                 $message="\n<p>\n".&mt("Full Name").": ".
                   2794:                 $name{'firstname'}.' '.$name{'middlename'}.' '
                   2795:                 .$name{'lastname'}.' '.$name{'generation'}.
1.501     bisitz   2796:                 "<br />\n".&mt('Student/Employee ID').": ".$name{'id'}.'<p>';
1.473     amueller 2797:             }
1.297     raeburn  2798:             @usersgroups = &Apache::lonnet::get_users_groups(
1.275     raeburn  2799:                                        $udom,$uname,$env{'request.course.id'});
1.297     raeburn  2800:             if (@usersgroups > 0) {
1.306     albertel 2801:                 unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
1.275     raeburn  2802:                     $cgroup = $usersgroups[0];
1.297     raeburn  2803:                 }
1.269     raeburn  2804:             }
1.12      www      2805:         }
1.43      albertel 2806:     }
1.2       www      2807: 
1.43      albertel 2808:     unless ($csec) { $csec=''; }
1.269     raeburn  2809:     unless ($cgroup) { $cgroup=''; }
1.12      www      2810: 
1.14      www      2811: # --------------------------------------------------------- Get all assessments
1.446     bisitz   2812:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 2813:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   2814:                 \%keyorder);
1.63      bowersj2 2815: 
1.57      albertel 2816:     $mapp{'0.0'} = '';
                   2817:     $symbp{'0.0'} = '';
1.99      albertel 2818: 
1.14      www      2819: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  2820:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      2821:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   2822:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   2823:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  2824:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   2825:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  2826:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   2827:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   2828:         my $totalstored = 0;
1.546     raeburn  2829:         my $now = time;
1.473     amueller 2830:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  2831:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  2832:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  2833:                 next if ($csec ne $env{'request.course.sec'});
                   2834:             }
1.556     raeburn  2835:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  2836:                 next if ($noeditgrp);
1.557     raeburn  2837:             }
                   2838:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   2839:                 $namematch = 'maplevelrecurse';
                   2840:             }
1.556     raeburn  2841:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  2842:                 my (@ok_slots,@fail_slots,@del_slots);
                   2843:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   2844:                 my ($level,@all) =
                   2845:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   2846:                                      $csec,$cgroup,$courseopt);
                   2847:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   2848:                     next if ($slot_name eq '');
                   2849:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   2850:                         push(@ok_slots,$slot_name);
                   2851: 
                   2852:                     } else {
                   2853:                         push(@fail_slots,$slot_name);
                   2854:                     }
                   2855:                 }
                   2856:                 if (@ok_slots) {
                   2857:                     $values[$i] = join(':',@ok_slots);
                   2858:                 } else {
                   2859:                     $values[$i] = '';
                   2860:                 }
                   2861:                 if ($all[$level] ne '') {
                   2862:                     my @existing = split(/:/,$all[$level]);
                   2863:                     foreach my $slot_name (@existing) {
                   2864:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   2865:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   2866:                                 push(@del_slots,$slot_name);
                   2867:                             }
                   2868:                         }
                   2869:                     }
                   2870:                 }
1.554     raeburn  2871:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  2872:                 $name = $1;
1.533     raeburn  2873:                 my $val = $values[$i];
1.549     raeburn  2874:                 my $valmatch = '';
1.533     raeburn  2875:                 if ($name eq 'examcode') {
1.544     raeburn  2876:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   2877:                         $val = 'valid';
                   2878:                     }
1.546     raeburn  2879:                 } elsif ($name eq 'printstartdate') {
                   2880:                     if ($val =~ /^\d+$/) {
                   2881:                         if ($val > $now) {
                   2882:                             $val = 'future';
                   2883:                         }
                   2884:                     } 
                   2885:                 } elsif ($name eq 'printenddate') {
                   2886:                     if ($val =~ /^\d+$/) {
                   2887:                         if ($val < $now) {
                   2888:                             $val = 'past';
                   2889:                         }
                   2890:                     }
1.549     raeburn  2891:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   2892:                     my $stringtype = &get_stringtype($name);
                   2893:                     my $stringmatch = &standard_string_matches($stringtype);
                   2894:                     if (ref($stringmatch) eq 'ARRAY') {
                   2895:                         foreach my $item (@{$stringmatch}) {
                   2896:                             if (ref($item) eq 'ARRAY') {
                   2897:                                 my ($regexpname,$pattern) = @{$item};
                   2898:                                 if ($pattern ne '') {
                   2899:                                     if ($val =~ /$pattern/) {
                   2900:                                         $valmatch = $regexpname;
                   2901:                                         $val = '';
                   2902:                                         last;
                   2903:                                     }
                   2904:                                 }
                   2905:                             }
                   2906:                         }
                   2907:                     }
1.554     raeburn  2908:                 } elsif ($name eq 'interval') {
                   2909:                     my $intervaltype = &get_intervaltype($name);
                   2910:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   2911:                     if (ref($intervalmatch) eq 'ARRAY') {
                   2912:                         foreach my $item (@{$intervalmatch}) {
                   2913:                             if (ref($item) eq 'ARRAY') {
                   2914:                                 my ($regexpname,$pattern) = @{$item};
                   2915:                                 if ($pattern ne '') {
                   2916:                                     if ($val =~ /$pattern/) {
                   2917:                                         $valmatch = $regexpname;
                   2918:                                         $val = '';
                   2919:                                         last;
                   2920:                                     }
                   2921:                                 }
                   2922:                             }
                   2923:                         }
                   2924:                     }
1.533     raeburn  2925:                 }
1.504     raeburn  2926:                 $needsrelease =
1.557     raeburn  2927:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  2928:                 if ($needsrelease) {
1.505     raeburn  2929:                     unless ($got_chostname) {
1.514     raeburn  2930:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  2931:                         $got_chostname = 1;
1.546     raeburn  2932:                     } 
1.557     raeburn  2933:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  2934:                                                           $needsrelease,
                   2935:                                                           $cmajor,$cminor);
1.500     raeburn  2936:                 }
1.437     raeburn  2937:             }
1.504     raeburn  2938:             if ($needsnewer) {
1.557     raeburn  2939:                 undef($namematch);
                   2940:             } else {
                   2941:                 my $currneeded;
                   2942:                 if ($needsrelease) {
                   2943:                     $currneeded = $needsrelease;
                   2944:                 }
                   2945:                 if ($namematch) {
                   2946:                     $needsrelease =
                   2947:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   2948:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   2949:                         unless ($got_chostname) {
                   2950:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   2951:                             $got_chostname = 1;
                   2952:                         }
                   2953:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   2954:                                                               $needsrelease,
                   2955:                                                               $cmajor,$cminor);
                   2956:                     } else {
                   2957:                         undef($namematch);
                   2958:                     }
                   2959:                 }
                   2960:             }
                   2961:             if ($needsnewer) {
                   2962:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  2963:                                                 $cminor,$needsrelease);
                   2964:             } else {
                   2965:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   2966:                                      $values[$i],
                   2967:                                      $types[$i],
                   2968:                                      $uname,$udom,$csec,$cgroup);
                   2969:                 $totalstored ++;
                   2970:             }
1.473     amueller 2971:         }
1.68      www      2972: # ---------------------------------------------------------------- Done storing
1.504     raeburn  2973:         if ($totalstored) {
                   2974:             $message.='<p class="LC_warning">'
                   2975:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   2976:                      .&Apache::loncommon::help_open_topic('Caching')
                   2977:                      .'</p>';
                   2978:         }
1.68      www      2979:     }
1.57      albertel 2980: #----------------------------------------------- if all selected, fill in array
1.563     damieng  2981:     if ($pscat[0] eq "all") {
                   2982:         @pscat = (keys(%allparms));
                   2983:     }
                   2984:     if (!@pscat) {
                   2985:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   2986:     };
                   2987:     if ($psprt[0] eq "all" || !@psprt) {
                   2988:         @psprt = (keys(%allparts));
                   2989:     }
1.2       www      2990: # ------------------------------------------------------------------ Start page
1.63      bowersj2 2991: 
1.531     raeburn  2992:     my $crstype = &Apache::loncommon::course_type();
                   2993:     &startpage($r,$pssymb,$crstype);
1.57      albertel 2994: 
1.548     raeburn  2995:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.563     damieng  2996:             'date_interval','int','float','string') {
1.473     amueller 2997:         $r->print('<input type="hidden" value="'.
1.563     damieng  2998:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   2999:             '" name="recent_'.$item.'" />');
1.44      albertel 3000:     }
1.446     bisitz   3001: 
1.459     bisitz   3002:     # ----- Start Parameter Selection
                   3003: 
                   3004:     # Hide parm selection?
                   3005:     $r->print(<<ENDPARMSELSCRIPT);
                   3006: <script type="text/javascript">
                   3007: // <![CDATA[
                   3008: function parmsel_show() {
1.562     damieng  3009:     document.getElementById('parmsel').style.display = "";
                   3010:     document.getElementById('parmsellink').style.display = "none";
1.459     bisitz   3011: }
                   3012: // ]]>
                   3013: </script>
                   3014: ENDPARMSELSCRIPT
1.474     amueller 3015:     
1.445     neumanie 3016:     if (!$pssymb) {
1.563     damieng  3017:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3018:         my $parmselhiddenstyle=' style="display:none"';
                   3019:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3020:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3021:         } else  {
                   3022:            $r->print('<div id="parmsel">');
                   3023:         }
                   3024: 
1.491     bisitz   3025:         # Step 1
1.523     raeburn  3026:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3027:         $r->print('
1.474     amueller 3028: <script type="text/javascript">
1.523     raeburn  3029: // <![CDATA['.
                   3030:                  &showhide_js().'
1.474     amueller 3031: // ]]>
                   3032: </script>
1.523     raeburn  3033: ');
                   3034:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3035:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3036:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.474     amueller 3037:         &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491     bisitz   3038:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3039:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3040:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3041:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3042:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3043: 
                   3044:         # Step 2
1.523     raeburn  3045:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.536     raeburn  3046:         &displaymenu($r,\%allparms,\@pscat,\@psprt,\%keyorder,'parmmenuscroll');
1.491     bisitz   3047: 
                   3048:         # Step 3
1.523     raeburn  3049:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3050:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3051:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3052:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3053:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3054: 
                   3055:         # Update Display Button
1.486     www      3056:         $r->print('<p>'
                   3057:              .'<input type="submit" name="dis"'
1.511     www      3058:              .' value="'.&mt('Update Display').'" />'
1.486     www      3059:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3060:              .'</p>');
                   3061:         $r->print('</div>');
1.491     bisitz   3062: 
1.486     www      3063:         # Offer link to display parameter selection again
                   3064:         $r->print('<p id="parmsellink"');
                   3065:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3066:            $r->print($parmselhiddenstyle);
                   3067:         }
                   3068:         $r->print('>'
                   3069:              .'<a href="javascript:parmsel_show()">'
                   3070:              .&mt('Change Parameter Selection')
                   3071:              .'</a>'
                   3072:              .'</p>');
1.44      albertel 3073:     } else {
1.478     amueller 3074:         # parameter screen for a single resource. 
1.486     www      3075:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3076:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3077:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3078:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3079:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3080:                   '<br />');
                   3081:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3082:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3083:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3084:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3085:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3086:         $r->print('<p>'
1.459     bisitz   3087:              .'<input type="submit" name="dis"'
1.511     www      3088:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3089:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3090:              .'</p>');
1.459     bisitz   3091:     }
1.478     amueller 3092:     
1.486     www      3093:     # ----- End Parameter Selection
1.57      albertel 3094: 
1.459     bisitz   3095:     # Display Messages
                   3096:     $r->print('<div>'.$message.'</div>');
1.210     www      3097: 
1.57      albertel 3098: 
                   3099:     my @temp_pscat;
                   3100:     map {
                   3101:         my $cat = $_;
                   3102:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3103:     } @pscat;
                   3104: 
                   3105:     @pscat = @temp_pscat;
                   3106: 
1.548     raeburn  3107: 
1.209     www      3108:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3109: # ----------------------------------------------------------------- Start Table
1.57      albertel 3110:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3111:         my $csuname=$env{'user.name'};
                   3112:         my $csudom=$env{'user.domain'};
1.568     raeburn  3113:         my $readonly = 1;
                   3114:         if ($parm_permission->{'edit'}) {
                   3115:             undef($readonly); 
                   3116:         }
1.57      albertel 3117: 
1.203     www      3118:         if ($parmlev eq 'full') {
1.506     www      3119: #
                   3120: # This produces the cascading table output of parameters
                   3121: #
1.560     damieng  3122:             my $coursespan=$csec?10:6;
                   3123:             my $userspan=4;
                   3124:             if ($cgroup ne '') {
                   3125:                 $coursespan += 4;
                   3126:             }
1.473     amueller 3127: 
1.560     damieng  3128:             $r->print(&Apache::loncommon::start_data_table());
                   3129:             #
                   3130:             # This produces the headers
                   3131:             #
                   3132:             $r->print('<tr><td colspan="5"></td>');
                   3133:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3134:             if ($uname) {
1.473     amueller 3135:                 if (@usersgroups > 1) {
1.560     damieng  3136:                     $userspan ++;
                   3137:                 }
                   3138:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3139:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3140:             }
                   3141:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3142:                 'pie'    => "Parameter in Effect",
                   3143:                 'csv'    => "Current Session Value",
1.472     amueller 3144:                 'rl'     => "Resource Level",
1.473     amueller 3145:                 'ic'     => 'in Course',
                   3146:                 'aut'    => "Assessment URL and Title",
                   3147:                 'type'   => 'Type',
                   3148:                 'emof'   => "Enclosing Map or Folder",
                   3149:                 'part'   => 'Part',
1.472     amueller 3150:                 'pn'     => 'Parameter Name',
1.473     amueller 3151:                 'def'    => 'default',
                   3152:                 'femof'  => 'from Enclosing Map or Folder',
                   3153:                 'gen'    => 'general',
                   3154:                 'foremf' => 'for Enclosing Map or Folder',
1.556     raeburn  3155:                 'formfr' => 'for Map or Folder (recursive)',
1.473     amueller 3156:                 'fr'     => 'for Resource'
                   3157:             );
1.560     damieng  3158:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3159: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3160: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.556     raeburn  3161: </tr><tr><td colspan="5"></td><th colspan="3">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3162: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3163: 
1.10      www      3164: ENDTABLETWO
1.560     damieng  3165:             if ($csec) {
                   3166:                 $r->print('<th colspan="4">'.
                   3167:                 &mt("in Section")." $csec</th>");
                   3168:             }
                   3169:             if ($cgroup) {
1.556     raeburn  3170:                 $r->print('<th colspan="4">'.
1.472     amueller 3171:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3172:             }
                   3173:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3174: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3175: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.556     raeburn  3176: <th>$lt{'gen'}</th><th>$lt{'formfr'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3177: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3178: ENDTABLEHEADFOUR
1.57      albertel 3179: 
1.560     damieng  3180:             if ($csec) {
                   3181:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'formfr'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
                   3182:             }
1.473     amueller 3183: 
1.560     damieng  3184:             if ($cgroup) {
                   3185:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'formfr'}.'</th><th>'.&mt('foremf').'</th><th>'.$lt{'fr'}.'</th>');
                   3186:             }
                   3187: 
                   3188:             if ($uname) {
                   3189:                 if (@usersgroups > 1) {
                   3190:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3191:                 }
                   3192:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'formfr'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
                   3193:             }
                   3194: 
                   3195:             $r->print('</tr>');
1.506     www      3196: #
                   3197: # Done with the headers
                   3198: # 
1.560     damieng  3199:             my $defbgone='';
                   3200:             my $defbgtwo='';
                   3201:             my $defbgthree = '';
1.57      albertel 3202: 
1.560     damieng  3203:             foreach my $rid (@ids) {
1.57      albertel 3204: 
                   3205:                 my ($inmapid)=($rid=~/\.(\d+)$/);
                   3206: 
1.446     bisitz   3207:                 if ((!$pssymb &&
1.560     damieng  3208:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3209:                         ||
                   3210:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3211: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3212:                     if ($defbgone eq '#E0E099') {
                   3213:                         $defbgone='#E0E0DD';
1.57      albertel 3214:                     } else {
1.419     bisitz   3215:                         $defbgone='#E0E099';
1.57      albertel 3216:                     }
1.419     bisitz   3217:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3218:                         $defbgtwo='#FFFFDD';
1.57      albertel 3219:                     } else {
1.473     amueller 3220:                         $defbgtwo='#FFFF99';
1.57      albertel 3221:                     }
1.419     bisitz   3222:                     if ($defbgthree eq '#FFBB99') {
                   3223:                         $defbgthree='#FFBBDD';
1.269     raeburn  3224:                     } else {
1.419     bisitz   3225:                         $defbgthree='#FFBB99';
1.269     raeburn  3226:                     }
                   3227: 
1.57      albertel 3228:                     my $thistitle='';
                   3229:                     my %name=   ();
                   3230:                     undef %name;
                   3231:                     my %part=   ();
                   3232:                     my %display=();
                   3233:                     my %type=   ();
                   3234:                     my %default=();
1.196     www      3235:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.57      albertel 3236: 
1.506     www      3237:                     my $filter=$env{'form.filter'};
1.548     raeburn  3238:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3239:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.560     damieng  3240:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name');
                   3241:     # We may only want certain parameters listed
                   3242:                             if ($filter) {
                   3243:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3244:                             }
                   3245:                             $name{$tempkeyp}=$parmname;
                   3246:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part');
                   3247: 
                   3248:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display');
                   3249:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3250:                                 my $identifier;
                   3251:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3252:                                     $identifier = $1;
                   3253:                                 }
                   3254:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3255:                             } else {
                   3256:                                 $display{$tempkeyp} = $parmdis;
                   3257:                             }
                   3258:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3259:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3260:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp);
                   3261:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type');
                   3262:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title');
1.57      albertel 3263:                         }
                   3264:                     }
1.548     raeburn  3265:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3266:                     if ($totalparms>0) {
1.560     damieng  3267:                         my $firstrow=1;
1.473     amueller 3268:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.419     bisitz   3269:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3270:                              ' rowspan='.$totalparms.
1.419     bisitz   3271:                              '><tt><font size="-1">'.
1.57      albertel 3272:                              join(' / ',split(/\//,$uri)).
                   3273:                              '</font></tt><p><b>'.
1.154     albertel 3274:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3275:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3276:                           &escape($symbp{$rid}).
1.336     albertel 3277:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3278:                              " target=\"_self\">$title");
1.57      albertel 3279: 
                   3280:                         if ($thistitle) {
1.473     amueller 3281:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3282:                         }
                   3283:                         $r->print('</a></b></td>');
1.419     bisitz   3284:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3285:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3286:                                       '</td>');
                   3287: 
1.419     bisitz   3288:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3289:                                       ' rowspan='.$totalparms.
1.238     www      3290:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3291:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3292:                             unless ($firstrow) {
                   3293:                                 $r->print('<tr>');
                   3294:                             } else {
                   3295:                                 undef $firstrow;
                   3296:                             }
1.548     raeburn  3297:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3298:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3299:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.568     raeburn  3300:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly);
1.57      albertel 3301:                         }
                   3302:                     }
                   3303:                 }
                   3304:             } # end foreach ids
1.43      albertel 3305: # -------------------------------------------------- End entry for one resource
1.517     www      3306:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3307:         } # end of  full
1.57      albertel 3308: #--------------------------------------------------- Entry for parm level map
                   3309:         if ($parmlev eq 'map') {
1.419     bisitz   3310:             my $defbgone = '#E0E099';
                   3311:             my $defbgtwo = '#FFFF99';
                   3312:             my $defbgthree = '#FFBB99';
1.57      albertel 3313: 
                   3314:             my %maplist;
                   3315: 
                   3316:             if ($pschp eq 'all') {
1.446     bisitz   3317:                 %maplist = %allmaps;
1.57      albertel 3318:             } else {
                   3319:                 %maplist = ($pschp => $mapp{$pschp});
                   3320:             }
                   3321: 
                   3322: #-------------------------------------------- for each map, gather information
                   3323:             my $mapid;
1.560     damieng  3324:             foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {
1.60      albertel 3325:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3326: 
                   3327: #-----------------------  loop through ids and get all parameter types for map
                   3328: #-----------------------------------------          and associated information
                   3329:                 my %name = ();
                   3330:                 my %part = ();
                   3331:                 my %display = ();
                   3332:                 my %type = ();
                   3333:                 my %default = ();
                   3334:                 my $map = 0;
                   3335: 
1.473     amueller 3336: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3337: 
1.548     raeburn  3338:                 foreach my $id (@ids) {
                   3339:                     ($map)=($id =~ /([\d]*?)\./);
                   3340:                     my $rid = $id;
1.446     bisitz   3341: 
1.57      albertel 3342: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3343: 
1.560     damieng  3344:                     if ($map eq $mapid) {
1.473     amueller 3345:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.57      albertel 3346: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3347: 
                   3348: #--------------------------------------------------------------------
                   3349: # @catmarker contains list of all possible parameters including part #s
                   3350: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3351: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3352: # When storing information, store as part 0
                   3353: # When requesting information, request from full part
                   3354: #-------------------------------------------------------------------
1.548     raeburn  3355:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3356:                             my $tempkeyp = $fullkeyp;
                   3357:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 3358: 
1.548     raeburn  3359:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3360:                                 $part{$tempkeyp}="0";
                   3361:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name');
                   3362:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display');
                   3363:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   3364:                                     my $identifier;
                   3365:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3366:                                         $identifier = $1;
                   3367:                                     }
                   3368:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3369:                                 } else {
                   3370:                                     $display{$tempkeyp} = $parmdis;
                   3371:                                 }
                   3372:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3373:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3374:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
                   3375:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp);
                   3376:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type');
                   3377:                               }
                   3378:                         } # end loop through keys
1.560     damieng  3379:                     }
1.57      albertel 3380:                 } # end loop through ids
1.446     bisitz   3381: 
1.57      albertel 3382: #---------------------------------------------------- print header information
1.133     www      3383:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      3384:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   3385:                 my $tmp="";
1.57      albertel 3386:                 if ($uname) {
1.473     amueller 3387:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   3388:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   3389:                         &mt('in')." \n";
1.57      albertel 3390:                 } else {
1.401     bisitz   3391:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 3392:                 }
1.269     raeburn  3393:                 if ($cgroup) {
1.401     bisitz   3394:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   3395:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3396:                     $csec = '';
                   3397:                 } elsif ($csec) {
1.401     bisitz   3398:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   3399:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3400:                 }
1.401     bisitz   3401:                 $r->print('<div align="center"><h4>'
                   3402:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   3403:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   3404:                              ,$tmp
                   3405:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   3406:                              )
                   3407:                          ."<br /></h4>\n"
1.422     bisitz   3408:                 );
1.57      albertel 3409: #---------------------------------------------------------------- print table
1.419     bisitz   3410:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3411:                          .&Apache::loncommon::start_data_table_header_row()
                   3412:                          .'<th>'.&mt('Parameter Name').'</th>'
1.556     raeburn  3413:                          .'<th>'.&mt('Recursive Value').'</th>'
                   3414:                          .'<th>'.&mt('Non-Recursive Value').'</th>'
1.419     bisitz   3415:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   3416:                          .&Apache::loncommon::end_data_table_header_row()
                   3417:                 );
1.57      albertel 3418: 
1.548     raeburn  3419:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 3420:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3421:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  3422:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  3423:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   3424:                            $readonly);
1.57      albertel 3425:                 }
1.422     bisitz   3426:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   3427:                          .'</div>'
                   3428:                 );
1.57      albertel 3429:             } # end each map
                   3430:         } # end of $parmlev eq map
                   3431: #--------------------------------- Entry for parm level general (Course level)
                   3432:         if ($parmlev eq 'general') {
1.473     amueller 3433:             my $defbgone = '#E0E099';
1.419     bisitz   3434:             my $defbgtwo = '#FFFF99';
                   3435:             my $defbgthree = '#FFBB99';
1.57      albertel 3436: 
                   3437: #-------------------------------------------- for each map, gather information
                   3438:             my $mapid="0.0";
                   3439: #-----------------------  loop through ids and get all parameter types for map
                   3440: #-----------------------------------------          and associated information
                   3441:             my %name = ();
                   3442:             my %part = ();
                   3443:             my %display = ();
                   3444:             my %type = ();
                   3445:             my %default = ();
1.446     bisitz   3446: 
1.548     raeburn  3447:             foreach $id (@ids) {
                   3448:                 my $rid = $id;
1.446     bisitz   3449: 
1.196     www      3450:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.57      albertel 3451: 
                   3452: #--------------------------------------------------------------------
                   3453: # @catmarker contains list of all possible parameters including part #s
                   3454: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3455: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3456: # When storing information, store as part 0
                   3457: # When requesting information, request from full part
                   3458: #-------------------------------------------------------------------
1.548     raeburn  3459:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3460:                     my $tempkeyp = $fullkeyp;
                   3461:                     $tempkeyp =~ s/_\w+_/_0_/;
                   3462:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3463:                         $part{$tempkeyp}="0";
                   3464:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name');
                   3465:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display');
                   3466:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   3467:                             my $identifier;
                   3468:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3469:                                 $identifier = $1;
                   3470:                             }
                   3471:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3472:                         } else {
                   3473:                             $display{$tempkeyp} = $parmdis;
                   3474:                         }
                   3475:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3476:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3477:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
                   3478:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp);
                   3479:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type');
1.560     damieng  3480:                     }
1.57      albertel 3481:                 } # end loop through keys
                   3482:             } # end loop through ids
1.446     bisitz   3483: 
1.57      albertel 3484: #---------------------------------------------------- print header information
1.473     amueller 3485:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 3486:             $r->print(<<ENDMAPONE);
1.419     bisitz   3487: <center>
                   3488: <h4>$setdef
1.135     albertel 3489: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 3490: ENDMAPONE
                   3491:             if ($uname) {
1.473     amueller 3492:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 3493:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 3494:             } else {
1.135     albertel 3495:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 3496:             }
1.446     bisitz   3497: 
1.135     albertel 3498:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 3499:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 3500:             $r->print("</h4>\n");
1.57      albertel 3501: #---------------------------------------------------------------- print table
1.419     bisitz   3502:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3503:                      .&Apache::loncommon::start_data_table_header_row()
                   3504:                      .'<th>'.&mt('Parameter Name').'</th>'
                   3505:                      .'<th>'.&mt('Default Value').'</th>'
                   3506:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   3507:                      .&Apache::loncommon::end_data_table_header_row()
                   3508:             );
1.57      albertel 3509: 
1.548     raeburn  3510:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   3511:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3512:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  3513:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   3514:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   3515:                            $readonly);
1.57      albertel 3516:             }
1.419     bisitz   3517:             $r->print(&Apache::loncommon::end_data_table()
                   3518:                      .'</p>'
                   3519:                      .'</center>'
                   3520:             );
1.57      albertel 3521:         } # end of $parmlev eq general
1.43      albertel 3522:     }
1.507     www      3523:     $r->print('</form>');
                   3524:     &endSettingsScreen($r);
                   3525:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 3526: } # end sub assessparms
1.30      www      3527: 
1.560     damieng  3528: 
                   3529: 
1.120     www      3530: ##################################################
1.560     damieng  3531: # OVERVIEW MODE
1.207     www      3532: ##################################################
1.124     www      3533: 
1.563     damieng  3534: my $tableopen; # boolean, true if HTML table is already opened
                   3535: 
                   3536: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   3537: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   3538: # @returns {string}
1.124     www      3539: sub tablestart {
1.552     raeburn  3540:     my ($readonly) = @_;
1.124     www      3541:     if ($tableopen) {
1.552     raeburn  3542:         return '';
1.124     www      3543:     } else {
1.552     raeburn  3544:         $tableopen=1;
                   3545:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   3546:         if ($readonly) {
                   3547:             $output .= '<th>'.&mt('Current value').'</th>';
                   3548:         } else {
                   3549:             $output .= '<th>'.&mt('Delete').'</th><th>'.&mt('Set to ...').'</th>';
                   3550:         }
                   3551:         $output .= '</tr>';
                   3552:         return $output;
1.124     www      3553:     }
                   3554: }
                   3555: 
1.563     damieng  3556: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   3557: # @returns {string}
1.124     www      3558: sub tableend {
                   3559:     if ($tableopen) {
1.560     damieng  3560:         $tableopen=0;
                   3561:         return &Apache::loncommon::end_data_table();
1.124     www      3562:     } else {
1.560     damieng  3563:         return'';
1.124     www      3564:     }
                   3565: }
                   3566: 
1.563     damieng  3567: # Reads course and user information.
                   3568: # 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).
                   3569: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   3570: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   3571: # @param {string} $crs - course number
                   3572: # @param {string} $dom - course domain
                   3573: # @returns {hash reference|Array}
1.207     www      3574: sub readdata {
                   3575:     my ($crs,$dom)=@_;
                   3576: # Read coursedata
                   3577:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   3578: # Read userdata
                   3579: 
                   3580:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  3581:     foreach my $user (keys(%$classlist)) {
                   3582:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   3583:             my ($tuname,$tudom)=($1,$2);
                   3584:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   3585:             foreach my $userkey (keys(%{$useropt})) {
                   3586:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      3587:                     my $newkey=$userkey;
1.548     raeburn  3588:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   3589:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   3590:                 }
                   3591:             }
1.473     amueller 3592:         }
                   3593:     }
1.552     raeburn  3594:     if (wantarray) {
                   3595:         return ($resourcedata,$classlist);
                   3596:     } else {
                   3597:         return $resourcedata;
                   3598:     }
1.207     www      3599: }
                   3600: 
                   3601: 
1.563     damieng  3602: # Stores parameter data, using form parameters directly.
                   3603: #
                   3604: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
                   3605: # set_* (except settext, setipallow, setipdeny) - set a parameter value
                   3606: # del_* - remove a parameter
                   3607: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   3608: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   3609: # key_* - date values
                   3610: # days_* - for date intervals
                   3611: # hours_* - for date intervals
                   3612: # minutes_* - for date intervals
                   3613: # seconds_* - for date intervals
                   3614: # done_* - for date intervals
                   3615: # typeof_* - parameter type
                   3616: # 
                   3617: # @param {Apache2::RequestRec} $r - the Apache request
                   3618: # @param {string} $crs - course number
                   3619: # @param {string} $dom - course domain
1.208     www      3620: sub storedata {
                   3621:     my ($r,$crs,$dom)=@_;
1.207     www      3622: # Set userlevel immediately
                   3623: # Do an intermediate store of course level
                   3624:     my $olddata=&readdata($crs,$dom);
1.124     www      3625:     my %newdata=();
                   3626:     undef %newdata;
                   3627:     my @deldata=();
                   3628:     undef @deldata;
1.504     raeburn  3629:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  3630:     my $now = time;
1.560     damieng  3631:     foreach my $key (keys(%env)) {
                   3632:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   3633:             my $cmd=$1;
                   3634:             my $thiskey=$2;
                   3635:             next if ($cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny');
                   3636:             my ($tuname,$tudom)=&extractuser($thiskey);
                   3637:             my $tkey=$thiskey;
1.473     amueller 3638:             if ($tuname) {
1.560     damieng  3639:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   3640:             }
                   3641:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  3642:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   3643:                 if ($cmd eq 'set') {
                   3644:                     $data=$env{$key};
                   3645:                     $valmatch = '';
                   3646:                     $valchk = $data;
                   3647:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3648:                     $text = &mt('Saved modified parameter for');
                   3649:                     if ($typeof eq 'string_questiontype') {
                   3650:                         $name = 'type';
                   3651:                     } elsif ($typeof eq 'string_lenient') {
                   3652:                         $name = 'lenient';
                   3653:                         my $stringmatch = &standard_string_matches($typeof);
                   3654:                         if (ref($stringmatch) eq 'ARRAY') {
                   3655:                             foreach my $item (@{$stringmatch}) {
                   3656:                                 if (ref($item) eq 'ARRAY') {
                   3657:                                     my ($regexpname,$pattern) = @{$item};
                   3658:                                     if ($pattern ne '') {
                   3659:                                         if ($data =~ /$pattern/) {
                   3660:                                             $valmatch = $regexpname;
                   3661:                                             $valchk = '';
                   3662:                                             last;
                   3663:                                         }
1.560     damieng  3664:                                     }
1.549     raeburn  3665:                                 }
                   3666:                             }
                   3667:                         }
1.563     damieng  3668:                     } elsif ($typeof eq 'string_discussvote') {
                   3669:                         $name = 'discussvote';
                   3670:                     } elsif ($typeof eq 'string_examcode') {
                   3671:                         $name = 'examcode';
                   3672:                         if (&Apache::lonnet::validCODE($data)) {
                   3673:                             $valchk = 'valid';
                   3674:                         }
                   3675:                     } elsif ($typeof eq 'string_yesno') {
                   3676:                         if ($thiskey =~ /\.retrypartial$/) {
                   3677:                             $name = 'retrypartial';
                   3678:                         }
1.549     raeburn  3679:                     }
1.563     damieng  3680:                 } elsif ($cmd eq 'datepointer') {
                   3681:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   3682:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3683:                     $text = &mt('Saved modified date for');
                   3684:                     if ($typeof eq 'date_start') {
                   3685:                         if ($thiskey =~ /\.printstartdate$/) {
                   3686:                             $name = 'printstartdate';
                   3687:                             if (($data) && ($data > $now)) {
                   3688:                                 $valchk = 'future';
                   3689:                             }
1.560     damieng  3690:                         }
1.563     damieng  3691:                     } elsif ($typeof eq 'date_end') {
                   3692:                         if ($thiskey =~ /\.printenddate$/) {
                   3693:                             $name = 'printenddate';
                   3694:                             if (($data) && ($data < $now)) {
                   3695:                                 $valchk = 'past';
                   3696:                             }
1.560     damieng  3697:                         }
1.504     raeburn  3698:                     }
1.563     damieng  3699:                 } elsif ($cmd eq 'dateinterval') {
                   3700:                     $data=&get_date_interval_from_form($thiskey);
                   3701:                     if ($thiskey =~ /\.interval$/) {
                   3702:                         $name = 'interval';
                   3703:                         my $intervaltype = &get_intervaltype($name);
                   3704:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   3705:                         if (ref($intervalmatch) eq 'ARRAY') {
                   3706:                             foreach my $item (@{$intervalmatch}) {
                   3707:                                 if (ref($item) eq 'ARRAY') {
                   3708:                                     my ($regexpname,$pattern) = @{$item};
                   3709:                                     if ($pattern ne '') {
                   3710:                                         if ($data =~ /$pattern/) {
                   3711:                                             $valmatch = $regexpname;
                   3712:                                             $valchk = '';
                   3713:                                             last;
                   3714:                                         }
1.560     damieng  3715:                                     }
1.554     raeburn  3716:                                 }
                   3717:                             }
                   3718:                         }
                   3719:                     }
1.563     damieng  3720:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3721:                     $text = &mt('Saved modified date for');
1.554     raeburn  3722:                 }
1.563     damieng  3723:                 if ($thiskey =~ m{\.(?:sequence|page)___\(rec\)}) {
                   3724:                     $namematch = 'maplevelrecurse';
1.560     damieng  3725:                 }
1.563     damieng  3726:                 if (($name ne '') || ($namematch ne '')) {
                   3727:                     my ($needsrelease,$needsnewer);
                   3728:                     if ($name ne '') {
                   3729:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  3730:                         if ($needsrelease) {
                   3731:                             unless ($got_chostname) {
1.563     damieng  3732:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  3733:                                 $got_chostname = 1;
                   3734:                             }
1.563     damieng  3735:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   3736:                                                                 $needsrelease,
                   3737:                                                                 $cmajor,$cminor);
                   3738:                         }
                   3739:                     }
                   3740:                     if ($namematch ne '') {
                   3741:                         if ($needsnewer) {
                   3742:                             undef($namematch);
1.560     damieng  3743:                         } else {
1.563     damieng  3744:                             my $currneeded;
                   3745:                             if ($needsrelease) {
                   3746:                                 $currneeded = $needsrelease;
                   3747:                             }
                   3748:                             $needsrelease =
                   3749:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3750:                             if (($needsrelease) &&
                   3751:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3752:                                 unless ($got_chostname) {
                   3753:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3754:                                     $got_chostname = 1;
                   3755:                                 }
                   3756:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   3757:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   3758:                             } else {
                   3759:                                 undef($namematch);
                   3760:                             }
1.560     damieng  3761:                         }
1.557     raeburn  3762:                     }
1.563     damieng  3763:                     if ($needsnewer) {
                   3764:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   3765:                                                             $chostname,$cmajor,
                   3766:                                                             $cminor,$needsrelease));
                   3767:                         next;
                   3768:                     }
1.504     raeburn  3769:                 }
1.563     damieng  3770:                 if (defined($data) and $$olddata{$thiskey} ne $data) {
                   3771:                     if ($tuname) {
                   3772:                         if (&Apache::lonnet::put('resourcedata',{$tkey=>$data,
                   3773:                                             $tkey.'.type' => $typeof},
                   3774:                                     $tudom,$tuname) eq 'ok') {
                   3775:                             &log_parmset({$tkey=>$data,$tkey.'.type' => $typeof},0,$tuname,$tudom);
                   3776:                             $r->print('<br />'.$text.' '.
                   3777:                                 &Apache::loncommon::plainname($tuname,$tudom));
                   3778:                         } else {
                   3779:                             $r->print('<div class="LC_error">'.
                   3780:                                 &mt('Error saving parameters').'</div>');
                   3781:                         }
                   3782:                         &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
1.560     damieng  3783:                     } else {
1.563     damieng  3784:                         $newdata{$thiskey}=$data;
                   3785:                         $newdata{$thiskey.'.type'}=$typeof;
1.560     damieng  3786:                     }
                   3787:                 }
                   3788:             } elsif ($cmd eq 'del') {
                   3789:                 if ($tuname) {
                   3790:                     if (&Apache::lonnet::del('resourcedata',[$tkey],$tudom,$tuname) eq 'ok') {
                   3791:                             &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   3792:                         $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   3793:                     } else {
                   3794:                         $r->print('<div class="LC_error">'.
                   3795:                             &mt('Error deleting parameters').'</div>');
                   3796:                     }
                   3797:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   3798:                 } else {
                   3799:                     push (@deldata,$thiskey,$thiskey.'.type');
                   3800:                 }
1.473     amueller 3801:             }
                   3802:         }
                   3803:     }
1.207     www      3804: # Store all course level
1.144     www      3805:     my $delentries=$#deldata+1;
1.548     raeburn  3806:     my @newdatakeys=keys(%newdata);
1.144     www      3807:     my $putentries=$#newdatakeys+1;
                   3808:     if ($delentries) {
1.560     damieng  3809:         if (&Apache::lonnet::del('resourcedata',\@deldata,$dom,$crs) eq 'ok') {
                   3810:             my %loghash=map { $_ => '' } @deldata;
                   3811:             &log_parmset(\%loghash,1);
                   3812:             $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   3813:         } else {
                   3814:             $r->print('<div class="LC_error">'.
                   3815:                 &mt('Error deleting parameters').'</div>');
                   3816:         }
                   3817:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      3818:     }
                   3819:     if ($putentries) {
1.560     damieng  3820:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   3821:                     &log_parmset(\%newdata,0);
                   3822:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   3823:         } else {
                   3824:             $r->print('<div class="LC_error">'.
                   3825:                 &mt('Error saving parameters').'</div>');
                   3826:         }
                   3827:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      3828:     }
1.208     www      3829: }
1.207     www      3830: 
1.563     damieng  3831: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   3832: #
                   3833: # @param {string} $key - the key
                   3834: # @returns {Array}
1.208     www      3835: sub extractuser {
                   3836:     my $key=shift;
1.350     albertel 3837:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      3838: }
1.206     www      3839: 
1.563     damieng  3840: # Parses a parameter key and returns the components.
                   3841: #
                   3842: # @param {string} $key - 
                   3843: # @param {hash reference} $listdata - 
                   3844: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 3845: sub parse_listdata_key {
                   3846:     my ($key,$listdata) = @_;
                   3847:     # split into student/section affected, and
                   3848:     # the realm (folder/resource part and parameter
1.446     bisitz   3849:     my ($student,$realm) =
1.473     amueller 3850:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 3851:     # if course wide student would be undefined
                   3852:     if (!defined($student)) {
1.560     damieng  3853:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 3854:     }
                   3855:     # strip off the .type if it's not the Question type parameter
                   3856:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  3857:         $realm=~s/\.type//;
1.381     albertel 3858:     }
                   3859:     # split into resource+part and parameter name
1.388     albertel 3860:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   3861:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 3862:     return ($student,$res,$part,$parm);
                   3863: }
                   3864: 
1.563     damieng  3865: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   3866: #
                   3867: # @param {Apache2::RequestRec} $r - the Apache request
                   3868: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   3869: # @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
                   3870: # @param {string} $sortorder - realmstudent|studentrealm
                   3871: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   3872: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  3873: # @param {boolean} $readonly - true if editing not allowed
1.563     damieng  3874: # @returns{integer} - number of $listdata parameters processed
1.208     www      3875: sub listdata {
1.568     raeburn  3876:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552     raeburn  3877:     
1.207     www      3878: # Start list output
1.206     www      3879: 
1.122     www      3880:     my $oldsection='';
                   3881:     my $oldrealm='';
                   3882:     my $oldpart='';
1.123     www      3883:     my $pointer=0;
1.124     www      3884:     $tableopen=0;
1.145     www      3885:     my $foundkeys=0;
1.248     albertel 3886:     my %keyorder=&standardkeyorder();
1.381     albertel 3887: 
1.552     raeburn  3888:     my ($secidx,%grouphash);
                   3889:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3890:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  3891:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3892:             %grouphash = &Apache::longroup::coursegroups();
                   3893:         } elsif ($env{'request.course.groups'} ne '') {
                   3894:             map { $grouphash{$_} = 1; } split(/,/,$env{'request.course.groups'});
                   3895:         }
1.552     raeburn  3896:     }
                   3897: 
1.214     www      3898:     foreach my $thiskey (sort {
1.560     damieng  3899:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   3900:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381     albertel 3901: 
1.560     damieng  3902:         # get the numerical order for the param
                   3903:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   3904:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 3905: 
1.560     damieng  3906:         my $result=0;
1.381     albertel 3907: 
1.560     damieng  3908:         if ($sortorder eq 'realmstudent') {
1.381     albertel 3909:             if ($ares     ne $bres    ) {
1.560     damieng  3910:                 $result = ($ares     cmp $bres);
1.446     bisitz   3911:             } elsif ($astudent ne $bstudent) {
1.560     damieng  3912:                 $result = ($astudent cmp $bstudent);
                   3913:             } elsif ($apart    ne $bpart   ) {
                   3914:                 $result = ($apart    cmp $bpart);
                   3915:             }
                   3916:         } else {
                   3917:             if      ($astudent ne $bstudent) {
                   3918:                 $result = ($astudent cmp $bstudent);
                   3919:             } elsif ($ares     ne $bres    ) {
                   3920:                 $result = ($ares     cmp $bres);
                   3921:             } elsif ($apart    ne $bpart   ) {
                   3922:                 $result = ($apart    cmp $bpart);
                   3923:             }
1.473     amueller 3924:         }
1.446     bisitz   3925: 
1.560     damieng  3926:         if (!$result) {
1.381     albertel 3927:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  3928:                 $result = ($aparm <=> $bparm);
1.381     albertel 3929:             } elsif (defined($aparm)) {
1.560     damieng  3930:                 $result = -1;
1.381     albertel 3931:             } elsif (defined($bparm)) {
1.560     damieng  3932:                 $result = 1;
                   3933:             }
1.473     amueller 3934:         }
1.381     albertel 3935: 
1.560     damieng  3936:         $result;
                   3937:         
                   3938:     } keys(%{$listdata})) { # foreach my $thiskey
1.381     albertel 3939: 
1.560     damieng  3940:         if ($$listdata{$thiskey.'.type'}) {
                   3941:             my $thistype=$$listdata{$thiskey.'.type'};
                   3942:             if ($$resourcedata{$thiskey.'.type'}) {
                   3943:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   3944:             }
                   3945:             my ($middle,$part,$name)=
1.572     damieng  3946:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  3947:             my $section=&mt('All Students');
                   3948:             if ($middle=~/^\[(.*)\]/) {
                   3949:                 my $issection=$1;
                   3950:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   3951:                     my ($stuname,$studom) = ($1,$2);
                   3952:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3953:                         if (ref($classlist) eq 'HASH') {
                   3954:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   3955:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   3956:                             }
                   3957:                         }
                   3958:                     }
                   3959:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
                   3960:                 } else {
                   3961:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3962:                         if (exists($grouphash{$issection})) {
                   3963:                             $section=&mt('Group').': '.$issection;
                   3964:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   3965:                             $section = &mt('Section').': '.$issection;
                   3966:                         } else {
                   3967:                             next; 
1.552     raeburn  3968:                         }
1.560     damieng  3969:                     } else {
                   3970:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  3971:                     }
                   3972:                 }
1.560     damieng  3973:                 $middle=~s/^\[(.*)\]//;
                   3974:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3975:                 $readonly = 1;
                   3976:             }
                   3977:             $middle=~s/\.+$//;
                   3978:             $middle=~s/^\.+//;
                   3979:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
                   3980:             if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   3981:                 my $mapurl = $1;
                   3982:                 my $maplevel = $2;
                   3983:                 my $leveltitle = &mt('Folder/Map');
                   3984:                 if ($maplevel eq 'rec') {
                   3985:                     $leveltitle = &mt('Recursive');
                   3986:                 }
                   3987:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
                   3988:             } elsif ($middle) {
                   3989:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   3990:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   3991:                     ': '.&Apache::lonnet::gettitle($middle).
                   3992:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   3993:                     $id.')</span></span>';
                   3994:             }
                   3995:             if ($sortorder eq 'realmstudent') {
                   3996:                 if ($realm ne $oldrealm) {
                   3997:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   3998:                     $oldrealm=$realm;
                   3999:                     $oldsection='';
                   4000:                 }
                   4001:                 if ($section ne $oldsection) {
                   4002:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4003:                     $oldsection=$section;
                   4004:                     $oldpart='';
                   4005:                 }
1.552     raeburn  4006:             } else {
1.560     damieng  4007:                 if ($section ne $oldsection) {
                   4008:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4009:                     $oldsection=$section;
                   4010:                     $oldrealm='';
                   4011:                 }
                   4012:                 if ($realm ne $oldrealm) {
                   4013:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4014:                     $oldrealm=$realm;
                   4015:                     $oldpart='';
1.552     raeburn  4016:                 }
                   4017:             }
1.560     damieng  4018:             if ($part ne $oldpart) {
                   4019:                 $r->print(&tableend().
                   4020:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4021:                 $oldpart=$part;
1.556     raeburn  4022:             }
1.560     damieng  4023:     #
                   4024:     # Ready to print
                   4025:     #
1.470     raeburn  4026:             my $parmitem = &standard_parameter_names($name);
1.560     damieng  4027:             $r->print(&tablestart($readonly).
                   4028:                 &Apache::loncommon::start_data_table_row().
                   4029:                 '<td><b>'.&mt($parmitem).
                   4030:                 '</b></td>');
                   4031:             unless ($readonly) {
                   4032:                 $r->print('<td><input type="checkbox" name="del_'.
                   4033:                         $thiskey.'" /></td>');
                   4034:             }
                   4035:             $r->print('<td>');
                   4036:             $foundkeys++;
                   4037:             if (&isdateparm($thistype)) {
                   4038:                 my $jskey='key_'.$pointer;
                   4039:                 my $state;
                   4040:                 $pointer++;
                   4041:                 if ($readonly) {
                   4042:                     $state = 'disabled';
                   4043:                 }
                   4044:                 $r->print(
                   4045:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4046:                                                         $jskey,
                   4047:                                                         $$resourcedata{$thiskey},
                   4048:                                                         '',1,$state));
                   4049:                 unless  ($readonly) {
                   4050:                     $r->print(
                   4051:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
                   4052:     (($$resourcedata{$thiskey}!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$$resourcedata{$thiskey}.'">'.
                   4053:     &mt('Shift all dates based on this date').'</a></span>':'').
                   4054:     &date_sanity_info($$resourcedata{$thiskey})
                   4055:                     );
                   4056:                 }
                   4057:             } elsif ($thistype eq 'date_interval') {
                   4058:                 $r->print(&date_interval_selector($thiskey,$name,
                   4059:                         $$resourcedata{$thiskey},$readonly));
                   4060:             } elsif ($thistype =~ m/^string/) {
                   4061:                 $r->print(&string_selector($thistype,$thiskey,
                   4062:                         $$resourcedata{$thiskey},$name,$readonly));
                   4063:             } else {
                   4064:                 $r->print(&default_selector($thiskey,$$resourcedata{$thiskey},$readonly));
1.552     raeburn  4065:             }
1.560     damieng  4066:             unless ($readonly) {
                   4067:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   4068:                         $thistype.'" />');
1.552     raeburn  4069:             }
1.560     damieng  4070:             $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.473     amueller 4071:         }
1.121     www      4072:     }
1.208     www      4073:     return $foundkeys;
                   4074: }
                   4075: 
1.563     damieng  4076: # Returns a string representing the interval, directly using form data matching the given key.
                   4077: # The returned string may also include information related to proctored exams.
                   4078: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   4079: #
                   4080: # @param {string} $key - suffix for form fields related to the interval
                   4081: # @returns {string}
1.385     albertel 4082: sub get_date_interval_from_form {
                   4083:     my ($key) = @_;
                   4084:     my $seconds = 0;
                   4085:     foreach my $which (['days', 86400],
1.473     amueller 4086:                ['hours', 3600],
                   4087:                ['minutes', 60],
                   4088:                ['seconds',  1]) {
1.560     damieng  4089:         my ($name, $factor) = @{ $which };
                   4090:         if (defined($env{'form.'.$name.'_'.$key})) {
                   4091:             $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   4092:         }
1.473     amueller 4093:     }
1.560     damieng  4094:     if (($key =~ /\.interval$/) &&
                   4095:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  4096:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   4097:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   4098:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   4099:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   4100:                 $seconds .= '_proctor';
                   4101:             }
                   4102:         } else {
                   4103:             $seconds .= $env{'form.done_'.$key}; 
                   4104:         }
                   4105:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  4106:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  4107:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   4108:         }
1.554     raeburn  4109:     }
1.385     albertel 4110:     return $seconds;
                   4111: }
                   4112: 
                   4113: 
1.563     damieng  4114: # Returns HTML to enter a text value for a parameter.
                   4115: #
                   4116: # @param {string} $thiskey - parameter key
                   4117: # @param {string} $showval - the current value
                   4118: # @param {boolean} $readonly - true if the field should not be made editable
                   4119: # @returns {string}
1.383     albertel 4120: sub default_selector {
1.552     raeburn  4121:     my ($thiskey, $showval, $readonly) = @_;
                   4122:     my $disabled;
                   4123:     if ($readonly) {
                   4124:         $disabled = ' disabled="disabled"';
                   4125:     }
                   4126:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 4127: }
                   4128: 
1.563     damieng  4129: # Returns HTML to enter allow/deny rules related to IP addresses.
                   4130: #
                   4131: # @param {string} $thiskey - parameter key
                   4132: # @param {string} $showval - the current value
                   4133: # @param {boolean} $readonly - true if the fields should not be made editable
                   4134: # @returns {string}
1.549     raeburn  4135: sub string_ip_selector {
1.552     raeburn  4136:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  4137:     my %access = (
                   4138:                    allow => [],
                   4139:                    deny  => [],
                   4140:                  );
                   4141:     if ($showval ne '') {
                   4142:         my @current;
                   4143:         if ($showval =~ /,/) {
                   4144:             @current = split(/,/,$showval);
                   4145:         } else {
                   4146:             @current = ($showval);
                   4147:         }
                   4148:         foreach my $item (@current) {
                   4149:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4150:                 push(@{$access{'deny'}},$1);
                   4151:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4152:                 push(@{$access{'allow'}},$item);
                   4153:             }
                   4154:         }
                   4155:     }
                   4156:     if (!@{$access{'allow'}}) {
                   4157:         @{$access{'allow'}} = ('');
                   4158:     }
                   4159:     if (!@{$access{'deny'}}) {
                   4160:         @{$access{'deny'}} = ('');
                   4161:     }
1.552     raeburn  4162:     my ($disabled,$addmore);
1.567     raeburn  4163:     if ($readonly) {
1.552     raeburn  4164:         $disabled=' disabled="disabled"';
                   4165:     } else {
                   4166:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   4167:     }
1.549     raeburn  4168:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   4169: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   4170:     foreach my $acctype ('allow','deny') {
                   4171:         $output .= '
                   4172: <td valign="top">
                   4173: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   4174:   <div class="LC_string_ipacc_inner">'."\n";
                   4175:         my $num = 0;
                   4176:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  4177:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  4178:             if ($num > 0) {
                   4179:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   4180:             }
                   4181:             $output .= '</div>'."\n";
                   4182:             $num ++;
                   4183:         }
                   4184:         $output .= '
1.552     raeburn  4185:   </div>'.$addmore.'
1.549     raeburn  4186: </div>
                   4187: </td>';
                   4188:    }
                   4189:    $output .= '
                   4190: </tr>
                   4191: </table>'."\n";
                   4192:     return $output;
                   4193: }
                   4194: 
1.560     damieng  4195: 
                   4196: { # block using some constants related to parameter types (overview mode)
                   4197: 
1.446     bisitz   4198: my %strings =
1.383     albertel 4199:     (
                   4200:      'string_yesno'
                   4201:              => [[ 'yes', 'Yes' ],
1.560     damieng  4202:                  [ 'no', 'No' ]],
1.383     albertel 4203:      'string_problemstatus'
                   4204:              => [[ 'yes', 'Yes' ],
1.473     amueller 4205:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   4206:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   4207:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  4208:      'string_questiontype'
                   4209:              => [[ 'problem', 'Standard Problem'],
                   4210:                  [ 'survey', 'Survey'],
                   4211:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   4212:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  4213:                  [ 'anonsurvey', 'Anonymous Survey'],
                   4214:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   4215:                  [ 'practice', 'Practice'],
                   4216:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  4217:      'string_lenient'
                   4218:              => [['yes', 'Yes' ],
                   4219:                  [ 'no', 'No' ],
1.549     raeburn  4220:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   4221:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  4222:      'string_discussvote'
                   4223:              => [['yes','Yes'],
                   4224:                  ['notended','Yes, unless discussion ended'],
                   4225:                  ['no','No']],
1.549     raeburn  4226:      'string_ip'
                   4227:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
                   4228:                  ['_denyfrom_',], 'Hostname(s) or IP(s) from which access is disallowed'], 
1.383     albertel 4229:      );
                   4230: 
1.549     raeburn  4231: my %stringmatches = (
                   4232:          'string_lenient'
                   4233:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   4234:          'string_ip'
                   4235:               => [['_allowfrom_','[^\!]+'],
                   4236:                   ['_denyfrom_','\!']],
                   4237:     );
                   4238: 
                   4239: my %stringtypes = (
                   4240:                     type         => 'string_questiontype',
                   4241:                     lenient      => 'string_lenient',
                   4242:                     retrypartial => 'string_yesno',
                   4243:                     discussvote  => 'string_discussvote',
                   4244:                     examcode     => 'string_examcode',
                   4245:                     acc          => 'string_ip',
                   4246:                   );
                   4247: 
1.563     damieng  4248: # Returns the possible values and titles for a given string type, or undef if there are none.
                   4249: # Used by courseprefs.
                   4250: #
                   4251: # @param {string} $string_type - a parameter type for strings
                   4252: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  4253: sub standard_string_options {
                   4254:     my ($string_type) = @_;
                   4255:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   4256:         return $strings{$string_type};
                   4257:     }
                   4258:     return;
                   4259: }
1.383     albertel 4260: 
1.563     damieng  4261: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   4262: #
                   4263: # @param {string} $string_type - a parameter type for strings
                   4264: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  4265: sub standard_string_matches {
                   4266:     my ($string_type) = @_;
                   4267:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   4268:         return $stringmatches{$string_type};
                   4269:     }
                   4270:     return;
                   4271: }
                   4272: 
1.563     damieng  4273: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   4274: #
                   4275: # @param {string} $name - parameter name
                   4276: # @returns {string}
1.549     raeburn  4277: sub get_stringtype {
                   4278:     my ($name) = @_;
                   4279:     if (exists($stringtypes{$name})) {
                   4280:         return $stringtypes{$name};
                   4281:     }
                   4282:     return;
                   4283: }
                   4284: 
1.563     damieng  4285: # Returns HTML to edit a string parameter.
                   4286: #
                   4287: # @param {string} $thistype - parameter type
                   4288: # @param {string} $thiskey - parameter key
                   4289: # @param {string} $showval - parameter current value
                   4290: # @param {string} $name - parameter name
                   4291: # @param {boolean} $readonly - true if the values should not be made editable
                   4292: # @returns {string}
1.383     albertel 4293: sub string_selector {
1.552     raeburn  4294:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   4295: 
1.383     albertel 4296:     if (!exists($strings{$thistype})) {
1.552     raeburn  4297:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 4298:     }
                   4299: 
1.504     raeburn  4300:     my %skiptype;
1.514     raeburn  4301:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  4302:             ($thistype eq 'string_lenient') ||
                   4303:             ($thistype eq 'string_discussvote') ||
                   4304:             ($thistype eq 'string_ip') ||
                   4305:             ($name eq 'retrypartial')) {
1.504     raeburn  4306:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   4307:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   4308:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  4309:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  4310:             my $parmmatch;
                   4311:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   4312:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   4313:                     if (ref($item) eq 'ARRAY') {
                   4314:                         if ($parmval eq $item->[0]) {
                   4315:                             $parmmatch = $parmval;
                   4316:                             $parmval = '';
                   4317:                             last;
                   4318:                         }
                   4319:                     }
                   4320:                 }
                   4321:             }
                   4322:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  4323:             if ($needsrelease) {
                   4324:                 unless ($got_chostname) {
1.514     raeburn  4325:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  4326:                     $got_chostname = 1;
                   4327:                 }
1.557     raeburn  4328:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  4329:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  4330:                 if ($needsnewer) {
1.549     raeburn  4331:                     if ($parmmatch ne '') {
                   4332:                         $skiptype{$parmmatch} = 1;
                   4333:                     } elsif ($parmval ne '') {
                   4334:                         $skiptype{$parmval} = 1;
                   4335:                     }
1.504     raeburn  4336:                 }
                   4337:             }
                   4338:         }
                   4339:     }
1.549     raeburn  4340: 
                   4341:     if ($thistype eq 'string_ip') {
1.552     raeburn  4342:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.549     raeburn  4343:     }
1.504     raeburn  4344: 
1.552     raeburn  4345:     my ($result,$disabled);
                   4346: 
                   4347:     if ($readonly) {
                   4348:         $disabled = ' disabled="disabled"';
                   4349:     }
1.504     raeburn  4350:     my $numinrow = 3;
                   4351:     if ($thistype eq 'string_problemstatus') {
                   4352:         $numinrow = 2;
                   4353:     } elsif ($thistype eq 'string_questiontype') {
                   4354:         if (keys(%skiptype) > 0) {
                   4355:              $numinrow = 4;
                   4356:         }
                   4357:     }
                   4358:     my $rem;
                   4359:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   4360:         my $i=0;
                   4361:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   4362:             next unless (ref($possibilities) eq 'ARRAY');
                   4363:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  4364:             next if ($skiptype{$name});
1.504     raeburn  4365:             $rem = $i%($numinrow);
                   4366:             if ($rem == 0) {
                   4367:                 if ($i > 0) {
                   4368:                     $result .= '</tr>';
                   4369:                 }
                   4370:                 $result .= '<tr>';
                   4371:             }
1.549     raeburn  4372:             my $colspan;
                   4373:             if ($i == @{ $strings{$thistype} }-1) {
                   4374:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   4375:                 if ($rem) {
                   4376:                     my $colsleft = $numinrow - $rem;
                   4377:                     if ($colsleft) {
                   4378:                         $colspan = $colsleft+1;
                   4379:                         $colspan = ' colspan="'.$colspan.'"';
                   4380:                     }
                   4381:                 }
                   4382:             }
                   4383:             my ($add,$onchange,$css_class);
                   4384:             if ($thistype eq 'string_lenient') {
                   4385:                 if ($name eq 'weighted') {
                   4386:                     my $display;
                   4387:                     my %relatives = &Apache::lonlocal::texthash(
                   4388:                                         corrchkd     => 'Correct (checked)',
                   4389:                                         corrunchkd   => 'Correct (unchecked)',
                   4390:                                         incorrchkd   => 'Incorrect (checked)',
                   4391:                                         incorrunchkd => 'Incorrect (unchecked)',
                   4392:                     );
                   4393:                     my %textval = (
                   4394:                                     corrchkd     => '1.0',
                   4395:                                     corrunchkd   => '1.0',
                   4396:                                     incorrchkd   => '0.0',
                   4397:                                     incorrunchkd => '0.0',
                   4398:                     );
                   4399:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   4400:                         $textval{'corrchkd'} = $1;
                   4401:                         $textval{'corrunchkd'} = $2;
                   4402:                         $textval{'incorrchkd'} = $3;
                   4403:                         $textval{'incorrunchkd'} = $4;
                   4404:                         $display = 'inline';
                   4405:                         $showval = $name;
                   4406:                     } else {
                   4407:                         $display = 'none';
                   4408:                     }
                   4409:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   4410:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   4411:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   4412:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   4413:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  4414:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  4415:                                 '</td></tr>';
                   4416:                     }
                   4417:                     $add .= '</table></div>'."\n";
                   4418:                 }
                   4419:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   4420:                 $css_class = ' class="LC_lenient_radio"';
                   4421:             }
                   4422:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  4423:                        '<span class="LC_nobreak"><label>'.
                   4424:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  4425:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  4426:             if ($showval eq $name) {
                   4427:                 $result .= ' checked="checked"';
                   4428:             }
1.549     raeburn  4429:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  4430:             $i++;
                   4431:         }
                   4432:         $result .= '</tr>';
1.473     amueller 4433:     }
1.504     raeburn  4434:     if ($result) {
                   4435:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 4436:     }
                   4437:     return $result;
                   4438: }
                   4439: 
1.554     raeburn  4440: my %intervals =
                   4441:     (
                   4442:      'date_interval'
                   4443:              => [[ 'done', 'Yes' ],
1.558     raeburn  4444:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  4445:                  [ '', 'No' ]],
                   4446:     );
                   4447: 
                   4448: my %intervalmatches = (
                   4449:          'date_interval'
1.559     raeburn  4450:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   4451:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  4452:     );
                   4453: 
                   4454: my %intervaltypes = (
                   4455:                       interval => 'date_interval',
                   4456:     );
                   4457: 
1.563     damieng  4458: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   4459: #
                   4460: # @param {string} $interval_type - a parameter type for intervals
                   4461: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  4462: sub standard_interval_matches {
                   4463:     my ($interval_type) = @_;
                   4464:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   4465:         return $intervalmatches{$interval_type};
                   4466:     }
                   4467:     return;
                   4468: }
                   4469: 
1.563     damieng  4470: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   4471: #
                   4472: # @param {string} $name - parameter name
                   4473: # @returns {string}
1.554     raeburn  4474: sub get_intervaltype {
                   4475:     my ($name) = @_;
                   4476:     if (exists($intervaltypes{$name})) {
                   4477:         return $intervaltypes{$name};
                   4478:     }
                   4479:     return;
                   4480: }
                   4481: 
1.563     damieng  4482: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   4483: # Used by courseprefs.
                   4484: #
                   4485: # @param {string} $interval_type - a parameter type for intervals
                   4486: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  4487: sub standard_interval_options {
                   4488:     my ($interval_type) = @_;
                   4489:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   4490:         return $intervals{$interval_type};
                   4491:     }
                   4492:     return;
                   4493: }
                   4494: 
1.563     damieng  4495: # Returns HTML to edit a date interval parameter.
                   4496: #
                   4497: # @param {string} $thiskey - parameter key
                   4498: # @param {string} $name - parameter name
                   4499: # @param {string} $showval - parameter current value
                   4500: # @param {boolean} $readonly - true if the values should not be made editable
                   4501: # @returns {string}
1.554     raeburn  4502: sub date_interval_selector {
                   4503:     my ($thiskey, $name, $showval, $readonly) = @_;
                   4504:     my ($result,%skipval);
                   4505:     if ($name eq 'interval') {
                   4506:         my $intervaltype = &get_intervaltype($name);
                   4507:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   4508:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   4509:             next unless (ref($possibilities) eq 'ARRAY');
                   4510:             my ($parmval, $description) = @{ $possibilities };
                   4511:             my $parmmatch;
                   4512:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   4513:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   4514:                     if (ref($item) eq 'ARRAY') {
                   4515:                         if ($parmval eq $item->[0]) {
                   4516:                             $parmmatch = $parmval;
                   4517:                             $parmval = '';
                   4518:                             last;
                   4519:                         }
                   4520:                     }
                   4521:                 }
                   4522:             }
                   4523:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   4524:             if ($needsrelease) {
                   4525:                 unless ($got_chostname) {
                   4526:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   4527:                     $got_chostname = 1;
                   4528:                 }
1.557     raeburn  4529:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  4530:                                                        $needsrelease,$cmajor,$cminor);
                   4531:                 if ($needsnewer) {
                   4532:                     if ($parmmatch ne '') {
                   4533:                         $skipval{$parmmatch} = 1;
                   4534:                     } elsif ($parmval ne '') {
                   4535:                         $skipval{$parmval} = 1;
                   4536:                     }
                   4537:                 }
                   4538:             }
                   4539:         }
                   4540:     }
                   4541: 
                   4542:     my $currval = $showval;
                   4543:     foreach my $which (['days', 86400, 31],
                   4544:                ['hours', 3600, 23],
                   4545:                ['minutes', 60, 59],
                   4546:                ['seconds',  1, 59]) {
1.560     damieng  4547:         my ($name, $factor, $max) = @{ $which };
                   4548:         my $amount = int($showval/$factor);
                   4549:         $showval  %= $factor;
                   4550:         my %select = ((map {$_ => $_} (0..$max)),
                   4551:                 'select_form_order' => [0..$max]);
                   4552:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   4553:                             \%select,'',$readonly);
                   4554:         $result .= ' '.&mt($name);
1.554     raeburn  4555:     }
                   4556:     if ($name eq 'interval') {
                   4557:         unless ($skipval{'done'}) {
                   4558:             my $checkedon = '';
1.558     raeburn  4559:             my $checkedproc = '';
                   4560:             my $currproctorkey = '';
                   4561:             my $currprocdisplay = 'hidden';
1.559     raeburn  4562:             my $currdonetext = &mt('Done');
1.554     raeburn  4563:             my $checkedoff = ' checked="checked"';
1.559     raeburn  4564:             if ($currval =~ /^(?:\d+)_done$/) {
                   4565:                 $checkedon = ' checked="checked"';
                   4566:                 $checkedoff = '';
                   4567:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   4568:                 $currdonetext = $1;
1.554     raeburn  4569:                 $checkedon = ' checked="checked"';
                   4570:                 $checkedoff = '';
1.558     raeburn  4571:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   4572:                 $currproctorkey = $1;
                   4573:                 $checkedproc = ' checked="checked"';
                   4574:                 $checkedoff = '';
                   4575:                 $currprocdisplay = 'text';
1.559     raeburn  4576:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   4577:                 $currdonetext = $1;
                   4578:                 $currproctorkey = $2;
                   4579:                 $checkedproc = ' checked="checked"';
                   4580:                 $checkedoff = '';
                   4581:                 $currprocdisplay = 'text';
1.554     raeburn  4582:             }
1.558     raeburn  4583:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  4584:             my $disabled;
                   4585:             if ($readonly) {
                   4586:                 $disabled = ' disabled="disabled"';
                   4587:             }
1.558     raeburn  4588:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  4589:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  4590:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  4591:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  4592:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  4593:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  4594:                        &mt('Yes, with proctor key').'</label>'.
                   4595:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  4596:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  4597:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567     raeburn  4598:                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  4599:         }
                   4600:     }
                   4601:     unless ($readonly) {
                   4602:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   4603:     }
                   4604:     return $result;
                   4605: }
                   4606: 
1.563     damieng  4607: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   4608: #
                   4609: # @param {string} $name - parameter name
                   4610: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   4611: # @param {string} $value - parameter value
                   4612: # @param {string} $chostname - course server name
                   4613: # @param {integer} $cmajor - major version number
                   4614: # @param {integer} $cminor - minor version number
                   4615: # @param {string} $needsrelease - release version needed (major.minor)
                   4616: # @returns {string}
1.549     raeburn  4617: sub oldversion_warning {
1.557     raeburn  4618:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   4619:     my $standard_name = &standard_parameter_names($name);
                   4620:     if ($namematch) {
                   4621:         my $level = &standard_parameter_levels($namematch);
                   4622:         my $msg = '';
                   4623:         if ($level) {
                   4624:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   4625:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   4626:         } else {
                   4627:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   4628:                       $standard_name,'<b>','</b>');
                   4629:         }
                   4630:         return '<p class="LC_warning">'.$msg.'<br />'.
                   4631:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   4632:                    $cmajor.'.'.$cminor,$chostname,
                   4633:                    $needsrelease).
                   4634:                    '</p>';
                   4635:     }
1.549     raeburn  4636:     my $desc;
                   4637:     my $stringtype = &get_stringtype($name);
                   4638:     if ($stringtype ne '') {
                   4639:         if ($name eq 'examcode') {
                   4640:             $desc = $value;
                   4641:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   4642:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   4643:                 next unless (ref($possibilities) eq 'ARRAY');
                   4644:                 my ($parmval, $description) = @{ $possibilities };
                   4645:                 my $parmmatch;
                   4646:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   4647:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   4648:                         if (ref($item) eq 'ARRAY') {
                   4649:                             my ($regexpname,$pattern) = @{$item};
                   4650:                             if ($parmval eq $regexpname) {
                   4651:                                 if ($value =~ /$pattern/) {
                   4652:                                     $desc = $description; 
                   4653:                                     $parmmatch = 1;
                   4654:                                     last;
                   4655:                                 }
                   4656:                             }
                   4657:                         }
                   4658:                     }
                   4659:                     last if ($parmmatch);
                   4660:                 } elsif ($parmval eq $value) {
                   4661:                     $desc = $description;
                   4662:                     last;
                   4663:                 }
                   4664:             }
                   4665:         }
                   4666:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   4667:         my $now = time;
                   4668:         if ($value =~ /^\d+$/) {
                   4669:             if ($name eq 'printstartdate') {
                   4670:                 if ($value > $now) {
                   4671:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   4672:                 }
                   4673:             } elsif ($name eq 'printenddate') {
                   4674:                 if ($value < $now) {
                   4675:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   4676:                 }
                   4677:             }
                   4678:         }
                   4679:     }
                   4680:     return '<p class="LC_warning">'.
1.557     raeburn  4681:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   4682:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   4683:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   4684:        $cmajor.'.'.$cminor,$chostname,
                   4685:        $needsrelease).
                   4686:        '</p>';
1.549     raeburn  4687: }
                   4688: 
1.560     damieng  4689: } # end of block using some constants related to parameter types
                   4690: 
1.549     raeburn  4691: 
1.563     damieng  4692: 
                   4693: # Shifts all start and end dates in the current course by $shift.
1.389     www      4694: #
1.563     damieng  4695: # @param {integer} $shift - time to shift, in seconds
                   4696: # @returns {string} - error name or 'ok'
1.389     www      4697: sub dateshift {
                   4698:     my ($shift)=@_;
                   4699:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   4700:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   4701:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   4702: # ugly retro fix for broken version of types
1.548     raeburn  4703:     foreach my $key (keys(%data)) {
1.389     www      4704:         if ($key=~/\wtype$/) {
                   4705:             my $newkey=$key;
                   4706:             $newkey=~s/type$/\.type/;
                   4707:             $data{$newkey}=$data{$key};
                   4708:             delete $data{$key};
                   4709:         }
                   4710:     }
1.391     www      4711:     my %storecontent=();
1.389     www      4712: # go through all parameters and look for dates
1.548     raeburn  4713:     foreach my $key (keys(%data)) {
1.389     www      4714:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
                   4715:           my $newdate=$data{$key}+$shift;
1.391     www      4716:           $storecontent{$key}=$newdate;
1.389     www      4717:        }
                   4718:     }
1.391     www      4719:     my $reply=&Apache::lonnet::cput
                   4720:                 ('resourcedata',\%storecontent,$dom,$crs);
                   4721:     if ($reply eq 'ok') {
                   4722:        &log_parmset(\%storecontent);
                   4723:     }
                   4724:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   4725:     return $reply;
1.389     www      4726: }
                   4727: 
1.563     damieng  4728: # Overview mode UI to edit course parameters.
                   4729: #
                   4730: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      4731: sub newoverview {
1.568     raeburn  4732:     my ($r,$parm_permission) = @_;
1.280     albertel 4733: 
1.208     www      4734:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   4735:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  4736:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  4737:     my $readonly = 1;
                   4738:     if ($parm_permission->{'edit'}) {
                   4739:         undef($readonly);
                   4740:     }
1.414     droeschl 4741:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 4742:         text=>"Overview Mode"});
1.523     raeburn  4743: 
                   4744:     my %loaditems = (
1.549     raeburn  4745:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  4746:                     );
                   4747:     my $js = '
                   4748: <script type="text/javascript">
                   4749: // <![CDATA[
                   4750: '.
                   4751:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   4752:             &showhide_js()."\n".
1.549     raeburn  4753:             &toggleparmtextbox_js()."\n".
                   4754:             &validateparms_js()."\n".
                   4755:             &ipacc_boxes_js()."\n".
1.558     raeburn  4756:             &done_proctor_js()."\n".
1.523     raeburn  4757: '// ]]>
                   4758: </script>
                   4759: ';
1.549     raeburn  4760: 
1.523     raeburn  4761:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   4762:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 4763:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      4764:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  4765:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      4766:     $r->print(<<ENDOVER);
1.549     raeburn  4767: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      4768: ENDOVER
1.211     www      4769:     my @ids=();
                   4770:     my %typep=();
                   4771:     my %keyp=();
                   4772:     my %allparms=();
                   4773:     my %allparts=();
                   4774:     my %allmaps=();
                   4775:     my %mapp=();
                   4776:     my %symbp=();
                   4777:     my %maptitles=();
                   4778:     my %uris=();
                   4779:     my %keyorder=&standardkeyorder();
                   4780:     my %defkeytype=();
                   4781: 
                   4782:     my %alllevs=();
                   4783:     $alllevs{'Resource Level'}='full';
1.215     www      4784:     $alllevs{'Map/Folder Level'}='map';
1.211     www      4785:     $alllevs{'Course Level'}='general';
                   4786: 
                   4787:     my $csec=$env{'form.csec'};
1.269     raeburn  4788:     my $cgroup=$env{'form.cgroup'};
1.211     www      4789: 
                   4790:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   4791:     my $pschp=$env{'form.pschp'};
1.506     www      4792: 
1.211     www      4793:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      4794:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      4795: 
1.446     bisitz   4796:     my @selected_sections =
1.473     amueller 4797:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      4798:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 4799:     foreach my $sec (@selected_sections) {
                   4800:         if ($sec eq 'all') {
1.211     www      4801:             @selected_sections = ('all');
                   4802:         }
                   4803:     }
1.552     raeburn  4804:     if ($env{'request.course.sec'} ne '') {
                   4805:         @selected_sections = ($env{'request.course.sec'});
                   4806:     }
1.269     raeburn  4807:     my @selected_groups =
                   4808:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      4809: 
                   4810:     my $pssymb='';
                   4811:     my $parmlev='';
1.446     bisitz   4812: 
1.211     www      4813:     unless ($env{'form.parmlev'}) {
                   4814:         $parmlev = 'map';
                   4815:     } else {
                   4816:         $parmlev = $env{'form.parmlev'};
                   4817:     }
                   4818: 
1.446     bisitz   4819:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 4820:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   4821:                 \%keyorder,\%defkeytype);
1.211     www      4822: 
1.374     albertel 4823:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 4824:         @psprt = keys(%allparts);
1.374     albertel 4825:     }
1.211     www      4826: # Menu to select levels, etc
                   4827: 
1.456     bisitz   4828:     $r->print('<div class="LC_Box">');
1.445     neumanie 4829:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   4830:     $r->print('<div>');
1.523     raeburn  4831:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      4832:     &levelmenu($r,\%alllevs,$parmlev);
                   4833:     if ($parmlev ne 'general') {
1.447     bisitz   4834:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.483     amueller 4835:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211     www      4836:     }
1.447     bisitz   4837:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 4838:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   4839:     $r->print('</div></div>');
1.446     bisitz   4840: 
1.456     bisitz   4841:     $r->print('<div class="LC_Box">');
1.452     bisitz   4842:     $r->print('<div>');
1.562     damieng  4843:     &displaymenu($r,\%allparms,\@pscat,\%keyorder); # FIXME: wrong parameters, could make keysindisplayorderCategory crash because $keyorder is undefined
1.453     schualex 4844:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   4845:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  4846:     my $sectionselector = &sectionmenu(\@selected_sections);
                   4847:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 4848:     $r->print('<table>'.
1.553     raeburn  4849:               '<tr><th>'.&mt('Parts').'</th>');
                   4850:     if ($sectionselector) {
                   4851:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   4852:     }
                   4853:     if ($groupselector) {
                   4854:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   4855:     }
                   4856:     $r->print('</tr><tr><td>');
1.211     www      4857:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  4858:     $r->print('</td>');
                   4859:     if ($sectionselector) { 
                   4860:         $r->print('<td>'.$sectionselector.'</td>');
                   4861:     }
                   4862:     if ($groupselector) {
                   4863:         $r->print('<td>'.$groupselector.'</td>');
                   4864:     }
                   4865:     $r->print('</tr></table>');
1.447     bisitz   4866:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 4867:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   4868:     $r->print('</div></div>');
                   4869: 
1.456     bisitz   4870:     $r->print('<div class="LC_Box">');
1.452     bisitz   4871:     $r->print('<div>');
1.214     www      4872:     my $sortorder=$env{'form.sortorder'};
                   4873:     unless ($sortorder) { $sortorder='realmstudent'; }
                   4874:     &sortmenu($r,$sortorder);
1.445     neumanie 4875:     $r->print('</div></div>');
1.446     bisitz   4876: 
1.214     www      4877:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   4878: 
1.211     www      4879: # Build the list data hash from the specified parms
                   4880: 
                   4881:     my $listdata;
                   4882:     %{$listdata}=();
                   4883: 
                   4884:     foreach my $cat (@pscat) {
1.269     raeburn  4885:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   4886:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      4887:     }
                   4888: 
1.212     www      4889:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      4890: 
1.481     amueller 4891:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      4892: 
                   4893: # Read modified data
                   4894: 
1.481     amueller 4895:         my $resourcedata=&readdata($crs,$dom);
1.211     www      4896: 
                   4897: # List data
                   4898: 
1.568     raeburn  4899:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
                   4900:     }
                   4901:     $r->print(&tableend());
                   4902:     unless ($readonly) {
                   4903:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      4904:     }
1.568     raeburn  4905:     $r->print('</form>');
1.507     www      4906:     &endSettingsScreen($r);
                   4907:     $r->print(&Apache::loncommon::end_page());
1.208     www      4908: }
                   4909: 
1.563     damieng  4910: # Fills $listdata with parameter information.
                   4911: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   4912: # The non-type value is always 1.
                   4913: #
                   4914: # @param {string} $cat - parameter name
1.566     damieng  4915: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4916: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   4917: # @param {hash reference} $listdata - the parameter data that will be modified
                   4918: # @param {array reference} $psprt - selected parts
                   4919: # @param {array reference} $selections - selected sections
                   4920: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  4921: # @param {hash reference} $allmaps - hash map pc -> map src
                   4922: # @param {array reference} $ids - resource and map ids
                   4923: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  4924: sub secgroup_lister {
                   4925:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   4926:     foreach my $item (@{$selections}) {
                   4927:         foreach my $part (@{$psprt}) {
                   4928:             my $rootparmkey=$env{'request.course.id'};
                   4929:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   4930:                 $rootparmkey.='.['.$item.']';
                   4931:             }
                   4932:             if ($parmlev eq 'general') {
                   4933: # course-level parameter
                   4934:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   4935:                 $$listdata{$newparmkey}=1;
                   4936:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   4937:             } elsif ($parmlev eq 'map') {
                   4938: # map-level parameter
1.548     raeburn  4939:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  4940:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   4941:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   4942:                     $$listdata{$newparmkey}=1;
                   4943:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
1.556     raeburn  4944:                     $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(rec).'.$part.'.'.$cat;
                   4945:                     $$listdata{$newparmkey}=1;
                   4946:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
1.269     raeburn  4947:                 }
                   4948:             } else {
                   4949: # resource-level parameter
                   4950:                 foreach my $rid (@{$ids}) {
                   4951:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   4952:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   4953:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   4954:                     $$listdata{$newparmkey}=1;
                   4955:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   4956:                 }
                   4957:             }
                   4958:         }
                   4959:     }
                   4960: }
                   4961: 
1.563     damieng  4962: # UI to edit parameter settings starting with a list of all existing parameters.
                   4963: # (called by setoverview action)
                   4964: #
                   4965: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      4966: sub overview {
1.568     raeburn  4967:     my ($r,$parm_permission) = @_;
1.208     www      4968:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   4969:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  4970:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  4971:     my $readonly = 1;
                   4972:     if ($parm_permission->{'edit'}) {
                   4973:         undef($readonly);
                   4974:     }
1.549     raeburn  4975:     my $js = '<script type="text/javascript">'."\n".
                   4976:              '// <![CDATA['."\n".
                   4977:              &toggleparmtextbox_js()."\n".
                   4978:              &validateparms_js()."\n".
                   4979:              &ipacc_boxes_js()."\n".
1.558     raeburn  4980:              &done_proctor_js()."\n".
1.549     raeburn  4981:              '// ]]>'."\n".
                   4982:              '</script>'."\n";
1.414     droeschl 4983:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 4984:     text=>"Overview Mode"});
1.549     raeburn  4985:     my %loaditems = (
                   4986:                       'onload'   => "showHideLenient();",
                   4987:                     );
                   4988: 
                   4989:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 4990:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      4991:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  4992:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  4993:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      4994: 
1.208     www      4995: # Store modified
                   4996: 
1.568     raeburn  4997:     unless ($readonly) {
                   4998:         &storedata($r,$crs,$dom);
                   4999:     }
1.208     www      5000: 
                   5001: # Read modified data
                   5002: 
1.552     raeburn  5003:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      5004: 
1.214     www      5005: 
                   5006:     my $sortorder=$env{'form.sortorder'};
                   5007:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5008:     &sortmenu($r,$sortorder);
                   5009: 
1.568     raeburn  5010:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   5011: 
                   5012:     if ($readonly) {
                   5013:         $r->print('<p>'.$submitbutton.'</p>');
                   5014:     }
                   5015: 
1.208     www      5016: # List data
                   5017: 
1.568     raeburn  5018:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   5019:     $r->print(&tableend().'<p>');
                   5020:     if ($foundkeys) {
                   5021:         unless ($readonly) {
                   5022:             $r->print('<p>'.$submitbutton.'</p>');
                   5023:         }
                   5024:     } else {
                   5025:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   5026:     }
                   5027:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      5028: }
1.121     www      5029: 
1.560     damieng  5030: # Unused sub.
1.563     damieng  5031: #
                   5032: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 5033: sub clean_parameters {
                   5034:     my ($r) = @_;
                   5035:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5036:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5037: 
1.414     droeschl 5038:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 5039:         text=>"Clean Parameters"});
1.333     albertel 5040:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   5041:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   5042:     $r->print(<<ENDOVER);
                   5043: $start_page
                   5044: $breadcrumbs
                   5045: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   5046: ENDOVER
                   5047: # Store modified
                   5048: 
                   5049:     &storedata($r,$crs,$dom);
                   5050: 
                   5051: # Read modified data
                   5052: 
                   5053:     my $resourcedata=&readdata($crs,$dom);
                   5054: 
                   5055: # List data
                   5056: 
                   5057:     $r->print('<h3>'.
1.473     amueller 5058:           &mt('These parameters refer to resources that do not exist.').
                   5059:           '</h3>'.
                   5060:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   5061:           '<br />');
1.333     albertel 5062:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 5063:           '<tr>'.
                   5064:           '<th>'.&mt('Delete').'</th>'.
                   5065:           '<th>'.&mt('Parameter').'</th>'.
                   5066:           '</tr>');
1.333     albertel 5067:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  5068:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   5069:             && $thiskey=~/\.type$/);
                   5070:         my %data = &parse_key($thiskey);
                   5071:         if (1) { #exists($data{'realm_exists'})
                   5072:             #&& !$data{'realm_exists'}) {
                   5073:             $r->print(&Apache::loncommon::start_data_table_row().
                   5074:                 '<tr>'.
                   5075:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   5076: 
                   5077:             $r->print('<td>');
                   5078:             my $display_value = $resourcedata->{$thiskey};
                   5079:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   5080:             $display_value =
                   5081:                 &Apache::lonlocal::locallocaltime($display_value);
                   5082:             }
1.470     raeburn  5083:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   5084:             $parmitem = &mt($parmitem);
1.560     damieng  5085:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   5086:                 $parmitem,$resourcedata->{$thiskey}));
                   5087:             $r->print('<br />');
                   5088:             if ($data{'scope_type'} eq 'all') {
                   5089:                 $r->print(&mt('All users'));
                   5090:             } elsif ($data{'scope_type'} eq 'user') {
                   5091:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
                   5092:             } elsif ($data{'scope_type'} eq 'section') {
                   5093:                 $r->print(&mt('Section: [_1]',$data{'scope'}));
                   5094:             } elsif ($data{'scope_type'} eq 'group') {
                   5095:                 $r->print(&mt('Group: [_1]',$data{'scope'}));
                   5096:             }
                   5097:             $r->print('<br />');
                   5098:             if ($data{'realm_type'} eq 'all') {
                   5099:                 $r->print(&mt('All Resources'));
                   5100:             } elsif ($data{'realm_type'} eq 'folder') {
                   5101:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   5102:             } elsif ($data{'realm_type'} eq 'symb') {
                   5103:             my ($map,$resid,$url) =
                   5104:                 &Apache::lonnet::decode_symb($data{'realm'});
                   5105:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   5106:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   5107:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   5108:             }
                   5109:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   5110:             $r->print('</td></tr>');
                   5111: 
1.473     amueller 5112:         }
1.333     albertel 5113:     }
                   5114:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 5115:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      5116:           '</p></form>');
                   5117:     &endSettingsScreen($r);
                   5118:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 5119: }
                   5120: 
1.563     damieng  5121: # UI to shift all dates (called by dateshift1 action).
                   5122: # Used by overview mode.
                   5123: #
                   5124: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5125: sub date_shift_one {
                   5126:     my ($r) = @_;
                   5127:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5128:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5129:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.390     www      5130: 
1.414     droeschl 5131:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5132:         text=>"Shifting Dates"});
1.390     www      5133:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5134:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5135:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5136:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   5137:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      5138:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   5139:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   5140:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   5141:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      5142:                                                         'timeshifted',
                   5143:                                                         $env{'form.timebase'},,
                   5144:                                                         '').
                   5145:               '</td></tr></table>'.
                   5146:               '<input type="hidden" name="action" value="dateshift2" />'.
                   5147:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
                   5148:               '<input type="submit" value="'.&mt('Shift all dates accordingly').'" /></form>');
1.507     www      5149:     &endSettingsScreen($r);
1.390     www      5150:     $r->print(&Apache::loncommon::end_page());
                   5151: }
                   5152: 
1.563     damieng  5153: # UI to shift all dates (second form).
                   5154: #
                   5155: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5156: sub date_shift_two {
                   5157:     my ($r) = @_;
                   5158:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5159:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5160:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 5161:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5162:         text=>"Shifting Dates"});
1.390     www      5163:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5164:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5165:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5166:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      5167:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.543     bisitz   5168:     $r->print('<h2>'.&mt('Shift Dates').'</h2>'.
                   5169:               '<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
1.390     www      5170:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
1.543     bisitz   5171:               &Apache::lonlocal::locallocaltime($timeshifted)).'</p>');
1.390     www      5172:     my $delta=$timeshifted-$env{'form.timebase'};
                   5173:     &dateshift($delta);
1.543     bisitz   5174:     $r->print(
                   5175:         &Apache::lonhtmlcommon::confirm_success(&mt('Done')).
                   5176:         '<br /><br />'.
                   5177:         &Apache::lonhtmlcommon::actionbox(
                   5178:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      5179:     &endSettingsScreen($r);
1.390     www      5180:     $r->print(&Apache::loncommon::end_page());
                   5181: }
                   5182: 
1.563     damieng  5183: # Returns the different components of a resourcedata key.
                   5184: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   5185: #       realm_exists, parameter_part, parameter_name.
                   5186: # Was used by clean_parameters (which is unused).
                   5187: #
                   5188: # @param {string} $key - the parameter key
                   5189: # @returns {hash}
1.333     albertel 5190: sub parse_key {
                   5191:     my ($key) = @_;
                   5192:     my %data;
                   5193:     my ($middle,$part,$name)=
1.572     damieng  5194:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 5195:     $data{'scope_type'} = 'all';
                   5196:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  5197:         $data{'scope'} = $1;
                   5198:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   5199:             $data{'scope_type'} = 'user';
                   5200:             $data{'scope'} = [$1,$2];
                   5201:         } else {
                   5202:             #FIXME check for group scope
                   5203:             $data{'scope_type'} = 'section';
                   5204:         }
                   5205:         $middle=~s/^\[(.*)\]//;
1.333     albertel 5206:     }
                   5207:     $middle=~s/\.+$//;
                   5208:     $middle=~s/^\.+//;
                   5209:     $data{'realm_type'}='all';
                   5210:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  5211:         $data{'realm'} = $1;
                   5212:         $data{'realm_type'} = 'folder';
                   5213:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5214:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 5215:     } elsif ($middle) {
1.560     damieng  5216:         $data{'realm'} = $middle;
                   5217:         $data{'realm_type'} = 'symb';
                   5218:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5219:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   5220:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 5221:     }
1.446     bisitz   5222: 
1.333     albertel 5223:     $data{'parameter_part'} = $part;
                   5224:     $data{'parameter_name'} = $name;
                   5225: 
                   5226:     return %data;
                   5227: }
                   5228: 
1.239     raeburn  5229: 
1.563     damieng  5230: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      5231: sub header {
1.507     www      5232:     return &Apache::loncommon::start_page('Settings');
1.416     jms      5233: }
1.193     albertel 5234: 
                   5235: 
                   5236: 
1.560     damieng  5237: ##################################################
                   5238: # MAIN MENU
                   5239: ##################################################
                   5240: 
1.563     damieng  5241: # Content and problem settings main menu.
                   5242: #
                   5243: # @param {Apache2::RequestRec} $r - the Apache request
                   5244: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 5245: sub print_main_menu {
                   5246:     my ($r,$parm_permission)=@_;
                   5247:     #
1.414     droeschl 5248:     $r->print(&header());
1.507     www      5249:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  5250:     my $crstype = &Apache::loncommon::course_type();
                   5251:     my $lc_crstype = lc($crstype);
                   5252: 
                   5253:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 5254:     $r->print(<<ENDMAINFORMHEAD);
                   5255: <form method="post" enctype="multipart/form-data"
                   5256:       action="/adm/parmset" name="studentform">
                   5257: ENDMAINFORMHEAD
                   5258: #
1.195     albertel 5259:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5260:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 5261:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 5262:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  5263:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  5264:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   5265:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  5266:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   5267:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   5268:                                         '/'.$env{'request.course.sec'});
                   5269:     }
1.568     raeburn  5270:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   5271:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   5272:                                         '/'.$env{'request.course.sec'});
                   5273:     }
                   5274:     my (%linktext,%linktitle,%url);
                   5275:     if ($parm_permission->{'edit'}) {
                   5276:         %linktext = (
                   5277:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   5278:                      settable        => 'Edit Resource Parameters - Table Mode',
                   5279:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   5280:                     );
                   5281:         %linktitle = (
                   5282:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   5283:                      settable        => 'Set/Modify resource parameters in table mode.',
                   5284:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   5285:                      );
                   5286:     } else {
                   5287:         %linktext = (
                   5288:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   5289:                      settable        => 'View Resource Parameters - Table Mode',
                   5290:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   5291:                    );
                   5292:         %linktitle = (
                   5293:                      newoverview     => 'Display resource parameters in overview mode.',
                   5294:                      settable        => 'Display resource parameters in table mode.',
                   5295:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   5296:                      );
                   5297:     }
                   5298:     if ($mgr) {
                   5299:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   5300:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   5301:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   5302:     } elsif ($vgr) {
                   5303:         $linktext{'resettimes'} = 'Display Student Access Times',
                   5304:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   5305:         $url{'resettimes'} = '/adm/accesstimes';
                   5306:     }
1.193     albertel 5307:     my @menu =
1.507     www      5308:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 5309:         items => [
                   5310:           { linktext => 'Portfolio Metadata',
                   5311:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  5312:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  5313:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 5314:             icon =>'contact-new.png'   ,
                   5315:             },
1.568     raeburn  5316:           { linktext => $linktext{'resettimes'},
                   5317:             url => $url{'resettimes'},
                   5318:             permission => ($vgr || $mgr),
                   5319:             linktitle => $linktitle{'resettimes'},
                   5320:             icon => 'start-here.png',
1.473     amueller 5321:             },
1.520     raeburn  5322:           { linktext => 'Blocking Communication/Resource Access',
                   5323:             url => '/adm/setblock',
1.568     raeburn  5324:             permission => ($vcb || $dcm),
1.520     raeburn  5325:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   5326:             icon => 'comblock.png',
                   5327:             },
1.473     amueller 5328:           { linktext => 'Set Parameter Setting Default Actions',
                   5329:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  5330:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 5331:             linktitle =>'Set default actions for parameters.'  ,
                   5332:             icon => 'folder-new.png'  ,
                   5333:             }]},
                   5334:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   5335:         items => [
                   5336:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   5337:             url => '/adm/helper/parameter.helper',
1.568     raeburn  5338:             permission => $parm_permission->{'helper'},
1.473     amueller 5339:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   5340:             icon => 'dialog-information.png'  ,
                   5341:             #help => 'Parameter_Helper',
                   5342:             },
1.568     raeburn  5343:           { linktext => $linktext{'newoverview'},
1.473     amueller 5344:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  5345:             permission => $parm_permission->{'newoverview'},
                   5346:             linktitle => $linktitle{'newoverview'},
                   5347:             icon => 'edit-find.png',
1.473     amueller 5348:             #help => 'Parameter_Overview',
                   5349:             },
1.568     raeburn  5350:           { linktext => $linktext{'settable'},
1.473     amueller 5351:             url => '/adm/parmset?action=settable',
1.568     raeburn  5352:             permission => $parm_permission->{'settable'},
                   5353:             linktitle => $linktitle{'settable'},
                   5354:             icon => 'edit-copy.png',
1.473     amueller 5355:             #help => 'Table_Mode',
                   5356:             }]},
1.417     droeschl 5357:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 5358:          items => [
1.570     raeburn  5359:           { linktext => $linktext{'setoverview'},
1.473     amueller 5360:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  5361:             permission => $parm_permission->{'setoverview'},
                   5362:             linktitle => $linktitle{'setoverview'},
                   5363:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 5364:             #help => 'Parameter_Overview',
                   5365:             },
                   5366:           { linktext => 'Change Log',
                   5367:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  5368:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  5369:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 5370:             icon => 'document-properties.png',
1.473     amueller 5371:             }]}
1.193     albertel 5372:           );
1.414     droeschl 5373:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  5374:     $r->print('</form>');
1.507     www      5375:     &endSettingsScreen($r);
1.539     raeburn  5376:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 5377:     return;
                   5378: }
1.414     droeschl 5379: 
1.416     jms      5380: 
                   5381: 
1.560     damieng  5382: ##################################################
                   5383: # PORTFOLIO METADATA
                   5384: ##################################################
                   5385: 
1.563     damieng  5386: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   5387: # It looks like field titles are not localized.
                   5388: #
                   5389: # @param {Apache2::RequestRec} $r - the Apache request
                   5390: # @param {string} $field_name - metadata field name
                   5391: # @param {string} $field_text - metadata field title, in English unless manually added
                   5392: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 5393: sub output_row {
1.347     banghart 5394:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 5395:     my $output;
1.263     banghart 5396:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   5397:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 5398:     if (!defined($options)) {
1.254     banghart 5399:         $options = 'active,stuadd';
1.261     banghart 5400:         $values = '';
1.252     banghart 5401:     }
1.337     banghart 5402:     if (!($options =~ /deleted/)) {
                   5403:         my @options= ( ['active', 'Show to student'],
1.418     schafran 5404:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 5405:                     ['choices','Provide choices for students to select from']);
1.473     amueller 5406: #           ['onlyone','Student may select only one choice']);
1.337     banghart 5407:         if ($added_flag) {
                   5408:             push @options,['deleted', 'Delete Metadata Field'];
                   5409:         }
1.351     banghart 5410:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   5411:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 5412:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 5413:         foreach my $opt (@options) {
1.560     damieng  5414:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   5415:             $output .= &Apache::loncommon::continue_data_table_row();
                   5416:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   5417:                     <input type="checkbox" name="'.
                   5418:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   5419:                     &mt($opt->[1]).'</label></td>';
                   5420:             $output .= &Apache::loncommon::end_data_table_row();
                   5421:         }
1.351     banghart 5422:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   5423:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 5424:         $output .= &Apache::loncommon::end_data_table_row();
                   5425:         my $multiple_checked;
                   5426:         my $single_checked;
                   5427:         if ($options =~ m/onlyone/) {
1.422     bisitz   5428:             $multiple_checked = '';
1.423     bisitz   5429:             $single_checked = ' checked="checked"';
1.351     banghart 5430:         } else {
1.423     bisitz   5431:             $multiple_checked = ' checked="checked"';
1.422     bisitz   5432:             $single_checked = '';
1.351     banghart 5433:         }
1.560     damieng  5434:         $output .= &Apache::loncommon::continue_data_table_row();
                   5435:         $output .= '<td>'.('&nbsp;' x 10).'
                   5436:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   5437:                     '.&mt('Student may select multiple choices from list').'</td>';
                   5438:         $output .= &Apache::loncommon::end_data_table_row();
                   5439:         $output .= &Apache::loncommon::continue_data_table_row();
                   5440:         $output .= '<td>'.('&nbsp;' x 10).'
                   5441:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   5442:                     '.&mt('Student may select only one choice from list').'</td>';
                   5443:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 5444:     }
                   5445:     return ($output);
                   5446: }
1.416     jms      5447: 
                   5448: 
1.560     damieng  5449: # UI to order portfolio metadata fields.
1.563     damieng  5450: # Currently useless because addmetafield does not work.
                   5451: #
                   5452: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 5453: sub order_meta_fields {
                   5454:     my ($r)=@_;
                   5455:     my $idx = 1;
                   5456:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5457:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5458:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 5459:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  5460:     &Apache::lonhtmlcommon::add_breadcrumb(
                   5461:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 5462:         text=>"Add Metadata Field"});
1.560     damieng  5463:     &Apache::lonhtmlcommon::add_breadcrumb(
                   5464:         {href=>"/adm/parmset?action=setrestrictmeta",
                   5465:         text=>"Restrict Metadata"},
                   5466:         {text=>"Order Metadata"});
1.345     banghart 5467:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  5468:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 5469:     if ($env{'form.storeorder'}) {
                   5470:         my $newpos = $env{'form.newpos'} - 1;
                   5471:         my $currentpos = $env{'form.currentpos'} - 1;
                   5472:         my @neworder = ();
1.548     raeburn  5473:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 5474:         my $i;
1.341     banghart 5475:         if ($newpos > $currentpos) {
1.340     banghart 5476:         # moving stuff up
                   5477:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  5478:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 5479:             }
                   5480:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  5481:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 5482:             }
                   5483:             $neworder[$newpos]=$oldorder[$currentpos];
                   5484:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  5485:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 5486:             }
                   5487:         } else {
                   5488:         # moving stuff down
1.473     amueller 5489:             for ($i=0;$i<$newpos;$i++) {
                   5490:                 $neworder[$i]=$oldorder[$i];
                   5491:             }
                   5492:             $neworder[$newpos]=$oldorder[$currentpos];
                   5493:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   5494:                 $neworder[$i]=$oldorder[$i-1];
                   5495:             }
                   5496:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   5497:                 $neworder[$i]=$oldorder[$i];
                   5498:             }
1.340     banghart 5499:         }
1.560     damieng  5500:         my $ordered_fields = join ",", @neworder;
1.343     banghart 5501:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  5502:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   5503:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 5504:     }
1.357     raeburn  5505:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 5506:     my $ordered_fields;
1.548     raeburn  5507:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 5508:     if (!@fields_in_order) {
                   5509:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  5510:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 5511:             push @fields_in_order, $key;
1.341     banghart 5512:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 5513:         }
1.341     banghart 5514:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   5515:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   5516:     }
1.340     banghart 5517:     $r->print('<table>');
                   5518:     my $num_fields = scalar(@fields_in_order);
                   5519:     foreach my $key (@fields_in_order) {
                   5520:         $r->print('<tr><td>');
                   5521:         $r->print('<form method="post" action="">');
1.537     bisitz   5522:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 5523:         for (my $i = 1;$i le $num_fields;$i ++) {
                   5524:             if ($i eq $idx) {
                   5525:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   5526:             } else {
                   5527:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   5528:             }
                   5529:         }
                   5530:         $r->print('</select></td><td>');
                   5531:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   5532:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   5533:         $r->print('</form>');
                   5534:         $r->print($$fields{$key}.'</td></tr>');
                   5535:         $idx ++;
                   5536:     }
                   5537:     $r->print('</table>');
1.507     www      5538:     &endSettingsScreen($r);
1.340     banghart 5539:     return 'ok';
                   5540: }
1.416     jms      5541: 
                   5542: 
1.563     damieng  5543: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   5544: # @returns {string}
1.359     banghart 5545: sub continue {
                   5546:     my $output;
                   5547:     $output .= '<form action="" method="post">';
                   5548:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
                   5549:     $output .= '<input type="submit" value="Continue" />';
                   5550:     return ($output);
                   5551: }
1.416     jms      5552: 
                   5553: 
1.563     damieng  5554: # UI to add a metadata field.
                   5555: # Currenly does not work because of an HTML error (the field is not visible).
                   5556: #
                   5557: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 5558: sub addmetafield {
                   5559:     my ($r)=@_;
1.414     droeschl 5560:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 5561:         text=>"Add Metadata Field"});
1.334     banghart 5562:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   5563:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 5564:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5565:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5566:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   5567:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 5568:     if (exists($env{'form.undelete'})) {
1.358     banghart 5569:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 5570:         foreach my $meta_field(@meta_fields) {
                   5571:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   5572:             $options =~ s/deleted//;
                   5573:             $options =~ s/,,/,/;
                   5574:             my $put_result = &Apache::lonnet::put('environment',
                   5575:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   5576: 
1.339     banghart 5577:             $r->print('Undeleted Metadata Field <strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}."</strong> with result ".$put_result.'<br />');
                   5578:         }
1.359     banghart 5579:         $r->print(&continue());
1.339     banghart 5580:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 5581:         my $meta_field = $env{'form.fieldname'};
                   5582:         my $display_field = $env{'form.fieldname'};
                   5583:         $meta_field =~ s/\W/_/g;
1.338     banghart 5584:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 5585:         my $put_result = &Apache::lonnet::put('environment',
                   5586:                             {'metadata.'.$meta_field.'.values'=>"",
                   5587:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   5588:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.359     banghart 5589:         $r->print('Added new Metadata Field <strong>'.$env{'form.fieldname'}."</strong> with result ".$put_result.'<br />');
                   5590:         $r->print(&continue());
1.335     banghart 5591:     } else {
1.357     raeburn  5592:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 5593:         if ($fields) {
                   5594:             $r->print('You may undelete previously deleted fields.<br />Check those you wish to undelete and click Undelete.<br />');
                   5595:             $r->print('<form method="post" action="">');
                   5596:             foreach my $key(keys(%$fields)) {
1.358     banghart 5597:                 $r->print('<input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'<br /');
1.339     banghart 5598:             }
                   5599:             $r->print('<input type="submit" name="undelete" value="Undelete" />');
                   5600:             $r->print('</form>');
                   5601:         }
1.571     damieng  5602:         $r->print('<hr /><strong>Or</strong> you may enter a new metadata field name.<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 5603:         $r->print('<input type="text" name="fieldname" /><br />');
                   5604:         $r->print('<input type="submit" value="Add Metadata Field" />');
1.334     banghart 5605:     }
1.361     albertel 5606:     $r->print('</form>');
1.507     www      5607:     &endSettingsScreen($r);
1.334     banghart 5608: }
1.416     jms      5609: 
                   5610: 
                   5611: 
1.560     damieng  5612: # Display or save portfolio metadata.
1.563     damieng  5613: #
                   5614: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 5615: sub setrestrictmeta {
1.240     banghart 5616:     my ($r)=@_;
1.242     banghart 5617:     my $next_meta;
1.244     banghart 5618:     my $output;
1.245     banghart 5619:     my $item_num;
1.246     banghart 5620:     my $put_result;
1.414     droeschl 5621:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 5622:         text=>"Restrict Metadata"});
1.280     albertel 5623:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 5624:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 5625:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5626:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5627:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   5628:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 5629:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 5630:     my $save_field = '';
1.259     banghart 5631:     if ($env{'form.restrictmeta'}) {
1.254     banghart 5632:         foreach my $field (sort(keys(%env))) {
1.252     banghart 5633:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 5634:                 my $options;
1.252     banghart 5635:                 my $meta_field = $1;
                   5636:                 my $meta_key = $2;
1.253     banghart 5637:                 if ($save_field ne $meta_field) {
1.252     banghart 5638:                     $save_field = $meta_field;
1.473     amueller 5639:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   5640:                         $options.='stuadd,';
                   5641:                     }
                   5642:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   5643:                         $options.='choices,';
                   5644:                     }
                   5645:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   5646:                         $options.='onlyone,';
                   5647:                     }
                   5648:                     if ($env{'form.'.$meta_field.'_active'}) {
                   5649:                         $options.='active,';
                   5650:                     }
                   5651:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   5652:                         $options.='deleted,';
                   5653:                     }
1.259     banghart 5654:                     my $name = $save_field;
1.560     damieng  5655:                     $put_result = &Apache::lonnet::put('environment',
                   5656:                         {'metadata.'.$meta_field.'.options'=>$options,
                   5657:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   5658:                         },$dom,$crs);
1.252     banghart 5659:                 }
                   5660:             }
                   5661:         }
                   5662:     }
1.296     albertel 5663:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 5664:                        {'freshen_cache' => 1});
1.335     banghart 5665:     # Get the default metadata fields
1.258     albertel 5666:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 5667:     # Now get possible added metadata fields
1.357     raeburn  5668:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.346     banghart 5669:     my $row_alt = 1;
1.347     banghart 5670:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 5671:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 5672:         if ($field ne 'courserestricted') {
1.346     banghart 5673:             $row_alt = $row_alt ? 0 : 1;
1.560     damieng  5674:             $output.= &output_row($r, $field, $metadata_fields{$field});
                   5675:         }
1.255     banghart 5676:     }
1.351     banghart 5677:     my $buttons = (<<ENDButtons);
                   5678:         <input type="submit" name="restrictmeta" value="Save" />
                   5679:         </form><br />
                   5680:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
                   5681:         <input type="submit" name="restrictmeta" value="Add a Metadata Field" />
                   5682:         </form>
                   5683:         <br />
                   5684:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
                   5685:         <input type="submit" name="restrictmeta" value="Order Metadata Fields" />
                   5686: ENDButtons
1.337     banghart 5687:     my $added_flag = 1;
1.335     banghart 5688:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.346     banghart 5689:         $row_alt = $row_alt ? 0 : 1;
1.563     damieng  5690:         $output.= &output_row($r, $field, $$added_metadata_fields{$field},$added_flag, $row_alt); # FIXME: wrong parameters
1.335     banghart 5691:     }
1.347     banghart 5692:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   5693:     $r->print(<<ENDenv);
1.259     banghart 5694:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 5695:         $output
1.351     banghart 5696:         $buttons
1.340     banghart 5697:         </form>
1.244     banghart 5698: ENDenv
1.507     www      5699:     &endSettingsScreen($r);
1.280     albertel 5700:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 5701:     return 'ok';
                   5702: }
1.416     jms      5703: 
                   5704: 
1.563     damieng  5705: # Returns metadata fields that have been manually added.
                   5706: #
                   5707: # @param {string} $cid - course id
                   5708: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 5709: sub get_added_meta_fieldnames {
1.357     raeburn  5710:     my ($cid) = @_;
1.335     banghart 5711:     my %fields;
                   5712:     foreach my $key(%env) {
1.357     raeburn  5713:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 5714:             my $field_name = $1;
                   5715:             my ($display_field_name) = $env{$key};
                   5716:             $fields{$field_name} = $display_field_name;
                   5717:         }
                   5718:     }
                   5719:     return \%fields;
                   5720: }
1.416     jms      5721: 
                   5722: 
1.563     damieng  5723: # Returns metadata fields that have been manually added and deleted.
                   5724: #
                   5725: # @param {string} $cid - course id
                   5726: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 5727: sub get_deleted_meta_fieldnames {
1.357     raeburn  5728:     my ($cid) = @_;
1.339     banghart 5729:     my %fields;
                   5730:     foreach my $key(%env) {
1.357     raeburn  5731:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 5732:             my $field_name = $1;
                   5733:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   5734:                 my ($display_field_name) = $env{$key};
                   5735:                 $fields{$field_name} = $display_field_name;
                   5736:             }
                   5737:         }
                   5738:     }
                   5739:     return \%fields;
                   5740: }
1.560     damieng  5741: 
                   5742: 
                   5743: ##################################################
                   5744: # PARAMETER SETTINGS DEFAULT ACTIONS
                   5745: ##################################################
                   5746: 
                   5747: # UI to change parameter setting default actions
1.563     damieng  5748: #
                   5749: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      5750: sub defaultsetter {
1.280     albertel 5751:     my ($r) = @_;
                   5752: 
1.414     droeschl 5753:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 5754:         text=>"Set Defaults"});
1.531     raeburn  5755:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5756:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5757:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   5758:     my $start_page =
1.531     raeburn  5759:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 5760:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      5761:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5762:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      5763:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 5764: 
1.221     www      5765:     my @ids=();
                   5766:     my %typep=();
                   5767:     my %keyp=();
                   5768:     my %allparms=();
                   5769:     my %allparts=();
                   5770:     my %allmaps=();
                   5771:     my %mapp=();
                   5772:     my %symbp=();
                   5773:     my %maptitles=();
                   5774:     my %uris=();
                   5775:     my %keyorder=&standardkeyorder();
                   5776:     my %defkeytype=();
                   5777: 
1.446     bisitz   5778:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 5779:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   5780:                 \%keyorder,\%defkeytype);
1.224     www      5781:     if ($env{'form.storerules'}) {
1.560     damieng  5782:         my %newrules=();
                   5783:         my @delrules=();
                   5784:         my %triggers=();
                   5785:         foreach my $key (keys(%env)) {
1.225     albertel 5786:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  5787:                 my $tempkey=$1;
                   5788:                 my $action=$env{$key};
1.226     www      5789:                 if ($action) {
1.560     damieng  5790:                     $newrules{$tempkey.'_action'}=$action;
                   5791:                     if ($action ne 'default') {
                   5792:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   5793:                         $triggers{$whichparm}.=$tempkey.':';
                   5794:                     }
                   5795:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   5796:                     if (&isdateparm($defkeytype{$tempkey})) {
                   5797:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   5798:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   5799:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   5800:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   5801:                     } else {
                   5802:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   5803:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   5804:                     }
                   5805:                 } else {
                   5806:                     push(@delrules,$tempkey.'_action');
                   5807:                     push(@delrules,$tempkey.'_type');
                   5808:                     push(@delrules,$tempkey.'_hours');
                   5809:                     push(@delrules,$tempkey.'_min');
                   5810:                     push(@delrules,$tempkey.'_sec');
                   5811:                     push(@delrules,$tempkey.'_value');
                   5812:                 }
1.473     amueller 5813:             }
                   5814:         }
1.560     damieng  5815:         foreach my $key (keys(%allparms)) {
                   5816:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 5817:         }
1.560     damieng  5818:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   5819:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   5820:         &resetrulescache();
1.224     www      5821:     }
1.227     www      5822:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 5823:                        'hours' => 'Hours',
                   5824:                        'min' => 'Minutes',
                   5825:                        'sec' => 'Seconds',
                   5826:                        'yes' => 'Yes',
                   5827:                        'no' => 'No');
1.222     www      5828:     my @standardoptions=('','default');
                   5829:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   5830:     my @dateoptions=('','default');
                   5831:     my @datedisplay=('',&mt('Default value when manually setting'));
                   5832:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  5833:         unless ($tempkey) { next; }
                   5834:         push @standardoptions,'when_setting_'.$tempkey;
                   5835:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   5836:         if (&isdateparm($defkeytype{$tempkey})) {
                   5837:             push @dateoptions,'later_than_'.$tempkey;
                   5838:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   5839:             push @dateoptions,'earlier_than_'.$tempkey;
                   5840:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   5841:         }
1.222     www      5842:     }
1.563     damieng  5843:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   5844:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 5845:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 5846:           &Apache::loncommon::start_data_table_header_row().
                   5847:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   5848:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   5849:           &Apache::loncommon::end_data_table_header_row());
1.221     www      5850:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  5851:         unless ($tempkey) { next; }
                   5852:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   5853:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   5854:         my $action=&rulescache($tempkey.'_action');
                   5855:         $r->print('<select name="'.$tempkey.'_action">');
                   5856:         if (&isdateparm($defkeytype{$tempkey})) {
                   5857:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   5858:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   5859:             $r->print("\n<option value='$dateoptions[$i]'".
                   5860:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   5861:                 ">$datedisplay[$i]</option>");
                   5862:             }
                   5863:         } else {
                   5864:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   5865:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   5866:             $r->print("\n<option value='$standardoptions[$i]'".
                   5867:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   5868:                 ">$standarddisplay[$i]</option>");
                   5869:             }
1.473     amueller 5870:         }
1.560     damieng  5871:         $r->print('</select>');
                   5872:         unless (&isdateparm($defkeytype{$tempkey})) {
                   5873:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   5874:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 5875:         }
1.560     damieng  5876:         $r->print("\n</td><td>\n");
1.222     www      5877: 
1.221     www      5878:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  5879:             my $days=&rulescache($tempkey.'_days');
                   5880:             my $hours=&rulescache($tempkey.'_hours');
                   5881:             my $min=&rulescache($tempkey.'_min');
                   5882:             my $sec=&rulescache($tempkey.'_sec');
                   5883:             $r->print(<<ENDINPUTDATE);
                   5884:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   5885:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   5886:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   5887:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  5888: ENDINPUTDATE
1.560     damieng  5889:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   5890:                 my $yeschecked='';
                   5891:                 my $nochecked='';
                   5892:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   5893:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   5894: 
                   5895:             $r->print(<<ENDYESNO);
                   5896:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   5897:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  5898: ENDYESNO
1.221     www      5899:         } else {
1.560     damieng  5900:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   5901:         }
1.318     albertel 5902:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      5903:     }
1.318     albertel 5904:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 5905:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      5906:           &mt('Save').'" /></form>'."\n");
                   5907:     &endSettingsScreen($r);
                   5908:     $r->print(&Apache::loncommon::end_page());
1.220     www      5909:     return;
                   5910: }
1.193     albertel 5911: 
1.560     damieng  5912: ##################################################
                   5913: # PARAMETER CHANGES LOG
                   5914: ##################################################
                   5915: 
1.563     damieng  5916: # Returns some info for a parameter log entry.
                   5917: # Returned entries:
                   5918: # $realm - HTML title for the parameter level and resource
                   5919: # $section - parameter section
                   5920: # $name - parameter name
                   5921: # $part - parameter part
                   5922: # $what - $part.'.'.$name
                   5923: # $middle - resource symb ?
                   5924: # $uname - user name (same as given)
                   5925: # $udom - user domain (same as given)
                   5926: # $issection - section or group name
                   5927: # $realmdescription - title for the parameter level and resource (without using HTML)
                   5928: #
                   5929: # FIXME: remove unused fields.
                   5930: #
                   5931: # @param {string} $key - parameter log key
                   5932: # @param {string} $uname - user name
                   5933: # @param {string} $udom - user domain
                   5934: # @param {string} $exeuser - unused
                   5935: # @param {string} $exedomain - unused
                   5936: # @param {boolean} $typeflag - .type log entry
                   5937: # @returns {Array}
1.290     www      5938: sub components {
1.330     albertel 5939:     my ($key,$uname,$udom,$exeuser,$exedomain,$typeflag)=@_;
                   5940: 
                   5941:     if ($typeflag) {
1.560     damieng  5942:         $key=~s/\.type$//;
1.290     www      5943:     }
1.330     albertel 5944: 
                   5945:     my ($middle,$part,$name)=
1.572     damieng  5946:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      5947:     my $issection;
1.330     albertel 5948: 
1.290     www      5949:     my $section=&mt('All Students');
                   5950:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  5951:         $issection=$1;
                   5952:         $section=&mt('Group/Section').': '.$issection;
                   5953:         $middle=~s/^\[(.*)\]//;
1.290     www      5954:     }
                   5955:     $middle=~s/\.+$//;
                   5956:     $middle=~s/^\.+//;
1.291     www      5957:     if ($uname) {
1.560     damieng  5958:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   5959:         $issection='';
1.291     www      5960:     }
1.316     albertel 5961:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   5962:     my $realmdescription=&mt('all resources');
1.556     raeburn  5963:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   5964:         my $mapurl = $1;
                   5965:         my $maplevel = $2;
                   5966:         my $leveltitle = &mt('Folder/Map');
                   5967:         if ($maplevel eq 'rec') {
                   5968:             $leveltitle = &mt('Recursive');
                   5969:         }
1.560     damieng  5970:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   5971:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   5972:             $mapurl.')</span></span>';
                   5973:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   5974:     } elsif ($middle) {
                   5975:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   5976:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   5977:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   5978:             ' in '.$map.' id: '.$id.')</span></span>';
                   5979:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      5980:     }
1.291     www      5981:     my $what=$part.'.'.$name;
1.330     albertel 5982:     return ($realm,$section,$name,$part,
1.473     amueller 5983:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      5984: }
1.293     www      5985: 
1.563     damieng  5986: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   5987: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      5988: 
1.563     damieng  5989: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 5990: sub load_parameter_names {
                   5991:     open(my $config,"<$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
                   5992:     while (my $configline=<$config>) {
1.560     damieng  5993:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   5994:         chomp($configline);
                   5995:         my ($short,$plain)=split(/:/,$configline);
                   5996:         my (undef,$name,$type)=split(/\&/,$short,3);
                   5997:         if ($type eq 'display') {
                   5998:             $standard_parms{$name} = $plain;
1.469     raeburn  5999:         } elsif ($type eq 'type') {
1.560     damieng  6000:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  6001:         }
1.328     albertel 6002:     }
                   6003:     close($config);
                   6004:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   6005:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575   ! raeburn  6006:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 6007: }
                   6008: 
1.563     damieng  6009: # Returns a parameter title for standard parameters, the name for others.
                   6010: #
                   6011: # @param {string} $name - parameter name
                   6012: # @returns {string}
1.292     www      6013: sub standard_parameter_names {
                   6014:     my ($name)=@_;
1.328     albertel 6015:     if (!%standard_parms) {
1.560     damieng  6016:         &load_parameter_names();
1.328     albertel 6017:     }
1.292     www      6018:     if ($standard_parms{$name}) {
1.560     damieng  6019:         return $standard_parms{$name};
1.446     bisitz   6020:     } else {
1.560     damieng  6021:         return $name;
1.292     www      6022:     }
                   6023: }
1.290     www      6024: 
1.563     damieng  6025: # Returns a parameter type for standard parameters, undef for others.
                   6026: #
                   6027: # @param {string} $name - parameter name
                   6028: # @returns {string}
1.469     raeburn  6029: sub standard_parameter_types {
                   6030:     my ($name)=@_;
                   6031:     if (!%standard_parms_types) {
                   6032:         &load_parameter_names();
                   6033:     }
                   6034:     if ($standard_parms_types{$name}) {
                   6035:         return $standard_parms_types{$name};
                   6036:     }
                   6037:     return;
                   6038: }
1.309     www      6039: 
1.563     damieng  6040: # Returns a parameter level title (not localized) from the parameter level name.
                   6041: #
                   6042: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   6043: # @returns {string}
1.557     raeburn  6044: sub standard_parameter_levels {
                   6045:     my ($name)=@_;
                   6046:     my %levels = (
                   6047:                     'resourcelevel'   => 'a single resource',
                   6048:                     'maplevel'        => 'the enclosing map/folder', 
                   6049:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   6050:                     'courselevel'     => 'the general (course) level',
                   6051:                  );
                   6052:     if ($levels{$name}) {
                   6053:         return $levels{$name};
                   6054:     }
                   6055:     return;
                   6056: }
                   6057: 
1.560     damieng  6058: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  6059: #
                   6060: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 6061: sub parm_change_log {
1.568     raeburn  6062:     my ($r,$parm_permission)=@_;
1.531     raeburn  6063:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6064:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  6065:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6066:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 6067:     text=>"Parameter Change Log"});
1.522     raeburn  6068:     my $js = '<script type="text/javascript">'."\n".
                   6069:              '// <![CDATA['."\n".
                   6070:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   6071:              '// ]]>'."\n".
                   6072:              '</script>'."\n";
                   6073:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 6074:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  6075:     &startSettingsScreen($r,'parmset',$crstype);
                   6076:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 6077: 
1.301     www      6078:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 6079: 
1.522     raeburn  6080:     $r->print('<div class="LC_left_float">'.
                   6081:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   6082:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 6083:                      method="post" name="parameterlog">');
1.446     bisitz   6084: 
1.311     albertel 6085:     my %saveable_parameters = ('show' => 'scalar',);
                   6086:     &Apache::loncommon::store_course_settings('parameter_log',
                   6087:                                               \%saveable_parameters);
                   6088:     &Apache::loncommon::restore_course_settings('parameter_log',
                   6089:                                                 \%saveable_parameters);
1.522     raeburn  6090:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   6091:               '<input type="submit" value="'.&mt('Display').'" />'.
                   6092:               '</form></fieldset></div><br clear="all" />');
1.301     www      6093: 
1.568     raeburn  6094:     my $readonly = 1;
                   6095:     if ($parm_permission->{'edit'}) {
                   6096:         undef($readonly);
                   6097:     }
1.531     raeburn  6098:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      6099:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 6100:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  6101:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   6102:     unless ($readonly) {
                   6103:         $r->print('<th>'.&mt('Announce').'</th>');
                   6104:     }
                   6105:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      6106:     my $shown=0;
1.349     www      6107:     my $folder='';
                   6108:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  6109:         my $last='';
                   6110:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   6111:                 &GDBM_READER(),0640)) {
                   6112:             $last=$hash{'last_known'};
                   6113:             untie(%hash);
                   6114:         }
                   6115:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   6116:     }
                   6117:     foreach my $id (sort {
                   6118:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   6119:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   6120:                 }
                   6121:                 my $aid = (split('00000',$a))[-1];
                   6122:                 my $bid = (split('00000',$b))[-1];
                   6123:                 return $bid<=>$aid;
1.473     amueller 6124:             } (keys(%parmlog))) {
1.294     www      6125:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  6126:         my $count = 0;
                   6127:         my $time =
                   6128:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   6129:         my $plainname =
                   6130:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   6131:                         $parmlog{$id}{'exe_udom'});
                   6132:         my $about_me_link =
                   6133:             &Apache::loncommon::aboutmewrapper($plainname,
                   6134:                             $parmlog{$id}{'exe_uname'},
                   6135:                             $parmlog{$id}{'exe_udom'});
                   6136:         my $send_msg_link='';
1.568     raeburn  6137:         if ((!$readonly) && 
                   6138:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  6139:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   6140:             $send_msg_link ='<br />'.
                   6141:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   6142:                             $parmlog{$id}{'exe_uname'},
                   6143:                             $parmlog{$id}{'exe_udom'});
                   6144:         }
                   6145:         my $row_start=&Apache::loncommon::start_data_table_row();
                   6146:         my $makenewrow=0;
                   6147:         my %istype=();
                   6148:         my $output;
                   6149:         foreach my $changed (reverse(sort(@changes))) {
                   6150:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   6151:             my $typeflag = ($changed =~/\.type$/ &&
                   6152:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 6153:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.560     damieng  6154:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},undef,undef,$typeflag);
                   6155:             if ($env{'request.course.sec'} ne '') {
                   6156:                 next if (($issection ne '') && ($issection ne $env{'request.course.sec'}));
                   6157:                 if ($uname ne '') {
                   6158:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   6159:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   6160:                 }
                   6161:             }
                   6162:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   6163:                 if ($folder) {
                   6164:                     if ($middle!~/^\Q$folder\E/) { next; }
                   6165:                 }
                   6166:             }
                   6167:             if ($typeflag) {
                   6168:                 $istype{$parmname}=$value;
                   6169:                 if (!$env{'form.includetypes'}) { next; }
                   6170:             }
                   6171:             $count++;
                   6172:             if ($makenewrow) {
                   6173:                 $output .= $row_start;
                   6174:             } else {
                   6175:                 $makenewrow=1;
                   6176:             }
1.470     raeburn  6177:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  6178:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   6179:                 &mt($parmitem).'</td><td>'.
                   6180:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   6181:             my $stillactive=0;
                   6182:             if ($parmlog{$id}{'delflag'}) {
                   6183:                 $output .= &mt('Deleted');
                   6184:             } else {
                   6185:                 if ($typeflag) {
1.470     raeburn  6186:                     my $parmitem = &standard_parameter_names($value); 
                   6187:                     $parmitem = &mt($parmitem);
1.560     damieng  6188:                     $output .= &mt('Type: [_1]',$parmitem);
                   6189:                 } else {
                   6190:                     my ($level,@all)=&parmval_by_symb($what,$middle,
                   6191:                         &Apache::lonnet::metadata($middle,$what),
                   6192:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  6193:                     my $showvalue = $value;
                   6194:                     if ($istype{$parmname} eq '') {
                   6195:                         my $type = &standard_parameter_types($parmname);
                   6196:                         if ($type ne '') {
                   6197:                             if (&isdateparm($type)) {
                   6198:                                 $showvalue =
                   6199:                                     &Apache::lonlocal::locallocaltime($value);
                   6200:                             }
                   6201:                         }
                   6202:                     } else {
1.560     damieng  6203:                         if (&isdateparm($istype{$parmname})) {
                   6204:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   6205:                         }
1.469     raeburn  6206:                     }
                   6207:                     $output .= $showvalue;
1.560     damieng  6208:                     if ($value ne $all[$level]) {
                   6209:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   6210:                     } else {
                   6211:                         $stillactive=1;
                   6212:                     }
                   6213:                 }
1.473     amueller 6214:             }
1.568     raeburn  6215:             $output .= '</td>';
                   6216: 
                   6217:             unless ($readonly) { 
                   6218:                 $output .= '<td>';
                   6219:                 if ($stillactive) {
                   6220:                     my $parmitem = &standard_parameter_names($parmname);
                   6221:                     $parmitem = &mt($parmitem);
                   6222:                     my $title=&mt('Changed [_1]',$parmitem);
                   6223:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   6224:                         $parmitem,$realmdescription,
                   6225:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   6226:                     if (($uname) && ($udom)) {
                   6227:                         $output .=
                   6228:                         &Apache::loncommon::messagewrapper('Notify User',
                   6229:                                                            $uname,$udom,$title,
                   6230:                                                            $description);
                   6231:                     } else {
                   6232:                         $output .=
                   6233:                             &Apache::lonrss::course_blog_link($id,$title,
                   6234:                                                               $description);
                   6235:                     }
1.560     damieng  6236:                 }
1.568     raeburn  6237:                 $output .= '</td>';
1.560     damieng  6238:             }
1.568     raeburn  6239:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 6240:         }
1.560     damieng  6241:         if ($env{'form.displayfilter'} eq 'containing') {
                   6242:             my $wholeentry=$about_me_link.':'.
                   6243:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   6244:             $output;
                   6245:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 6246:         }
1.349     www      6247:         if ($count) {
1.560     damieng  6248:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   6249:                         <td rowspan="'.$count.'">'.$about_me_link.
                   6250:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   6251:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   6252:             $send_msg_link.'</td>'.$output);
                   6253:             $shown++;
                   6254:         }
                   6255:         if (!($env{'form.show'} eq &mt('all')
                   6256:             || $shown<=$env{'form.show'})) { last; }
1.286     www      6257:     }
1.301     www      6258:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      6259:     &endSettingsScreen($r);
1.284     www      6260:     $r->print(&Apache::loncommon::end_page());
                   6261: }
                   6262: 
1.560     damieng  6263: ##################################################
                   6264: # MISC !
                   6265: ##################################################
                   6266: 
1.563     damieng  6267: # Stores slot information.
1.560     damieng  6268: # Used by table UI
1.563     damieng  6269: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   6270: #
                   6271: # @param {string} $slot_name - slot name
                   6272: # @param {string} $cdom - course domain
                   6273: # @param {string} $cnum - course number
                   6274: # @param {string} $symb - resource symb
                   6275: # @param {string} $uname - user name
                   6276: # @param {string} $udom - user domain
                   6277: # @returns {string} - 'ok' or error name
1.437     raeburn  6278: sub update_slots {
                   6279:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   6280:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   6281:     if (!keys(%slot)) {
                   6282:         return 'error: slot does not exist';
                   6283:     }
                   6284:     my $max=$slot{'maxspace'};
                   6285:     if (!defined($max)) { $max=99999; }
                   6286: 
                   6287:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   6288:                                        "^$slot_name\0");
                   6289:     my ($tmp)=%consumed;
                   6290:     if ($tmp=~/^error: 2 / ) {
                   6291:         return 'error: unable to determine current slot status';
                   6292:     }
                   6293:     my $last=0;
                   6294:     foreach my $key (keys(%consumed)) {
                   6295:         my $num=(split('\0',$key))[1];
                   6296:         if ($num > $last) { $last=$num; }
                   6297:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   6298:             return 'ok';
                   6299:         }
                   6300:     }
                   6301: 
                   6302:     if (scalar(keys(%consumed)) >= $max) {
                   6303:         return 'error: no space left in slot';
                   6304:     }
                   6305:     my $wanted=$last+1;
                   6306: 
                   6307:     my %reservation=('name'      => $uname.':'.$udom,
                   6308:                      'timestamp' => time,
                   6309:                      'symb'      => $symb);
                   6310: 
                   6311:     my $success=&Apache::lonnet::newput('slot_reservations',
                   6312:                                         {"$slot_name\0$wanted" =>
                   6313:                                              \%reservation},
                   6314:                                         $cdom, $cnum);
1.438     raeburn  6315:     if ($success eq 'ok') {
                   6316:         my %storehash = (
                   6317:                           symb    => $symb,
                   6318:                           slot    => $slot_name,
                   6319:                           action  => 'reserve',
                   6320:                           context => 'parameter',
                   6321:                         );
1.526     raeburn  6322:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  6323:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  6324: 
1.526     raeburn  6325:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  6326:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  6327:     }
1.437     raeburn  6328:     return $success;
                   6329: }
                   6330: 
1.563     damieng  6331: # Deletes a slot reservation.
1.560     damieng  6332: # Used by table UI
1.563     damieng  6333: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   6334: #
                   6335: # @param {string} $slot_name - slot name
                   6336: # @param {string} $cdom - course domain
                   6337: # @param {string} $cnum - course number
                   6338: # @param {string} $uname - user name
                   6339: # @param {string} $udom - user domain
                   6340: # @param {string} $symb - resource symb
                   6341: # @returns {string} - 'ok' or error name
1.437     raeburn  6342: sub delete_slots {
                   6343:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   6344:     my $delresult;
                   6345:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   6346:                                          $cnum, "^$slot_name\0");
                   6347:     if (&Apache::lonnet::error(%consumed)) {
                   6348:         return 'error: unable to determine current slot status';
                   6349:     }
                   6350:     my ($tmp)=%consumed;
                   6351:     if ($tmp=~/^error: 2 /) {
                   6352:         return 'error: unable to determine current slot status';
                   6353:     }
                   6354:     foreach my $key (keys(%consumed)) {
                   6355:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   6356:             my $num=(split('\0',$key))[1];
                   6357:             my $entry = $slot_name.'\0'.$num;
                   6358:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   6359:                                               $cdom,$cnum);
                   6360:             if ($delresult eq 'ok') {
                   6361:                 my %storehash = (
                   6362:                                   symb    => $symb,
                   6363:                                   slot    => $slot_name,
                   6364:                                   action  => 'release',
                   6365:                                   context => 'parameter',
                   6366:                                 );
1.526     raeburn  6367:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  6368:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  6369:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  6370:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  6371:             }
                   6372:         }
                   6373:     }
                   6374:     return $delresult;
                   6375: }
                   6376: 
1.563     damieng  6377: # Returns true if there is a current course.
1.560     damieng  6378: # Used by handler
1.563     damieng  6379: #
                   6380: # @returns {boolean}
1.355     albertel 6381: sub check_for_course_info {
                   6382:     my $navmap = Apache::lonnavmaps::navmap->new();
                   6383:     return 1 if ($navmap);
                   6384:     return 0;
                   6385: }
                   6386: 
1.563     damieng  6387: # Returns the current course host and host LON-CAPA version.
                   6388: #
                   6389: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  6390: sub parameter_release_vars { 
1.504     raeburn  6391:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6392:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   6393:    my $chostname = &Apache::lonnet::hostname($chome);
                   6394:    my ($cmajor,$cminor) = 
                   6395:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   6396:    return ($chostname,$cmajor,$cminor);
                   6397: }
                   6398: 
1.563     damieng  6399: # Checks if the course host version can handle a parameter required version,
                   6400: # and if it does, stores the release needed for the course.
                   6401: #
                   6402: # @param {string} $name - parameter name
                   6403: # @param {string} $value - parameter value
                   6404: # @param {string} $valmatch - name of the test used for checking the value
                   6405: # @param {string} $namematch - name of the test used for checking the name
                   6406: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   6407: # @param {integer} $cmajor - course major version number
                   6408: # @param {integer} $cminor - course minor version number
                   6409: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  6410: sub parameter_releasecheck {
1.557     raeburn  6411:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  6412:     my $needsnewer;
                   6413:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   6414:     if (($cmajor < $needsmajor) || 
                   6415:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   6416:         $needsnewer = 1;
1.557     raeburn  6417:     } elsif ($name) {
                   6418:         if ($valmatch) {
                   6419:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   6420:         } elsif ($value) { 
                   6421:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   6422:         }
                   6423:     } elsif ($namematch) {
                   6424:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  6425:     }
                   6426:     return $needsnewer;
                   6427: }
                   6428: 
1.568     raeburn  6429: sub get_permission {
                   6430:     my %permission;
                   6431:     my $allowed = 0;
                   6432:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   6433:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   6434:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   6435:                   $env{'request.course.sec'}))) {
                   6436:         %permission= (
                   6437:                        'edit'               => 1,
                   6438:                        'set'                => 1,
                   6439:                        'setoverview'        => 1,
                   6440:                        'addmetadata'        => 1,
                   6441:                        'ordermetadata'      => 1,
                   6442:                        'setrestrictmeta'    => 1,
                   6443:                        'newoverview'        => 1,
                   6444:                        'setdefaults'        => 1,
                   6445:                        'settable'           => 1,
                   6446:                        'parameterchangelog' => 1,
                   6447:                        'cleanparameters'    => 1,
                   6448:                        'dateshift1'         => 1,
                   6449:                        'dateshift2'         => 1,
                   6450:                        'helper'             => 1,
                   6451:          );
                   6452:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   6453:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   6454:                   $env{'request.course.sec'}))) {
                   6455:         %permission = (
                   6456:                        'set'                => 1,
                   6457:                        'settable'           => 1,
                   6458:                        'newoverview'        => 1,
                   6459:                        'setoverview'        => 1,
                   6460:                        'parameterchangelog' => 1,
                   6461:                       );
                   6462:     }
                   6463:     foreach my $perm (values(%permission)) {
                   6464:         if ($perm) { $allowed=1; last; }
                   6465:     }
                   6466:     return (\%permission,$allowed);
                   6467: }
                   6468: 
1.560     damieng  6469: ##################################################
                   6470: # HANDLER
                   6471: ##################################################
                   6472: 
                   6473: # Main handler for lonparmset.
                   6474: # Sub called based on request parameters action and command:
                   6475: # no command or action: print_main_menu
                   6476: # command 'set': assessparms (direct access to table mode for a resource)
                   6477: #                (this can also be accessed simply with the symb parameter)
                   6478: # action 'setoverview': overview (display all existing parameter settings)
                   6479: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   6480: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   6481: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   6482: # action 'newoverview': newoverview (overview mode)
                   6483: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   6484: # action 'settable': assessparms (table mode)
                   6485: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   6486: #                              blog postings, user notification changes)
                   6487: # action 'cleanparameters': clean_parameters (unused)
                   6488: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   6489: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      6490: sub handler {
1.43      albertel 6491:     my $r=shift;
1.30      www      6492: 
1.376     albertel 6493:     &reset_caches();
                   6494: 
1.414     droeschl 6495:     &Apache::loncommon::content_type($r,'text/html');
                   6496:     $r->send_http_header;
                   6497:     return OK if $r->header_only;
                   6498: 
1.193     albertel 6499:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 6500:                         ['action','state',
1.205     www      6501:                                              'pres_marker',
                   6502:                                              'pres_value',
1.206     www      6503:                                              'pres_type',
1.506     www      6504:                                              'filter','part',
1.390     www      6505:                                              'udom','uname','symb','serial','timebase']);
1.131     www      6506: 
1.83      bowersj2 6507: 
1.193     albertel 6508:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 6509:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      6510:                         text=>"Content and Problem Settings",
1.473     amueller 6511:                         faq=>10,
                   6512:                         bug=>'Instructor Interface',
1.442     droeschl 6513:                                             help =>
                   6514:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      6515: 
1.30      www      6516: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  6517:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 6518:     my $exists = &check_for_course_info();
                   6519: 
1.568     raeburn  6520:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 6521:         #
                   6522:         # Main switch on form.action and form.state, as appropriate
                   6523:         #
                   6524:         # Check first if coming from someone else headed directly for
                   6525:         #  the table mode
1.568     raeburn  6526:         if (($parm_permission->{'set'}) && 
                   6527:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   6528:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   6529:             &assessparms($r,$parm_permission);
1.193     albertel 6530:         } elsif (! exists($env{'form.action'})) {
                   6531:             &print_main_menu($r,$parm_permission);
1.568     raeburn  6532:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   6533:             &print_main_menu($r,$parm_permission);
1.414     droeschl 6534:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  6535:             &overview($r,$parm_permission);
1.560     damieng  6536:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   6537:             &addmetafield($r);
                   6538:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   6539:             &order_meta_fields($r);
1.414     droeschl 6540:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  6541:             &setrestrictmeta($r);
1.414     droeschl 6542:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  6543:             &newoverview($r,$parm_permission);
1.414     droeschl 6544:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  6545:             &defaultsetter($r);
                   6546:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  6547:             &assessparms($r,$parm_permission);
1.414     droeschl 6548:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  6549:             &parm_change_log($r,$parm_permission);
1.414     droeschl 6550:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  6551:             &clean_parameters($r);
1.414     droeschl 6552:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      6553:             &date_shift_one($r);
1.414     droeschl 6554:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      6555:             &date_shift_two($r);
1.446     bisitz   6556:         }
1.43      albertel 6557:     } else {
1.1       www      6558: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  6559:         if ($exists) {
                   6560:             $env{'user.error.msg'}=
                   6561:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   6562:         } else {
                   6563:             $env{'user.error.msg'}=
                   6564:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   6565:         }
                   6566:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 6567:     }
1.376     albertel 6568:     &reset_caches();
                   6569: 
1.43      albertel 6570:     return OK;
1.1       www      6571: }
                   6572: 
                   6573: 1;
                   6574: __END__
                   6575: 
                   6576: 

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