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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.574   ! raeburn     4: # $Id: lonparmset.pm,v 1.573 2017/07/04 21:20:14 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.465     amueller 1942:     );    
                   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)) {
                   2036:             $r->print('<span class="LC_nobreak">'
                   2037:                      .'<label><input type="checkbox" name="pscat" '
                   2038:                      .'value="'.$tempkey.'" ');
                   2039:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2040:                 $r->print( ' checked="checked"');
                   2041:             }
                   2042:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2043:                                                       : $tempkey)
1.536     raeburn  2044:                      .'</label></span><br />'."\n");
1.465     amueller 2045:         }
1.536     raeburn  2046:         $r->print('</div>');
1.465     amueller 2047:     }
1.536     raeburn  2048:     $r->print("\n");
1.453     schualex 2049: }
1.562     damieng  2050: 
                   2051: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
                   2052: # FIXME: remove unused parameters
1.468     amueller 2053: #
1.562     damieng  2054: # @param {Apache2::RequestRec} $r - the Apache request
                   2055: # @param {hash reference} $allparms - hash parameter name -> parameter title (unused)
                   2056: # @param {array reference} $pscat - list of selected parameter names (unused)
                   2057: # @param {hash reference} $keyorder - hash parameter key -> appearance rank (unused)
1.453     schualex 2058: sub shortCuts {
                   2059:     my ($r,$allparms,$pscat,$keyorder)=@_;
                   2060: 
1.491     bisitz   2061:     # Parameter Selection
                   2062:     $r->print(
                   2063:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2064:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2065:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2066:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2067:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2068:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2069:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2070:        .&Apache::lonhtmlcommon::end_funclist()
                   2071:     );
                   2072: 
                   2073:     # Add Selection for...
                   2074:     $r->print(
                   2075:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2076:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2077:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2078:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2079:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2080:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2081:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2082:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2083:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2084:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2085:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2086:        .&Apache::lonhtmlcommon::end_funclist()
                   2087:     );
1.208     www      2088: }
                   2089: 
1.562     damieng  2090: # Prints HTML to select parts to view (except for the title).
                   2091: # Used by table and overview modes.
                   2092: #
                   2093: # @param {Apache2::RequestRec} $r - the Apache request
                   2094: # @param {hash reference} $allparts - hash parameter part -> part title
                   2095: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2096: sub partmenu {
1.446     bisitz   2097:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2098:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2099:     if ($selsize > 8) {
                   2100:         $selsize = 8;
                   2101:     }
1.446     bisitz   2102: 
1.523     raeburn  2103:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2104:     $r->print('<option value="all"');
1.562     damieng  2105:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2106:     $r->print('>'.&mt('All Parts').'</option>');
                   2107:     my %temphash=();
                   2108:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2109:     foreach my $tempkey (sort {
1.560     damieng  2110:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2111:             } keys(%{$allparts})) {
                   2112:         unless ($tempkey =~ /\./) {
                   2113:             $r->print('<option value="'.$tempkey.'"');
                   2114:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2115:                 $r->print(' selected="selected"');
                   2116:             }
                   2117:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2118:         }
1.208     www      2119:     }
1.446     bisitz   2120:     $r->print('</select>');
1.209     www      2121: }
                   2122: 
1.562     damieng  2123: # Prints HTML to select a user and/or a group.
                   2124: # Used by table mode.
                   2125: #
                   2126: # @param {Apache2::RequestRec} $r - the Apache request
                   2127: # @param {string} $uname - selected user name
                   2128: # @param {string} $id - selected Student/Employee ID
                   2129: # @param {string} $udom - selected user domain
                   2130: # @param {string} $csec - selected section name
                   2131: # @param {string} $cgroup - selected group name
                   2132: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2133: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2134: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2135: sub usermenu {
1.553     raeburn  2136:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2137:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
                   2138:         &Apache::loncommon::selectstudent_link('parmform','uname','udom');
                   2139:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.412     bisitz   2140: 
1.209     www      2141:     my $sections='';
1.300     albertel 2142:     my %sectionhash = &Apache::loncommon::get_sections();
                   2143: 
1.269     raeburn  2144:     my $groups;
1.553     raeburn  2145:     my %grouphash;
                   2146:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2147:         %grouphash = &Apache::longroup::coursegroups();
                   2148:     } elsif ($env{'request.course.groups'} ne '') {
                   2149:         map { $grouphash{$_} = 1; } split(/,/,$env{'request.course.groups'});
                   2150:     }
1.299     albertel 2151: 
1.412     bisitz   2152:     my $g_s_header='';
                   2153:     my $g_s_footer='';
1.446     bisitz   2154: 
1.552     raeburn  2155:     my $currsec = $env{'request.course.sec'};
                   2156:     if ($currsec) {
                   2157:         $sections=&mt('Section:').' '.$currsec;
                   2158:         if (%grouphash) {
                   2159:             $sections .= ';'.('&nbsp;' x2);
                   2160:         }
                   2161:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2162:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2163:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2164:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2165:         }
                   2166:         $sections .= '>';
1.548     raeburn  2167:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2168:         $sections.='<option value="'.$section.'" '.
                   2169:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2170:                                                               '</option>';
1.209     www      2171:         }
                   2172:         $sections.='</select>';
1.269     raeburn  2173:     }
1.412     bisitz   2174: 
1.552     raeburn  2175:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2176:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2177:         $sections .= qq|
                   2178: <script type="text/javascript">
1.454     bisitz   2179: // <![CDATA[
1.269     raeburn  2180: function group_or_section(caller) {
                   2181:    if (caller == "cgroup") {
                   2182:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2183:            document.parmform.csec.selectedIndex = 0;
                   2184:        }
                   2185:    } else {
                   2186:        if (document.parmform.csec.selectedIndex != 0) {
                   2187:            document.parmform.cgroup.selectedIndex = 0;
                   2188:        }
                   2189:    }
                   2190: }
1.454     bisitz   2191: // ]]>
1.269     raeburn  2192: </script>
                   2193: |;
1.554     raeburn  2194:     } else {
1.269     raeburn  2195:         $sections .= qq|
                   2196: <script type="text/javascript">
1.454     bisitz   2197: // <![CDATA[
1.269     raeburn  2198: function group_or_section(caller) {
                   2199:     return;
                   2200: }
1.454     bisitz   2201: // ]]>
1.269     raeburn  2202: </script>
                   2203: |;
1.446     bisitz   2204:     }
1.299     albertel 2205: 
                   2206:     if (%grouphash) {
1.412     bisitz   2207:         $groups=&mt('Group:').' <select name="cgroup"';
1.552     raeburn  2208:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2209:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2210:         }
                   2211:         $groups .= '>';
1.548     raeburn  2212:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2213:             $groups.='<option value="'.$grp.'" ';
                   2214:             if ($grp eq $cgroup) {
                   2215:                 unless ((defined($uname)) && ($grp eq '')) {
                   2216:                     $groups .=  'selected="selected" ';
                   2217:                 }
                   2218:             } elsif (!defined($cgroup)) {
                   2219:                 if (@{$usersgroups} == 1) {
                   2220:                     if ($grp eq $$usersgroups[0]) {
                   2221:                         $groups .=  'selected="selected" ';
                   2222:                     }
                   2223:                 }
                   2224:             }
                   2225:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2226:         }
                   2227:         $groups.='</select>';
                   2228:     }
1.412     bisitz   2229: 
1.445     neumanie 2230:     if (%sectionhash || %grouphash) {
1.446     bisitz   2231:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2232:         $r->print($sections.$groups);
1.448     bisitz   2233:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2234:     } else {
                   2235:         $r->print($sections); 
1.445     neumanie 2236:     }
1.446     bisitz   2237: 
                   2238:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2239:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2240:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2241:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2242:                  ,$chooseopt));
1.209     www      2243: }
                   2244: 
1.562     damieng  2245: # Prints HTML to select parameters from a list of all parameters.
                   2246: # Uses parmmenu and parmboxes.
                   2247: # Used by table and overview modes.
1.468     amueller 2248: #
1.562     damieng  2249: # @param {Apache2::RequestRec} $r - the Apache request
                   2250: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2251: # @param {array reference} $pscat - list of selected parameter names
                   2252: # @param {array reference} $psprt - list of selected parameter parts (unused)
                   2253: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2254: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2255: sub displaymenu {
1.536     raeburn  2256:     my ($r,$allparms,$pscat,$psprt,$keyorder,$divid)=@_;
1.510     www      2257: 
1.445     neumanie 2258:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2259:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2260: 
1.562     damieng  2261:     &parmmenu($r,$allparms,$pscat,$keyorder); # only $allparms is used by parmmenu
1.536     raeburn  2262:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2263:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2264:     $r->print(&Apache::loncommon::end_scrollbox());
                   2265: 
                   2266:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2267:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2268:  
1.209     www      2269: }
                   2270: 
1.562     damieng  2271: # Prints HTML to select a map.
                   2272: # Used by table mode and overview mode.
                   2273: #
                   2274: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2275: # @param {hash reference} $allmaps - hash map pc -> map src
                   2276: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2277: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2278: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445     neumanie 2279: sub mapmenu {
1.499     raeburn  2280:     my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468     amueller 2281:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2282:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2283:     my $tree=[];
                   2284:     my $treeinfo={};
                   2285:     if (defined($navmap)) {
1.499     raeburn  2286:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2287:         my $curRes;
                   2288:         my $depth = 0;
1.468     amueller 2289:         my %parent = ();
                   2290:         my $startcount = 5;
                   2291:         my $lastcontainer = $startcount;
                   2292: # preparing what is to show ...
1.461     neumanie 2293:         while ($curRes = $it->next()) {
                   2294:             if ($curRes == $it->BEGIN_MAP()) {
                   2295:                 $depth++;
1.468     amueller 2296:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2297:             }
                   2298:             if ($curRes == $it->END_MAP()) {
                   2299:                 $depth--;
1.468     amueller 2300:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2301:             }
                   2302:             if (ref($curRes)) {
1.468     amueller 2303:                 my $symb = $curRes->symb();
                   2304:                 my $ressymb = $symb;
1.461     neumanie 2305:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2306:                     my $type = 'sequence';
                   2307:                     if ($curRes->is_page()) {
                   2308:                         $type = 'page';
                   2309:                     }
                   2310:                     my $id= $curRes->id();
1.468     amueller 2311:                     my $srcf = $curRes->src();
                   2312:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2313:                     if(!exists($treeinfo->{$id})) {
                   2314:                         push(@$tree,$id);
1.473     amueller 2315:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2316:                         $treeinfo->{$id} = {
1.461     neumanie 2317:                                     depth => $depth,
                   2318:                                     type  => $type,
1.468     amueller 2319:                                     name  => $resource_name,
                   2320:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2321:                                     };
1.462     neumanie 2322:                     }
1.461     neumanie 2323:                 }
                   2324:             }
                   2325:         }
1.462     neumanie 2326:     }
1.473     amueller 2327: # Show it ...    
1.484     amueller 2328:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461     neumanie 2329:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2330:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2331:         my $whitespace =
                   2332:             '<img src="'
                   2333:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2334:            .'" alt="" />';
                   2335: 
1.498     bisitz   2336:         # Info about selectable folders/maps
                   2337:         $r->print(
                   2338:             '<div class="LC_info">'
1.508     www      2339:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2340:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2341:            .'</div>'
                   2342:         );
                   2343: 
1.536     raeburn  2344:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2345:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2346: 
1.498     bisitz   2347:         # Display row: "All Maps or Folders"
                   2348:         $r->print(
1.523     raeburn  2349:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2350:            .'<td>'
                   2351:            .'<label>'
                   2352:            .'<input type="radio" name="pschp"'
1.497     bisitz   2353:         );
                   2354:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2355:         $r->print(
                   2356:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2357:            .&mt('All Maps or Folders')
                   2358:            .'</label>'
                   2359:            .'<hr /></td>'
                   2360:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2361:         );
1.497     bisitz   2362: 
1.532     raeburn  2363:         # Display row: "Main Content"
1.468     amueller 2364:         if (exists($$allmaps{1})) {
1.498     bisitz   2365:             $r->print(
                   2366:                 &Apache::loncommon::start_data_table_row()
                   2367:                .'<td>'
                   2368:                .'<label>'
                   2369:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2370:             );
1.497     bisitz   2371:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2372:             $r->print(
                   2373:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2374:                .$$maptitles{1}
                   2375:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2376:                .'</label>'
                   2377:                .'</td>'
                   2378:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2379:             );
                   2380:         }
1.497     bisitz   2381: 
                   2382:         # Display rows for all course maps and folders
1.468     amueller 2383:         foreach my $id (@{$tree}) {
                   2384:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2385:             # Indentation
1.468     amueller 2386:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2387:             my $indent;
                   2388:             for (my $i = 0; $i < $depth; $i++) {
                   2389:                 $indent.= $whitespace;
                   2390:             }
1.461     neumanie 2391:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2392:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2393:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2394:             }
1.468     amueller 2395:             my $symb_name = $$symbp{$id};
                   2396:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2397:             $symb_name = $tail;
1.498     bisitz   2398:             $r->print(
                   2399:                 &Apache::loncommon::start_data_table_row()
                   2400:                .'<td>'
                   2401:                .'<label>'
1.463     bisitz   2402:             );
1.498     bisitz   2403:             # Only offer radio button for folders/maps which can be parameterized
                   2404:             if ($allmaps_inverted{$symb_name}) {
                   2405:                 $r->print(
                   2406:                     '<input type ="radio" name="pschp"'
                   2407:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2408:                 );
                   2409:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2410:                 $r->print('/>');
                   2411:             } else {
                   2412:                 $r->print($whitespace);
1.461     neumanie 2413:             }
1.498     bisitz   2414:             $r->print(
                   2415:                 $indent.$icon.'&nbsp;'
                   2416:                .$treeinfo->{$id}->{name}
                   2417:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2418:                .'</label>'
                   2419:                .'</td>'
                   2420:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2421:             );
1.461     neumanie 2422:         }
1.497     bisitz   2423: 
1.523     raeburn  2424:         $r->print(&Apache::loncommon::end_data_table().
                   2425:                   '<br style="line-height:2px;" />'.
                   2426:                   &Apache::loncommon::end_scrollbox());
1.209     www      2427:     }
                   2428: }
                   2429: 
1.563     damieng  2430: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2431: # Used by table and overview modes.
                   2432: #
                   2433: # @param {Apache2::RequestRec} $r - the Apache request
                   2434: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2435: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2436: sub levelmenu {
1.446     bisitz   2437:     my ($r,$alllevs,$parmlev)=@_;
                   2438: 
1.548     raeburn  2439:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2440:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2441:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2442:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2443:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2444:         if ($parmlev eq $$alllevs{$lev}) {
                   2445:             $r->print(' selected="selected"');
                   2446:         }
                   2447:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2448:     }
1.446     bisitz   2449:     $r->print("</select>");
1.208     www      2450: }
                   2451: 
1.211     www      2452: 
1.563     damieng  2453: # Returns HTML to select a section (with a select HTML element).
                   2454: # Used by overview mode.
                   2455: #
                   2456: # @param {array reference} $selectedsections - list of selected section ids
                   2457: # @returns {string}
1.211     www      2458: sub sectionmenu {
1.553     raeburn  2459:     my ($selectedsections)=@_;
1.300     albertel 2460:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2461:     return '' if (!%sectionhash);
1.300     albertel 2462: 
1.552     raeburn  2463:     my (@possibles,$disabled);
                   2464:     if ($env{'request.course.sec'} ne '') {
                   2465:         @possibles = ($env{'request.course.sec'});
                   2466:         $selectedsections = [$env{'request.course.sec'}];
                   2467:         $disabled = ' disabled="disabled"';
                   2468:     } else {
                   2469:         @possibles = ('all',sort(keys(%sectionhash)));
                   2470:     }
1.553     raeburn  2471:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2472:     foreach my $s (@possibles) {
1.553     raeburn  2473:         $output .= '    <option value="'.$s.'"';
                   2474:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2475:             $output .= ' selected="selected"';
1.473     amueller 2476:         }
1.553     raeburn  2477:         $output .= '>'."$s</option>\n";
1.300     albertel 2478:     }
1.553     raeburn  2479:     $output .= "</select>\n";
                   2480:     return $output;
1.269     raeburn  2481: }
                   2482: 
1.563     damieng  2483: # Returns HTML to select a group (with a select HTML element).
                   2484: # Used by overview mode.
                   2485: #
                   2486: # @param {array reference} $selectedgroups - list of selected group names
                   2487: # @returns {string}
1.269     raeburn  2488: sub groupmenu {
1.553     raeburn  2489:     my ($selectedgroups)=@_;
                   2490:     my %grouphash;
                   2491:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2492:         %grouphash = &Apache::longroup::coursegroups();
                   2493:     } elsif ($env{'request.course.groups'} ne '') {
                   2494:          map { $grouphash{$_} = 1; } split(/,/,$env{'request.course.groups'});
                   2495:     }
                   2496:     return '' if (!%grouphash);
1.299     albertel 2497: 
1.553     raeburn  2498:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2499:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2500:         $output .= '    <option value="'.$group.'"';
                   2501:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2502:             $output .=  ' selected="selected"';
1.473     amueller 2503:         }
1.553     raeburn  2504:         $output .= '>'."$group</option>\n";
1.211     www      2505:     }
1.553     raeburn  2506:     $output .= "</select>\n";
                   2507:     return $output;
1.211     www      2508: }
                   2509: 
1.563     damieng  2510: # Returns an array with the given parameter split by comma.
                   2511: # Used by assessparms (table mode).
                   2512: #
                   2513: # @param {string} $keyp - the string to split
                   2514: # @returns {Array<string>}
1.210     www      2515: sub keysplit {
                   2516:     my $keyp=shift;
                   2517:     return (split(/\,/,$keyp));
                   2518: }
                   2519: 
1.563     damieng  2520: # Returns the keys in $name, sorted using $keyorder.
                   2521: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   2522: # Used by assessparms (table mode) for resource level.
                   2523: #
                   2524: # @param {hash reference} $name - parameter key -> parameter name
                   2525: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2526: # @returns {Array<string>}
1.210     www      2527: sub keysinorder {
                   2528:     my ($name,$keyorder)=@_;
                   2529:     return sort {
1.560     damieng  2530:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  2531:     } (keys(%{$name}));
1.210     www      2532: }
                   2533: 
1.563     damieng  2534: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   2535: # Used by assessparms (table mode) for map and general levels.
                   2536: #
                   2537: # @param {hash reference} $name - parameter key -> parameter name
                   2538: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2539: # @returns {Array<string>}
1.236     albertel 2540: sub keysinorder_bytype {
                   2541:     my ($name,$keyorder)=@_;
                   2542:     return sort {
1.563     damieng  2543:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  2544:         my $tb=(split('_',$b))[-1];
                   2545:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   2546:             return ($a cmp $b);
                   2547:         }
                   2548:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  2549:     } (keys(%{$name}));
1.236     albertel 2550: }
                   2551: 
1.563     damieng  2552: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   2553: # Used by defaultsetter (parameter settings default actions).
                   2554: #
                   2555: # @param {hash reference} $name - hash parameter name -> parameter title
                   2556: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2557: # @returns {Array<string>}
1.211     www      2558: sub keysindisplayorder {
                   2559:     my ($name,$keyorder)=@_;
                   2560:     return sort {
1.560     damieng  2561:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  2562:     } (keys(%{$name}));
1.211     www      2563: }
                   2564: 
1.563     damieng  2565: # Prints HTML with a choice to sort results by realm or student first.
                   2566: # Used by overview mode.
                   2567: #
                   2568: # @param {Apache2::RequestRec} $r - the Apache request
                   2569: # @param {string} $sortorder - realmstudent|studentrealm
1.214     www      2570: sub sortmenu {
                   2571:     my ($r,$sortorder)=@_;
1.236     albertel 2572:     $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214     www      2573:     if ($sortorder eq 'realmstudent') {
1.422     bisitz   2574:        $r->print(' checked="checked"');
1.214     www      2575:     }
                   2576:     $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236     albertel 2577:     $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214     www      2578:     if ($sortorder eq 'studentrealm') {
1.422     bisitz   2579:        $r->print(' checked="checked"');
1.214     www      2580:     }
1.236     albertel 2581:     $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473     amueller 2582:           '</label>');
1.214     www      2583: }
                   2584: 
1.563     damieng  2585: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   2586: #
                   2587: # @returns {hash}
1.211     www      2588: sub standardkeyorder {
                   2589:     return ('parameter_0_opendate' => 1,
1.473     amueller 2590:         'parameter_0_duedate' => 2,
                   2591:         'parameter_0_answerdate' => 3,
                   2592:         'parameter_0_interval' => 4,
                   2593:         'parameter_0_weight' => 5,
                   2594:         'parameter_0_maxtries' => 6,
                   2595:         'parameter_0_hinttries' => 7,
                   2596:         'parameter_0_contentopen' => 8,
                   2597:         'parameter_0_contentclose' => 9,
                   2598:         'parameter_0_type' => 10,
                   2599:         'parameter_0_problemstatus' => 11,
                   2600:         'parameter_0_hiddenresource' => 12,
                   2601:         'parameter_0_hiddenparts' => 13,
                   2602:         'parameter_0_display' => 14,
                   2603:         'parameter_0_ordered' => 15,
                   2604:         'parameter_0_tol' => 16,
                   2605:         'parameter_0_sig' => 17,
                   2606:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  2607:         'parameter_0_discussend' => 19,
                   2608:         'parameter_0_discusshide' => 20,
                   2609:         'parameter_0_discussvote' => 21,
1.560     damieng  2610:         'parameter_0_printstartdate'  =>  22,
                   2611:         'parameter_0_printenddate' =>  23);
1.211     www      2612: }
                   2613: 
1.59      matthew  2614: 
1.560     damieng  2615: # Table mode UI.
1.563     damieng  2616: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   2617: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   2618: #
                   2619: # Parameters used from the request:
                   2620: # action - handler action (see handler), usermenu is checking for value 'settable'
                   2621: # cgroup - selected group
                   2622: # command - 'set': direct access to table mode for a resource
                   2623: # csec - selected section
                   2624: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   2625: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   2626: # id - student/employee ID
                   2627: # parmlev - selected level (full|map|general)
                   2628: # part - selected part (unused ?)
                   2629: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   2630: # pres_type - &&&-separated parameter types
                   2631: # pres_value - &&&-separated parameter values
                   2632: # prevvisit - '1' if the user has submitted the form before
                   2633: # pscat (multiple values) - selected parameter names
1.566     damieng  2634: # pschp - selected map pc, or 'all'
1.563     damieng  2635: # psprt (multiple values) - list of selected parameter parts
                   2636: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   2637: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   2638: # symb - resource symb (when a single resource is selected)
                   2639: # udom - selected user domain
                   2640: # uname - selected user name
                   2641: # url - used only with command 'set', the resource url
                   2642: #
                   2643: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  2644: # @param $parm_permission - ref to hash of permissions
                   2645: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      2646: sub assessparms {
1.1       www      2647: 
1.568     raeburn  2648:     my ($r,$parm_permission) = @_;
1.201     www      2649: 
1.512     foxr     2650: 
                   2651: # -------------------------------------------------------- Variable declaration
1.566     damieng  2652:     my @ids=(); # resource and map ids
                   2653:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   2654:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   2655:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   2656:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   2657:     my %uris=(); # hash resource/map id -> resource src
                   2658:     my %maptitles=(); # hash map pc or src -> map title
                   2659:     my %allmaps=(); # hash map pc -> map src
1.563     damieng  2660:     my %alllevs=(); # hash English level title -> value
                   2661: 
                   2662:     my $uname; # selected user name
                   2663:     my $udom; # selected user domain
                   2664:     my $uhome; # server with the user's files, or 'no_host'
                   2665:     my $csec; # selected section name
                   2666:     my $cgroup; # selected group name
                   2667:     my @usersgroups = (); # list of the user groups
1.446     bisitz   2668: 
1.190     albertel 2669:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      2670: 
1.57      albertel 2671:     $alllevs{'Resource Level'}='full';
1.215     www      2672:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 2673:     $alllevs{'Course Level'}='general';
                   2674: 
1.563     damieng  2675:     my %allparms; # hash parameter name -> parameter title
                   2676:     my %allparts; # hash parameter part -> part title
1.512     foxr     2677: # ------------------------------------------------------------------------------
                   2678: 
1.210     www      2679: #
                   2680: # Order in which these parameters will be displayed
                   2681: #
1.211     www      2682:     my %keyorder=&standardkeyorder();
                   2683: 
1.512     foxr     2684: #    @ids=();
                   2685: #    %symbp=();       # These seem defined above already.
                   2686: #    %typep=();
1.43      albertel 2687: 
                   2688:     my $message='';
                   2689: 
1.190     albertel 2690:     $csec=$env{'form.csec'};
1.552     raeburn  2691:     if ($env{'request.course.sec'} ne '') {
                   2692:         $csec = $env{'request.course.sec'};    
                   2693:     }
                   2694: 
1.553     raeburn  2695: # Check group privs.
1.269     raeburn  2696:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  2697:     my $noeditgrp; 
                   2698:     if ($cgroup ne '') {
                   2699:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2700:             if (($env{'request.course.groups'} eq '') || 
                   2701:                 (!grep(/^\Q$cgroup\E$/,split(/,/,$env{'request.course.groups'})))) {
                   2702:                 $noeditgrp = 1;
                   2703:             }
                   2704:         }
                   2705:     }
1.188     www      2706: 
1.190     albertel 2707:     if      ($udom=$env{'form.udom'}) {
                   2708:     } elsif ($udom=$env{'request.role.domain'}) {
                   2709:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 2710:     } else {
1.473     amueller 2711:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 2712:     }
1.468     amueller 2713:     
1.43      albertel 2714: 
1.134     albertel 2715:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 2716:     my $pschp=$env{'form.pschp'};
1.506     www      2717: 
                   2718: 
1.134     albertel 2719:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      2720:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      2721:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 2722: 
1.43      albertel 2723:     my $pssymb='';
1.57      albertel 2724:     my $parmlev='';
1.446     bisitz   2725: 
1.190     albertel 2726:     unless ($env{'form.parmlev'}) {
1.57      albertel 2727:         $parmlev = 'map';
                   2728:     } else {
1.190     albertel 2729:         $parmlev = $env{'form.parmlev'};
1.57      albertel 2730:     }
1.26      www      2731: 
1.29      www      2732: # ----------------------------------------------- Was this started from grades?
                   2733: 
1.560     damieng  2734:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   2735:             (!$env{'form.dis'})) {
1.473     amueller 2736:         my $url=$env{'form.url'};
                   2737:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   2738:         $pssymb=&Apache::lonnet::symbread($url);
                   2739:         if (!@pscat) { @pscat=('all'); }
                   2740:         $pschp='';
1.57      albertel 2741:         $parmlev = 'full';
1.190     albertel 2742:     } elsif ($env{'form.symb'}) {
1.473     amueller 2743:         $pssymb=$env{'form.symb'};
                   2744:         if (!@pscat) { @pscat=('all'); }
                   2745:         $pschp='';
1.57      albertel 2746:         $parmlev = 'full';
1.43      albertel 2747:     } else {
1.473     amueller 2748:         $env{'form.url'}='';
1.43      albertel 2749:     }
                   2750: 
1.190     albertel 2751:     my $id=$env{'form.id'};
1.43      albertel 2752:     if (($id) && ($udom)) {
1.555     raeburn  2753:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 2754:         if ($uname) {
                   2755:             $id='';
                   2756:         } else {
                   2757:             $message=
1.540     bisitz   2758:                 '<p class="LC_warning">'.
                   2759:                 &mt('Unknown ID [_1] at domain [_2]',
                   2760:                     "'".$id."'","'".$udom."'").
                   2761:                 '</p>';
1.473     amueller 2762:         }
1.43      albertel 2763:     } else {
1.473     amueller 2764:         $uname=$env{'form.uname'};
1.43      albertel 2765:     }
                   2766:     unless ($udom) { $uname=''; }
                   2767:     $uhome='';
                   2768:     if ($uname) {
1.473     amueller 2769:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 2770:         if ($uhome eq 'no_host') {
1.473     amueller 2771:             $message=
1.540     bisitz   2772:                 '<p class="LC_warning">'.
                   2773:                 &mt('Unknown user [_1] at domain [_2]',
                   2774:                     "'".$uname."'","'".$udom."'").
                   2775:                 '</p>';
1.473     amueller 2776:             $uname='';
1.12      www      2777:         } else {
1.473     amueller 2778:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   2779:                           $env{'request.course.id'});
                   2780:             if ($csec eq '-1') {
1.540     bisitz   2781:                 $message=
                   2782:                     '<p class="LC_warning">'.
                   2783:                     &mt('User [_1] at domain [_2] not in this course',
                   2784:                         "'".$uname."'","'".$udom."'").
                   2785:                     '</p>';
1.473     amueller 2786:                 $uname='';
                   2787:                 $csec=$env{'form.csec'};
1.269     raeburn  2788:                 $cgroup=$env{'form.cgroup'};
1.473     amueller 2789:             } else {
                   2790:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   2791:                   ('firstname','middlename','lastname','generation','id'));
                   2792:                 $message="\n<p>\n".&mt("Full Name").": ".
                   2793:                 $name{'firstname'}.' '.$name{'middlename'}.' '
                   2794:                 .$name{'lastname'}.' '.$name{'generation'}.
1.501     bisitz   2795:                 "<br />\n".&mt('Student/Employee ID').": ".$name{'id'}.'<p>';
1.473     amueller 2796:             }
1.297     raeburn  2797:             @usersgroups = &Apache::lonnet::get_users_groups(
1.275     raeburn  2798:                                        $udom,$uname,$env{'request.course.id'});
1.297     raeburn  2799:             if (@usersgroups > 0) {
1.306     albertel 2800:                 unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
1.275     raeburn  2801:                     $cgroup = $usersgroups[0];
1.297     raeburn  2802:                 }
1.269     raeburn  2803:             }
1.12      www      2804:         }
1.43      albertel 2805:     }
1.2       www      2806: 
1.43      albertel 2807:     unless ($csec) { $csec=''; }
1.269     raeburn  2808:     unless ($cgroup) { $cgroup=''; }
1.12      www      2809: 
1.14      www      2810: # --------------------------------------------------------- Get all assessments
1.446     bisitz   2811:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 2812:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   2813:                 \%keyorder);
1.63      bowersj2 2814: 
1.57      albertel 2815:     $mapp{'0.0'} = '';
                   2816:     $symbp{'0.0'} = '';
1.99      albertel 2817: 
1.14      www      2818: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  2819:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      2820:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   2821:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   2822:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  2823:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   2824:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  2825:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   2826:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   2827:         my $totalstored = 0;
1.546     raeburn  2828:         my $now = time;
1.473     amueller 2829:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  2830:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  2831:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  2832:                 next if ($csec ne $env{'request.course.sec'});
                   2833:             }
1.556     raeburn  2834:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  2835:                 next if ($noeditgrp);
1.557     raeburn  2836:             }
                   2837:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   2838:                 $namematch = 'maplevelrecurse';
                   2839:             }
1.556     raeburn  2840:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  2841:                 my (@ok_slots,@fail_slots,@del_slots);
                   2842:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   2843:                 my ($level,@all) =
                   2844:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   2845:                                      $csec,$cgroup,$courseopt);
                   2846:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   2847:                     next if ($slot_name eq '');
                   2848:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   2849:                         push(@ok_slots,$slot_name);
                   2850: 
                   2851:                     } else {
                   2852:                         push(@fail_slots,$slot_name);
                   2853:                     }
                   2854:                 }
                   2855:                 if (@ok_slots) {
                   2856:                     $values[$i] = join(':',@ok_slots);
                   2857:                 } else {
                   2858:                     $values[$i] = '';
                   2859:                 }
                   2860:                 if ($all[$level] ne '') {
                   2861:                     my @existing = split(/:/,$all[$level]);
                   2862:                     foreach my $slot_name (@existing) {
                   2863:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   2864:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   2865:                                 push(@del_slots,$slot_name);
                   2866:                             }
                   2867:                         }
                   2868:                     }
                   2869:                 }
1.554     raeburn  2870:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  2871:                 $name = $1;
1.533     raeburn  2872:                 my $val = $values[$i];
1.549     raeburn  2873:                 my $valmatch = '';
1.533     raeburn  2874:                 if ($name eq 'examcode') {
1.544     raeburn  2875:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   2876:                         $val = 'valid';
                   2877:                     }
1.546     raeburn  2878:                 } elsif ($name eq 'printstartdate') {
                   2879:                     if ($val =~ /^\d+$/) {
                   2880:                         if ($val > $now) {
                   2881:                             $val = 'future';
                   2882:                         }
                   2883:                     } 
                   2884:                 } elsif ($name eq 'printenddate') {
                   2885:                     if ($val =~ /^\d+$/) {
                   2886:                         if ($val < $now) {
                   2887:                             $val = 'past';
                   2888:                         }
                   2889:                     }
1.549     raeburn  2890:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   2891:                     my $stringtype = &get_stringtype($name);
                   2892:                     my $stringmatch = &standard_string_matches($stringtype);
                   2893:                     if (ref($stringmatch) eq 'ARRAY') {
                   2894:                         foreach my $item (@{$stringmatch}) {
                   2895:                             if (ref($item) eq 'ARRAY') {
                   2896:                                 my ($regexpname,$pattern) = @{$item};
                   2897:                                 if ($pattern ne '') {
                   2898:                                     if ($val =~ /$pattern/) {
                   2899:                                         $valmatch = $regexpname;
                   2900:                                         $val = '';
                   2901:                                         last;
                   2902:                                     }
                   2903:                                 }
                   2904:                             }
                   2905:                         }
                   2906:                     }
1.554     raeburn  2907:                 } elsif ($name eq 'interval') {
                   2908:                     my $intervaltype = &get_intervaltype($name);
                   2909:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   2910:                     if (ref($intervalmatch) eq 'ARRAY') {
                   2911:                         foreach my $item (@{$intervalmatch}) {
                   2912:                             if (ref($item) eq 'ARRAY') {
                   2913:                                 my ($regexpname,$pattern) = @{$item};
                   2914:                                 if ($pattern ne '') {
                   2915:                                     if ($val =~ /$pattern/) {
                   2916:                                         $valmatch = $regexpname;
                   2917:                                         $val = '';
                   2918:                                         last;
                   2919:                                     }
                   2920:                                 }
                   2921:                             }
                   2922:                         }
                   2923:                     }
1.533     raeburn  2924:                 }
1.504     raeburn  2925:                 $needsrelease =
1.557     raeburn  2926:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  2927:                 if ($needsrelease) {
1.505     raeburn  2928:                     unless ($got_chostname) {
1.514     raeburn  2929:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  2930:                         $got_chostname = 1;
1.546     raeburn  2931:                     } 
1.557     raeburn  2932:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  2933:                                                           $needsrelease,
                   2934:                                                           $cmajor,$cminor);
1.500     raeburn  2935:                 }
1.437     raeburn  2936:             }
1.504     raeburn  2937:             if ($needsnewer) {
1.557     raeburn  2938:                 undef($namematch);
                   2939:             } else {
                   2940:                 my $currneeded;
                   2941:                 if ($needsrelease) {
                   2942:                     $currneeded = $needsrelease;
                   2943:                 }
                   2944:                 if ($namematch) {
                   2945:                     $needsrelease =
                   2946:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   2947:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   2948:                         unless ($got_chostname) {
                   2949:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   2950:                             $got_chostname = 1;
                   2951:                         }
                   2952:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   2953:                                                               $needsrelease,
                   2954:                                                               $cmajor,$cminor);
                   2955:                     } else {
                   2956:                         undef($namematch);
                   2957:                     }
                   2958:                 }
                   2959:             }
                   2960:             if ($needsnewer) {
                   2961:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  2962:                                                 $cminor,$needsrelease);
                   2963:             } else {
                   2964:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   2965:                                      $values[$i],
                   2966:                                      $types[$i],
                   2967:                                      $uname,$udom,$csec,$cgroup);
                   2968:                 $totalstored ++;
                   2969:             }
1.473     amueller 2970:         }
1.68      www      2971: # ---------------------------------------------------------------- Done storing
1.504     raeburn  2972:         if ($totalstored) {
                   2973:             $message.='<p class="LC_warning">'
                   2974:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   2975:                      .&Apache::loncommon::help_open_topic('Caching')
                   2976:                      .'</p>';
                   2977:         }
1.68      www      2978:     }
1.57      albertel 2979: #----------------------------------------------- if all selected, fill in array
1.563     damieng  2980:     if ($pscat[0] eq "all") {
                   2981:         @pscat = (keys(%allparms));
                   2982:     }
                   2983:     if (!@pscat) {
                   2984:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   2985:     };
                   2986:     if ($psprt[0] eq "all" || !@psprt) {
                   2987:         @psprt = (keys(%allparts));
                   2988:     }
1.2       www      2989: # ------------------------------------------------------------------ Start page
1.63      bowersj2 2990: 
1.531     raeburn  2991:     my $crstype = &Apache::loncommon::course_type();
                   2992:     &startpage($r,$pssymb,$crstype);
1.57      albertel 2993: 
1.548     raeburn  2994:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.563     damieng  2995:             'date_interval','int','float','string') {
1.473     amueller 2996:         $r->print('<input type="hidden" value="'.
1.563     damieng  2997:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   2998:             '" name="recent_'.$item.'" />');
1.44      albertel 2999:     }
1.446     bisitz   3000: 
1.459     bisitz   3001:     # ----- Start Parameter Selection
                   3002: 
                   3003:     # Hide parm selection?
                   3004:     $r->print(<<ENDPARMSELSCRIPT);
                   3005: <script type="text/javascript">
                   3006: // <![CDATA[
                   3007: function parmsel_show() {
1.562     damieng  3008:     document.getElementById('parmsel').style.display = "";
                   3009:     document.getElementById('parmsellink').style.display = "none";
1.459     bisitz   3010: }
                   3011: // ]]>
                   3012: </script>
                   3013: ENDPARMSELSCRIPT
1.474     amueller 3014:     
1.445     neumanie 3015:     if (!$pssymb) {
1.563     damieng  3016:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3017:         my $parmselhiddenstyle=' style="display:none"';
                   3018:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3019:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3020:         } else  {
                   3021:            $r->print('<div id="parmsel">');
                   3022:         }
                   3023: 
1.491     bisitz   3024:         # Step 1
1.523     raeburn  3025:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3026:         $r->print('
1.474     amueller 3027: <script type="text/javascript">
1.523     raeburn  3028: // <![CDATA['.
                   3029:                  &showhide_js().'
1.474     amueller 3030: // ]]>
                   3031: </script>
1.523     raeburn  3032: ');
                   3033:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3034:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3035:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.474     amueller 3036:         &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491     bisitz   3037:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3038:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3039:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3040:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3041:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3042: 
                   3043:         # Step 2
1.523     raeburn  3044:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.536     raeburn  3045:         &displaymenu($r,\%allparms,\@pscat,\@psprt,\%keyorder,'parmmenuscroll');
1.491     bisitz   3046: 
                   3047:         # Step 3
1.523     raeburn  3048:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3049:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3050:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3051:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3052:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3053: 
                   3054:         # Update Display Button
1.486     www      3055:         $r->print('<p>'
                   3056:              .'<input type="submit" name="dis"'
1.511     www      3057:              .' value="'.&mt('Update Display').'" />'
1.486     www      3058:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3059:              .'</p>');
                   3060:         $r->print('</div>');
1.491     bisitz   3061: 
1.486     www      3062:         # Offer link to display parameter selection again
                   3063:         $r->print('<p id="parmsellink"');
                   3064:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3065:            $r->print($parmselhiddenstyle);
                   3066:         }
                   3067:         $r->print('>'
                   3068:              .'<a href="javascript:parmsel_show()">'
                   3069:              .&mt('Change Parameter Selection')
                   3070:              .'</a>'
                   3071:              .'</p>');
1.44      albertel 3072:     } else {
1.478     amueller 3073:         # parameter screen for a single resource. 
1.486     www      3074:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3075:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3076:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3077:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3078:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3079:                   '<br />');
                   3080:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3081:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3082:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3083:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3084:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3085:         $r->print('<p>'
1.459     bisitz   3086:              .'<input type="submit" name="dis"'
1.511     www      3087:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3088:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3089:              .'</p>');
1.459     bisitz   3090:     }
1.478     amueller 3091:     
1.486     www      3092:     # ----- End Parameter Selection
1.57      albertel 3093: 
1.459     bisitz   3094:     # Display Messages
                   3095:     $r->print('<div>'.$message.'</div>');
1.210     www      3096: 
1.57      albertel 3097: 
                   3098:     my @temp_pscat;
                   3099:     map {
                   3100:         my $cat = $_;
                   3101:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3102:     } @pscat;
                   3103: 
                   3104:     @pscat = @temp_pscat;
                   3105: 
1.548     raeburn  3106: 
1.209     www      3107:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3108: # ----------------------------------------------------------------- Start Table
1.57      albertel 3109:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3110:         my $csuname=$env{'user.name'};
                   3111:         my $csudom=$env{'user.domain'};
1.568     raeburn  3112:         my $readonly = 1;
                   3113:         if ($parm_permission->{'edit'}) {
                   3114:             undef($readonly); 
                   3115:         }
1.57      albertel 3116: 
1.203     www      3117:         if ($parmlev eq 'full') {
1.506     www      3118: #
                   3119: # This produces the cascading table output of parameters
                   3120: #
1.560     damieng  3121:             my $coursespan=$csec?10:6;
                   3122:             my $userspan=4;
                   3123:             if ($cgroup ne '') {
                   3124:                 $coursespan += 4;
                   3125:             }
1.473     amueller 3126: 
1.560     damieng  3127:             $r->print(&Apache::loncommon::start_data_table());
                   3128:             #
                   3129:             # This produces the headers
                   3130:             #
                   3131:             $r->print('<tr><td colspan="5"></td>');
                   3132:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3133:             if ($uname) {
1.473     amueller 3134:                 if (@usersgroups > 1) {
1.560     damieng  3135:                     $userspan ++;
                   3136:                 }
                   3137:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3138:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3139:             }
                   3140:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3141:                 'pie'    => "Parameter in Effect",
                   3142:                 'csv'    => "Current Session Value",
1.472     amueller 3143:                 'rl'     => "Resource Level",
1.473     amueller 3144:                 'ic'     => 'in Course',
                   3145:                 'aut'    => "Assessment URL and Title",
                   3146:                 'type'   => 'Type',
                   3147:                 'emof'   => "Enclosing Map or Folder",
                   3148:                 'part'   => 'Part',
1.472     amueller 3149:                 'pn'     => 'Parameter Name',
1.473     amueller 3150:                 'def'    => 'default',
                   3151:                 'femof'  => 'from Enclosing Map or Folder',
                   3152:                 'gen'    => 'general',
                   3153:                 'foremf' => 'for Enclosing Map or Folder',
1.556     raeburn  3154:                 'formfr' => 'for Map or Folder (recursive)',
1.473     amueller 3155:                 'fr'     => 'for Resource'
                   3156:             );
1.560     damieng  3157:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3158: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3159: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.556     raeburn  3160: </tr><tr><td colspan="5"></td><th colspan="3">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3161: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3162: 
1.10      www      3163: ENDTABLETWO
1.560     damieng  3164:             if ($csec) {
                   3165:                 $r->print('<th colspan="4">'.
                   3166:                 &mt("in Section")." $csec</th>");
                   3167:             }
                   3168:             if ($cgroup) {
1.556     raeburn  3169:                 $r->print('<th colspan="4">'.
1.472     amueller 3170:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3171:             }
                   3172:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3173: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3174: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.556     raeburn  3175: <th>$lt{'gen'}</th><th>$lt{'formfr'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3176: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3177: ENDTABLEHEADFOUR
1.57      albertel 3178: 
1.560     damieng  3179:             if ($csec) {
                   3180:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'formfr'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
                   3181:             }
1.473     amueller 3182: 
1.560     damieng  3183:             if ($cgroup) {
                   3184:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'formfr'}.'</th><th>'.&mt('foremf').'</th><th>'.$lt{'fr'}.'</th>');
                   3185:             }
                   3186: 
                   3187:             if ($uname) {
                   3188:                 if (@usersgroups > 1) {
                   3189:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3190:                 }
                   3191:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'formfr'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
                   3192:             }
                   3193: 
                   3194:             $r->print('</tr>');
1.506     www      3195: #
                   3196: # Done with the headers
                   3197: # 
1.560     damieng  3198:             my $defbgone='';
                   3199:             my $defbgtwo='';
                   3200:             my $defbgthree = '';
1.57      albertel 3201: 
1.560     damieng  3202:             foreach my $rid (@ids) {
1.57      albertel 3203: 
                   3204:                 my ($inmapid)=($rid=~/\.(\d+)$/);
                   3205: 
1.446     bisitz   3206:                 if ((!$pssymb &&
1.560     damieng  3207:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3208:                         ||
                   3209:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3210: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3211:                     if ($defbgone eq '#E0E099') {
                   3212:                         $defbgone='#E0E0DD';
1.57      albertel 3213:                     } else {
1.419     bisitz   3214:                         $defbgone='#E0E099';
1.57      albertel 3215:                     }
1.419     bisitz   3216:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3217:                         $defbgtwo='#FFFFDD';
1.57      albertel 3218:                     } else {
1.473     amueller 3219:                         $defbgtwo='#FFFF99';
1.57      albertel 3220:                     }
1.419     bisitz   3221:                     if ($defbgthree eq '#FFBB99') {
                   3222:                         $defbgthree='#FFBBDD';
1.269     raeburn  3223:                     } else {
1.419     bisitz   3224:                         $defbgthree='#FFBB99';
1.269     raeburn  3225:                     }
                   3226: 
1.57      albertel 3227:                     my $thistitle='';
                   3228:                     my %name=   ();
                   3229:                     undef %name;
                   3230:                     my %part=   ();
                   3231:                     my %display=();
                   3232:                     my %type=   ();
                   3233:                     my %default=();
1.196     www      3234:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.57      albertel 3235: 
1.506     www      3236:                     my $filter=$env{'form.filter'};
1.548     raeburn  3237:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3238:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.560     damieng  3239:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name');
                   3240:     # We may only want certain parameters listed
                   3241:                             if ($filter) {
                   3242:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3243:                             }
                   3244:                             $name{$tempkeyp}=$parmname;
                   3245:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part');
                   3246: 
                   3247:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display');
                   3248:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3249:                                 my $identifier;
                   3250:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3251:                                     $identifier = $1;
                   3252:                                 }
                   3253:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3254:                             } else {
                   3255:                                 $display{$tempkeyp} = $parmdis;
                   3256:                             }
                   3257:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3258:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3259:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp);
                   3260:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type');
                   3261:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title');
1.57      albertel 3262:                         }
                   3263:                     }
1.548     raeburn  3264:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3265:                     if ($totalparms>0) {
1.560     damieng  3266:                         my $firstrow=1;
1.473     amueller 3267:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.419     bisitz   3268:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3269:                              ' rowspan='.$totalparms.
1.419     bisitz   3270:                              '><tt><font size="-1">'.
1.57      albertel 3271:                              join(' / ',split(/\//,$uri)).
                   3272:                              '</font></tt><p><b>'.
1.154     albertel 3273:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3274:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3275:                           &escape($symbp{$rid}).
1.336     albertel 3276:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3277:                              " target=\"_self\">$title");
1.57      albertel 3278: 
                   3279:                         if ($thistitle) {
1.473     amueller 3280:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3281:                         }
                   3282:                         $r->print('</a></b></td>');
1.419     bisitz   3283:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3284:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3285:                                       '</td>');
                   3286: 
1.419     bisitz   3287:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3288:                                       ' rowspan='.$totalparms.
1.238     www      3289:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3290:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3291:                             unless ($firstrow) {
                   3292:                                 $r->print('<tr>');
                   3293:                             } else {
                   3294:                                 undef $firstrow;
                   3295:                             }
1.548     raeburn  3296:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3297:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3298:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.568     raeburn  3299:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly);
1.57      albertel 3300:                         }
                   3301:                     }
                   3302:                 }
                   3303:             } # end foreach ids
1.43      albertel 3304: # -------------------------------------------------- End entry for one resource
1.517     www      3305:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3306:         } # end of  full
1.57      albertel 3307: #--------------------------------------------------- Entry for parm level map
                   3308:         if ($parmlev eq 'map') {
1.419     bisitz   3309:             my $defbgone = '#E0E099';
                   3310:             my $defbgtwo = '#FFFF99';
                   3311:             my $defbgthree = '#FFBB99';
1.57      albertel 3312: 
                   3313:             my %maplist;
                   3314: 
                   3315:             if ($pschp eq 'all') {
1.446     bisitz   3316:                 %maplist = %allmaps;
1.57      albertel 3317:             } else {
                   3318:                 %maplist = ($pschp => $mapp{$pschp});
                   3319:             }
                   3320: 
                   3321: #-------------------------------------------- for each map, gather information
                   3322:             my $mapid;
1.560     damieng  3323:             foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {
1.60      albertel 3324:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3325: 
                   3326: #-----------------------  loop through ids and get all parameter types for map
                   3327: #-----------------------------------------          and associated information
                   3328:                 my %name = ();
                   3329:                 my %part = ();
                   3330:                 my %display = ();
                   3331:                 my %type = ();
                   3332:                 my %default = ();
                   3333:                 my $map = 0;
                   3334: 
1.473     amueller 3335: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3336: 
1.548     raeburn  3337:                 foreach my $id (@ids) {
                   3338:                     ($map)=($id =~ /([\d]*?)\./);
                   3339:                     my $rid = $id;
1.446     bisitz   3340: 
1.57      albertel 3341: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3342: 
1.560     damieng  3343:                     if ($map eq $mapid) {
1.473     amueller 3344:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.57      albertel 3345: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3346: 
                   3347: #--------------------------------------------------------------------
                   3348: # @catmarker contains list of all possible parameters including part #s
                   3349: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3350: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3351: # When storing information, store as part 0
                   3352: # When requesting information, request from full part
                   3353: #-------------------------------------------------------------------
1.548     raeburn  3354:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3355:                             my $tempkeyp = $fullkeyp;
                   3356:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 3357: 
1.548     raeburn  3358:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3359:                                 $part{$tempkeyp}="0";
                   3360:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name');
                   3361:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display');
                   3362:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   3363:                                     my $identifier;
                   3364:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3365:                                         $identifier = $1;
                   3366:                                     }
                   3367:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3368:                                 } else {
                   3369:                                     $display{$tempkeyp} = $parmdis;
                   3370:                                 }
                   3371:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3372:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3373:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
                   3374:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp);
                   3375:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type');
                   3376:                               }
                   3377:                         } # end loop through keys
1.560     damieng  3378:                     }
1.57      albertel 3379:                 } # end loop through ids
1.446     bisitz   3380: 
1.57      albertel 3381: #---------------------------------------------------- print header information
1.133     www      3382:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      3383:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   3384:                 my $tmp="";
1.57      albertel 3385:                 if ($uname) {
1.473     amueller 3386:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   3387:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   3388:                         &mt('in')." \n";
1.57      albertel 3389:                 } else {
1.401     bisitz   3390:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 3391:                 }
1.269     raeburn  3392:                 if ($cgroup) {
1.401     bisitz   3393:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   3394:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3395:                     $csec = '';
                   3396:                 } elsif ($csec) {
1.401     bisitz   3397:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   3398:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  3399:                 }
1.401     bisitz   3400:                 $r->print('<div align="center"><h4>'
                   3401:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   3402:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   3403:                              ,$tmp
                   3404:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   3405:                              )
                   3406:                          ."<br /></h4>\n"
1.422     bisitz   3407:                 );
1.57      albertel 3408: #---------------------------------------------------------------- print table
1.419     bisitz   3409:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3410:                          .&Apache::loncommon::start_data_table_header_row()
                   3411:                          .'<th>'.&mt('Parameter Name').'</th>'
1.556     raeburn  3412:                          .'<th>'.&mt('Recursive Value').'</th>'
                   3413:                          .'<th>'.&mt('Non-Recursive Value').'</th>'
1.419     bisitz   3414:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   3415:                          .&Apache::loncommon::end_data_table_header_row()
                   3416:                 );
1.57      albertel 3417: 
1.548     raeburn  3418:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 3419:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3420:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  3421:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  3422:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   3423:                            $readonly);
1.57      albertel 3424:                 }
1.422     bisitz   3425:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   3426:                          .'</div>'
                   3427:                 );
1.57      albertel 3428:             } # end each map
                   3429:         } # end of $parmlev eq map
                   3430: #--------------------------------- Entry for parm level general (Course level)
                   3431:         if ($parmlev eq 'general') {
1.473     amueller 3432:             my $defbgone = '#E0E099';
1.419     bisitz   3433:             my $defbgtwo = '#FFFF99';
                   3434:             my $defbgthree = '#FFBB99';
1.57      albertel 3435: 
                   3436: #-------------------------------------------- for each map, gather information
                   3437:             my $mapid="0.0";
                   3438: #-----------------------  loop through ids and get all parameter types for map
                   3439: #-----------------------------------------          and associated information
                   3440:             my %name = ();
                   3441:             my %part = ();
                   3442:             my %display = ();
                   3443:             my %type = ();
                   3444:             my %default = ();
1.446     bisitz   3445: 
1.548     raeburn  3446:             foreach $id (@ids) {
                   3447:                 my $rid = $id;
1.446     bisitz   3448: 
1.196     www      3449:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.57      albertel 3450: 
                   3451: #--------------------------------------------------------------------
                   3452: # @catmarker contains list of all possible parameters including part #s
                   3453: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3454: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3455: # When storing information, store as part 0
                   3456: # When requesting information, request from full part
                   3457: #-------------------------------------------------------------------
1.548     raeburn  3458:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3459:                     my $tempkeyp = $fullkeyp;
                   3460:                     $tempkeyp =~ s/_\w+_/_0_/;
                   3461:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3462:                         $part{$tempkeyp}="0";
                   3463:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name');
                   3464:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display');
                   3465:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   3466:                             my $identifier;
                   3467:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3468:                                 $identifier = $1;
                   3469:                             }
                   3470:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3471:                         } else {
                   3472:                             $display{$tempkeyp} = $parmdis;
                   3473:                         }
                   3474:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3475:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3476:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
                   3477:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp);
                   3478:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type');
1.560     damieng  3479:                     }
1.57      albertel 3480:                 } # end loop through keys
                   3481:             } # end loop through ids
1.446     bisitz   3482: 
1.57      albertel 3483: #---------------------------------------------------- print header information
1.473     amueller 3484:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 3485:             $r->print(<<ENDMAPONE);
1.419     bisitz   3486: <center>
                   3487: <h4>$setdef
1.135     albertel 3488: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 3489: ENDMAPONE
                   3490:             if ($uname) {
1.473     amueller 3491:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 3492:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 3493:             } else {
1.135     albertel 3494:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 3495:             }
1.446     bisitz   3496: 
1.135     albertel 3497:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 3498:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 3499:             $r->print("</h4>\n");
1.57      albertel 3500: #---------------------------------------------------------------- print table
1.419     bisitz   3501:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   3502:                      .&Apache::loncommon::start_data_table_header_row()
                   3503:                      .'<th>'.&mt('Parameter Name').'</th>'
                   3504:                      .'<th>'.&mt('Default Value').'</th>'
                   3505:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   3506:                      .&Apache::loncommon::end_data_table_header_row()
                   3507:             );
1.57      albertel 3508: 
1.548     raeburn  3509:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   3510:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  3511:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  3512:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   3513:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   3514:                            $readonly);
1.57      albertel 3515:             }
1.419     bisitz   3516:             $r->print(&Apache::loncommon::end_data_table()
                   3517:                      .'</p>'
                   3518:                      .'</center>'
                   3519:             );
1.57      albertel 3520:         } # end of $parmlev eq general
1.43      albertel 3521:     }
1.507     www      3522:     $r->print('</form>');
                   3523:     &endSettingsScreen($r);
                   3524:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 3525: } # end sub assessparms
1.30      www      3526: 
1.560     damieng  3527: 
                   3528: 
1.120     www      3529: ##################################################
1.560     damieng  3530: # OVERVIEW MODE
1.207     www      3531: ##################################################
1.124     www      3532: 
1.563     damieng  3533: my $tableopen; # boolean, true if HTML table is already opened
                   3534: 
                   3535: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   3536: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   3537: # @returns {string}
1.124     www      3538: sub tablestart {
1.552     raeburn  3539:     my ($readonly) = @_;
1.124     www      3540:     if ($tableopen) {
1.552     raeburn  3541:         return '';
1.124     www      3542:     } else {
1.552     raeburn  3543:         $tableopen=1;
                   3544:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   3545:         if ($readonly) {
                   3546:             $output .= '<th>'.&mt('Current value').'</th>';
                   3547:         } else {
                   3548:             $output .= '<th>'.&mt('Delete').'</th><th>'.&mt('Set to ...').'</th>';
                   3549:         }
                   3550:         $output .= '</tr>';
                   3551:         return $output;
1.124     www      3552:     }
                   3553: }
                   3554: 
1.563     damieng  3555: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   3556: # @returns {string}
1.124     www      3557: sub tableend {
                   3558:     if ($tableopen) {
1.560     damieng  3559:         $tableopen=0;
                   3560:         return &Apache::loncommon::end_data_table();
1.124     www      3561:     } else {
1.560     damieng  3562:         return'';
1.124     www      3563:     }
                   3564: }
                   3565: 
1.563     damieng  3566: # Reads course and user information.
                   3567: # 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).
                   3568: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   3569: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   3570: # @param {string} $crs - course number
                   3571: # @param {string} $dom - course domain
                   3572: # @returns {hash reference|Array}
1.207     www      3573: sub readdata {
                   3574:     my ($crs,$dom)=@_;
                   3575: # Read coursedata
                   3576:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   3577: # Read userdata
                   3578: 
                   3579:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  3580:     foreach my $user (keys(%$classlist)) {
                   3581:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   3582:             my ($tuname,$tudom)=($1,$2);
                   3583:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   3584:             foreach my $userkey (keys(%{$useropt})) {
                   3585:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      3586:                     my $newkey=$userkey;
1.548     raeburn  3587:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   3588:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   3589:                 }
                   3590:             }
1.473     amueller 3591:         }
                   3592:     }
1.552     raeburn  3593:     if (wantarray) {
                   3594:         return ($resourcedata,$classlist);
                   3595:     } else {
                   3596:         return $resourcedata;
                   3597:     }
1.207     www      3598: }
                   3599: 
                   3600: 
1.563     damieng  3601: # Stores parameter data, using form parameters directly.
                   3602: #
                   3603: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
                   3604: # set_* (except settext, setipallow, setipdeny) - set a parameter value
                   3605: # del_* - remove a parameter
                   3606: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   3607: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   3608: # key_* - date values
                   3609: # days_* - for date intervals
                   3610: # hours_* - for date intervals
                   3611: # minutes_* - for date intervals
                   3612: # seconds_* - for date intervals
                   3613: # done_* - for date intervals
                   3614: # typeof_* - parameter type
                   3615: # 
                   3616: # @param {Apache2::RequestRec} $r - the Apache request
                   3617: # @param {string} $crs - course number
                   3618: # @param {string} $dom - course domain
1.208     www      3619: sub storedata {
                   3620:     my ($r,$crs,$dom)=@_;
1.207     www      3621: # Set userlevel immediately
                   3622: # Do an intermediate store of course level
                   3623:     my $olddata=&readdata($crs,$dom);
1.124     www      3624:     my %newdata=();
                   3625:     undef %newdata;
                   3626:     my @deldata=();
                   3627:     undef @deldata;
1.504     raeburn  3628:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  3629:     my $now = time;
1.560     damieng  3630:     foreach my $key (keys(%env)) {
                   3631:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   3632:             my $cmd=$1;
                   3633:             my $thiskey=$2;
                   3634:             next if ($cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny');
                   3635:             my ($tuname,$tudom)=&extractuser($thiskey);
                   3636:             my $tkey=$thiskey;
1.473     amueller 3637:             if ($tuname) {
1.560     damieng  3638:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   3639:             }
                   3640:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  3641:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   3642:                 if ($cmd eq 'set') {
                   3643:                     $data=$env{$key};
                   3644:                     $valmatch = '';
                   3645:                     $valchk = $data;
                   3646:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3647:                     $text = &mt('Saved modified parameter for');
                   3648:                     if ($typeof eq 'string_questiontype') {
                   3649:                         $name = 'type';
                   3650:                     } elsif ($typeof eq 'string_lenient') {
                   3651:                         $name = 'lenient';
                   3652:                         my $stringmatch = &standard_string_matches($typeof);
                   3653:                         if (ref($stringmatch) eq 'ARRAY') {
                   3654:                             foreach my $item (@{$stringmatch}) {
                   3655:                                 if (ref($item) eq 'ARRAY') {
                   3656:                                     my ($regexpname,$pattern) = @{$item};
                   3657:                                     if ($pattern ne '') {
                   3658:                                         if ($data =~ /$pattern/) {
                   3659:                                             $valmatch = $regexpname;
                   3660:                                             $valchk = '';
                   3661:                                             last;
                   3662:                                         }
1.560     damieng  3663:                                     }
1.549     raeburn  3664:                                 }
                   3665:                             }
                   3666:                         }
1.563     damieng  3667:                     } elsif ($typeof eq 'string_discussvote') {
                   3668:                         $name = 'discussvote';
                   3669:                     } elsif ($typeof eq 'string_examcode') {
                   3670:                         $name = 'examcode';
                   3671:                         if (&Apache::lonnet::validCODE($data)) {
                   3672:                             $valchk = 'valid';
                   3673:                         }
                   3674:                     } elsif ($typeof eq 'string_yesno') {
                   3675:                         if ($thiskey =~ /\.retrypartial$/) {
                   3676:                             $name = 'retrypartial';
                   3677:                         }
1.549     raeburn  3678:                     }
1.563     damieng  3679:                 } elsif ($cmd eq 'datepointer') {
                   3680:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   3681:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3682:                     $text = &mt('Saved modified date for');
                   3683:                     if ($typeof eq 'date_start') {
                   3684:                         if ($thiskey =~ /\.printstartdate$/) {
                   3685:                             $name = 'printstartdate';
                   3686:                             if (($data) && ($data > $now)) {
                   3687:                                 $valchk = 'future';
                   3688:                             }
1.560     damieng  3689:                         }
1.563     damieng  3690:                     } elsif ($typeof eq 'date_end') {
                   3691:                         if ($thiskey =~ /\.printenddate$/) {
                   3692:                             $name = 'printenddate';
                   3693:                             if (($data) && ($data < $now)) {
                   3694:                                 $valchk = 'past';
                   3695:                             }
1.560     damieng  3696:                         }
1.504     raeburn  3697:                     }
1.563     damieng  3698:                 } elsif ($cmd eq 'dateinterval') {
                   3699:                     $data=&get_date_interval_from_form($thiskey);
                   3700:                     if ($thiskey =~ /\.interval$/) {
                   3701:                         $name = 'interval';
                   3702:                         my $intervaltype = &get_intervaltype($name);
                   3703:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   3704:                         if (ref($intervalmatch) eq 'ARRAY') {
                   3705:                             foreach my $item (@{$intervalmatch}) {
                   3706:                                 if (ref($item) eq 'ARRAY') {
                   3707:                                     my ($regexpname,$pattern) = @{$item};
                   3708:                                     if ($pattern ne '') {
                   3709:                                         if ($data =~ /$pattern/) {
                   3710:                                             $valmatch = $regexpname;
                   3711:                                             $valchk = '';
                   3712:                                             last;
                   3713:                                         }
1.560     damieng  3714:                                     }
1.554     raeburn  3715:                                 }
                   3716:                             }
                   3717:                         }
                   3718:                     }
1.563     damieng  3719:                     $typeof=$env{'form.typeof_'.$thiskey};
                   3720:                     $text = &mt('Saved modified date for');
1.554     raeburn  3721:                 }
1.563     damieng  3722:                 if ($thiskey =~ m{\.(?:sequence|page)___\(rec\)}) {
                   3723:                     $namematch = 'maplevelrecurse';
1.560     damieng  3724:                 }
1.563     damieng  3725:                 if (($name ne '') || ($namematch ne '')) {
                   3726:                     my ($needsrelease,$needsnewer);
                   3727:                     if ($name ne '') {
                   3728:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  3729:                         if ($needsrelease) {
                   3730:                             unless ($got_chostname) {
1.563     damieng  3731:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  3732:                                 $got_chostname = 1;
                   3733:                             }
1.563     damieng  3734:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   3735:                                                                 $needsrelease,
                   3736:                                                                 $cmajor,$cminor);
                   3737:                         }
                   3738:                     }
                   3739:                     if ($namematch ne '') {
                   3740:                         if ($needsnewer) {
                   3741:                             undef($namematch);
1.560     damieng  3742:                         } else {
1.563     damieng  3743:                             my $currneeded;
                   3744:                             if ($needsrelease) {
                   3745:                                 $currneeded = $needsrelease;
                   3746:                             }
                   3747:                             $needsrelease =
                   3748:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3749:                             if (($needsrelease) &&
                   3750:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3751:                                 unless ($got_chostname) {
                   3752:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3753:                                     $got_chostname = 1;
                   3754:                                 }
                   3755:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   3756:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   3757:                             } else {
                   3758:                                 undef($namematch);
                   3759:                             }
1.560     damieng  3760:                         }
1.557     raeburn  3761:                     }
1.563     damieng  3762:                     if ($needsnewer) {
                   3763:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   3764:                                                             $chostname,$cmajor,
                   3765:                                                             $cminor,$needsrelease));
                   3766:                         next;
                   3767:                     }
1.504     raeburn  3768:                 }
1.563     damieng  3769:                 if (defined($data) and $$olddata{$thiskey} ne $data) {
                   3770:                     if ($tuname) {
                   3771:                         if (&Apache::lonnet::put('resourcedata',{$tkey=>$data,
                   3772:                                             $tkey.'.type' => $typeof},
                   3773:                                     $tudom,$tuname) eq 'ok') {
                   3774:                             &log_parmset({$tkey=>$data,$tkey.'.type' => $typeof},0,$tuname,$tudom);
                   3775:                             $r->print('<br />'.$text.' '.
                   3776:                                 &Apache::loncommon::plainname($tuname,$tudom));
                   3777:                         } else {
                   3778:                             $r->print('<div class="LC_error">'.
                   3779:                                 &mt('Error saving parameters').'</div>');
                   3780:                         }
                   3781:                         &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
1.560     damieng  3782:                     } else {
1.563     damieng  3783:                         $newdata{$thiskey}=$data;
                   3784:                         $newdata{$thiskey.'.type'}=$typeof;
1.560     damieng  3785:                     }
                   3786:                 }
                   3787:             } elsif ($cmd eq 'del') {
                   3788:                 if ($tuname) {
                   3789:                     if (&Apache::lonnet::del('resourcedata',[$tkey],$tudom,$tuname) eq 'ok') {
                   3790:                             &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   3791:                         $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   3792:                     } else {
                   3793:                         $r->print('<div class="LC_error">'.
                   3794:                             &mt('Error deleting parameters').'</div>');
                   3795:                     }
                   3796:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   3797:                 } else {
                   3798:                     push (@deldata,$thiskey,$thiskey.'.type');
                   3799:                 }
1.473     amueller 3800:             }
                   3801:         }
                   3802:     }
1.207     www      3803: # Store all course level
1.144     www      3804:     my $delentries=$#deldata+1;
1.548     raeburn  3805:     my @newdatakeys=keys(%newdata);
1.144     www      3806:     my $putentries=$#newdatakeys+1;
                   3807:     if ($delentries) {
1.560     damieng  3808:         if (&Apache::lonnet::del('resourcedata',\@deldata,$dom,$crs) eq 'ok') {
                   3809:             my %loghash=map { $_ => '' } @deldata;
                   3810:             &log_parmset(\%loghash,1);
                   3811:             $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   3812:         } else {
                   3813:             $r->print('<div class="LC_error">'.
                   3814:                 &mt('Error deleting parameters').'</div>');
                   3815:         }
                   3816:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      3817:     }
                   3818:     if ($putentries) {
1.560     damieng  3819:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   3820:                     &log_parmset(\%newdata,0);
                   3821:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   3822:         } else {
                   3823:             $r->print('<div class="LC_error">'.
                   3824:                 &mt('Error saving parameters').'</div>');
                   3825:         }
                   3826:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      3827:     }
1.208     www      3828: }
1.207     www      3829: 
1.563     damieng  3830: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   3831: #
                   3832: # @param {string} $key - the key
                   3833: # @returns {Array}
1.208     www      3834: sub extractuser {
                   3835:     my $key=shift;
1.350     albertel 3836:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      3837: }
1.206     www      3838: 
1.563     damieng  3839: # Parses a parameter key and returns the components.
                   3840: #
                   3841: # @param {string} $key - 
                   3842: # @param {hash reference} $listdata - 
                   3843: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 3844: sub parse_listdata_key {
                   3845:     my ($key,$listdata) = @_;
                   3846:     # split into student/section affected, and
                   3847:     # the realm (folder/resource part and parameter
1.446     bisitz   3848:     my ($student,$realm) =
1.473     amueller 3849:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 3850:     # if course wide student would be undefined
                   3851:     if (!defined($student)) {
1.560     damieng  3852:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 3853:     }
                   3854:     # strip off the .type if it's not the Question type parameter
                   3855:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  3856:         $realm=~s/\.type//;
1.381     albertel 3857:     }
                   3858:     # split into resource+part and parameter name
1.388     albertel 3859:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   3860:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 3861:     return ($student,$res,$part,$parm);
                   3862: }
                   3863: 
1.563     damieng  3864: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   3865: #
                   3866: # @param {Apache2::RequestRec} $r - the Apache request
                   3867: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   3868: # @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
                   3869: # @param {string} $sortorder - realmstudent|studentrealm
                   3870: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   3871: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  3872: # @param {boolean} $readonly - true if editing not allowed
1.563     damieng  3873: # @returns{integer} - number of $listdata parameters processed
1.208     www      3874: sub listdata {
1.568     raeburn  3875:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552     raeburn  3876:     
1.207     www      3877: # Start list output
1.206     www      3878: 
1.122     www      3879:     my $oldsection='';
                   3880:     my $oldrealm='';
                   3881:     my $oldpart='';
1.123     www      3882:     my $pointer=0;
1.124     www      3883:     $tableopen=0;
1.145     www      3884:     my $foundkeys=0;
1.248     albertel 3885:     my %keyorder=&standardkeyorder();
1.381     albertel 3886: 
1.552     raeburn  3887:     my ($secidx,%grouphash);
                   3888:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3889:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  3890:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3891:             %grouphash = &Apache::longroup::coursegroups();
                   3892:         } elsif ($env{'request.course.groups'} ne '') {
                   3893:             map { $grouphash{$_} = 1; } split(/,/,$env{'request.course.groups'});
                   3894:         }
1.552     raeburn  3895:     }
                   3896: 
1.214     www      3897:     foreach my $thiskey (sort {
1.560     damieng  3898:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   3899:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381     albertel 3900: 
1.560     damieng  3901:         # get the numerical order for the param
                   3902:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   3903:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 3904: 
1.560     damieng  3905:         my $result=0;
1.381     albertel 3906: 
1.560     damieng  3907:         if ($sortorder eq 'realmstudent') {
1.381     albertel 3908:             if ($ares     ne $bres    ) {
1.560     damieng  3909:                 $result = ($ares     cmp $bres);
1.446     bisitz   3910:             } elsif ($astudent ne $bstudent) {
1.560     damieng  3911:                 $result = ($astudent cmp $bstudent);
                   3912:             } elsif ($apart    ne $bpart   ) {
                   3913:                 $result = ($apart    cmp $bpart);
                   3914:             }
                   3915:         } else {
                   3916:             if      ($astudent ne $bstudent) {
                   3917:                 $result = ($astudent cmp $bstudent);
                   3918:             } elsif ($ares     ne $bres    ) {
                   3919:                 $result = ($ares     cmp $bres);
                   3920:             } elsif ($apart    ne $bpart   ) {
                   3921:                 $result = ($apart    cmp $bpart);
                   3922:             }
1.473     amueller 3923:         }
1.446     bisitz   3924: 
1.560     damieng  3925:         if (!$result) {
1.381     albertel 3926:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  3927:                 $result = ($aparm <=> $bparm);
1.381     albertel 3928:             } elsif (defined($aparm)) {
1.560     damieng  3929:                 $result = -1;
1.381     albertel 3930:             } elsif (defined($bparm)) {
1.560     damieng  3931:                 $result = 1;
                   3932:             }
1.473     amueller 3933:         }
1.381     albertel 3934: 
1.560     damieng  3935:         $result;
                   3936:         
                   3937:     } keys(%{$listdata})) { # foreach my $thiskey
1.381     albertel 3938: 
1.560     damieng  3939:         if ($$listdata{$thiskey.'.type'}) {
                   3940:             my $thistype=$$listdata{$thiskey.'.type'};
                   3941:             if ($$resourcedata{$thiskey.'.type'}) {
                   3942:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   3943:             }
                   3944:             my ($middle,$part,$name)=
1.572     damieng  3945:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  3946:             my $section=&mt('All Students');
                   3947:             if ($middle=~/^\[(.*)\]/) {
                   3948:                 my $issection=$1;
                   3949:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   3950:                     my ($stuname,$studom) = ($1,$2);
                   3951:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3952:                         if (ref($classlist) eq 'HASH') {
                   3953:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   3954:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   3955:                             }
                   3956:                         }
                   3957:                     }
                   3958:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
                   3959:                 } else {
                   3960:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3961:                         if (exists($grouphash{$issection})) {
                   3962:                             $section=&mt('Group').': '.$issection;
                   3963:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   3964:                             $section = &mt('Section').': '.$issection;
                   3965:                         } else {
                   3966:                             next; 
1.552     raeburn  3967:                         }
1.560     damieng  3968:                     } else {
                   3969:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  3970:                     }
                   3971:                 }
1.560     damieng  3972:                 $middle=~s/^\[(.*)\]//;
                   3973:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   3974:                 $readonly = 1;
                   3975:             }
                   3976:             $middle=~s/\.+$//;
                   3977:             $middle=~s/^\.+//;
                   3978:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
                   3979:             if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   3980:                 my $mapurl = $1;
                   3981:                 my $maplevel = $2;
                   3982:                 my $leveltitle = &mt('Folder/Map');
                   3983:                 if ($maplevel eq 'rec') {
                   3984:                     $leveltitle = &mt('Recursive');
                   3985:                 }
                   3986:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
                   3987:             } elsif ($middle) {
                   3988:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   3989:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   3990:                     ': '.&Apache::lonnet::gettitle($middle).
                   3991:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   3992:                     $id.')</span></span>';
                   3993:             }
                   3994:             if ($sortorder eq 'realmstudent') {
                   3995:                 if ($realm ne $oldrealm) {
                   3996:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   3997:                     $oldrealm=$realm;
                   3998:                     $oldsection='';
                   3999:                 }
                   4000:                 if ($section ne $oldsection) {
                   4001:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4002:                     $oldsection=$section;
                   4003:                     $oldpart='';
                   4004:                 }
1.552     raeburn  4005:             } else {
1.560     damieng  4006:                 if ($section ne $oldsection) {
                   4007:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4008:                     $oldsection=$section;
                   4009:                     $oldrealm='';
                   4010:                 }
                   4011:                 if ($realm ne $oldrealm) {
                   4012:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4013:                     $oldrealm=$realm;
                   4014:                     $oldpart='';
1.552     raeburn  4015:                 }
                   4016:             }
1.560     damieng  4017:             if ($part ne $oldpart) {
                   4018:                 $r->print(&tableend().
                   4019:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4020:                 $oldpart=$part;
1.556     raeburn  4021:             }
1.560     damieng  4022:     #
                   4023:     # Ready to print
                   4024:     #
1.470     raeburn  4025:             my $parmitem = &standard_parameter_names($name);
1.560     damieng  4026:             $r->print(&tablestart($readonly).
                   4027:                 &Apache::loncommon::start_data_table_row().
                   4028:                 '<td><b>'.&mt($parmitem).
                   4029:                 '</b></td>');
                   4030:             unless ($readonly) {
                   4031:                 $r->print('<td><input type="checkbox" name="del_'.
                   4032:                         $thiskey.'" /></td>');
                   4033:             }
                   4034:             $r->print('<td>');
                   4035:             $foundkeys++;
                   4036:             if (&isdateparm($thistype)) {
                   4037:                 my $jskey='key_'.$pointer;
                   4038:                 my $state;
                   4039:                 $pointer++;
                   4040:                 if ($readonly) {
                   4041:                     $state = 'disabled';
                   4042:                 }
                   4043:                 $r->print(
                   4044:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4045:                                                         $jskey,
                   4046:                                                         $$resourcedata{$thiskey},
                   4047:                                                         '',1,$state));
                   4048:                 unless  ($readonly) {
                   4049:                     $r->print(
                   4050:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
                   4051:     (($$resourcedata{$thiskey}!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$$resourcedata{$thiskey}.'">'.
                   4052:     &mt('Shift all dates based on this date').'</a></span>':'').
                   4053:     &date_sanity_info($$resourcedata{$thiskey})
                   4054:                     );
                   4055:                 }
                   4056:             } elsif ($thistype eq 'date_interval') {
                   4057:                 $r->print(&date_interval_selector($thiskey,$name,
                   4058:                         $$resourcedata{$thiskey},$readonly));
                   4059:             } elsif ($thistype =~ m/^string/) {
                   4060:                 $r->print(&string_selector($thistype,$thiskey,
                   4061:                         $$resourcedata{$thiskey},$name,$readonly));
                   4062:             } else {
                   4063:                 $r->print(&default_selector($thiskey,$$resourcedata{$thiskey},$readonly));
1.552     raeburn  4064:             }
1.560     damieng  4065:             unless ($readonly) {
                   4066:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   4067:                         $thistype.'" />');
1.552     raeburn  4068:             }
1.560     damieng  4069:             $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.473     amueller 4070:         }
1.121     www      4071:     }
1.208     www      4072:     return $foundkeys;
                   4073: }
                   4074: 
1.563     damieng  4075: # Returns a string representing the interval, directly using form data matching the given key.
                   4076: # The returned string may also include information related to proctored exams.
                   4077: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   4078: #
                   4079: # @param {string} $key - suffix for form fields related to the interval
                   4080: # @returns {string}
1.385     albertel 4081: sub get_date_interval_from_form {
                   4082:     my ($key) = @_;
                   4083:     my $seconds = 0;
                   4084:     foreach my $which (['days', 86400],
1.473     amueller 4085:                ['hours', 3600],
                   4086:                ['minutes', 60],
                   4087:                ['seconds',  1]) {
1.560     damieng  4088:         my ($name, $factor) = @{ $which };
                   4089:         if (defined($env{'form.'.$name.'_'.$key})) {
                   4090:             $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   4091:         }
1.473     amueller 4092:     }
1.560     damieng  4093:     if (($key =~ /\.interval$/) &&
                   4094:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  4095:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   4096:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   4097:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   4098:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   4099:                 $seconds .= '_proctor';
                   4100:             }
                   4101:         } else {
                   4102:             $seconds .= $env{'form.done_'.$key}; 
                   4103:         }
                   4104:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  4105:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  4106:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   4107:         }
1.554     raeburn  4108:     }
1.385     albertel 4109:     return $seconds;
                   4110: }
                   4111: 
                   4112: 
1.563     damieng  4113: # Returns HTML to enter a text value for a parameter.
                   4114: #
                   4115: # @param {string} $thiskey - parameter key
                   4116: # @param {string} $showval - the current value
                   4117: # @param {boolean} $readonly - true if the field should not be made editable
                   4118: # @returns {string}
1.383     albertel 4119: sub default_selector {
1.552     raeburn  4120:     my ($thiskey, $showval, $readonly) = @_;
                   4121:     my $disabled;
                   4122:     if ($readonly) {
                   4123:         $disabled = ' disabled="disabled"';
                   4124:     }
                   4125:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 4126: }
                   4127: 
1.563     damieng  4128: # Returns HTML to enter allow/deny rules related to IP addresses.
                   4129: #
                   4130: # @param {string} $thiskey - parameter key
                   4131: # @param {string} $showval - the current value
                   4132: # @param {boolean} $readonly - true if the fields should not be made editable
                   4133: # @returns {string}
1.549     raeburn  4134: sub string_ip_selector {
1.552     raeburn  4135:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  4136:     my %access = (
                   4137:                    allow => [],
                   4138:                    deny  => [],
                   4139:                  );
                   4140:     if ($showval ne '') {
                   4141:         my @current;
                   4142:         if ($showval =~ /,/) {
                   4143:             @current = split(/,/,$showval);
                   4144:         } else {
                   4145:             @current = ($showval);
                   4146:         }
                   4147:         foreach my $item (@current) {
                   4148:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4149:                 push(@{$access{'deny'}},$1);
                   4150:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   4151:                 push(@{$access{'allow'}},$item);
                   4152:             }
                   4153:         }
                   4154:     }
                   4155:     if (!@{$access{'allow'}}) {
                   4156:         @{$access{'allow'}} = ('');
                   4157:     }
                   4158:     if (!@{$access{'deny'}}) {
                   4159:         @{$access{'deny'}} = ('');
                   4160:     }
1.552     raeburn  4161:     my ($disabled,$addmore);
1.567     raeburn  4162:     if ($readonly) {
1.552     raeburn  4163:         $disabled=' disabled="disabled"';
                   4164:     } else {
                   4165:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   4166:     }
1.549     raeburn  4167:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   4168: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   4169:     foreach my $acctype ('allow','deny') {
                   4170:         $output .= '
                   4171: <td valign="top">
                   4172: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   4173:   <div class="LC_string_ipacc_inner">'."\n";
                   4174:         my $num = 0;
                   4175:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  4176:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  4177:             if ($num > 0) {
                   4178:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   4179:             }
                   4180:             $output .= '</div>'."\n";
                   4181:             $num ++;
                   4182:         }
                   4183:         $output .= '
1.552     raeburn  4184:   </div>'.$addmore.'
1.549     raeburn  4185: </div>
                   4186: </td>';
                   4187:    }
                   4188:    $output .= '
                   4189: </tr>
                   4190: </table>'."\n";
                   4191:     return $output;
                   4192: }
                   4193: 
1.560     damieng  4194: 
                   4195: { # block using some constants related to parameter types (overview mode)
                   4196: 
1.446     bisitz   4197: my %strings =
1.383     albertel 4198:     (
                   4199:      'string_yesno'
                   4200:              => [[ 'yes', 'Yes' ],
1.560     damieng  4201:                  [ 'no', 'No' ]],
1.383     albertel 4202:      'string_problemstatus'
                   4203:              => [[ 'yes', 'Yes' ],
1.473     amueller 4204:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   4205:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   4206:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  4207:      'string_questiontype'
                   4208:              => [[ 'problem', 'Standard Problem'],
                   4209:                  [ 'survey', 'Survey'],
                   4210:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   4211:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  4212:                  [ 'anonsurvey', 'Anonymous Survey'],
                   4213:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   4214:                  [ 'practice', 'Practice'],
                   4215:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  4216:      'string_lenient'
                   4217:              => [['yes', 'Yes' ],
                   4218:                  [ 'no', 'No' ],
1.549     raeburn  4219:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   4220:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  4221:      'string_discussvote'
                   4222:              => [['yes','Yes'],
                   4223:                  ['notended','Yes, unless discussion ended'],
                   4224:                  ['no','No']],
1.549     raeburn  4225:      'string_ip'
                   4226:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
                   4227:                  ['_denyfrom_',], 'Hostname(s) or IP(s) from which access is disallowed'], 
1.383     albertel 4228:      );
                   4229: 
1.549     raeburn  4230: my %stringmatches = (
                   4231:          'string_lenient'
                   4232:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   4233:          'string_ip'
                   4234:               => [['_allowfrom_','[^\!]+'],
                   4235:                   ['_denyfrom_','\!']],
                   4236:     );
                   4237: 
                   4238: my %stringtypes = (
                   4239:                     type         => 'string_questiontype',
                   4240:                     lenient      => 'string_lenient',
                   4241:                     retrypartial => 'string_yesno',
                   4242:                     discussvote  => 'string_discussvote',
                   4243:                     examcode     => 'string_examcode',
                   4244:                     acc          => 'string_ip',
                   4245:                   );
                   4246: 
1.563     damieng  4247: # Returns the possible values and titles for a given string type, or undef if there are none.
                   4248: # Used by courseprefs.
                   4249: #
                   4250: # @param {string} $string_type - a parameter type for strings
                   4251: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  4252: sub standard_string_options {
                   4253:     my ($string_type) = @_;
                   4254:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   4255:         return $strings{$string_type};
                   4256:     }
                   4257:     return;
                   4258: }
1.383     albertel 4259: 
1.563     damieng  4260: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   4261: #
                   4262: # @param {string} $string_type - a parameter type for strings
                   4263: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  4264: sub standard_string_matches {
                   4265:     my ($string_type) = @_;
                   4266:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   4267:         return $stringmatches{$string_type};
                   4268:     }
                   4269:     return;
                   4270: }
                   4271: 
1.563     damieng  4272: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   4273: #
                   4274: # @param {string} $name - parameter name
                   4275: # @returns {string}
1.549     raeburn  4276: sub get_stringtype {
                   4277:     my ($name) = @_;
                   4278:     if (exists($stringtypes{$name})) {
                   4279:         return $stringtypes{$name};
                   4280:     }
                   4281:     return;
                   4282: }
                   4283: 
1.563     damieng  4284: # Returns HTML to edit a string parameter.
                   4285: #
                   4286: # @param {string} $thistype - parameter type
                   4287: # @param {string} $thiskey - parameter key
                   4288: # @param {string} $showval - parameter current value
                   4289: # @param {string} $name - parameter name
                   4290: # @param {boolean} $readonly - true if the values should not be made editable
                   4291: # @returns {string}
1.383     albertel 4292: sub string_selector {
1.552     raeburn  4293:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   4294: 
1.383     albertel 4295:     if (!exists($strings{$thistype})) {
1.552     raeburn  4296:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 4297:     }
                   4298: 
1.504     raeburn  4299:     my %skiptype;
1.514     raeburn  4300:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  4301:             ($thistype eq 'string_lenient') ||
                   4302:             ($thistype eq 'string_discussvote') ||
                   4303:             ($thistype eq 'string_ip') ||
                   4304:             ($name eq 'retrypartial')) {
1.504     raeburn  4305:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   4306:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   4307:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  4308:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  4309:             my $parmmatch;
                   4310:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   4311:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   4312:                     if (ref($item) eq 'ARRAY') {
                   4313:                         if ($parmval eq $item->[0]) {
                   4314:                             $parmmatch = $parmval;
                   4315:                             $parmval = '';
                   4316:                             last;
                   4317:                         }
                   4318:                     }
                   4319:                 }
                   4320:             }
                   4321:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  4322:             if ($needsrelease) {
                   4323:                 unless ($got_chostname) {
1.514     raeburn  4324:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  4325:                     $got_chostname = 1;
                   4326:                 }
1.557     raeburn  4327:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  4328:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  4329:                 if ($needsnewer) {
1.549     raeburn  4330:                     if ($parmmatch ne '') {
                   4331:                         $skiptype{$parmmatch} = 1;
                   4332:                     } elsif ($parmval ne '') {
                   4333:                         $skiptype{$parmval} = 1;
                   4334:                     }
1.504     raeburn  4335:                 }
                   4336:             }
                   4337:         }
                   4338:     }
1.549     raeburn  4339: 
                   4340:     if ($thistype eq 'string_ip') {
1.552     raeburn  4341:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.549     raeburn  4342:     }
1.504     raeburn  4343: 
1.552     raeburn  4344:     my ($result,$disabled);
                   4345: 
                   4346:     if ($readonly) {
                   4347:         $disabled = ' disabled="disabled"';
                   4348:     }
1.504     raeburn  4349:     my $numinrow = 3;
                   4350:     if ($thistype eq 'string_problemstatus') {
                   4351:         $numinrow = 2;
                   4352:     } elsif ($thistype eq 'string_questiontype') {
                   4353:         if (keys(%skiptype) > 0) {
                   4354:              $numinrow = 4;
                   4355:         }
                   4356:     }
                   4357:     my $rem;
                   4358:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   4359:         my $i=0;
                   4360:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   4361:             next unless (ref($possibilities) eq 'ARRAY');
                   4362:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  4363:             next if ($skiptype{$name});
1.504     raeburn  4364:             $rem = $i%($numinrow);
                   4365:             if ($rem == 0) {
                   4366:                 if ($i > 0) {
                   4367:                     $result .= '</tr>';
                   4368:                 }
                   4369:                 $result .= '<tr>';
                   4370:             }
1.549     raeburn  4371:             my $colspan;
                   4372:             if ($i == @{ $strings{$thistype} }-1) {
                   4373:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   4374:                 if ($rem) {
                   4375:                     my $colsleft = $numinrow - $rem;
                   4376:                     if ($colsleft) {
                   4377:                         $colspan = $colsleft+1;
                   4378:                         $colspan = ' colspan="'.$colspan.'"';
                   4379:                     }
                   4380:                 }
                   4381:             }
                   4382:             my ($add,$onchange,$css_class);
                   4383:             if ($thistype eq 'string_lenient') {
                   4384:                 if ($name eq 'weighted') {
                   4385:                     my $display;
                   4386:                     my %relatives = &Apache::lonlocal::texthash(
                   4387:                                         corrchkd     => 'Correct (checked)',
                   4388:                                         corrunchkd   => 'Correct (unchecked)',
                   4389:                                         incorrchkd   => 'Incorrect (checked)',
                   4390:                                         incorrunchkd => 'Incorrect (unchecked)',
                   4391:                     );
                   4392:                     my %textval = (
                   4393:                                     corrchkd     => '1.0',
                   4394:                                     corrunchkd   => '1.0',
                   4395:                                     incorrchkd   => '0.0',
                   4396:                                     incorrunchkd => '0.0',
                   4397:                     );
                   4398:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   4399:                         $textval{'corrchkd'} = $1;
                   4400:                         $textval{'corrunchkd'} = $2;
                   4401:                         $textval{'incorrchkd'} = $3;
                   4402:                         $textval{'incorrunchkd'} = $4;
                   4403:                         $display = 'inline';
                   4404:                         $showval = $name;
                   4405:                     } else {
                   4406:                         $display = 'none';
                   4407:                     }
                   4408:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   4409:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   4410:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   4411:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   4412:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  4413:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  4414:                                 '</td></tr>';
                   4415:                     }
                   4416:                     $add .= '</table></div>'."\n";
                   4417:                 }
                   4418:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   4419:                 $css_class = ' class="LC_lenient_radio"';
                   4420:             }
                   4421:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  4422:                        '<span class="LC_nobreak"><label>'.
                   4423:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  4424:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  4425:             if ($showval eq $name) {
                   4426:                 $result .= ' checked="checked"';
                   4427:             }
1.549     raeburn  4428:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  4429:             $i++;
                   4430:         }
                   4431:         $result .= '</tr>';
1.473     amueller 4432:     }
1.504     raeburn  4433:     if ($result) {
                   4434:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 4435:     }
                   4436:     return $result;
                   4437: }
                   4438: 
1.554     raeburn  4439: my %intervals =
                   4440:     (
                   4441:      'date_interval'
                   4442:              => [[ 'done', 'Yes' ],
1.558     raeburn  4443:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  4444:                  [ '', 'No' ]],
                   4445:     );
                   4446: 
                   4447: my %intervalmatches = (
                   4448:          'date_interval'
1.559     raeburn  4449:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   4450:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  4451:     );
                   4452: 
                   4453: my %intervaltypes = (
                   4454:                       interval => 'date_interval',
                   4455:     );
                   4456: 
1.563     damieng  4457: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   4458: #
                   4459: # @param {string} $interval_type - a parameter type for intervals
                   4460: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  4461: sub standard_interval_matches {
                   4462:     my ($interval_type) = @_;
                   4463:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   4464:         return $intervalmatches{$interval_type};
                   4465:     }
                   4466:     return;
                   4467: }
                   4468: 
1.563     damieng  4469: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   4470: #
                   4471: # @param {string} $name - parameter name
                   4472: # @returns {string}
1.554     raeburn  4473: sub get_intervaltype {
                   4474:     my ($name) = @_;
                   4475:     if (exists($intervaltypes{$name})) {
                   4476:         return $intervaltypes{$name};
                   4477:     }
                   4478:     return;
                   4479: }
                   4480: 
1.563     damieng  4481: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   4482: # Used by courseprefs.
                   4483: #
                   4484: # @param {string} $interval_type - a parameter type for intervals
                   4485: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  4486: sub standard_interval_options {
                   4487:     my ($interval_type) = @_;
                   4488:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   4489:         return $intervals{$interval_type};
                   4490:     }
                   4491:     return;
                   4492: }
                   4493: 
1.563     damieng  4494: # Returns HTML to edit a date interval parameter.
                   4495: #
                   4496: # @param {string} $thiskey - parameter key
                   4497: # @param {string} $name - parameter name
                   4498: # @param {string} $showval - parameter current value
                   4499: # @param {boolean} $readonly - true if the values should not be made editable
                   4500: # @returns {string}
1.554     raeburn  4501: sub date_interval_selector {
                   4502:     my ($thiskey, $name, $showval, $readonly) = @_;
                   4503:     my ($result,%skipval);
                   4504:     if ($name eq 'interval') {
                   4505:         my $intervaltype = &get_intervaltype($name);
                   4506:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   4507:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   4508:             next unless (ref($possibilities) eq 'ARRAY');
                   4509:             my ($parmval, $description) = @{ $possibilities };
                   4510:             my $parmmatch;
                   4511:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   4512:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   4513:                     if (ref($item) eq 'ARRAY') {
                   4514:                         if ($parmval eq $item->[0]) {
                   4515:                             $parmmatch = $parmval;
                   4516:                             $parmval = '';
                   4517:                             last;
                   4518:                         }
                   4519:                     }
                   4520:                 }
                   4521:             }
                   4522:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   4523:             if ($needsrelease) {
                   4524:                 unless ($got_chostname) {
                   4525:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   4526:                     $got_chostname = 1;
                   4527:                 }
1.557     raeburn  4528:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  4529:                                                        $needsrelease,$cmajor,$cminor);
                   4530:                 if ($needsnewer) {
                   4531:                     if ($parmmatch ne '') {
                   4532:                         $skipval{$parmmatch} = 1;
                   4533:                     } elsif ($parmval ne '') {
                   4534:                         $skipval{$parmval} = 1;
                   4535:                     }
                   4536:                 }
                   4537:             }
                   4538:         }
                   4539:     }
                   4540: 
                   4541:     my $currval = $showval;
                   4542:     foreach my $which (['days', 86400, 31],
                   4543:                ['hours', 3600, 23],
                   4544:                ['minutes', 60, 59],
                   4545:                ['seconds',  1, 59]) {
1.560     damieng  4546:         my ($name, $factor, $max) = @{ $which };
                   4547:         my $amount = int($showval/$factor);
                   4548:         $showval  %= $factor;
                   4549:         my %select = ((map {$_ => $_} (0..$max)),
                   4550:                 'select_form_order' => [0..$max]);
                   4551:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   4552:                             \%select,'',$readonly);
                   4553:         $result .= ' '.&mt($name);
1.554     raeburn  4554:     }
                   4555:     if ($name eq 'interval') {
                   4556:         unless ($skipval{'done'}) {
                   4557:             my $checkedon = '';
1.558     raeburn  4558:             my $checkedproc = '';
                   4559:             my $currproctorkey = '';
                   4560:             my $currprocdisplay = 'hidden';
1.559     raeburn  4561:             my $currdonetext = &mt('Done');
1.554     raeburn  4562:             my $checkedoff = ' checked="checked"';
1.559     raeburn  4563:             if ($currval =~ /^(?:\d+)_done$/) {
                   4564:                 $checkedon = ' checked="checked"';
                   4565:                 $checkedoff = '';
                   4566:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   4567:                 $currdonetext = $1;
1.554     raeburn  4568:                 $checkedon = ' checked="checked"';
                   4569:                 $checkedoff = '';
1.558     raeburn  4570:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   4571:                 $currproctorkey = $1;
                   4572:                 $checkedproc = ' checked="checked"';
                   4573:                 $checkedoff = '';
                   4574:                 $currprocdisplay = 'text';
1.559     raeburn  4575:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   4576:                 $currdonetext = $1;
                   4577:                 $currproctorkey = $2;
                   4578:                 $checkedproc = ' checked="checked"';
                   4579:                 $checkedoff = '';
                   4580:                 $currprocdisplay = 'text';
1.554     raeburn  4581:             }
1.558     raeburn  4582:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  4583:             my $disabled;
                   4584:             if ($readonly) {
                   4585:                 $disabled = ' disabled="disabled"';
                   4586:             }
1.558     raeburn  4587:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  4588:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  4589:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  4590:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  4591:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  4592:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  4593:                        &mt('Yes, with proctor key').'</label>'.
                   4594:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  4595:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  4596:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567     raeburn  4597:                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  4598:         }
                   4599:     }
                   4600:     unless ($readonly) {
                   4601:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   4602:     }
                   4603:     return $result;
                   4604: }
                   4605: 
1.563     damieng  4606: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   4607: #
                   4608: # @param {string} $name - parameter name
                   4609: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   4610: # @param {string} $value - parameter value
                   4611: # @param {string} $chostname - course server name
                   4612: # @param {integer} $cmajor - major version number
                   4613: # @param {integer} $cminor - minor version number
                   4614: # @param {string} $needsrelease - release version needed (major.minor)
                   4615: # @returns {string}
1.549     raeburn  4616: sub oldversion_warning {
1.557     raeburn  4617:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   4618:     my $standard_name = &standard_parameter_names($name);
                   4619:     if ($namematch) {
                   4620:         my $level = &standard_parameter_levels($namematch);
                   4621:         my $msg = '';
                   4622:         if ($level) {
                   4623:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   4624:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   4625:         } else {
                   4626:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   4627:                       $standard_name,'<b>','</b>');
                   4628:         }
                   4629:         return '<p class="LC_warning">'.$msg.'<br />'.
                   4630:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   4631:                    $cmajor.'.'.$cminor,$chostname,
                   4632:                    $needsrelease).
                   4633:                    '</p>';
                   4634:     }
1.549     raeburn  4635:     my $desc;
                   4636:     my $stringtype = &get_stringtype($name);
                   4637:     if ($stringtype ne '') {
                   4638:         if ($name eq 'examcode') {
                   4639:             $desc = $value;
                   4640:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   4641:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   4642:                 next unless (ref($possibilities) eq 'ARRAY');
                   4643:                 my ($parmval, $description) = @{ $possibilities };
                   4644:                 my $parmmatch;
                   4645:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   4646:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   4647:                         if (ref($item) eq 'ARRAY') {
                   4648:                             my ($regexpname,$pattern) = @{$item};
                   4649:                             if ($parmval eq $regexpname) {
                   4650:                                 if ($value =~ /$pattern/) {
                   4651:                                     $desc = $description; 
                   4652:                                     $parmmatch = 1;
                   4653:                                     last;
                   4654:                                 }
                   4655:                             }
                   4656:                         }
                   4657:                     }
                   4658:                     last if ($parmmatch);
                   4659:                 } elsif ($parmval eq $value) {
                   4660:                     $desc = $description;
                   4661:                     last;
                   4662:                 }
                   4663:             }
                   4664:         }
                   4665:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   4666:         my $now = time;
                   4667:         if ($value =~ /^\d+$/) {
                   4668:             if ($name eq 'printstartdate') {
                   4669:                 if ($value > $now) {
                   4670:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   4671:                 }
                   4672:             } elsif ($name eq 'printenddate') {
                   4673:                 if ($value < $now) {
                   4674:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   4675:                 }
                   4676:             }
                   4677:         }
                   4678:     }
                   4679:     return '<p class="LC_warning">'.
1.557     raeburn  4680:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   4681:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   4682:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   4683:        $cmajor.'.'.$cminor,$chostname,
                   4684:        $needsrelease).
                   4685:        '</p>';
1.549     raeburn  4686: }
                   4687: 
1.560     damieng  4688: } # end of block using some constants related to parameter types
                   4689: 
1.549     raeburn  4690: 
1.563     damieng  4691: 
                   4692: # Shifts all start and end dates in the current course by $shift.
1.389     www      4693: #
1.563     damieng  4694: # @param {integer} $shift - time to shift, in seconds
                   4695: # @returns {string} - error name or 'ok'
1.389     www      4696: sub dateshift {
                   4697:     my ($shift)=@_;
                   4698:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   4699:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   4700:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   4701: # ugly retro fix for broken version of types
1.548     raeburn  4702:     foreach my $key (keys(%data)) {
1.389     www      4703:         if ($key=~/\wtype$/) {
                   4704:             my $newkey=$key;
                   4705:             $newkey=~s/type$/\.type/;
                   4706:             $data{$newkey}=$data{$key};
                   4707:             delete $data{$key};
                   4708:         }
                   4709:     }
1.391     www      4710:     my %storecontent=();
1.389     www      4711: # go through all parameters and look for dates
1.548     raeburn  4712:     foreach my $key (keys(%data)) {
1.389     www      4713:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
                   4714:           my $newdate=$data{$key}+$shift;
1.391     www      4715:           $storecontent{$key}=$newdate;
1.389     www      4716:        }
                   4717:     }
1.391     www      4718:     my $reply=&Apache::lonnet::cput
                   4719:                 ('resourcedata',\%storecontent,$dom,$crs);
                   4720:     if ($reply eq 'ok') {
                   4721:        &log_parmset(\%storecontent);
                   4722:     }
                   4723:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   4724:     return $reply;
1.389     www      4725: }
                   4726: 
1.563     damieng  4727: # Overview mode UI to edit course parameters.
                   4728: #
                   4729: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      4730: sub newoverview {
1.568     raeburn  4731:     my ($r,$parm_permission) = @_;
1.280     albertel 4732: 
1.208     www      4733:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   4734:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  4735:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  4736:     my $readonly = 1;
                   4737:     if ($parm_permission->{'edit'}) {
                   4738:         undef($readonly);
                   4739:     }
1.414     droeschl 4740:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 4741:         text=>"Overview Mode"});
1.523     raeburn  4742: 
                   4743:     my %loaditems = (
1.549     raeburn  4744:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  4745:                     );
                   4746:     my $js = '
                   4747: <script type="text/javascript">
                   4748: // <![CDATA[
                   4749: '.
                   4750:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   4751:             &showhide_js()."\n".
1.549     raeburn  4752:             &toggleparmtextbox_js()."\n".
                   4753:             &validateparms_js()."\n".
                   4754:             &ipacc_boxes_js()."\n".
1.558     raeburn  4755:             &done_proctor_js()."\n".
1.523     raeburn  4756: '// ]]>
                   4757: </script>
                   4758: ';
1.549     raeburn  4759: 
1.523     raeburn  4760:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   4761:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 4762:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      4763:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  4764:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      4765:     $r->print(<<ENDOVER);
1.549     raeburn  4766: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      4767: ENDOVER
1.211     www      4768:     my @ids=();
                   4769:     my %typep=();
                   4770:     my %keyp=();
                   4771:     my %allparms=();
                   4772:     my %allparts=();
                   4773:     my %allmaps=();
                   4774:     my %mapp=();
                   4775:     my %symbp=();
                   4776:     my %maptitles=();
                   4777:     my %uris=();
                   4778:     my %keyorder=&standardkeyorder();
                   4779:     my %defkeytype=();
                   4780: 
                   4781:     my %alllevs=();
                   4782:     $alllevs{'Resource Level'}='full';
1.215     www      4783:     $alllevs{'Map/Folder Level'}='map';
1.211     www      4784:     $alllevs{'Course Level'}='general';
                   4785: 
                   4786:     my $csec=$env{'form.csec'};
1.269     raeburn  4787:     my $cgroup=$env{'form.cgroup'};
1.211     www      4788: 
                   4789:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   4790:     my $pschp=$env{'form.pschp'};
1.506     www      4791: 
1.211     www      4792:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      4793:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      4794: 
1.446     bisitz   4795:     my @selected_sections =
1.473     amueller 4796:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      4797:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 4798:     foreach my $sec (@selected_sections) {
                   4799:         if ($sec eq 'all') {
1.211     www      4800:             @selected_sections = ('all');
                   4801:         }
                   4802:     }
1.552     raeburn  4803:     if ($env{'request.course.sec'} ne '') {
                   4804:         @selected_sections = ($env{'request.course.sec'});
                   4805:     }
1.269     raeburn  4806:     my @selected_groups =
                   4807:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      4808: 
                   4809:     my $pssymb='';
                   4810:     my $parmlev='';
1.446     bisitz   4811: 
1.211     www      4812:     unless ($env{'form.parmlev'}) {
                   4813:         $parmlev = 'map';
                   4814:     } else {
                   4815:         $parmlev = $env{'form.parmlev'};
                   4816:     }
                   4817: 
1.446     bisitz   4818:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 4819:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   4820:                 \%keyorder,\%defkeytype);
1.211     www      4821: 
1.374     albertel 4822:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 4823:         @psprt = keys(%allparts);
1.374     albertel 4824:     }
1.211     www      4825: # Menu to select levels, etc
                   4826: 
1.456     bisitz   4827:     $r->print('<div class="LC_Box">');
1.445     neumanie 4828:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   4829:     $r->print('<div>');
1.523     raeburn  4830:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      4831:     &levelmenu($r,\%alllevs,$parmlev);
                   4832:     if ($parmlev ne 'general') {
1.447     bisitz   4833:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.483     amueller 4834:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211     www      4835:     }
1.447     bisitz   4836:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 4837:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   4838:     $r->print('</div></div>');
1.446     bisitz   4839: 
1.456     bisitz   4840:     $r->print('<div class="LC_Box">');
1.452     bisitz   4841:     $r->print('<div>');
1.562     damieng  4842:     &displaymenu($r,\%allparms,\@pscat,\%keyorder); # FIXME: wrong parameters, could make keysindisplayorderCategory crash because $keyorder is undefined
1.453     schualex 4843:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   4844:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  4845:     my $sectionselector = &sectionmenu(\@selected_sections);
                   4846:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 4847:     $r->print('<table>'.
1.553     raeburn  4848:               '<tr><th>'.&mt('Parts').'</th>');
                   4849:     if ($sectionselector) {
                   4850:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   4851:     }
                   4852:     if ($groupselector) {
                   4853:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   4854:     }
                   4855:     $r->print('</tr><tr><td>');
1.211     www      4856:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  4857:     $r->print('</td>');
                   4858:     if ($sectionselector) { 
                   4859:         $r->print('<td>'.$sectionselector.'</td>');
                   4860:     }
                   4861:     if ($groupselector) {
                   4862:         $r->print('<td>'.$groupselector.'</td>');
                   4863:     }
                   4864:     $r->print('</tr></table>');
1.447     bisitz   4865:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 4866:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   4867:     $r->print('</div></div>');
                   4868: 
1.456     bisitz   4869:     $r->print('<div class="LC_Box">');
1.452     bisitz   4870:     $r->print('<div>');
1.214     www      4871:     my $sortorder=$env{'form.sortorder'};
                   4872:     unless ($sortorder) { $sortorder='realmstudent'; }
                   4873:     &sortmenu($r,$sortorder);
1.445     neumanie 4874:     $r->print('</div></div>');
1.446     bisitz   4875: 
1.214     www      4876:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   4877: 
1.211     www      4878: # Build the list data hash from the specified parms
                   4879: 
                   4880:     my $listdata;
                   4881:     %{$listdata}=();
                   4882: 
                   4883:     foreach my $cat (@pscat) {
1.269     raeburn  4884:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   4885:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      4886:     }
                   4887: 
1.212     www      4888:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      4889: 
1.481     amueller 4890:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      4891: 
                   4892: # Read modified data
                   4893: 
1.481     amueller 4894:         my $resourcedata=&readdata($crs,$dom);
1.211     www      4895: 
                   4896: # List data
                   4897: 
1.568     raeburn  4898:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
                   4899:     }
                   4900:     $r->print(&tableend());
                   4901:     unless ($readonly) {
                   4902:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      4903:     }
1.568     raeburn  4904:     $r->print('</form>');
1.507     www      4905:     &endSettingsScreen($r);
                   4906:     $r->print(&Apache::loncommon::end_page());
1.208     www      4907: }
                   4908: 
1.563     damieng  4909: # Fills $listdata with parameter information.
                   4910: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   4911: # The non-type value is always 1.
                   4912: #
                   4913: # @param {string} $cat - parameter name
1.566     damieng  4914: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4915: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   4916: # @param {hash reference} $listdata - the parameter data that will be modified
                   4917: # @param {array reference} $psprt - selected parts
                   4918: # @param {array reference} $selections - selected sections
                   4919: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  4920: # @param {hash reference} $allmaps - hash map pc -> map src
                   4921: # @param {array reference} $ids - resource and map ids
                   4922: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  4923: sub secgroup_lister {
                   4924:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   4925:     foreach my $item (@{$selections}) {
                   4926:         foreach my $part (@{$psprt}) {
                   4927:             my $rootparmkey=$env{'request.course.id'};
                   4928:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   4929:                 $rootparmkey.='.['.$item.']';
                   4930:             }
                   4931:             if ($parmlev eq 'general') {
                   4932: # course-level parameter
                   4933:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   4934:                 $$listdata{$newparmkey}=1;
                   4935:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   4936:             } elsif ($parmlev eq 'map') {
                   4937: # map-level parameter
1.548     raeburn  4938:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  4939:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   4940:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   4941:                     $$listdata{$newparmkey}=1;
                   4942:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
1.556     raeburn  4943:                     $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(rec).'.$part.'.'.$cat;
                   4944:                     $$listdata{$newparmkey}=1;
                   4945:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
1.269     raeburn  4946:                 }
                   4947:             } else {
                   4948: # resource-level parameter
                   4949:                 foreach my $rid (@{$ids}) {
                   4950:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   4951:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   4952:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   4953:                     $$listdata{$newparmkey}=1;
                   4954:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   4955:                 }
                   4956:             }
                   4957:         }
                   4958:     }
                   4959: }
                   4960: 
1.563     damieng  4961: # UI to edit parameter settings starting with a list of all existing parameters.
                   4962: # (called by setoverview action)
                   4963: #
                   4964: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      4965: sub overview {
1.568     raeburn  4966:     my ($r,$parm_permission) = @_;
1.208     www      4967:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   4968:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  4969:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  4970:     my $readonly = 1;
                   4971:     if ($parm_permission->{'edit'}) {
                   4972:         undef($readonly);
                   4973:     }
1.549     raeburn  4974:     my $js = '<script type="text/javascript">'."\n".
                   4975:              '// <![CDATA['."\n".
                   4976:              &toggleparmtextbox_js()."\n".
                   4977:              &validateparms_js()."\n".
                   4978:              &ipacc_boxes_js()."\n".
1.558     raeburn  4979:              &done_proctor_js()."\n".
1.549     raeburn  4980:              '// ]]>'."\n".
                   4981:              '</script>'."\n";
1.414     droeschl 4982:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 4983:     text=>"Overview Mode"});
1.549     raeburn  4984:     my %loaditems = (
                   4985:                       'onload'   => "showHideLenient();",
                   4986:                     );
                   4987: 
                   4988:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 4989:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      4990:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  4991:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  4992:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      4993: 
1.208     www      4994: # Store modified
                   4995: 
1.568     raeburn  4996:     unless ($readonly) {
                   4997:         &storedata($r,$crs,$dom);
                   4998:     }
1.208     www      4999: 
                   5000: # Read modified data
                   5001: 
1.552     raeburn  5002:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      5003: 
1.214     www      5004: 
                   5005:     my $sortorder=$env{'form.sortorder'};
                   5006:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5007:     &sortmenu($r,$sortorder);
                   5008: 
1.568     raeburn  5009:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   5010: 
                   5011:     if ($readonly) {
                   5012:         $r->print('<p>'.$submitbutton.'</p>');
                   5013:     }
                   5014: 
1.208     www      5015: # List data
                   5016: 
1.568     raeburn  5017:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   5018:     $r->print(&tableend().'<p>');
                   5019:     if ($foundkeys) {
                   5020:         unless ($readonly) {
                   5021:             $r->print('<p>'.$submitbutton.'</p>');
                   5022:         }
                   5023:     } else {
                   5024:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   5025:     }
                   5026:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      5027: }
1.121     www      5028: 
1.560     damieng  5029: # Unused sub.
1.563     damieng  5030: #
                   5031: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 5032: sub clean_parameters {
                   5033:     my ($r) = @_;
                   5034:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5035:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5036: 
1.414     droeschl 5037:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 5038:         text=>"Clean Parameters"});
1.333     albertel 5039:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   5040:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   5041:     $r->print(<<ENDOVER);
                   5042: $start_page
                   5043: $breadcrumbs
                   5044: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   5045: ENDOVER
                   5046: # Store modified
                   5047: 
                   5048:     &storedata($r,$crs,$dom);
                   5049: 
                   5050: # Read modified data
                   5051: 
                   5052:     my $resourcedata=&readdata($crs,$dom);
                   5053: 
                   5054: # List data
                   5055: 
                   5056:     $r->print('<h3>'.
1.473     amueller 5057:           &mt('These parameters refer to resources that do not exist.').
                   5058:           '</h3>'.
                   5059:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   5060:           '<br />');
1.333     albertel 5061:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 5062:           '<tr>'.
                   5063:           '<th>'.&mt('Delete').'</th>'.
                   5064:           '<th>'.&mt('Parameter').'</th>'.
                   5065:           '</tr>');
1.333     albertel 5066:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  5067:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   5068:             && $thiskey=~/\.type$/);
                   5069:         my %data = &parse_key($thiskey);
                   5070:         if (1) { #exists($data{'realm_exists'})
                   5071:             #&& !$data{'realm_exists'}) {
                   5072:             $r->print(&Apache::loncommon::start_data_table_row().
                   5073:                 '<tr>'.
                   5074:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   5075: 
                   5076:             $r->print('<td>');
                   5077:             my $display_value = $resourcedata->{$thiskey};
                   5078:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   5079:             $display_value =
                   5080:                 &Apache::lonlocal::locallocaltime($display_value);
                   5081:             }
1.470     raeburn  5082:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   5083:             $parmitem = &mt($parmitem);
1.560     damieng  5084:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   5085:                 $parmitem,$resourcedata->{$thiskey}));
                   5086:             $r->print('<br />');
                   5087:             if ($data{'scope_type'} eq 'all') {
                   5088:                 $r->print(&mt('All users'));
                   5089:             } elsif ($data{'scope_type'} eq 'user') {
                   5090:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
                   5091:             } elsif ($data{'scope_type'} eq 'section') {
                   5092:                 $r->print(&mt('Section: [_1]',$data{'scope'}));
                   5093:             } elsif ($data{'scope_type'} eq 'group') {
                   5094:                 $r->print(&mt('Group: [_1]',$data{'scope'}));
                   5095:             }
                   5096:             $r->print('<br />');
                   5097:             if ($data{'realm_type'} eq 'all') {
                   5098:                 $r->print(&mt('All Resources'));
                   5099:             } elsif ($data{'realm_type'} eq 'folder') {
                   5100:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   5101:             } elsif ($data{'realm_type'} eq 'symb') {
                   5102:             my ($map,$resid,$url) =
                   5103:                 &Apache::lonnet::decode_symb($data{'realm'});
                   5104:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   5105:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   5106:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   5107:             }
                   5108:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   5109:             $r->print('</td></tr>');
                   5110: 
1.473     amueller 5111:         }
1.333     albertel 5112:     }
                   5113:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 5114:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      5115:           '</p></form>');
                   5116:     &endSettingsScreen($r);
                   5117:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 5118: }
                   5119: 
1.563     damieng  5120: # UI to shift all dates (called by dateshift1 action).
                   5121: # Used by overview mode.
                   5122: #
                   5123: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5124: sub date_shift_one {
                   5125:     my ($r) = @_;
                   5126:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5127:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5128:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.390     www      5129: 
1.414     droeschl 5130:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5131:         text=>"Shifting Dates"});
1.390     www      5132:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5133:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5134:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5135:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   5136:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      5137:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   5138:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   5139:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   5140:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      5141:                                                         'timeshifted',
                   5142:                                                         $env{'form.timebase'},,
                   5143:                                                         '').
                   5144:               '</td></tr></table>'.
                   5145:               '<input type="hidden" name="action" value="dateshift2" />'.
                   5146:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
                   5147:               '<input type="submit" value="'.&mt('Shift all dates accordingly').'" /></form>');
1.507     www      5148:     &endSettingsScreen($r);
1.390     www      5149:     $r->print(&Apache::loncommon::end_page());
                   5150: }
                   5151: 
1.563     damieng  5152: # UI to shift all dates (second form).
                   5153: #
                   5154: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      5155: sub date_shift_two {
                   5156:     my ($r) = @_;
                   5157:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5158:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5159:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 5160:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 5161:         text=>"Shifting Dates"});
1.390     www      5162:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   5163:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      5164:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5165:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      5166:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.543     bisitz   5167:     $r->print('<h2>'.&mt('Shift Dates').'</h2>'.
                   5168:               '<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
1.390     www      5169:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
1.543     bisitz   5170:               &Apache::lonlocal::locallocaltime($timeshifted)).'</p>');
1.390     www      5171:     my $delta=$timeshifted-$env{'form.timebase'};
                   5172:     &dateshift($delta);
1.543     bisitz   5173:     $r->print(
                   5174:         &Apache::lonhtmlcommon::confirm_success(&mt('Done')).
                   5175:         '<br /><br />'.
                   5176:         &Apache::lonhtmlcommon::actionbox(
                   5177:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      5178:     &endSettingsScreen($r);
1.390     www      5179:     $r->print(&Apache::loncommon::end_page());
                   5180: }
                   5181: 
1.563     damieng  5182: # Returns the different components of a resourcedata key.
                   5183: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   5184: #       realm_exists, parameter_part, parameter_name.
                   5185: # Was used by clean_parameters (which is unused).
                   5186: #
                   5187: # @param {string} $key - the parameter key
                   5188: # @returns {hash}
1.333     albertel 5189: sub parse_key {
                   5190:     my ($key) = @_;
                   5191:     my %data;
                   5192:     my ($middle,$part,$name)=
1.572     damieng  5193:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 5194:     $data{'scope_type'} = 'all';
                   5195:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  5196:         $data{'scope'} = $1;
                   5197:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   5198:             $data{'scope_type'} = 'user';
                   5199:             $data{'scope'} = [$1,$2];
                   5200:         } else {
                   5201:             #FIXME check for group scope
                   5202:             $data{'scope_type'} = 'section';
                   5203:         }
                   5204:         $middle=~s/^\[(.*)\]//;
1.333     albertel 5205:     }
                   5206:     $middle=~s/\.+$//;
                   5207:     $middle=~s/^\.+//;
                   5208:     $data{'realm_type'}='all';
                   5209:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  5210:         $data{'realm'} = $1;
                   5211:         $data{'realm_type'} = 'folder';
                   5212:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5213:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 5214:     } elsif ($middle) {
1.560     damieng  5215:         $data{'realm'} = $middle;
                   5216:         $data{'realm_type'} = 'symb';
                   5217:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   5218:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   5219:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 5220:     }
1.446     bisitz   5221: 
1.333     albertel 5222:     $data{'parameter_part'} = $part;
                   5223:     $data{'parameter_name'} = $name;
                   5224: 
                   5225:     return %data;
                   5226: }
                   5227: 
1.239     raeburn  5228: 
1.563     damieng  5229: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      5230: sub header {
1.507     www      5231:     return &Apache::loncommon::start_page('Settings');
1.416     jms      5232: }
1.193     albertel 5233: 
                   5234: 
                   5235: 
1.560     damieng  5236: ##################################################
                   5237: # MAIN MENU
                   5238: ##################################################
                   5239: 
1.563     damieng  5240: # Content and problem settings main menu.
                   5241: #
                   5242: # @param {Apache2::RequestRec} $r - the Apache request
                   5243: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 5244: sub print_main_menu {
                   5245:     my ($r,$parm_permission)=@_;
                   5246:     #
1.414     droeschl 5247:     $r->print(&header());
1.507     www      5248:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  5249:     my $crstype = &Apache::loncommon::course_type();
                   5250:     my $lc_crstype = lc($crstype);
                   5251: 
                   5252:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 5253:     $r->print(<<ENDMAINFORMHEAD);
                   5254: <form method="post" enctype="multipart/form-data"
                   5255:       action="/adm/parmset" name="studentform">
                   5256: ENDMAINFORMHEAD
                   5257: #
1.195     albertel 5258:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5259:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 5260:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 5261:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  5262:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  5263:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   5264:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  5265:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   5266:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   5267:                                         '/'.$env{'request.course.sec'});
                   5268:     }
1.568     raeburn  5269:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   5270:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   5271:                                         '/'.$env{'request.course.sec'});
                   5272:     }
                   5273:     my (%linktext,%linktitle,%url);
                   5274:     if ($parm_permission->{'edit'}) {
                   5275:         %linktext = (
                   5276:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   5277:                      settable        => 'Edit Resource Parameters - Table Mode',
                   5278:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   5279:                     );
                   5280:         %linktitle = (
                   5281:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   5282:                      settable        => 'Set/Modify resource parameters in table mode.',
                   5283:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   5284:                      );
                   5285:     } else {
                   5286:         %linktext = (
                   5287:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   5288:                      settable        => 'View Resource Parameters - Table Mode',
                   5289:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   5290:                    );
                   5291:         %linktitle = (
                   5292:                      newoverview     => 'Display resource parameters in overview mode.',
                   5293:                      settable        => 'Display resource parameters in table mode.',
                   5294:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   5295:                      );
                   5296:     }
                   5297:     if ($mgr) {
                   5298:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   5299:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   5300:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   5301:     } elsif ($vgr) {
                   5302:         $linktext{'resettimes'} = 'Display Student Access Times',
                   5303:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   5304:         $url{'resettimes'} = '/adm/accesstimes';
                   5305:     }
1.193     albertel 5306:     my @menu =
1.507     www      5307:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 5308:         items => [
                   5309:           { linktext => 'Portfolio Metadata',
                   5310:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  5311:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  5312:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 5313:             icon =>'contact-new.png'   ,
                   5314:             },
1.568     raeburn  5315:           { linktext => $linktext{'resettimes'},
                   5316:             url => $url{'resettimes'},
                   5317:             permission => ($vgr || $mgr),
                   5318:             linktitle => $linktitle{'resettimes'},
                   5319:             icon => 'start-here.png',
1.473     amueller 5320:             },
1.520     raeburn  5321:           { linktext => 'Blocking Communication/Resource Access',
                   5322:             url => '/adm/setblock',
1.568     raeburn  5323:             permission => ($vcb || $dcm),
1.520     raeburn  5324:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   5325:             icon => 'comblock.png',
                   5326:             },
1.473     amueller 5327:           { linktext => 'Set Parameter Setting Default Actions',
                   5328:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  5329:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 5330:             linktitle =>'Set default actions for parameters.'  ,
                   5331:             icon => 'folder-new.png'  ,
                   5332:             }]},
                   5333:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   5334:         items => [
                   5335:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   5336:             url => '/adm/helper/parameter.helper',
1.568     raeburn  5337:             permission => $parm_permission->{'helper'},
1.473     amueller 5338:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   5339:             icon => 'dialog-information.png'  ,
                   5340:             #help => 'Parameter_Helper',
                   5341:             },
1.568     raeburn  5342:           { linktext => $linktext{'newoverview'},
1.473     amueller 5343:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  5344:             permission => $parm_permission->{'newoverview'},
                   5345:             linktitle => $linktitle{'newoverview'},
                   5346:             icon => 'edit-find.png',
1.473     amueller 5347:             #help => 'Parameter_Overview',
                   5348:             },
1.568     raeburn  5349:           { linktext => $linktext{'settable'},
1.473     amueller 5350:             url => '/adm/parmset?action=settable',
1.568     raeburn  5351:             permission => $parm_permission->{'settable'},
                   5352:             linktitle => $linktitle{'settable'},
                   5353:             icon => 'edit-copy.png',
1.473     amueller 5354:             #help => 'Table_Mode',
                   5355:             }]},
1.417     droeschl 5356:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 5357:          items => [
1.570     raeburn  5358:           { linktext => $linktext{'setoverview'},
1.473     amueller 5359:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  5360:             permission => $parm_permission->{'setoverview'},
                   5361:             linktitle => $linktitle{'setoverview'},
                   5362:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 5363:             #help => 'Parameter_Overview',
                   5364:             },
                   5365:           { linktext => 'Change Log',
                   5366:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  5367:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  5368:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 5369:             icon => 'document-properties.png',
1.473     amueller 5370:             }]}
1.193     albertel 5371:           );
1.414     droeschl 5372:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  5373:     $r->print('</form>');
1.507     www      5374:     &endSettingsScreen($r);
1.539     raeburn  5375:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 5376:     return;
                   5377: }
1.414     droeschl 5378: 
1.416     jms      5379: 
                   5380: 
1.560     damieng  5381: ##################################################
                   5382: # PORTFOLIO METADATA
                   5383: ##################################################
                   5384: 
1.563     damieng  5385: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   5386: # It looks like field titles are not localized.
                   5387: #
                   5388: # @param {Apache2::RequestRec} $r - the Apache request
                   5389: # @param {string} $field_name - metadata field name
                   5390: # @param {string} $field_text - metadata field title, in English unless manually added
                   5391: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 5392: sub output_row {
1.347     banghart 5393:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 5394:     my $output;
1.263     banghart 5395:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   5396:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 5397:     if (!defined($options)) {
1.254     banghart 5398:         $options = 'active,stuadd';
1.261     banghart 5399:         $values = '';
1.252     banghart 5400:     }
1.337     banghart 5401:     if (!($options =~ /deleted/)) {
                   5402:         my @options= ( ['active', 'Show to student'],
1.418     schafran 5403:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 5404:                     ['choices','Provide choices for students to select from']);
1.473     amueller 5405: #           ['onlyone','Student may select only one choice']);
1.337     banghart 5406:         if ($added_flag) {
                   5407:             push @options,['deleted', 'Delete Metadata Field'];
                   5408:         }
1.351     banghart 5409:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   5410:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 5411:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 5412:         foreach my $opt (@options) {
1.560     damieng  5413:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   5414:             $output .= &Apache::loncommon::continue_data_table_row();
                   5415:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   5416:                     <input type="checkbox" name="'.
                   5417:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   5418:                     &mt($opt->[1]).'</label></td>';
                   5419:             $output .= &Apache::loncommon::end_data_table_row();
                   5420:         }
1.351     banghart 5421:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   5422:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 5423:         $output .= &Apache::loncommon::end_data_table_row();
                   5424:         my $multiple_checked;
                   5425:         my $single_checked;
                   5426:         if ($options =~ m/onlyone/) {
1.422     bisitz   5427:             $multiple_checked = '';
1.423     bisitz   5428:             $single_checked = ' checked="checked"';
1.351     banghart 5429:         } else {
1.423     bisitz   5430:             $multiple_checked = ' checked="checked"';
1.422     bisitz   5431:             $single_checked = '';
1.351     banghart 5432:         }
1.560     damieng  5433:         $output .= &Apache::loncommon::continue_data_table_row();
                   5434:         $output .= '<td>'.('&nbsp;' x 10).'
                   5435:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   5436:                     '.&mt('Student may select multiple choices from list').'</td>';
                   5437:         $output .= &Apache::loncommon::end_data_table_row();
                   5438:         $output .= &Apache::loncommon::continue_data_table_row();
                   5439:         $output .= '<td>'.('&nbsp;' x 10).'
                   5440:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   5441:                     '.&mt('Student may select only one choice from list').'</td>';
                   5442:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 5443:     }
                   5444:     return ($output);
                   5445: }
1.416     jms      5446: 
                   5447: 
1.560     damieng  5448: # UI to order portfolio metadata fields.
1.563     damieng  5449: # Currently useless because addmetafield does not work.
                   5450: #
                   5451: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 5452: sub order_meta_fields {
                   5453:     my ($r)=@_;
                   5454:     my $idx = 1;
                   5455:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5456:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5457:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 5458:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  5459:     &Apache::lonhtmlcommon::add_breadcrumb(
                   5460:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 5461:         text=>"Add Metadata Field"});
1.560     damieng  5462:     &Apache::lonhtmlcommon::add_breadcrumb(
                   5463:         {href=>"/adm/parmset?action=setrestrictmeta",
                   5464:         text=>"Restrict Metadata"},
                   5465:         {text=>"Order Metadata"});
1.345     banghart 5466:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  5467:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 5468:     if ($env{'form.storeorder'}) {
                   5469:         my $newpos = $env{'form.newpos'} - 1;
                   5470:         my $currentpos = $env{'form.currentpos'} - 1;
                   5471:         my @neworder = ();
1.548     raeburn  5472:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 5473:         my $i;
1.341     banghart 5474:         if ($newpos > $currentpos) {
1.340     banghart 5475:         # moving stuff up
                   5476:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  5477:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 5478:             }
                   5479:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  5480:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 5481:             }
                   5482:             $neworder[$newpos]=$oldorder[$currentpos];
                   5483:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  5484:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 5485:             }
                   5486:         } else {
                   5487:         # moving stuff down
1.473     amueller 5488:             for ($i=0;$i<$newpos;$i++) {
                   5489:                 $neworder[$i]=$oldorder[$i];
                   5490:             }
                   5491:             $neworder[$newpos]=$oldorder[$currentpos];
                   5492:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   5493:                 $neworder[$i]=$oldorder[$i-1];
                   5494:             }
                   5495:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   5496:                 $neworder[$i]=$oldorder[$i];
                   5497:             }
1.340     banghart 5498:         }
1.560     damieng  5499:         my $ordered_fields = join ",", @neworder;
1.343     banghart 5500:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  5501:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   5502:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 5503:     }
1.357     raeburn  5504:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 5505:     my $ordered_fields;
1.548     raeburn  5506:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 5507:     if (!@fields_in_order) {
                   5508:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  5509:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 5510:             push @fields_in_order, $key;
1.341     banghart 5511:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 5512:         }
1.341     banghart 5513:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   5514:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   5515:     }
1.340     banghart 5516:     $r->print('<table>');
                   5517:     my $num_fields = scalar(@fields_in_order);
                   5518:     foreach my $key (@fields_in_order) {
                   5519:         $r->print('<tr><td>');
                   5520:         $r->print('<form method="post" action="">');
1.537     bisitz   5521:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 5522:         for (my $i = 1;$i le $num_fields;$i ++) {
                   5523:             if ($i eq $idx) {
                   5524:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   5525:             } else {
                   5526:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   5527:             }
                   5528:         }
                   5529:         $r->print('</select></td><td>');
                   5530:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   5531:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   5532:         $r->print('</form>');
                   5533:         $r->print($$fields{$key}.'</td></tr>');
                   5534:         $idx ++;
                   5535:     }
                   5536:     $r->print('</table>');
1.507     www      5537:     &endSettingsScreen($r);
1.340     banghart 5538:     return 'ok';
                   5539: }
1.416     jms      5540: 
                   5541: 
1.563     damieng  5542: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   5543: # @returns {string}
1.359     banghart 5544: sub continue {
                   5545:     my $output;
                   5546:     $output .= '<form action="" method="post">';
                   5547:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
                   5548:     $output .= '<input type="submit" value="Continue" />';
                   5549:     return ($output);
                   5550: }
1.416     jms      5551: 
                   5552: 
1.563     damieng  5553: # UI to add a metadata field.
                   5554: # Currenly does not work because of an HTML error (the field is not visible).
                   5555: #
                   5556: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 5557: sub addmetafield {
                   5558:     my ($r)=@_;
1.414     droeschl 5559:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 5560:         text=>"Add Metadata Field"});
1.334     banghart 5561:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   5562:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 5563:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5564:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5565:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   5566:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 5567:     if (exists($env{'form.undelete'})) {
1.358     banghart 5568:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 5569:         foreach my $meta_field(@meta_fields) {
                   5570:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   5571:             $options =~ s/deleted//;
                   5572:             $options =~ s/,,/,/;
                   5573:             my $put_result = &Apache::lonnet::put('environment',
                   5574:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   5575: 
1.339     banghart 5576:             $r->print('Undeleted Metadata Field <strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}."</strong> with result ".$put_result.'<br />');
                   5577:         }
1.359     banghart 5578:         $r->print(&continue());
1.339     banghart 5579:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 5580:         my $meta_field = $env{'form.fieldname'};
                   5581:         my $display_field = $env{'form.fieldname'};
                   5582:         $meta_field =~ s/\W/_/g;
1.338     banghart 5583:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 5584:         my $put_result = &Apache::lonnet::put('environment',
                   5585:                             {'metadata.'.$meta_field.'.values'=>"",
                   5586:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   5587:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.359     banghart 5588:         $r->print('Added new Metadata Field <strong>'.$env{'form.fieldname'}."</strong> with result ".$put_result.'<br />');
                   5589:         $r->print(&continue());
1.335     banghart 5590:     } else {
1.357     raeburn  5591:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 5592:         if ($fields) {
                   5593:             $r->print('You may undelete previously deleted fields.<br />Check those you wish to undelete and click Undelete.<br />');
                   5594:             $r->print('<form method="post" action="">');
                   5595:             foreach my $key(keys(%$fields)) {
1.358     banghart 5596:                 $r->print('<input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'<br /');
1.339     banghart 5597:             }
                   5598:             $r->print('<input type="submit" name="undelete" value="Undelete" />');
                   5599:             $r->print('</form>');
                   5600:         }
1.571     damieng  5601:         $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 5602:         $r->print('<input type="text" name="fieldname" /><br />');
                   5603:         $r->print('<input type="submit" value="Add Metadata Field" />');
1.334     banghart 5604:     }
1.361     albertel 5605:     $r->print('</form>');
1.507     www      5606:     &endSettingsScreen($r);
1.334     banghart 5607: }
1.416     jms      5608: 
                   5609: 
                   5610: 
1.560     damieng  5611: # Display or save portfolio metadata.
1.563     damieng  5612: #
                   5613: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 5614: sub setrestrictmeta {
1.240     banghart 5615:     my ($r)=@_;
1.242     banghart 5616:     my $next_meta;
1.244     banghart 5617:     my $output;
1.245     banghart 5618:     my $item_num;
1.246     banghart 5619:     my $put_result;
1.414     droeschl 5620:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 5621:         text=>"Restrict Metadata"});
1.280     albertel 5622:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 5623:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 5624:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5625:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5626:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   5627:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 5628:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 5629:     my $save_field = '';
1.259     banghart 5630:     if ($env{'form.restrictmeta'}) {
1.254     banghart 5631:         foreach my $field (sort(keys(%env))) {
1.252     banghart 5632:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 5633:                 my $options;
1.252     banghart 5634:                 my $meta_field = $1;
                   5635:                 my $meta_key = $2;
1.253     banghart 5636:                 if ($save_field ne $meta_field) {
1.252     banghart 5637:                     $save_field = $meta_field;
1.473     amueller 5638:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   5639:                         $options.='stuadd,';
                   5640:                     }
                   5641:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   5642:                         $options.='choices,';
                   5643:                     }
                   5644:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   5645:                         $options.='onlyone,';
                   5646:                     }
                   5647:                     if ($env{'form.'.$meta_field.'_active'}) {
                   5648:                         $options.='active,';
                   5649:                     }
                   5650:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   5651:                         $options.='deleted,';
                   5652:                     }
1.259     banghart 5653:                     my $name = $save_field;
1.560     damieng  5654:                     $put_result = &Apache::lonnet::put('environment',
                   5655:                         {'metadata.'.$meta_field.'.options'=>$options,
                   5656:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   5657:                         },$dom,$crs);
1.252     banghart 5658:                 }
                   5659:             }
                   5660:         }
                   5661:     }
1.296     albertel 5662:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 5663:                        {'freshen_cache' => 1});
1.335     banghart 5664:     # Get the default metadata fields
1.258     albertel 5665:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 5666:     # Now get possible added metadata fields
1.357     raeburn  5667:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.346     banghart 5668:     my $row_alt = 1;
1.347     banghart 5669:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 5670:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 5671:         if ($field ne 'courserestricted') {
1.346     banghart 5672:             $row_alt = $row_alt ? 0 : 1;
1.560     damieng  5673:             $output.= &output_row($r, $field, $metadata_fields{$field});
                   5674:         }
1.255     banghart 5675:     }
1.351     banghart 5676:     my $buttons = (<<ENDButtons);
                   5677:         <input type="submit" name="restrictmeta" value="Save" />
                   5678:         </form><br />
                   5679:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
                   5680:         <input type="submit" name="restrictmeta" value="Add a Metadata Field" />
                   5681:         </form>
                   5682:         <br />
                   5683:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
                   5684:         <input type="submit" name="restrictmeta" value="Order Metadata Fields" />
                   5685: ENDButtons
1.337     banghart 5686:     my $added_flag = 1;
1.335     banghart 5687:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.346     banghart 5688:         $row_alt = $row_alt ? 0 : 1;
1.563     damieng  5689:         $output.= &output_row($r, $field, $$added_metadata_fields{$field},$added_flag, $row_alt); # FIXME: wrong parameters
1.335     banghart 5690:     }
1.347     banghart 5691:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   5692:     $r->print(<<ENDenv);
1.259     banghart 5693:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 5694:         $output
1.351     banghart 5695:         $buttons
1.340     banghart 5696:         </form>
1.244     banghart 5697: ENDenv
1.507     www      5698:     &endSettingsScreen($r);
1.280     albertel 5699:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 5700:     return 'ok';
                   5701: }
1.416     jms      5702: 
                   5703: 
1.563     damieng  5704: # Returns metadata fields that have been manually added.
                   5705: #
                   5706: # @param {string} $cid - course id
                   5707: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 5708: sub get_added_meta_fieldnames {
1.357     raeburn  5709:     my ($cid) = @_;
1.335     banghart 5710:     my %fields;
                   5711:     foreach my $key(%env) {
1.357     raeburn  5712:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 5713:             my $field_name = $1;
                   5714:             my ($display_field_name) = $env{$key};
                   5715:             $fields{$field_name} = $display_field_name;
                   5716:         }
                   5717:     }
                   5718:     return \%fields;
                   5719: }
1.416     jms      5720: 
                   5721: 
1.563     damieng  5722: # Returns metadata fields that have been manually added and deleted.
                   5723: #
                   5724: # @param {string} $cid - course id
                   5725: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 5726: sub get_deleted_meta_fieldnames {
1.357     raeburn  5727:     my ($cid) = @_;
1.339     banghart 5728:     my %fields;
                   5729:     foreach my $key(%env) {
1.357     raeburn  5730:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 5731:             my $field_name = $1;
                   5732:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   5733:                 my ($display_field_name) = $env{$key};
                   5734:                 $fields{$field_name} = $display_field_name;
                   5735:             }
                   5736:         }
                   5737:     }
                   5738:     return \%fields;
                   5739: }
1.560     damieng  5740: 
                   5741: 
                   5742: ##################################################
                   5743: # PARAMETER SETTINGS DEFAULT ACTIONS
                   5744: ##################################################
                   5745: 
                   5746: # UI to change parameter setting default actions
1.563     damieng  5747: #
                   5748: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      5749: sub defaultsetter {
1.280     albertel 5750:     my ($r) = @_;
                   5751: 
1.414     droeschl 5752:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 5753:         text=>"Set Defaults"});
1.531     raeburn  5754:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5755:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   5756:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   5757:     my $start_page =
1.531     raeburn  5758:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 5759:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      5760:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5761:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      5762:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 5763: 
1.221     www      5764:     my @ids=();
                   5765:     my %typep=();
                   5766:     my %keyp=();
                   5767:     my %allparms=();
                   5768:     my %allparts=();
                   5769:     my %allmaps=();
                   5770:     my %mapp=();
                   5771:     my %symbp=();
                   5772:     my %maptitles=();
                   5773:     my %uris=();
                   5774:     my %keyorder=&standardkeyorder();
                   5775:     my %defkeytype=();
                   5776: 
1.446     bisitz   5777:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 5778:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   5779:                 \%keyorder,\%defkeytype);
1.224     www      5780:     if ($env{'form.storerules'}) {
1.560     damieng  5781:         my %newrules=();
                   5782:         my @delrules=();
                   5783:         my %triggers=();
                   5784:         foreach my $key (keys(%env)) {
1.225     albertel 5785:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  5786:                 my $tempkey=$1;
                   5787:                 my $action=$env{$key};
1.226     www      5788:                 if ($action) {
1.560     damieng  5789:                     $newrules{$tempkey.'_action'}=$action;
                   5790:                     if ($action ne 'default') {
                   5791:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   5792:                         $triggers{$whichparm}.=$tempkey.':';
                   5793:                     }
                   5794:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   5795:                     if (&isdateparm($defkeytype{$tempkey})) {
                   5796:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   5797:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   5798:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   5799:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   5800:                     } else {
                   5801:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   5802:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   5803:                     }
                   5804:                 } else {
                   5805:                     push(@delrules,$tempkey.'_action');
                   5806:                     push(@delrules,$tempkey.'_type');
                   5807:                     push(@delrules,$tempkey.'_hours');
                   5808:                     push(@delrules,$tempkey.'_min');
                   5809:                     push(@delrules,$tempkey.'_sec');
                   5810:                     push(@delrules,$tempkey.'_value');
                   5811:                 }
1.473     amueller 5812:             }
                   5813:         }
1.560     damieng  5814:         foreach my $key (keys(%allparms)) {
                   5815:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 5816:         }
1.560     damieng  5817:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   5818:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   5819:         &resetrulescache();
1.224     www      5820:     }
1.227     www      5821:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 5822:                        'hours' => 'Hours',
                   5823:                        'min' => 'Minutes',
                   5824:                        'sec' => 'Seconds',
                   5825:                        'yes' => 'Yes',
                   5826:                        'no' => 'No');
1.222     www      5827:     my @standardoptions=('','default');
                   5828:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   5829:     my @dateoptions=('','default');
                   5830:     my @datedisplay=('',&mt('Default value when manually setting'));
                   5831:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  5832:         unless ($tempkey) { next; }
                   5833:         push @standardoptions,'when_setting_'.$tempkey;
                   5834:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   5835:         if (&isdateparm($defkeytype{$tempkey})) {
                   5836:             push @dateoptions,'later_than_'.$tempkey;
                   5837:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   5838:             push @dateoptions,'earlier_than_'.$tempkey;
                   5839:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   5840:         }
1.222     www      5841:     }
1.563     damieng  5842:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   5843:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 5844:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 5845:           &Apache::loncommon::start_data_table_header_row().
                   5846:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   5847:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   5848:           &Apache::loncommon::end_data_table_header_row());
1.221     www      5849:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  5850:         unless ($tempkey) { next; }
                   5851:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   5852:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   5853:         my $action=&rulescache($tempkey.'_action');
                   5854:         $r->print('<select name="'.$tempkey.'_action">');
                   5855:         if (&isdateparm($defkeytype{$tempkey})) {
                   5856:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   5857:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   5858:             $r->print("\n<option value='$dateoptions[$i]'".
                   5859:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   5860:                 ">$datedisplay[$i]</option>");
                   5861:             }
                   5862:         } else {
                   5863:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   5864:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   5865:             $r->print("\n<option value='$standardoptions[$i]'".
                   5866:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   5867:                 ">$standarddisplay[$i]</option>");
                   5868:             }
1.473     amueller 5869:         }
1.560     damieng  5870:         $r->print('</select>');
                   5871:         unless (&isdateparm($defkeytype{$tempkey})) {
                   5872:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   5873:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 5874:         }
1.560     damieng  5875:         $r->print("\n</td><td>\n");
1.222     www      5876: 
1.221     www      5877:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  5878:             my $days=&rulescache($tempkey.'_days');
                   5879:             my $hours=&rulescache($tempkey.'_hours');
                   5880:             my $min=&rulescache($tempkey.'_min');
                   5881:             my $sec=&rulescache($tempkey.'_sec');
                   5882:             $r->print(<<ENDINPUTDATE);
                   5883:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   5884:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   5885:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   5886:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  5887: ENDINPUTDATE
1.560     damieng  5888:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   5889:                 my $yeschecked='';
                   5890:                 my $nochecked='';
                   5891:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   5892:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   5893: 
                   5894:             $r->print(<<ENDYESNO);
                   5895:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   5896:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  5897: ENDYESNO
1.221     www      5898:         } else {
1.560     damieng  5899:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   5900:         }
1.318     albertel 5901:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      5902:     }
1.318     albertel 5903:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 5904:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      5905:           &mt('Save').'" /></form>'."\n");
                   5906:     &endSettingsScreen($r);
                   5907:     $r->print(&Apache::loncommon::end_page());
1.220     www      5908:     return;
                   5909: }
1.193     albertel 5910: 
1.560     damieng  5911: ##################################################
                   5912: # PARAMETER CHANGES LOG
                   5913: ##################################################
                   5914: 
1.563     damieng  5915: # Returns some info for a parameter log entry.
                   5916: # Returned entries:
                   5917: # $realm - HTML title for the parameter level and resource
                   5918: # $section - parameter section
                   5919: # $name - parameter name
                   5920: # $part - parameter part
                   5921: # $what - $part.'.'.$name
                   5922: # $middle - resource symb ?
                   5923: # $uname - user name (same as given)
                   5924: # $udom - user domain (same as given)
                   5925: # $issection - section or group name
                   5926: # $realmdescription - title for the parameter level and resource (without using HTML)
                   5927: #
                   5928: # FIXME: remove unused fields.
                   5929: #
                   5930: # @param {string} $key - parameter log key
                   5931: # @param {string} $uname - user name
                   5932: # @param {string} $udom - user domain
                   5933: # @param {string} $exeuser - unused
                   5934: # @param {string} $exedomain - unused
                   5935: # @param {boolean} $typeflag - .type log entry
                   5936: # @returns {Array}
1.290     www      5937: sub components {
1.330     albertel 5938:     my ($key,$uname,$udom,$exeuser,$exedomain,$typeflag)=@_;
                   5939: 
                   5940:     if ($typeflag) {
1.560     damieng  5941:         $key=~s/\.type$//;
1.290     www      5942:     }
1.330     albertel 5943: 
                   5944:     my ($middle,$part,$name)=
1.572     damieng  5945:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      5946:     my $issection;
1.330     albertel 5947: 
1.290     www      5948:     my $section=&mt('All Students');
                   5949:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  5950:         $issection=$1;
                   5951:         $section=&mt('Group/Section').': '.$issection;
                   5952:         $middle=~s/^\[(.*)\]//;
1.290     www      5953:     }
                   5954:     $middle=~s/\.+$//;
                   5955:     $middle=~s/^\.+//;
1.291     www      5956:     if ($uname) {
1.560     damieng  5957:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   5958:         $issection='';
1.291     www      5959:     }
1.316     albertel 5960:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   5961:     my $realmdescription=&mt('all resources');
1.556     raeburn  5962:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   5963:         my $mapurl = $1;
                   5964:         my $maplevel = $2;
                   5965:         my $leveltitle = &mt('Folder/Map');
                   5966:         if ($maplevel eq 'rec') {
                   5967:             $leveltitle = &mt('Recursive');
                   5968:         }
1.560     damieng  5969:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   5970:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   5971:             $mapurl.')</span></span>';
                   5972:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   5973:     } elsif ($middle) {
                   5974:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   5975:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   5976:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   5977:             ' in '.$map.' id: '.$id.')</span></span>';
                   5978:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      5979:     }
1.291     www      5980:     my $what=$part.'.'.$name;
1.330     albertel 5981:     return ($realm,$section,$name,$part,
1.473     amueller 5982:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      5983: }
1.293     www      5984: 
1.563     damieng  5985: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   5986: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      5987: 
1.563     damieng  5988: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 5989: sub load_parameter_names {
                   5990:     open(my $config,"<$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
                   5991:     while (my $configline=<$config>) {
1.560     damieng  5992:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   5993:         chomp($configline);
                   5994:         my ($short,$plain)=split(/:/,$configline);
                   5995:         my (undef,$name,$type)=split(/\&/,$short,3);
                   5996:         if ($type eq 'display') {
                   5997:             $standard_parms{$name} = $plain;
1.469     raeburn  5998:         } elsif ($type eq 'type') {
1.560     damieng  5999:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  6000:         }
1.328     albertel 6001:     }
                   6002:     close($config);
                   6003:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   6004:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
                   6005: }
                   6006: 
1.563     damieng  6007: # Returns a parameter title for standard parameters, the name for others.
                   6008: #
                   6009: # @param {string} $name - parameter name
                   6010: # @returns {string}
1.292     www      6011: sub standard_parameter_names {
                   6012:     my ($name)=@_;
1.328     albertel 6013:     if (!%standard_parms) {
1.560     damieng  6014:         &load_parameter_names();
1.328     albertel 6015:     }
1.292     www      6016:     if ($standard_parms{$name}) {
1.560     damieng  6017:         return $standard_parms{$name};
1.446     bisitz   6018:     } else {
1.560     damieng  6019:         return $name;
1.292     www      6020:     }
                   6021: }
1.290     www      6022: 
1.563     damieng  6023: # Returns a parameter type for standard parameters, undef for others.
                   6024: #
                   6025: # @param {string} $name - parameter name
                   6026: # @returns {string}
1.469     raeburn  6027: sub standard_parameter_types {
                   6028:     my ($name)=@_;
                   6029:     if (!%standard_parms_types) {
                   6030:         &load_parameter_names();
                   6031:     }
                   6032:     if ($standard_parms_types{$name}) {
                   6033:         return $standard_parms_types{$name};
                   6034:     }
                   6035:     return;
                   6036: }
1.309     www      6037: 
1.563     damieng  6038: # Returns a parameter level title (not localized) from the parameter level name.
                   6039: #
                   6040: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   6041: # @returns {string}
1.557     raeburn  6042: sub standard_parameter_levels {
                   6043:     my ($name)=@_;
                   6044:     my %levels = (
                   6045:                     'resourcelevel'   => 'a single resource',
                   6046:                     'maplevel'        => 'the enclosing map/folder', 
                   6047:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   6048:                     'courselevel'     => 'the general (course) level',
                   6049:                  );
                   6050:     if ($levels{$name}) {
                   6051:         return $levels{$name};
                   6052:     }
                   6053:     return;
                   6054: }
                   6055: 
1.560     damieng  6056: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  6057: #
                   6058: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 6059: sub parm_change_log {
1.568     raeburn  6060:     my ($r,$parm_permission)=@_;
1.531     raeburn  6061:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6062:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  6063:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6064:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 6065:     text=>"Parameter Change Log"});
1.522     raeburn  6066:     my $js = '<script type="text/javascript">'."\n".
                   6067:              '// <![CDATA['."\n".
                   6068:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   6069:              '// ]]>'."\n".
                   6070:              '</script>'."\n";
                   6071:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 6072:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  6073:     &startSettingsScreen($r,'parmset',$crstype);
                   6074:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 6075: 
1.301     www      6076:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 6077: 
1.522     raeburn  6078:     $r->print('<div class="LC_left_float">'.
                   6079:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   6080:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 6081:                      method="post" name="parameterlog">');
1.446     bisitz   6082: 
1.311     albertel 6083:     my %saveable_parameters = ('show' => 'scalar',);
                   6084:     &Apache::loncommon::store_course_settings('parameter_log',
                   6085:                                               \%saveable_parameters);
                   6086:     &Apache::loncommon::restore_course_settings('parameter_log',
                   6087:                                                 \%saveable_parameters);
1.522     raeburn  6088:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   6089:               '<input type="submit" value="'.&mt('Display').'" />'.
                   6090:               '</form></fieldset></div><br clear="all" />');
1.301     www      6091: 
1.568     raeburn  6092:     my $readonly = 1;
                   6093:     if ($parm_permission->{'edit'}) {
                   6094:         undef($readonly);
                   6095:     }
1.531     raeburn  6096:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      6097:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 6098:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  6099:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   6100:     unless ($readonly) {
                   6101:         $r->print('<th>'.&mt('Announce').'</th>');
                   6102:     }
                   6103:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      6104:     my $shown=0;
1.349     www      6105:     my $folder='';
                   6106:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  6107:         my $last='';
                   6108:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   6109:                 &GDBM_READER(),0640)) {
                   6110:             $last=$hash{'last_known'};
                   6111:             untie(%hash);
                   6112:         }
                   6113:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   6114:     }
                   6115:     foreach my $id (sort {
                   6116:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   6117:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   6118:                 }
                   6119:                 my $aid = (split('00000',$a))[-1];
                   6120:                 my $bid = (split('00000',$b))[-1];
                   6121:                 return $bid<=>$aid;
1.473     amueller 6122:             } (keys(%parmlog))) {
1.294     www      6123:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  6124:         my $count = 0;
                   6125:         my $time =
                   6126:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   6127:         my $plainname =
                   6128:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   6129:                         $parmlog{$id}{'exe_udom'});
                   6130:         my $about_me_link =
                   6131:             &Apache::loncommon::aboutmewrapper($plainname,
                   6132:                             $parmlog{$id}{'exe_uname'},
                   6133:                             $parmlog{$id}{'exe_udom'});
                   6134:         my $send_msg_link='';
1.568     raeburn  6135:         if ((!$readonly) && 
                   6136:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  6137:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   6138:             $send_msg_link ='<br />'.
                   6139:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   6140:                             $parmlog{$id}{'exe_uname'},
                   6141:                             $parmlog{$id}{'exe_udom'});
                   6142:         }
                   6143:         my $row_start=&Apache::loncommon::start_data_table_row();
                   6144:         my $makenewrow=0;
                   6145:         my %istype=();
                   6146:         my $output;
                   6147:         foreach my $changed (reverse(sort(@changes))) {
                   6148:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   6149:             my $typeflag = ($changed =~/\.type$/ &&
                   6150:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 6151:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.560     damieng  6152:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},undef,undef,$typeflag);
                   6153:             if ($env{'request.course.sec'} ne '') {
                   6154:                 next if (($issection ne '') && ($issection ne $env{'request.course.sec'}));
                   6155:                 if ($uname ne '') {
                   6156:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   6157:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   6158:                 }
                   6159:             }
                   6160:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   6161:                 if ($folder) {
                   6162:                     if ($middle!~/^\Q$folder\E/) { next; }
                   6163:                 }
                   6164:             }
                   6165:             if ($typeflag) {
                   6166:                 $istype{$parmname}=$value;
                   6167:                 if (!$env{'form.includetypes'}) { next; }
                   6168:             }
                   6169:             $count++;
                   6170:             if ($makenewrow) {
                   6171:                 $output .= $row_start;
                   6172:             } else {
                   6173:                 $makenewrow=1;
                   6174:             }
1.470     raeburn  6175:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  6176:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   6177:                 &mt($parmitem).'</td><td>'.
                   6178:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   6179:             my $stillactive=0;
                   6180:             if ($parmlog{$id}{'delflag'}) {
                   6181:                 $output .= &mt('Deleted');
                   6182:             } else {
                   6183:                 if ($typeflag) {
1.470     raeburn  6184:                     my $parmitem = &standard_parameter_names($value); 
                   6185:                     $parmitem = &mt($parmitem);
1.560     damieng  6186:                     $output .= &mt('Type: [_1]',$parmitem);
                   6187:                 } else {
                   6188:                     my ($level,@all)=&parmval_by_symb($what,$middle,
                   6189:                         &Apache::lonnet::metadata($middle,$what),
                   6190:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  6191:                     my $showvalue = $value;
                   6192:                     if ($istype{$parmname} eq '') {
                   6193:                         my $type = &standard_parameter_types($parmname);
                   6194:                         if ($type ne '') {
                   6195:                             if (&isdateparm($type)) {
                   6196:                                 $showvalue =
                   6197:                                     &Apache::lonlocal::locallocaltime($value);
                   6198:                             }
                   6199:                         }
                   6200:                     } else {
1.560     damieng  6201:                         if (&isdateparm($istype{$parmname})) {
                   6202:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   6203:                         }
1.469     raeburn  6204:                     }
                   6205:                     $output .= $showvalue;
1.560     damieng  6206:                     if ($value ne $all[$level]) {
                   6207:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   6208:                     } else {
                   6209:                         $stillactive=1;
                   6210:                     }
                   6211:                 }
1.473     amueller 6212:             }
1.568     raeburn  6213:             $output .= '</td>';
                   6214: 
                   6215:             unless ($readonly) { 
                   6216:                 $output .= '<td>';
                   6217:                 if ($stillactive) {
                   6218:                     my $parmitem = &standard_parameter_names($parmname);
                   6219:                     $parmitem = &mt($parmitem);
                   6220:                     my $title=&mt('Changed [_1]',$parmitem);
                   6221:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   6222:                         $parmitem,$realmdescription,
                   6223:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   6224:                     if (($uname) && ($udom)) {
                   6225:                         $output .=
                   6226:                         &Apache::loncommon::messagewrapper('Notify User',
                   6227:                                                            $uname,$udom,$title,
                   6228:                                                            $description);
                   6229:                     } else {
                   6230:                         $output .=
                   6231:                             &Apache::lonrss::course_blog_link($id,$title,
                   6232:                                                               $description);
                   6233:                     }
1.560     damieng  6234:                 }
1.568     raeburn  6235:                 $output .= '</td>';
1.560     damieng  6236:             }
1.568     raeburn  6237:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 6238:         }
1.560     damieng  6239:         if ($env{'form.displayfilter'} eq 'containing') {
                   6240:             my $wholeentry=$about_me_link.':'.
                   6241:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   6242:             $output;
                   6243:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 6244:         }
1.349     www      6245:         if ($count) {
1.560     damieng  6246:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   6247:                         <td rowspan="'.$count.'">'.$about_me_link.
                   6248:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   6249:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   6250:             $send_msg_link.'</td>'.$output);
                   6251:             $shown++;
                   6252:         }
                   6253:         if (!($env{'form.show'} eq &mt('all')
                   6254:             || $shown<=$env{'form.show'})) { last; }
1.286     www      6255:     }
1.301     www      6256:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      6257:     &endSettingsScreen($r);
1.284     www      6258:     $r->print(&Apache::loncommon::end_page());
                   6259: }
                   6260: 
1.560     damieng  6261: ##################################################
                   6262: # MISC !
                   6263: ##################################################
                   6264: 
1.563     damieng  6265: # Stores slot information.
1.560     damieng  6266: # Used by table UI
1.563     damieng  6267: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   6268: #
                   6269: # @param {string} $slot_name - slot name
                   6270: # @param {string} $cdom - course domain
                   6271: # @param {string} $cnum - course number
                   6272: # @param {string} $symb - resource symb
                   6273: # @param {string} $uname - user name
                   6274: # @param {string} $udom - user domain
                   6275: # @returns {string} - 'ok' or error name
1.437     raeburn  6276: sub update_slots {
                   6277:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   6278:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   6279:     if (!keys(%slot)) {
                   6280:         return 'error: slot does not exist';
                   6281:     }
                   6282:     my $max=$slot{'maxspace'};
                   6283:     if (!defined($max)) { $max=99999; }
                   6284: 
                   6285:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   6286:                                        "^$slot_name\0");
                   6287:     my ($tmp)=%consumed;
                   6288:     if ($tmp=~/^error: 2 / ) {
                   6289:         return 'error: unable to determine current slot status';
                   6290:     }
                   6291:     my $last=0;
                   6292:     foreach my $key (keys(%consumed)) {
                   6293:         my $num=(split('\0',$key))[1];
                   6294:         if ($num > $last) { $last=$num; }
                   6295:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   6296:             return 'ok';
                   6297:         }
                   6298:     }
                   6299: 
                   6300:     if (scalar(keys(%consumed)) >= $max) {
                   6301:         return 'error: no space left in slot';
                   6302:     }
                   6303:     my $wanted=$last+1;
                   6304: 
                   6305:     my %reservation=('name'      => $uname.':'.$udom,
                   6306:                      'timestamp' => time,
                   6307:                      'symb'      => $symb);
                   6308: 
                   6309:     my $success=&Apache::lonnet::newput('slot_reservations',
                   6310:                                         {"$slot_name\0$wanted" =>
                   6311:                                              \%reservation},
                   6312:                                         $cdom, $cnum);
1.438     raeburn  6313:     if ($success eq 'ok') {
                   6314:         my %storehash = (
                   6315:                           symb    => $symb,
                   6316:                           slot    => $slot_name,
                   6317:                           action  => 'reserve',
                   6318:                           context => 'parameter',
                   6319:                         );
1.526     raeburn  6320:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  6321:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  6322: 
1.526     raeburn  6323:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  6324:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  6325:     }
1.437     raeburn  6326:     return $success;
                   6327: }
                   6328: 
1.563     damieng  6329: # Deletes a slot reservation.
1.560     damieng  6330: # Used by table UI
1.563     damieng  6331: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   6332: #
                   6333: # @param {string} $slot_name - slot name
                   6334: # @param {string} $cdom - course domain
                   6335: # @param {string} $cnum - course number
                   6336: # @param {string} $uname - user name
                   6337: # @param {string} $udom - user domain
                   6338: # @param {string} $symb - resource symb
                   6339: # @returns {string} - 'ok' or error name
1.437     raeburn  6340: sub delete_slots {
                   6341:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   6342:     my $delresult;
                   6343:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   6344:                                          $cnum, "^$slot_name\0");
                   6345:     if (&Apache::lonnet::error(%consumed)) {
                   6346:         return 'error: unable to determine current slot status';
                   6347:     }
                   6348:     my ($tmp)=%consumed;
                   6349:     if ($tmp=~/^error: 2 /) {
                   6350:         return 'error: unable to determine current slot status';
                   6351:     }
                   6352:     foreach my $key (keys(%consumed)) {
                   6353:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   6354:             my $num=(split('\0',$key))[1];
                   6355:             my $entry = $slot_name.'\0'.$num;
                   6356:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   6357:                                               $cdom,$cnum);
                   6358:             if ($delresult eq 'ok') {
                   6359:                 my %storehash = (
                   6360:                                   symb    => $symb,
                   6361:                                   slot    => $slot_name,
                   6362:                                   action  => 'release',
                   6363:                                   context => 'parameter',
                   6364:                                 );
1.526     raeburn  6365:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  6366:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  6367:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  6368:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  6369:             }
                   6370:         }
                   6371:     }
                   6372:     return $delresult;
                   6373: }
                   6374: 
1.563     damieng  6375: # Returns true if there is a current course.
1.560     damieng  6376: # Used by handler
1.563     damieng  6377: #
                   6378: # @returns {boolean}
1.355     albertel 6379: sub check_for_course_info {
                   6380:     my $navmap = Apache::lonnavmaps::navmap->new();
                   6381:     return 1 if ($navmap);
                   6382:     return 0;
                   6383: }
                   6384: 
1.563     damieng  6385: # Returns the current course host and host LON-CAPA version.
                   6386: #
                   6387: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  6388: sub parameter_release_vars { 
1.504     raeburn  6389:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6390:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   6391:    my $chostname = &Apache::lonnet::hostname($chome);
                   6392:    my ($cmajor,$cminor) = 
                   6393:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   6394:    return ($chostname,$cmajor,$cminor);
                   6395: }
                   6396: 
1.563     damieng  6397: # Checks if the course host version can handle a parameter required version,
                   6398: # and if it does, stores the release needed for the course.
                   6399: #
                   6400: # @param {string} $name - parameter name
                   6401: # @param {string} $value - parameter value
                   6402: # @param {string} $valmatch - name of the test used for checking the value
                   6403: # @param {string} $namematch - name of the test used for checking the name
                   6404: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   6405: # @param {integer} $cmajor - course major version number
                   6406: # @param {integer} $cminor - course minor version number
                   6407: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  6408: sub parameter_releasecheck {
1.557     raeburn  6409:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  6410:     my $needsnewer;
                   6411:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   6412:     if (($cmajor < $needsmajor) || 
                   6413:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   6414:         $needsnewer = 1;
1.557     raeburn  6415:     } elsif ($name) {
                   6416:         if ($valmatch) {
                   6417:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   6418:         } elsif ($value) { 
                   6419:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   6420:         }
                   6421:     } elsif ($namematch) {
                   6422:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  6423:     }
                   6424:     return $needsnewer;
                   6425: }
                   6426: 
1.568     raeburn  6427: sub get_permission {
                   6428:     my %permission;
                   6429:     my $allowed = 0;
                   6430:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   6431:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   6432:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   6433:                   $env{'request.course.sec'}))) {
                   6434:         %permission= (
                   6435:                        'edit'               => 1,
                   6436:                        'set'                => 1,
                   6437:                        'setoverview'        => 1,
                   6438:                        'addmetadata'        => 1,
                   6439:                        'ordermetadata'      => 1,
                   6440:                        'setrestrictmeta'    => 1,
                   6441:                        'newoverview'        => 1,
                   6442:                        'setdefaults'        => 1,
                   6443:                        'settable'           => 1,
                   6444:                        'parameterchangelog' => 1,
                   6445:                        'cleanparameters'    => 1,
                   6446:                        'dateshift1'         => 1,
                   6447:                        'dateshift2'         => 1,
                   6448:                        'helper'             => 1,
                   6449:          );
                   6450:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   6451:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   6452:                   $env{'request.course.sec'}))) {
                   6453:         %permission = (
                   6454:                        'set'                => 1,
                   6455:                        'settable'           => 1,
                   6456:                        'newoverview'        => 1,
                   6457:                        'setoverview'        => 1,
                   6458:                        'parameterchangelog' => 1,
                   6459:                       );
                   6460:     }
                   6461:     foreach my $perm (values(%permission)) {
                   6462:         if ($perm) { $allowed=1; last; }
                   6463:     }
                   6464:     return (\%permission,$allowed);
                   6465: }
                   6466: 
1.560     damieng  6467: ##################################################
                   6468: # HANDLER
                   6469: ##################################################
                   6470: 
                   6471: # Main handler for lonparmset.
                   6472: # Sub called based on request parameters action and command:
                   6473: # no command or action: print_main_menu
                   6474: # command 'set': assessparms (direct access to table mode for a resource)
                   6475: #                (this can also be accessed simply with the symb parameter)
                   6476: # action 'setoverview': overview (display all existing parameter settings)
                   6477: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   6478: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   6479: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   6480: # action 'newoverview': newoverview (overview mode)
                   6481: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   6482: # action 'settable': assessparms (table mode)
                   6483: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   6484: #                              blog postings, user notification changes)
                   6485: # action 'cleanparameters': clean_parameters (unused)
                   6486: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   6487: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      6488: sub handler {
1.43      albertel 6489:     my $r=shift;
1.30      www      6490: 
1.376     albertel 6491:     &reset_caches();
                   6492: 
1.414     droeschl 6493:     &Apache::loncommon::content_type($r,'text/html');
                   6494:     $r->send_http_header;
                   6495:     return OK if $r->header_only;
                   6496: 
1.193     albertel 6497:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 6498:                         ['action','state',
1.205     www      6499:                                              'pres_marker',
                   6500:                                              'pres_value',
1.206     www      6501:                                              'pres_type',
1.506     www      6502:                                              'filter','part',
1.390     www      6503:                                              'udom','uname','symb','serial','timebase']);
1.131     www      6504: 
1.83      bowersj2 6505: 
1.193     albertel 6506:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 6507:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      6508:                         text=>"Content and Problem Settings",
1.473     amueller 6509:                         faq=>10,
                   6510:                         bug=>'Instructor Interface',
1.442     droeschl 6511:                                             help =>
                   6512:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      6513: 
1.30      www      6514: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  6515:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 6516:     my $exists = &check_for_course_info();
                   6517: 
1.568     raeburn  6518:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 6519:         #
                   6520:         # Main switch on form.action and form.state, as appropriate
                   6521:         #
                   6522:         # Check first if coming from someone else headed directly for
                   6523:         #  the table mode
1.568     raeburn  6524:         if (($parm_permission->{'set'}) && 
                   6525:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   6526:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   6527:             &assessparms($r,$parm_permission);
1.193     albertel 6528:         } elsif (! exists($env{'form.action'})) {
                   6529:             &print_main_menu($r,$parm_permission);
1.568     raeburn  6530:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   6531:             &print_main_menu($r,$parm_permission);
1.414     droeschl 6532:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  6533:             &overview($r,$parm_permission);
1.560     damieng  6534:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   6535:             &addmetafield($r);
                   6536:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   6537:             &order_meta_fields($r);
1.414     droeschl 6538:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  6539:             &setrestrictmeta($r);
1.414     droeschl 6540:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  6541:             &newoverview($r,$parm_permission);
1.414     droeschl 6542:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  6543:             &defaultsetter($r);
                   6544:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  6545:             &assessparms($r,$parm_permission);
1.414     droeschl 6546:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  6547:             &parm_change_log($r,$parm_permission);
1.414     droeschl 6548:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  6549:             &clean_parameters($r);
1.414     droeschl 6550:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      6551:             &date_shift_one($r);
1.414     droeschl 6552:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      6553:             &date_shift_two($r);
1.446     bisitz   6554:         }
1.43      albertel 6555:     } else {
1.1       www      6556: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  6557:         if ($exists) {
                   6558:             $env{'user.error.msg'}=
                   6559:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   6560:         } else {
                   6561:             $env{'user.error.msg'}=
                   6562:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   6563:         }
                   6564:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 6565:     }
1.376     albertel 6566:     &reset_caches();
                   6567: 
1.43      albertel 6568:     return OK;
1.1       www      6569: }
                   6570: 
                   6571: 1;
                   6572: __END__
                   6573: 
                   6574: 

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