Annotation of loncom/interface/lonparmset.pm, revision 1.615
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.615 ! raeburn 4: # $Id: lonparmset.pm,v 1.614 2022/05/31 14:16:29 raeburn Exp $
1.40 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.59 matthew 28: ###################################################################
29: ###################################################################
30:
31: =pod
32:
33: =head1 NAME
34:
35: lonparmset - Handler to set parameters for assessments and course
36:
37: =head1 SYNOPSIS
38:
1.579 raeburn 39: lonparmset provides an interface to setting content parameters in a
40: course.
1.560 damieng 41:
42: It contains all the code for the "Content and Problem Settings" UI, except
43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
44: and lonblockingmenu.pm.
1.59 matthew 45:
46: =head1 DESCRIPTION
47:
48: This module sets coursewide and assessment parameters.
49:
50: =head1 INTERNAL SUBROUTINES
51:
1.416 jms 52: =over
1.59 matthew 53:
1.416 jms 54: =item parmval()
1.59 matthew 55:
56: Figure out a cascading parameter.
57:
1.71 albertel 58: Inputs: $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162 albertel 59: $id - a bighash Id number
1.71 albertel 60: $def - the resource's default value 'stupid emacs
61:
1.556 raeburn 62: Returns: A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71 albertel 63:
1.556 raeburn 64: 18 - General Course
65: 17 - Map or Folder level in course (recursive)
66: 16 - Map or Folder level in course (non-recursive)
67: 15 - resource default
68: 14 - map default
69: 13 - resource level in course
70: 12 - General for section
71: 11 - Map or Folder level for section (recursive)
72: 10 - Map or Folder level for section (non-recursive)
73: 9 - resource level in section
74: 8 - General for group
75: 7 - Map or Folder level for group (recursive)
76: 6 - Map or Folder level for group (non-recursive)
77: 5 - resource level in group
78: 4 - General for specific student
79: 3 - Map or Folder level for specific student (recursive)
80: 2 - Map or Folder level for specific student (non-recursive)
1.71 albertel 81: 1 - resource level for specific student
1.2 www 82:
1.416 jms 83: =item parmval_by_symb()
84:
85: =item reset_caches()
86:
87: =item cacheparmhash()
88:
89: =item parmhash()
90:
91: =item symbcache()
92:
93: =item preset_defaults()
94:
95: =item date_sanity_info()
96:
97: =item storeparm()
98:
99: Store a parameter by symb
100:
101: Takes
102: - symb
103: - name of parameter
104: - level
105: - new value
106: - new type
107: - username
108: - userdomain
109:
110: =item log_parmset()
111:
112: =item storeparm_by_symb_inner()
113:
114: =item valout()
115:
116: Format a value for output.
117:
118: Inputs: $value, $type, $editable
119:
120: Returns: $value, formatted for output. If $type indicates it is a date,
121: localtime($value) is returned.
122: $editable will return an icon to click on
123:
124: =item plink()
125:
126: Produces a link anchor.
127:
128: Inputs: $type,$dis,$value,$marker,$return,$call
129:
130: Returns: scalar with html code for a link which will envoke the
131: javascript function 'pjump'.
132:
133: =item page_js()
134:
135: =item startpage()
136:
137: =item print_row()
138:
139: =item print_td()
140:
1.580 raeburn 141: =item check_other_groups()
1.416 jms 142:
143: =item parm_control_group()
144:
145: =item extractResourceInformation() :
146:
1.512 foxr 147: extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416 jms 148:
1.542 raeburn 149: Input: See list below
150:
151: =over 4
1.416 jms 152:
1.512 foxr 153: =item * B<env{'user.name'}> : Current username
1.416 jms 154:
1.512 foxr 155: =item * B<env{'user.domain'}> : Domain of current user.
1.416 jms 156:
1.542 raeburn 157: =item * B<env{"request.course.fn"}> : Course
158:
159: =back
1.416 jms 160:
1.512 foxr 161: Outputs: See list below:
1.416 jms 162:
1.542 raeburn 163: =over 4
164:
1.512 foxr 165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416 jms 166:
1.512 foxr 167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416 jms 168:
1.512 foxr 169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416 jms 170:
1.512 foxr 171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416 jms 172:
1.512 foxr 173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
174:
175: =item * B<allmaps> (out) : hash, ???
1.416 jms 176:
177: =item * B<mapp> : ??
178:
179: =item * B<symbp> : hash, id->full sym?
180:
1.512 foxr 181: =item * B<maptitles>
182:
183: =item * B<uris>
1.416 jms 184:
1.512 foxr 185: =item * B<keyorder>
186:
187: =item * B<defkeytype>
1.416 jms 188:
1.542 raeburn 189: =back
190:
1.416 jms 191: =item isdateparm()
192:
193: =item parmmenu()
194:
195: =item partmenu()
196:
197: =item usermenu()
198:
199: =item displaymenu()
200:
201: =item mapmenu()
202:
203: =item levelmenu()
204:
205: =item sectionmenu()
206:
207: =item keysplit()
208:
209: =item keysinorder()
210:
211: =item keysinorder_bytype()
212:
213: =item keysindisplayorder()
214:
215: =item standardkeyorder()
216:
217: =item assessparms() :
218:
219: Show assessment data and parameters. This is a large routine that should
220: be simplified and shortened... someday.
221:
1.513 foxr 222: Inputs: $r - the Apache request object.
223:
1.416 jms 224: Returns: nothing
225:
226: Variables used (guessed by Jeremy):
227:
1.542 raeburn 228: =over
229:
1.416 jms 230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
231:
232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
233:
234: =item * B<@catmarker> contains list of all possible parameters including part #s
235:
236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
237:
238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
239: When storing information, store as part 0
240: When requesting information, request from full part
241:
1.542 raeburn 242: =back
243:
1.416 jms 244: =item tablestart()
245:
246: =item tableend()
247:
248: =item extractuser()
249:
250: =item parse_listdata_key()
251:
252: =item listdata()
253:
254: =item date_interval_selector()
255:
256: =item get_date_interval_from_form()
257:
258: =item default_selector()
259:
260: =item string_selector()
261:
262: =item dateshift()
263:
264: =item newoverview()
265:
266: =item secgroup_lister()
267:
268: =item overview()
269:
270: =item clean_parameters()
271:
272: =item date_shift_one()
273:
274: =item date_shift_two()
275:
276: =item parse_key()
277:
278: =item header()
279:
280: Output html header for page
281:
282: =item print_main_menu()
283:
284: =item output_row()
285:
286: Set portfolio metadata
287:
288: =item order_meta_fields()
289:
290: =item addmetafield()
291:
292: =item setrestrictmeta()
293:
294: =item get_added_meta_fieldnames()
295:
296: =item get_deleted_meta_fieldnames()
297:
298: =item defaultsetter()
299:
300: =item components()
301:
302: =item load_parameter_names()
303:
304: =item parm_change_log()
305:
306: =item handler() :
307:
1.450 raeburn 308: Main handler. Calls &assessparms subroutine.
1.416 jms 309:
310: =back
311:
1.59 matthew 312: =cut
313:
1.416 jms 314: ###################################################################
315: ###################################################################
316:
317: package Apache::lonparmset;
318:
319: use strict;
320: use Apache::lonnet;
321: use Apache::Constants qw(:common :http REDIRECT);
322: use Apache::lonhtmlcommon();
323: use Apache::loncommon;
324: use GDBM_File;
325: use Apache::lonhomework;
326: use Apache::lonxml;
327: use Apache::lonlocal;
328: use Apache::lonnavmaps;
329: use Apache::longroup;
330: use Apache::lonrss;
1.506 www 331: use HTML::Entities;
1.416 jms 332: use LONCAPA qw(:DEFAULT :match);
333:
334:
1.560 damieng 335: ##################################################
336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
337: ##################################################
338:
339: # Page header
1.561 damieng 340: #
341: # @param {Apache2::RequestRec} $r - Apache request object
342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
343: # @param {string} $crstype - course type ('Community' for community settings)
1.507 www 344: sub startSettingsScreen {
1.531 raeburn 345: my ($r,$mode,$crstype)=@_;
1.507 www 346:
1.531 raeburn 347: my $tabtext = &mt('Course Settings');
348: if ($crstype eq 'Community') {
349: $tabtext = &mt('Community Settings');
350: }
1.507 www 351: $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
352: $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b> '.
1.531 raeburn 353: $tabtext.
1.507 www 354: ' </b></a></li>');
355:
1.523 raeburn 356: $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507 www 357: &mt('Content and Problem Settings').'</b></a></li>');
358: $r->print("\n".'</ul>'."\n");
1.523 raeburn 359: $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507 www 360: }
361:
1.560 damieng 362: # Page footer
1.507 www 363: sub endSettingsScreen {
364: my ($r)=@_;
365: $r->print('</div></div></div>');
366: }
367:
368:
369:
1.560 damieng 370: ##################################################
1.563 damieng 371: # (mostly) TABLE MODE
1.560 damieng 372: # (parmval is also used for the log of parameter changes)
373: ##################################################
374:
1.566 damieng 375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561 damieng 376: #
377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 378: # @param {string} $id - resource id or map pc
1.561 damieng 379: # @param {string} $def - the resource's default value for this parameter
380: # @param {string} $uname - user name
381: # @param {string} $udom - user domain
382: # @param {string} $csec - section name
383: # @param {string} $cgroup - group name
384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
385: # @returns {Array}
1.2 www 386: sub parmval {
1.275 raeburn 387: my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
388: return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
389: $cgroup,$courseopt);
1.201 www 390: }
391:
1.561 damieng 392: # Returns an array containing
393: # - the most specific level that is defined for that parameter (integer)
394: # - an array with the level as index and the parameter value as value (when defined)
395: # (level 1 is the most specific and will have precedence)
396: #
397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 398: # @param {string} $symb - resource symb or map src
1.561 damieng 399: # @param {string} $def - the resource's default value for this parameter
400: # @param {string} $uname - user name
401: # @param {string} $udom - user domain
402: # @param {string} $csec - section name
403: # @param {string} $cgroup - group name
404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
405: # @returns {Array}
1.201 www 406: sub parmval_by_symb {
1.275 raeburn 407: my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200 www 408:
1.352 albertel 409: my $useropt;
410: if ($uname ne '' && $udom ne '') {
1.561 damieng 411: $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352 albertel 412: }
1.200 www 413:
1.8 www 414: my $result='';
1.44 albertel 415: my @outpar=();
1.2 www 416: # ----------------------------------------------------- Cascading lookup scheme
1.446 bisitz 417: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 418: $map = &Apache::lonnet::deversion($map);
1.561 damieng 419:
420: # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
421: # any change should be reflected there.
422:
1.201 www 423: my $symbparm=$symb.'.'.$what;
1.556 raeburn 424: my $recurseparm=$map.'___(rec).'.$what;
1.201 www 425: my $mapparm=$map.'___(all).'.$what;
1.10 www 426:
1.269 raeburn 427: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
428: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 429: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 430: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
431:
1.190 albertel 432: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
433: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 434: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 435: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
436:
437: my $courselevel=$env{'request.course.id'}.'.'.$what;
438: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 439: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 440: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2 www 441:
1.11 www 442:
1.182 albertel 443: # --------------------------------------------------------- first, check course
1.11 www 444:
1.561 damieng 445: # 18 - General Course
1.200 www 446: if (defined($$courseopt{$courselevel})) {
1.556 raeburn 447: $outpar[18]=$$courseopt{$courselevel};
448: $result=18;
449: }
450:
1.561 damieng 451: # 17 - Map or Folder level in course (recursive)
1.556 raeburn 452: if (defined($$courseopt{$courseleveli})) {
453: $outpar[17]=$$courseopt{$courseleveli};
454: $result=17;
1.43 albertel 455: }
1.11 www 456:
1.561 damieng 457: # 16 - Map or Folder level in course (non-recursive)
1.200 www 458: if (defined($$courseopt{$courselevelm})) {
1.556 raeburn 459: $outpar[16]=$$courseopt{$courselevelm};
460: $result=16;
1.43 albertel 461: }
1.11 www 462:
1.182 albertel 463: # ------------------------------------------------------- second, check default
464:
1.561 damieng 465: # 15 - resource default
1.556 raeburn 466: if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182 albertel 467:
468: # ------------------------------------------------------ third, check map parms
469:
1.556 raeburn 470:
1.561 damieng 471: # 14 - map default
1.376 albertel 472: my $thisparm=&parmhash($symbparm);
1.556 raeburn 473: if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182 albertel 474:
1.561 damieng 475: # 13 - resource level in course
1.200 www 476: if (defined($$courseopt{$courselevelr})) {
1.556 raeburn 477: $outpar[13]=$$courseopt{$courselevelr};
478: $result=13;
1.43 albertel 479: }
1.11 www 480:
1.182 albertel 481: # ------------------------------------------------------ fourth, back to course
1.352 albertel 482: if ($csec ne '') {
1.561 damieng 483: # 12 - General for section
1.200 www 484: if (defined($$courseopt{$seclevel})) {
1.556 raeburn 485: $outpar[12]=$$courseopt{$seclevel};
486: $result=12;
487: }
1.561 damieng 488: # 11 - Map or Folder level for section (recursive)
1.556 raeburn 489: if (defined($$courseopt{$secleveli})) {
490: $outpar[11]=$$courseopt{$secleveli};
491: $result=11;
492: }
1.561 damieng 493: # 10 - Map or Folder level for section (non-recursive)
1.200 www 494: if (defined($$courseopt{$seclevelm})) {
1.556 raeburn 495: $outpar[10]=$$courseopt{$seclevelm};
496: $result=10;
497: }
1.561 damieng 498: # 9 - resource level in section
1.200 www 499: if (defined($$courseopt{$seclevelr})) {
1.556 raeburn 500: $outpar[9]=$$courseopt{$seclevelr};
501: $result=9;
502: }
1.43 albertel 503: }
1.275 raeburn 504: # ------------------------------------------------------ fifth, check course group
1.352 albertel 505: if ($cgroup ne '') {
1.561 damieng 506: # 8 - General for group
1.269 raeburn 507: if (defined($$courseopt{$grplevel})) {
1.556 raeburn 508: $outpar[8]=$$courseopt{$grplevel};
509: $result=8;
510: }
1.561 damieng 511: # 7 - Map or Folder level for group (recursive)
1.556 raeburn 512: if (defined($$courseopt{$grpleveli})) {
513: $outpar[7]=$$courseopt{$grpleveli};
514: $result=7;
1.269 raeburn 515: }
1.561 damieng 516: # 6 - Map or Folder level for group (non-recursive)
1.269 raeburn 517: if (defined($$courseopt{$grplevelm})) {
1.556 raeburn 518: $outpar[6]=$$courseopt{$grplevelm};
519: $result=6;
1.269 raeburn 520: }
1.561 damieng 521: # 5 - resource level in group
1.269 raeburn 522: if (defined($$courseopt{$grplevelr})) {
1.556 raeburn 523: $outpar[5]=$$courseopt{$grplevelr};
524: $result=5;
1.269 raeburn 525: }
526: }
1.11 www 527:
1.556 raeburn 528: # ---------------------------------------------------------- sixth, check user
1.11 www 529:
1.352 albertel 530: if ($uname ne '') {
1.561 damieng 531: # 4 - General for specific student
532: if (defined($$useropt{$courselevel})) {
533: $outpar[4]=$$useropt{$courselevel};
534: $result=4;
535: }
1.556 raeburn 536:
1.561 damieng 537: # 3 - Map or Folder level for specific student (recursive)
538: if (defined($$useropt{$courseleveli})) {
539: $outpar[3]=$$useropt{$courseleveli};
540: $result=3;
541: }
1.473 amueller 542:
1.561 damieng 543: # 2 - Map or Folder level for specific student (non-recursive)
544: if (defined($$useropt{$courselevelm})) {
545: $outpar[2]=$$useropt{$courselevelm};
546: $result=2;
547: }
1.473 amueller 548:
1.561 damieng 549: # 1 - resource level for specific student
550: if (defined($$useropt{$courselevelr})) {
551: $outpar[1]=$$useropt{$courselevelr};
552: $result=1;
553: }
1.43 albertel 554: }
1.44 albertel 555: return ($result,@outpar);
1.2 www 556: }
557:
1.198 www 558:
559:
1.376 albertel 560: # --- Caches local to lonparmset
561:
1.446 bisitz 562:
1.561 damieng 563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376 albertel 564: sub reset_caches {
565: &resetparmhash();
566: &resetsymbcache();
567: &resetrulescache();
1.203 www 568: }
569:
1.561 damieng 570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376 albertel 572: {
1.561 damieng 573: my $parmhashid; # course identifier, to initialize the cache only once for a course
574: my %parmhash; # the parameter cache
575: # reset map parameter hash
1.376 albertel 576: sub resetparmhash {
1.560 damieng 577: undef($parmhashid);
578: undef(%parmhash);
1.376 albertel 579: }
1.446 bisitz 580:
1.561 damieng 581: # dump the _parms.db database into %parmhash
1.376 albertel 582: sub cacheparmhash {
1.560 damieng 583: if ($parmhashid eq $env{'request.course.fn'}) { return; }
584: my %parmhashfile;
585: if (tie(%parmhashfile,'GDBM_File',
586: $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
587: %parmhash=%parmhashfile;
588: untie(%parmhashfile);
589: $parmhashid=$env{'request.course.fn'};
590: }
1.201 www 591: }
1.446 bisitz 592:
1.561 damieng 593: # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376 albertel 594: sub parmhash {
1.560 damieng 595: my ($id) = @_;
596: &cacheparmhash();
597: return $parmhash{$id};
1.376 albertel 598: }
1.560 damieng 599: }
1.376 albertel 600:
1.566 damieng 601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446 bisitz 602: {
1.561 damieng 603: my $symbsid; # course identifier, to initialize the cache only once for a course
604: my %symbs; # hash id->symb
605: # reset the id->symb cache
1.376 albertel 606: sub resetsymbcache {
1.560 damieng 607: undef($symbsid);
608: undef(%symbs);
1.376 albertel 609: }
1.446 bisitz 610:
1.566 damieng 611: # returns the resource symb or map src corresponding to a resource id or map pc
612: # (using lonnavmaps and a cache)
1.376 albertel 613: sub symbcache {
1.560 damieng 614: my $id=shift;
615: if ($symbsid ne $env{'request.course.id'}) {
616: undef(%symbs);
617: }
618: if (!$symbs{$id}) {
619: my $navmap = Apache::lonnavmaps::navmap->new();
620: if ($id=~/\./) {
621: my $resource=$navmap->getById($id);
622: $symbs{$id}=$resource->symb();
623: } else {
624: my $resource=$navmap->getByMapPc($id);
625: $symbs{$id}=&Apache::lonnet::declutter($resource->src());
626: }
627: $symbsid=$env{'request.course.id'};
1.473 amueller 628: }
1.560 damieng 629: return $symbs{$id};
1.473 amueller 630: }
1.560 damieng 631: }
1.201 www 632:
1.561 damieng 633: # cache for parameter default actions (stored in parmdefactions.db)
1.446 bisitz 634: {
1.561 damieng 635: my $rulesid; # course identifier, to initialize the cache only once for a course
636: my %rules; # parameter default actions hash
1.376 albertel 637: sub resetrulescache {
1.560 damieng 638: undef($rulesid);
639: undef(%rules);
1.376 albertel 640: }
1.446 bisitz 641:
1.561 damieng 642: # returns the value for a given key in the parameter default action hash
1.376 albertel 643: sub rulescache {
1.560 damieng 644: my $id=shift;
645: if ($rulesid ne $env{'request.course.id'}
646: && !defined($rules{$id})) {
647: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
648: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
649: %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
650: $rulesid=$env{'request.course.id'};
651: }
652: return $rules{$id};
1.221 www 653: }
654: }
655:
1.416 jms 656:
1.561 damieng 657: # Returns the values of the parameter type default action
658: # "default value when manually setting".
659: # If none is defined, ('','','','','') is returned.
660: #
661: # @param {string} $type - parameter type
662: # @returns {Array<string>} - (hours, min, sec, value)
1.229 www 663: sub preset_defaults {
664: my $type=shift;
665: if (&rulescache($type.'_action') eq 'default') {
1.560 damieng 666: # yes, there is something
667: return (&rulescache($type.'_hours'),
668: &rulescache($type.'_min'),
669: &rulescache($type.'_sec'),
670: &rulescache($type.'_value'));
1.229 www 671: } else {
1.560 damieng 672: # nothing there or something else
673: return ('','','','','');
1.229 www 674: }
675: }
676:
1.416 jms 677:
1.561 damieng 678: # Checks that a date is after enrollment start date and before
679: # enrollment end date.
680: # Returns HTML with a warning if it is not, or the empty string otherwise.
681: # This is used by both overview and table modes.
682: #
683: # @param {integer} $checkdate - the date to check.
684: # @returns {string} - HTML possibly containing a localized warning message.
1.277 www 685: sub date_sanity_info {
686: my $checkdate=shift;
687: unless ($checkdate) { return ''; }
688: my $result='';
689: my $crsprefix='course.'.$env{'request.course.id'}.'.';
690: if ($env{$crsprefix.'default_enrollment_end_date'}) {
691: if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413 bisitz 692: $result.='<div class="LC_warning">'
693: .&mt('After course enrollment end!')
694: .'</div>';
1.277 www 695: }
696: }
697: if ($env{$crsprefix.'default_enrollment_start_date'}) {
698: if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413 bisitz 699: $result.='<div class="LC_warning">'
700: .&mt('Before course enrollment start!')
701: .'</div>';
1.277 www 702: }
703: }
1.413 bisitz 704: # Preparation for additional warnings about dates in the past/future.
705: # An improved, more context sensitive version is recommended,
706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
707: # if ($checkdate<time) {
708: # $result.='<div class="LC_info">'
709: # .'('.&mt('in the past').')'
710: # .'</div>';
711: # }
712: # if ($checkdate>time) {
713: # $result.='<div class="LC_info">'
714: # .'('.&mt('in the future').')'
715: # .'</div>';
716: # }
1.277 www 717: return $result;
718: }
1.561 damieng 719:
720:
721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186 www 722: #
1.566 damieng 723: # @param {string} $sresid - resource id or map pc
1.565 damieng 724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 725: # @param {integer} $snum - level
726: # @param {string} $nval - new value
727: # @param {string} $ntype - new type
728: # @param {string} $uname - username
729: # @param {string} $udom - userdomain
730: # @param {string} $csec - section name
731: # @param {string} $cgroup - group name
1.186 www 732: sub storeparm {
1.269 raeburn 733: my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275 raeburn 734: &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197 www 735: }
736:
1.561 damieng 737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
738:
739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
741: #
1.566 damieng 742: # @param {string} $symb - resource symb or map src
1.565 damieng 743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 744: # @param {integer} $snum - level
745: # @param {string} $nval - new value
746: # @param {string} $ntype - new type
747: # @param {string} $uname - username
748: # @param {string} $udom - userdomain
749: # @param {string} $csec - section name
750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
751: # @param {string} $cgroup - group name
1.197 www 752: sub storeparm_by_symb {
1.275 raeburn 753: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226 www 754: unless ($recflag) {
1.560 damieng 755: # first time call
756: %recstack=();
757: $recflag=1;
1.226 www 758: }
1.560 damieng 759: # store parameter
1.226 www 760: &storeparm_by_symb_inner
1.473 amueller 761: ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560 damieng 762: # don't do anything if parameter was reset
1.266 www 763: unless ($nval) { return; }
1.226 www 764: my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560 damieng 765: # remember that this was set
1.226 www 766: $recstack{$parm}=1;
1.560 damieng 767: # what does this trigger?
1.226 www 768: foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560 damieng 769: # don't backfire
770: unless ((!$triggered) || ($recstack{$triggered})) {
771: my $action=&rulescache($triggered.'_action');
772: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
773: # set triggered parameter on same level
774: my $newspnam=$prefix.$triggered;
775: my $newvalue='';
776: my $active=1;
777: if ($action=~/^when\_setting/) {
778: # are there restrictions?
779: if (&rulescache($triggered.'_triggervalue')=~/\w/) {
780: $active=0;
1.565 damieng 781: foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560 damieng 782: if (lc($possiblevalue) eq lc($nval)) { $active=1; }
783: }
784: }
785: $newvalue=&rulescache($triggered.'_value');
786: } else {
787: my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
788: if ($action=~/^later\_than/) {
789: $newvalue=$nval+$totalsecs;
790: } else {
791: $newvalue=$nval-$totalsecs;
792: }
793: }
794: if ($active) {
795: &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
796: $uname,$udom,$csec,$recflag,$cgroup);
797: }
798: }
1.226 www 799: }
800: return '';
801: }
802:
1.561 damieng 803: # Adds all given arguments to the course parameter log.
804: # @returns {string} - the answer to the lonnet query.
1.293 www 805: sub log_parmset {
1.525 raeburn 806: return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284 www 807: }
808:
1.561 damieng 809: # Store a parameter value and type by symb, without using the parameter default actions.
810: # Expire related sheets.
811: #
1.566 damieng 812: # @param {string} $symb - resource symb or map src
1.561 damieng 813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
814: # @param {integer} $snum - level
815: # @param {string} $nval - new value
816: # @param {string} $ntype - new type
817: # @param {string} $uname - username
818: # @param {string} $udom - userdomain
819: # @param {string} $csec - section name
820: # @param {string} $cgroup - group name
821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226 www 822: sub storeparm_by_symb_inner {
1.197 www 823: # ---------------------------------------------------------- Get symb, map, etc
1.269 raeburn 824: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197 www 825: # ---------------------------------------------------------- Construct prefixes
1.186 www 826: $spnam=~s/\_([^\_]+)$/\.$1/;
1.446 bisitz 827: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 828: $map = &Apache::lonnet::deversion($map);
829:
1.197 www 830: my $symbparm=$symb.'.'.$spnam;
1.556 raeburn 831: my $recurseparm=$map.'___(rec).'.$spnam;
1.197 www 832: my $mapparm=$map.'___(all).'.$spnam;
833:
1.269 raeburn 834: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
835: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 836: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 837: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
838:
1.190 albertel 839: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
840: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 841: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 842: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446 bisitz 843:
1.190 albertel 844: my $courselevel=$env{'request.course.id'}.'.'.$spnam;
845: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 846: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 847: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446 bisitz 848:
1.186 www 849: my $storeunder='';
1.578 raeburn 850: my $possreplace='';
1.556 raeburn 851: if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578 raeburn 852: if (($snum==17) || ($snum==3)) {
853: $storeunder=$courseleveli;
854: $possreplace=$courselevelm;
855: }
856: if (($snum==16) || ($snum==2)) {
857: $storeunder=$courselevelm;
858: $possreplace=$courseleveli;
859: }
1.556 raeburn 860: if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
861: if ($snum==12) { $storeunder=$seclevel; }
1.578 raeburn 862: if ($snum==11) {
863: $storeunder=$secleveli;
864: $possreplace=$seclevelm;
865: }
866: if ($snum==10) {
867: $storeunder=$seclevelm;
868: $possreplace=$secleveli;
869: }
1.556 raeburn 870: if ($snum==9) { $storeunder=$seclevelr; }
871: if ($snum==8) { $storeunder=$grplevel; }
1.578 raeburn 872: if ($snum==7) {
873: $storeunder=$grpleveli;
874: $possreplace=$grplevelm;
875: }
876: if ($snum==6) {
877: $storeunder=$grplevelm;
878: $possreplace=$grpleveli;
879: }
1.556 raeburn 880: if ($snum==5) { $storeunder=$grplevelr; }
1.269 raeburn 881:
1.446 bisitz 882:
1.186 www 883: my $delete;
884: if ($nval eq '') { $delete=1;}
885: my %storecontent = ($storeunder => $nval,
1.473 amueller 886: $storeunder.'.type' => $ntype);
1.186 www 887: my $reply='';
1.560 damieng 888:
1.556 raeburn 889: if ($snum>4) {
1.186 www 890: # ---------------------------------------------------------------- Store Course
891: #
1.560 damieng 892: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
893: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
894: # Expire sheets
895: &Apache::lonnet::expirespread('','','studentcalc');
896: if (($snum==13) || ($snum==9) || ($snum==5)) {
897: &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578 raeburn 898: } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560 damieng 899: &Apache::lonnet::expirespread('','','assesscalc',$map);
900: } else {
901: &Apache::lonnet::expirespread('','','assesscalc');
902: }
903: # Store parameter
904: if ($delete) {
905: $reply=&Apache::lonnet::del
906: ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
907: &log_parmset(\%storecontent,1);
908: } else {
909: $reply=&Apache::lonnet::cput
910: ('resourcedata',\%storecontent,$cdom,$cnum);
911: &log_parmset(\%storecontent);
1.578 raeburn 912: if ($possreplace) {
913: my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
914: if (ref($resdata) eq 'HASH') {
915: if (exists($resdata->{$possreplace})) {
916: if (&Apache::lonnet::del
917: ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
918: &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);
919: }
920: }
921: }
922: }
1.560 damieng 923: }
924: &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186 www 925: } else {
926: # ------------------------------------------------------------------ Store User
927: #
1.560 damieng 928: # Expire sheets
929: &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
930: if ($snum==1) {
931: &Apache::lonnet::expirespread
932: ($uname,$udom,'assesscalc',$symb);
1.578 raeburn 933: } elsif (($snum==2) || ($snum==3)) {
1.560 damieng 934: &Apache::lonnet::expirespread
935: ($uname,$udom,'assesscalc',$map);
936: } else {
937: &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
938: }
939: # Store parameter
940: if ($delete) {
941: $reply=&Apache::lonnet::del
942: ('resourcedata',[keys(%storecontent)],$udom,$uname);
943: &log_parmset(\%storecontent,1,$uname,$udom);
944: } else {
945: $reply=&Apache::lonnet::cput
946: ('resourcedata',\%storecontent,$udom,$uname);
947: &log_parmset(\%storecontent,0,$uname,$udom);
1.578 raeburn 948: if ($possreplace) {
949: my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
950: if (ref($resdata) eq 'HASH') {
951: if (exists($resdata->{$possreplace})) {
952: if (&Apache::lonnet::del
953: ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
954: &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
955: $uname,$udom);
956: }
957: }
958: }
959: }
1.560 damieng 960: }
961: &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186 www 962: }
1.446 bisitz 963:
1.186 www 964: if ($reply=~/^error\:(.*)/) {
1.560 damieng 965: return "<span class=\"LC_error\">Write Error: $1</span>";
1.186 www 966: }
967: return '';
968: }
969:
1.9 www 970:
1.561 damieng 971: # Returns HTML with the value of the given parameter,
972: # using a readable format for dates, and
973: # a warning if there is a problem with a date.
974: # Used by table mode.
975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
976: #
977: # @param {string} $value - the parameter value
978: # @param {string} $type - the parameter type
979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9 www 980: sub valout {
1.600 raeburn 981: my ($value,$type,$editable)=@_;
1.59 matthew 982: my $result = '';
983: # Values of zero are valid.
984: if (! $value && $value ne '0') {
1.528 bisitz 985: if ($editable) {
986: $result =
987: '<img src="/res/adm/pages/editmap.png"'
988: .' alt="'.&mt('Change').'"'
1.539 raeburn 989: .' title="'.&mt('Change').'" style="border:0;" />';
1.528 bisitz 990: } else {
991: $result=' ';
992: }
1.59 matthew 993: } else {
1.66 www 994: if ($type eq 'date_interval') {
1.559 raeburn 995: my ($totalsecs,$donesuffix) = split(/_/,$value,2);
996: my ($usesdone,$donebuttontext,$proctor,$secretkey);
997: if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
998: $donebuttontext = $1;
999: (undef,$proctor,$secretkey) = split(/_/,$2);
1000: $usesdone = 'done';
1001: } elsif ($donesuffix =~ /^done(|_.+)$/) {
1002: $donebuttontext = &mt('Done');
1003: ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
1004: }
1.554 raeburn 1005: my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413 bisitz 1006: my @timer;
1.66 www 1007: $year=$year-70;
1008: $mday--;
1009: if ($year) {
1.413 bisitz 1010: # $result.=&mt('[quant,_1,yr]',$year).' ';
1011: push(@timer,&mt('[quant,_1,yr]',$year));
1.66 www 1012: }
1013: if ($mon) {
1.413 bisitz 1014: # $result.=&mt('[quant,_1,mth]',$mon).' ';
1015: push(@timer,&mt('[quant,_1,mth]',$mon));
1.66 www 1016: }
1017: if ($mday) {
1.413 bisitz 1018: # $result.=&mt('[quant,_1,day]',$mday).' ';
1019: push(@timer,&mt('[quant,_1,day]',$mday));
1.66 www 1020: }
1021: if ($hour) {
1.413 bisitz 1022: # $result.=&mt('[quant,_1,hr]',$hour).' ';
1023: push(@timer,&mt('[quant,_1,hr]',$hour));
1.66 www 1024: }
1025: if ($min) {
1.413 bisitz 1026: # $result.=&mt('[quant,_1,min]',$min).' ';
1027: push(@timer,&mt('[quant,_1,min]',$min));
1.66 www 1028: }
1029: if ($sec) {
1.413 bisitz 1030: # $result.=&mt('[quant,_1,sec]',$sec).' ';
1031: push(@timer,&mt('[quant,_1,sec]',$sec));
1.66 www 1032: }
1.413 bisitz 1033: # $result=~s/\s+$//;
1034: if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
1035: push(@timer,&mt('[quant,_1,sec]',0));
1036: }
1037: $result.=join(", ",@timer);
1.559 raeburn 1038: if ($usesdone eq 'done') {
1.558 raeburn 1039: if ($secretkey) {
1.559 raeburn 1040: $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
1.558 raeburn 1041: } else {
1.559 raeburn 1042: $result .= ' + "'.$donebuttontext.'"';
1043: }
1.554 raeburn 1044: }
1.213 www 1045: } elsif (&isdateparm($type)) {
1.361 albertel 1046: $result = &Apache::lonlocal::locallocaltime($value).
1.560 damieng 1047: &date_sanity_info($value);
1.59 matthew 1048: } else {
1049: $result = $value;
1.517 www 1050: $result=~s/\,/\, /gs;
1.560 damieng 1051: $result = &HTML::Entities::encode($result,'"<>&');
1.59 matthew 1052: }
1053: }
1054: return $result;
1.9 www 1055: }
1056:
1.59 matthew 1057:
1.561 damieng 1058: # Returns HTML containing a link on a parameter value, for table mode.
1059: # The link uses the javascript function 'pjump'.
1060: #
1061: # @param {string} $type - parameter type
1062: # @param {string} $dis - dialog title for editing the parameter value and type
1063: # @param {string} $value - parameter value
1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588 raeburn 1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5 www 1069: sub plink {
1.588 raeburn 1070: my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23 www 1071: my $winvalue=$value;
1072: unless ($winvalue) {
1.592 raeburn 1073: if (&isdateparm($type) || (&is_specialstring($type))) {
1.190 albertel 1074: $winvalue=$env{'form.recent_'.$type};
1.591 raeburn 1075: } elsif ($type eq 'string_yesno') {
1076: if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
1077: $winvalue=$env{'form.recent_string'};
1078: }
1.23 www 1079: } else {
1.190 albertel 1080: $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23 www 1081: }
1082: }
1.229 www 1083: my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
1084: my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
1085: unless (defined($winvalue)) { $winvalue=$val; }
1.593 raeburn 1086: my $valout = &valout($value,$type,1);
1.429 raeburn 1087: my $unencmarker = $marker;
1.378 albertel 1088: foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588 raeburn 1089: \$hour, \$min, \$sec, \$extra) {
1.560 damieng 1090: $$item = &HTML::Entities::encode($$item,'"<>&');
1091: $$item =~ s/\'/\\\'/g;
1.378 albertel 1092: }
1.429 raeburn 1093: return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473 amueller 1094: '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588 raeburn 1095: .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578 raeburn 1096: $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
1097: &mt('recursive').'</td></tr>' : '').'</table>';
1098:
1.5 www 1099: }
1100:
1.561 damieng 1101: # Javascript for table mode.
1.280 albertel 1102: sub page_js {
1103:
1.81 www 1104: my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88 matthew 1105: my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280 albertel 1106:
1107: return(<<ENDJS);
1108: <script type="text/javascript">
1.454 bisitz 1109: // <![CDATA[
1.44 albertel 1110:
1.88 matthew 1111: $pjump_def
1.44 albertel 1112:
1113: function psub() {
1.591 raeburn 1114: var specstring = /^string_!(yesno|any)/i;
1.44 albertel 1115: if (document.parmform.pres_marker.value!='') {
1116: document.parmform.action+='#'+document.parmform.pres_marker.value;
1117: var typedef=new Array();
1118: typedef=document.parmform.pres_type.value.split('_');
1.562 damieng 1119: if (document.parmform.pres_type.value!='') {
1.589 raeburn 1120: if ((typedef[0]=='date') ||
1.591 raeburn 1121: (specstring.test(document.parmform.pres_type.value))) {
1.562 damieng 1122: eval('document.parmform.recent_'+
1123: document.parmform.pres_type.value+
1124: '.value=document.parmform.pres_value.value;');
1125: } else {
1126: eval('document.parmform.recent_'+typedef[0]+
1127: '.value=document.parmform.pres_value.value;');
1128: }
1.44 albertel 1129: }
1130: document.parmform.submit();
1131: } else {
1132: document.parmform.pres_value.value='';
1133: document.parmform.pres_marker.value='';
1134: }
1135: }
1136:
1.57 albertel 1137: function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
1138: var options = "width=" + w + ",height=" + h + ",";
1139: options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
1140: options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
1141: var newWin = window.open(url, wdwName, options);
1142: newWin.focus();
1143: }
1.523 raeburn 1144:
1.454 bisitz 1145: // ]]>
1.523 raeburn 1146:
1.44 albertel 1147: </script>
1.81 www 1148: $selscript
1.280 albertel 1149: ENDJS
1150:
1151: }
1.507 www 1152:
1.561 damieng 1153: # Javascript to show or hide the map selection (function showHide_courseContent),
1154: # for table and overview modes.
1.523 raeburn 1155: sub showhide_js {
1156: return <<"COURSECONTENTSCRIPT";
1157:
1158: function showHide_courseContent() {
1159: var parmlevValue=document.getElementById("parmlev").value;
1160: if (parmlevValue == 'general') {
1161: document.getElementById('mapmenu').style.display="none";
1162: } else {
1163: if ((parmlevValue == "full") || (parmlevValue == "map")) {
1164: document.getElementById('mapmenu').style.display ="";
1165: } else {
1166: document.getElementById('mapmenu').style.display="none";
1167: }
1168: }
1169: return;
1170: }
1171:
1172: COURSECONTENTSCRIPT
1173: }
1174:
1.561 damieng 1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549 raeburn 1176: sub toggleparmtextbox_js {
1177: return <<"ENDSCRIPT";
1178:
1179: if (!document.getElementsByClassName) {
1180: function getElementsByClassName(node, classname) {
1181: var a = [];
1182: var re = new RegExp('(^| )'+classname+'( |$)');
1183: var els = node.getElementsByTagName("*");
1184: for(var i=0,j=els.length; i<j; i++)
1185: if(re.test(els[i].className))a.push(els[i]);
1186: return a;
1187: }
1188: }
1189:
1190: function showHideLenient() {
1191: var lenients;
1192: var setRegExp = /^set_/;
1193: if (document.getElementsByClassName) {
1194: lenients = document.getElementsByClassName('LC_lenient_radio');
1195: } else {
1196: lenients = getElementsByClassName(document.body,'LC_lenient_radio');
1197: }
1198: if (lenients != 'undefined') {
1199: for (var i=0; i<lenients.length; i++) {
1200: if (lenients[i].checked) {
1201: if (lenients[i].value == 'weighted') {
1202: if (setRegExp.test(lenients[i].name)) {
1203: var identifier = lenients[i].name.replace(setRegExp,'');
1204: toggleParmTextbox(document.parmform,identifier);
1205: }
1206: }
1207: }
1208: }
1209: }
1210: return;
1211: }
1212:
1213: function toggleParmTextbox(form,key) {
1214: var divfortext = document.getElementById('LC_parmtext_'+key);
1215: if (divfortext) {
1216: var caller = form.elements['set_'+key];
1217: if (caller.length) {
1218: for (i=0; i<caller.length; i++) {
1219: if (caller[i].checked) {
1220: if (caller[i].value == 'weighted') {
1221: divfortext.style.display = 'inline';
1222: } else {
1223: divfortext.style.display = 'none';
1224: }
1225: }
1226: }
1227: }
1228: }
1229: return;
1230: }
1231:
1232: ENDSCRIPT
1233: }
1234:
1.561 damieng 1235: # Javascript function validateParms, for overview mode
1.549 raeburn 1236: sub validateparms_js {
1237: return <<'ENDSCRIPT';
1238:
1239: function validateParms() {
1240: var textRegExp = /^settext_/;
1241: var tailLenient = /\.lenient$/;
1242: var patternRelWeight = /^\-?[\d.]+$/;
1243: var patternLenientStd = /^(yes|no|default)$/;
1.597 raeburn 1244: var ipRegExp = /^setip/;
1.549 raeburn 1245: var ipallowRegExp = /^setipallow_/;
1246: var ipdenyRegExp = /^setipdeny_/;
1.597 raeburn 1247: var deeplinkRegExp = /^deeplink_/;
1.601 raeburn 1248: var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;
1249: var dlLinkProtectRegExp = /^deeplink_protect_/;
1250: var dlLtidRegExp = /^deeplink_ltid_/;
1251: var dlLticRegExp = /^deeplink_ltic_/;
1.597 raeburn 1252: var dlKeyRegExp = /^deeplink_key_/;
1253: var dlMenusRegExp = /^deeplink_menus_/;
1254: var dlCollsRegExp = /^deeplink_colls_/;
1.613 raeburn 1255: var dlTargetRegExp = /^deeplink_target_/;
1.549 raeburn 1256: var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1257: if ((document.parmform.elements.length != 'undefined') && (document.parmform.elements.length) != 'null') {
1258: if (document.parmform.elements.length) {
1259: for (i=0; i<document.parmform.elements.length; i++) {
1260: var name=document.parmform.elements[i].name;
1.588 raeburn 1261: if (textRegExp.test(name)) {
1.549 raeburn 1262: var identifier = name.replace(textRegExp,'');
1263: if (tailLenient.test(identifier)) {
1264: if (document.parmform.elements['set_'+identifier].length) {
1265: for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
1266: if (document.parmform.elements['set_'+identifier][j].checked) {
1267: if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
1268: var relweight = document.parmform.elements[i].value;
1269: relweight = relweight.replace(/^\s+|\s+$/g,'');
1270: if (!patternRelWeight.test(relweight)) {
1271: relweight = '0.0';
1272: }
1273: if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
1274: document.parmform.elements['set_'+identifier][j].value = relweight;
1275: } else {
1276: document.parmform.elements['set_'+identifier][j].value += ','+relweight;
1277: }
1278: }
1279: break;
1280: }
1281: }
1282: }
1283: }
1.597 raeburn 1284: } else if (ipRegExp.test(name)) {
1285: if (ipallowRegExp.test(name)) {
1286: var identifier = name.replace(ipallowRegExp,'');
1287: var possallow = document.parmform.elements[i].value;
1288: possallow = possallow.replace(/^\s+|\s+$/g,'');
1289: if (patternIP.test(possallow)) {
1290: if (document.parmform.elements['set_'+identifier].value) {
1291: possallow = ','+possallow;
1292: }
1293: document.parmform.elements['set_'+identifier].value += possallow;
1294: }
1295: } else if (ipdenyRegExp.test(name)) {
1296: var identifier = name.replace(ipdenyRegExp,'');
1297: var possdeny = document.parmform.elements[i].value;
1298: possdeny = possdeny.replace(/^\s+|\s+$/g,'');
1299: if (patternIP.test(possdeny)) {
1300: possdeny = '!'+possdeny;
1301: if (document.parmform.elements['set_'+identifier].value) {
1302: possdeny = ','+possdeny;
1303: }
1304: document.parmform.elements['set_'+identifier].value += possdeny;
1.588 raeburn 1305: }
1306: }
1307: } else if (deeplinkRegExp.test(name)) {
1.597 raeburn 1308: if (dlListScopeRegExp.test(name)) {
1309: var identifier = name.replace(dlListScopeRegExp,'');
1310: var idx = document.parmform.elements[i].selectedIndex;
1311: if (idx > 0) {
1312: var possdeeplink = document.parmform.elements[i].options[idx].value
1313: possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
1314: if (document.parmform.elements['set_'+identifier].value) {
1315: possdeeplink = ','+possdeeplink;
1316: }
1317: document.parmform.elements['set_'+identifier].value += possdeeplink;
1318: }
1.601 raeburn 1319: } else if (dlLinkProtectRegExp.test(name)) {
1.597 raeburn 1320: if (document.parmform.elements[i].checked) {
1.601 raeburn 1321: var identifier = name.replace(dlLinkProtectRegExp,'');
1.597 raeburn 1322: var posslinkurl = document.parmform.elements[i].value;
1323: posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
1324: if (document.parmform.elements['set_'+identifier].value) {
1325: posslinkurl = ','+posslinkurl;
1326: }
1327: document.parmform.elements['set_'+identifier].value += posslinkurl;
1328: }
1.601 raeburn 1329: } else if (dlLtidRegExp.test(name)) {
1330: var identifier = name.replace(dlLtidRegExp,'');
1331: if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
1332: var possltid = document.parmform.elements[i].value;
1333: possltid = possltid.replace(/\D+/g,'');
1334: if (possltid.length) {
1.597 raeburn 1335: if (document.parmform.elements['set_'+identifier].value) {
1.601 raeburn 1336: possltid = ':'+possltid;
1.597 raeburn 1337: }
1.601 raeburn 1338: document.parmform.elements['set_'+identifier].value += possltid;
1.597 raeburn 1339: } else {
1340: document.parmform.elements['set_'+identifier].value = '';
1.601 raeburn 1341: alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597 raeburn 1342: return false;
1343: }
1344: }
1.601 raeburn 1345: } else if (dlLticRegExp.test(name)) {
1346: var identifier = name.replace(dlLticRegExp,'');
1347: if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
1348: var possltic = document.parmform.elements[i].value;
1349: possltic = possltic.replace(/\D+/g,'');
1350: if (possltic.length) {
1351: if (document.parmform.elements['set_'+identifier].value) {
1352: possltic = ':'+possltic;
1353: }
1354: document.parmform.elements['set_'+identifier].value += possltic;
1355: } else {
1356: document.parmform.elements['set_'+identifier].value = '';
1357: alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1358: return false;
1359: }
1360: }
1.597 raeburn 1361: } else if (dlKeyRegExp.test(name)) {
1362: var identifier = name.replace(dlKeyRegExp,'');
1.601 raeburn 1363: if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597 raeburn 1364: var posskey = document.parmform.elements[i].value;
1365: posskey = posskey.replace(/^\s+|\s+$/g,'');
1366: var origlength = posskey.length;
1367: posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
1368: var newlength = posskey.length;
1369: if (newlength > 0) {
1370: var change = origlength - newlength;
1371: if (change) {
1372: alert(change+' disallowed character(s) removed from deeplink key');
1373: }
1374: if (document.parmform.elements['set_'+identifier].value) {
1375: posskey = ':'+posskey;
1376: }
1377: document.parmform.elements['set_'+identifier].value += posskey;
1378: } else {
1379: document.parmform.elements['set_'+identifier].value = '';
1380: if (newlength < origlength) {
1381: alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
1382: } else {
1383: alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
1384: }
1385: return false;
1386: }
1387: }
1388: } else if (dlMenusRegExp.test(name)) {
1389: if (document.parmform.elements[i].checked) {
1390: var identifier = name.replace(dlMenusRegExp,'');
1391: var posslinkmenu = document.parmform.elements[i].value;
1392: posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
1393: if (posslinkmenu == 'std') {
1394: posslinkmenu = '0';
1395: if (document.parmform.elements['set_'+identifier].value) {
1396: posslinkmenu = ','+posslinkmenu;
1397: }
1398: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1399: }
1400: }
1401: } else if (dlCollsRegExp.test(name)) {
1402: var identifier = name.replace(dlCollsRegExp,'');
1403: if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
1404: var posslinkmenu = document.parmform.elements[i].value;
1405: if (document.parmform.elements['set_'+identifier].value) {
1406: posslinkmenu = ','+posslinkmenu;
1407: }
1408: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1409: }
1.614 raeburn 1410: } else if (dlTargetRegExp.test(name)) {
1411: var identifier = name.replace(dlTargetRegExp,'');
1.613 raeburn 1412: var idx = document.parmform.elements[i].selectedIndex;
1413: if (idx > 0) {
1414: var possdeeplink = document.parmform.elements[i].options[idx].value
1415: possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
1416: if (document.parmform.elements['set_'+identifier].value) {
1417: possdeeplink = ','+possdeeplink;
1418: }
1.614 raeburn 1419: document.parmform.elements['set_'+identifier].value += possdeeplink;
1.613 raeburn 1420: }
1.549 raeburn 1421: }
1422: }
1423: }
1424: }
1425: }
1426: return true;
1427: }
1428:
1.597 raeburn 1429: function isRadioSet(name,expected) {
1430: var menuitems = document.getElementsByName(name);
1431: var radioLength = menuitems.length;
1432: result = false;
1433: if (radioLength > 1) {
1434: for (var j=0; j<radioLength; j++) {
1435: if (menuitems[j].checked) {
1436: if (menuitems[j].value == expected) {
1437: result = true;
1438: break;
1439: }
1440: }
1441: }
1442: }
1443: return result;
1444: }
1445:
1.549 raeburn 1446: ENDSCRIPT
1447: }
1448:
1.561 damieng 1449: # Javascript initialization, for overview mode
1.549 raeburn 1450: sub ipacc_boxes_js {
1451: my $remove = &mt('Remove');
1452: return <<"END";
1453: \$(document).ready(function() {
1454: var wrapper = \$(".LC_string_ipacc_wrap");
1455: var add_button = \$(".LC_add_ipacc_button");
1456: var ipaccRegExp = /^LC_string_ipacc_/;
1457:
1458: \$(add_button).click(function(e){
1459: e.preventDefault();
1460: var identifier = \$(this).closest("div").attr("id");
1461: identifier = identifier.replace(ipaccRegExp,'');
1.551 raeburn 1462: \$(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 1463: });
1464:
1465: \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
1466: e.preventDefault(); \$(this).closest("div").remove();
1467: })
1468: });
1469:
1470:
1471: END
1472: }
1473:
1.561 damieng 1474: # Javascript function toggleSecret, for overview mode.
1.558 raeburn 1475: sub done_proctor_js {
1.611 raeburn 1476: my $defaultdone = &mt('Done');
1477: &js_escape(\$defaultdone);
1.558 raeburn 1478: return <<"END";
1479: function toggleSecret(form,radio,key) {
1480: var radios = form[radio+key];
1481: if (radios.length) {
1482: for (var i=0; i<radios.length; i++) {
1483: if (radios[i].checked) {
1484: if (radios[i].value == '_done_proctor') {
1485: if (document.getElementById('done_'+key+'_proctorkey')) {
1486: document.getElementById('done_'+key+'_proctorkey').type='text';
1487: }
1488: } else {
1489: if (document.getElementById('done_'+key+'_proctorkey')) {
1490: document.getElementById('done_'+key+'_proctorkey').type='hidden';
1491: document.getElementById('done_'+key+'_proctorkey').value='';
1492: }
1493: }
1.611 raeburn 1494: if (document.getElementById('done_'+key+'_buttontext')) {
1495: if (radios[i].value == '') {
1496: document.getElementById('done_'+key+'_buttontext').value = '';
1497: } else {
1498: if (document.getElementById('done_'+key+'_buttontext').value == '') {
1499: document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
1500: }
1501: }
1502: }
1.558 raeburn 1503: }
1504: }
1505: }
1506: }
1507: END
1508:
1509: }
1510:
1.588 raeburn 1511: # Javascript function toggle
1512: sub deeplink_js {
1513: return <<"END";
1514: function toggleDeepLink(form,item,key) {
1515: var radios = form['deeplink_'+item+'_'+key];
1516: if (radios.length) {
1517: var keybox;
1518: if (document.getElementById('deeplink_key_'+item+'_'+key)) {
1519: keybox = document.getElementById('deeplink_key_'+item+'_'+key);
1520: }
1.601 raeburn 1521: var divoptions = new Array();
1522: if (item == 'protect') {
1523: divoptions = ['ltic','ltid'];
1.597 raeburn 1524: } else {
1525: if (item == 'menus') {
1.601 raeburn 1526: divoptions = ['colls'];
1.597 raeburn 1527: }
1528: }
1.601 raeburn 1529: var seldivs = new Array();
1530: if ((item == 'protect') || (item == 'menus')) {
1531: for (var i=0; i<divoptions.length; i++) {
1532: if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
1533: seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
1534: } else {
1535: seldivs[i] = '';
1536: }
1537: }
1.588 raeburn 1538: }
1539: for (var i=0; i<radios.length; i++) {
1540: if (radios[i].checked) {
1.601 raeburn 1541: if ((item == 'protect') || (item == 'menus')) {
1542: for (var j=0; j<seldivs.length; j++) {
1543: if (radios[i].value == divoptions[j]) {
1544: if (seldivs[j] != '') {
1545: seldivs[j].style.display = 'inline-block';
1546: }
1547: if (item == 'protect') {
1548: keybox.type = 'hidden';
1549: keybox.value = '';
1550: }
1551: } else {
1552: if (seldivs[j] != '') {
1553: seldivs[j].style.display = 'none';
1554: form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
1555: }
1556: }
1.597 raeburn 1557: }
1.601 raeburn 1558: if (item == 'protect') {
1.597 raeburn 1559: if (radios[i].value == 'key') {
1560: keybox.type = 'text';
1561: } else {
1562: keybox.type = 'hidden';
1563: }
1.588 raeburn 1564: }
1565: }
1566: }
1567: }
1568: }
1569: }
1570: END
1571:
1572: }
1573:
1.561 damieng 1574: # Prints HTML page start for table mode.
1575: # @param {Apache2::RequestRec} $r - the Apache request
1576: # @param {string} $psymb - resource symb
1577: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280 albertel 1578: sub startpage {
1.531 raeburn 1579: my ($r,$psymb,$crstype) = @_;
1.281 albertel 1580:
1.515 raeburn 1581: my %loaditems = (
1582: 'onload' => "group_or_section('cgroup')",
1583: );
1584: if (!$psymb) {
1.523 raeburn 1585: $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515 raeburn 1586: }
1.280 albertel 1587:
1.560 damieng 1588: if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
1589: (!$env{'form.dis'})) || ($env{'form.symb'})) {
1590: &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
1591: text=>"Problem Parameters"});
1.414 droeschl 1592: } else {
1.560 damieng 1593: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1594: text=>"Table Mode",
1595: help => 'Course_Setting_Parameters'});
1.414 droeschl 1596: }
1.523 raeburn 1597: my $js = &page_js().'
1598: <script type="text/javascript">
1599: // <![CDATA[
1600: '.
1601: &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
1602: // ]]>
1603: </script>
1604: ';
1.446 bisitz 1605: my $start_page =
1.523 raeburn 1606: &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
1607: {'add_entries' => \%loaditems,});
1.446 bisitz 1608: my $breadcrumbs =
1.473 amueller 1609: &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506 www 1610: my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
1611: my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507 www 1612: $r->print($start_page.$breadcrumbs);
1.531 raeburn 1613: &startSettingsScreen($r,'parmset',$crstype);
1.280 albertel 1614: $r->print(<<ENDHEAD);
1.193 albertel 1615: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419 bisitz 1616: <input type="hidden" value="" name="pres_value" />
1617: <input type="hidden" value="" name="pres_type" />
1618: <input type="hidden" value="" name="pres_marker" />
1619: <input type="hidden" value="1" name="prevvisit" />
1.506 www 1620: <input type="hidden" value="$escfilter" name="filter" />
1621: <input type="hidden" value="$escpart" name="part" />
1.44 albertel 1622: ENDHEAD
1623: }
1624:
1.209 www 1625:
1.561 damieng 1626: # Prints a row for table mode (except for the tr start).
1627: # Every time a hash reference is passed, a single entry is used, so print_row
1628: # could just use these values, but why make it simple when it can be complicated ?
1629: #
1630: # @param {Apache2::RequestRec} $r - the Apache request
1631: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
1632: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
1633: # @param {hash reference} $name - parameter key -> parameter name
1.566 damieng 1634: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561 damieng 1635: # @param {string} $rid - resource id
1636: # @param {hash reference} $default - parameter key -> resource parameter default value
1637: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
1638: # @param {hash reference} $display - parameter key -> full title for the parameter
1639: # @param {string} $defbgone - user level and other levels background color
1640: # @param {string} $defbgtwo - section level background color, also used for part number
1641: # @param {string} $defbgthree - group level background color
1642: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1643: # @param {string} $uname - user name
1644: # @param {string} $udom - user domain
1645: # @param {string} $csec - section name
1646: # @param {string} $cgroup - group name
1647: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1648: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582 raeburn 1649: # @param {boolean} $readonly - true if no editing allowed.
1650: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
1651: # @param {hash reference} - $maptitles - - hash map id or src -> map title
1652: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
1653: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set
1.44 albertel 1654: sub print_row {
1.201 www 1655: my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568 raeburn 1656: $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582 raeburn 1657: $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275 raeburn 1658: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1659: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1660: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582 raeburn 1661: my $numlinks = 0;
1.553 raeburn 1662:
1.560 damieng 1663: # get the values for the parameter in cascading order
1664: # empty levels will remain empty
1.44 albertel 1665: my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473 amueller 1666: $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1667: # get the type for the parameters
1668: # problem: these may not be set for all levels
1.66 www 1669: my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275 raeburn 1670: $$name{$which}.'.type',$rid,
1.473 amueller 1671: $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1672: # cascade down manually
1.182 albertel 1673: my $cascadetype=$$defaulttype{$which};
1.556 raeburn 1674: for (my $i=18;$i>0;$i--) {
1.560 damieng 1675: if ($typeoutpar[$i]) {
1.66 www 1676: $cascadetype=$typeoutpar[$i];
1.560 damieng 1677: } else {
1.66 www 1678: $typeoutpar[$i]=$cascadetype;
1679: }
1680: }
1.57 albertel 1681: my $parm=$$display{$which};
1682:
1.203 www 1683: if ($parmlev eq 'full') {
1.419 bisitz 1684: $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506 www 1685: .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433 raeburn 1686: } else {
1.57 albertel 1687: $parm=~s|\[.*\]\s||g;
1688: }
1.231 www 1689: my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
1690: if ($automatic) {
1.560 damieng 1691: $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231 www 1692: }
1.427 bisitz 1693: $r->print('<td>'.$parm.'</td>');
1.446 bisitz 1694:
1.44 albertel 1695: my $thismarker=$which;
1696: $thismarker=~s/^parameter\_//;
1697: my $mprefix=$rid.'&'.$thismarker.'&';
1.582 raeburn 1698: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1699: my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588 raeburn 1700: $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582 raeburn 1701: if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
1702: if ($result eq '') {
1703: $recurse_check = 1;
1704: } elsif (($uname ne '') && ($result > 3)) {
1705: $recurse_check = 1;
1706: } elsif (($cgroup ne '') && ($result > 7)) {
1707: $recurse_check = 1;
1708: } elsif (($csec ne '') && ($result > 11)) {
1709: $recurse_check = 1;
1710: } elsif ($result > 17) {
1711: $recurse_check = 1;
1712: }
1713: if ($recurse_check) {
1714: my $what = $$part{$which}.'.'.$$name{$which};
1715: my $prefix;
1716: if (($uname ne '') && ($udom ne '')) {
1717: my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1718: $prefix = $env{'request.course.id'};
1719: $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
1720: if (ref($recursinfo) eq 'ARRAY') {
1721: $effparm_rec = 1;
1722: $effparm_level = &mt('user: [_1]',$uname);
1723: }
1724: }
1725: if (($cgroup ne '') && (!$effparm_rec)) {
1726: $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
1727: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1728: if (ref($recursinfo) eq 'ARRAY') {
1729: $effparm_rec = 1;
1730: $effparm_level = &mt('group: [_1]',$cgroup);
1731: }
1732: }
1733: if (($csec ne '') && (!$effparm_rec)) {
1734: $prefix = $env{'request.course.id'}.'.['.$csec.']';
1735: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1736: if (ref($recursinfo) eq 'ARRAY') {
1737: $effparm_rec = 1;
1738: $effparm_level = &mt('section: [_1]',$csec);
1739: }
1740: }
1741: if (!$effparm_rec) {
1742: $prefix = $env{'request.course.id'};
1743: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1744: if (ref($recursinfo) eq 'ARRAY') {
1745: $effparm_rec = 1;
1746: }
1747: }
1748: }
1749: }
1750: if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
1751: $effparm_rec = 1;
1752: }
1753: if ((!$effparm_rec) &&
1754: (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) &&
1755: ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578 raeburn 1756: $effparm_rec = 1;
1757: }
1.588 raeburn 1758: if ($parmname eq 'deeplink') {
1.601 raeburn 1759: my ($domltistr,$crsltistr);
1.588 raeburn 1760: my %lti =
1761: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 1762: 'linkprot');
1.601 raeburn 1763: if (keys(%lti)) {
1764: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1.604 raeburn 1765: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
1766: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588 raeburn 1767: }
1768: }
1.601 raeburn 1769: $domltistr =~ s/,$//;
1770: if ($domltistr) {
1771: $extra = 'ltid_'.$domltistr;
1772: }
1.588 raeburn 1773: }
1.601 raeburn 1774: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
1775: if (keys(%courselti)) {
1776: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
1777: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
1778: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
1779: }
1780: }
1781: $crsltistr =~ s/,$//;
1782: if ($crsltistr) {
1783: if ($extra) {
1784: $extra .= '&';
1785: }
1786: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 1787: }
1788: }
1.597 raeburn 1789: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
1790: my @colls;
1791: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
1792: my ($num,$value) = split(/\%/,$item);
1793: if ($num =~ /^\d+$/) {
1794: push(@colls,$num);
1795: }
1796: }
1797: if (@colls) {
1798: if ($extra) {
1799: $extra .= '&';
1800: }
1801: $extra .= 'menus_'.join(',',@colls);
1802: }
1803: }
1.588 raeburn 1804: }
1.57 albertel 1805: if ($parmlev eq 'general') {
1806: if ($uname) {
1.588 raeburn 1807: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 1808: } elsif ($cgroup) {
1.588 raeburn 1809: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 1810: } elsif ($csec) {
1.588 raeburn 1811: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1812: } else {
1.588 raeburn 1813: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1814: }
1815: } elsif ($parmlev eq 'map') {
1816: if ($uname) {
1.588 raeburn 1817: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 1818: } elsif ($cgroup) {
1.588 raeburn 1819: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 1820: } elsif ($csec) {
1.588 raeburn 1821: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1822: } else {
1.588 raeburn 1823: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1824: }
1825: } else {
1.275 raeburn 1826: if ($uname) {
1827: if (@{$usersgroups} > 1) {
1.582 raeburn 1828: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 1829: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 1830: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 1831: if (($coursereply) && ($result > 4)) {
1.275 raeburn 1832: if (defined($controlgrp)) {
1833: if ($cgroup ne $controlgrp) {
1.582 raeburn 1834: $eff_groupparm = $grp_parm;
1835: undef($result);
1836: undef($effparm_rec);
1837: if ($grp_is_rec) {
1838: $effparm_rec = 1;
1839: }
1.275 raeburn 1840: }
1841: }
1842: }
1843: }
1844: }
1.57 albertel 1845:
1.588 raeburn 1846: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1847: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1848: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1849: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1850: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1851:
1852: if ($csec) {
1.588 raeburn 1853: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1854: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1855: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1856: }
1.269 raeburn 1857:
1858: if ($cgroup) {
1.588 raeburn 1859: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1860: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1861: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 1862: }
1.446 bisitz 1863:
1.548 raeburn 1864: if ($uname) {
1.275 raeburn 1865: if ($othergrp) {
1866: $r->print($othergrp);
1867: }
1.588 raeburn 1868: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1869: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1870: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1871: }
1.57 albertel 1872: } # end of $parmlev if/else
1.582 raeburn 1873: if (ref($recursinfo) eq 'ARRAY') {
1874: my $rectitle = &mt('recursive');
1875: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
1876: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
1877: $rectitle = &mt('set in: [_1]','"'.
1878: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
1879: "'$parmname','$$part{$which}'".');">'.
1880: $maptitles->{$recursinfo->[2]}.'</a>"');
1881:
1882: $numlinks ++;
1883: }
1884: }
1885: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 1886: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 1887: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1888: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
1889: $effparm_level.'</span></td>');
1890: } else {
1891: if ($result) {
1.593 raeburn 1892: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 1893: }
1894: if ($eff_groupparm) {
1895: $effective_parm = $eff_groupparm;
1896: }
1897: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1898: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
1899: '</span>':'').'</td>');
1900: }
1.203 www 1901: if ($parmlev eq 'full') {
1.136 albertel 1902: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 1903: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 1904: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 1905: if (!defined($sessionvaltype)) {
1906: $sessionvaltype=$$defaulttype{$which};
1907: }
1.419 bisitz 1908: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 1909: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 1910: '</font></td>');
1.136 albertel 1911: }
1.44 albertel 1912: $r->print('</tr>');
1.57 albertel 1913: $r->print("\n");
1.582 raeburn 1914: if (($numlinks) && (ref($reclinks))) {
1915: $$reclinks = $numlinks;
1916: }
1.44 albertel 1917: }
1.59 matthew 1918:
1.561 damieng 1919: # Prints a cell for table mode.
1920: #
1921: # FIXME: some of these parameter names are uninspired ($which and $value)
1922: # Also, it would make more sense to pass the display for this cell rather
1923: # than the full display hash and the key to use.
1924: #
1925: # @param {Apache2::RequestRec} $r - the Apache request
1926: # @param {integer} $which - level
1927: # @param {string} $defbg - cell background color
1928: # @param {integer} $result - the most specific level that is defined for that parameter
1929: # @param {array reference} $outpar - array level -> parameter value (when defined)
1930: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
1931: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
1932: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
1933: # @param {hash reference} $display - parameter key -> full title for the parameter
1934: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 1935: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 1936: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 1937: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 1938: sub print_td {
1.578 raeburn 1939: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 1940: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 1941: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
1942: $ineffect = 0;
1943: $currval = $$outpar[$which];
1944: $currtype = $$typeoutpar[$which];
1945: $currlevel = $which;
1946: if (($result) && ($result == $which)) {
1947: $ineffect = 1;
1948: }
1949: if ($ismaplevel) {
1950: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
1951: if (($result) && ($result == $which)) {
1952: $recursive = 1;
1953: }
1954: } elsif ($$outpar[$which+1] ne '') {
1955: $recursive = 1;
1956: $currlevel = $which+1;
1957: $currval = $$outpar[$currlevel];
1958: $currtype = $$typeoutpar[$currlevel];
1959: if (($result) && ($result == $currlevel)) {
1960: $ineffect = 1;
1961: }
1962: }
1963: }
1964: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 1965: ';" align="center">');
1.437 raeburn 1966: my $nolink = 0;
1.568 raeburn 1967: if ($readonly) {
1.552 raeburn 1968: $nolink = 1;
1.568 raeburn 1969: } else {
1.578 raeburn 1970: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 1971: $nolink = 1;
1.568 raeburn 1972: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 1973: $nolink = 1;
1.568 raeburn 1974: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
1975: if ($noeditgrp) {
1976: $nolink = 1;
1977: }
1978: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 1979: $nolink = 1;
1.568 raeburn 1980: } elsif ($mprefix =~ /examcode\&$/) {
1981: unless ($which == 2) {
1982: $nolink = 1;
1983: }
1.533 raeburn 1984: }
1.437 raeburn 1985: }
1986: if ($nolink) {
1.577 raeburn 1987: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 1988: $r->print(&valout($currval,$currtype));
1.114 www 1989: } else {
1.578 raeburn 1990: $r->print(&plink($currtype,
1991: $$display{$value},$currval,
1.588 raeburn 1992: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
1993: $extra));
1.114 www 1994: }
1995: $r->print('</td>'."\n");
1.57 albertel 1996: }
1997:
1.561 damieng 1998: # Returns HTML and other info for the cell added when a user is selected
1999: # and that user is in several groups. This is the cell with the title "Control by other group".
2000: #
2001: # @param {string} $what - parameter part.'.'.parameter name
2002: # @param {string} $rid - resource id
2003: # @param {string} $cgroup - group name
2004: # @param {string} $defbg - cell background color
2005: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2006: # @param {integer} $result - level
2007: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 2008: # @returns {Array} - array (parameter value for the other group, HTML for the cell, HTML with the value, name of the other group, true if recursive)
1.580 raeburn 2009: sub check_other_groups {
2010: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 2011: my $courseid = $env{'request.course.id'};
2012: my $output;
2013: my $symb = &symbcache($rid);
2014: my $symbparm=$symb.'.'.$what;
2015: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 2016: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 2017: my $mapparm=$map.'___(all).'.$what;
2018: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 2019: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
2020: $recurseparm,$what,$courseopt);
1.275 raeburn 2021: my $bgcolor = $defbg;
1.582 raeburn 2022: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2023: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2024: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2025: if ($result > 3) {
1.419 bisitz 2026: $bgcolor = '#AAFFAA';
1.275 raeburn 2027: }
1.593 raeburn 2028: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2029: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2030: if ($resultgroup && $resultlevel) {
1.582 raeburn 2031: if ($resultlevel eq 'recursive') {
2032: $resultlevel = 'map/folder';
2033: $grp_is_rec = 1;
2034: }
2035: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2036: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2037:
1.275 raeburn 2038: } else {
2039: $output .= ' ';
2040: }
2041: $output .= '</td>';
2042: } else {
1.419 bisitz 2043: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2044: }
1.582 raeburn 2045: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2046: }
2047:
1.561 damieng 2048: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2049: # Used by check_other_groups.
1.561 damieng 2050: #
2051: # @param {string} $courseid - the course id
2052: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2053: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2054: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2055: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2056: # @param {string} $what - parameter part.'.'.parameter name
2057: # @param {hash reference} $courseopt - course parameters hash
2058: # @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 2059: sub parm_control_group {
1.556 raeburn 2060: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2061: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2062: my $grpfound = 0;
1.556 raeburn 2063: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2064: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2065: foreach my $group (@{$usersgroups}) {
2066: if ($grpfound) { last; }
2067: for (my $i=0; $i<@levels; $i++) {
2068: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2069: if (defined($$courseopt{$item})) {
2070: $coursereply = $$courseopt{$item};
2071: $resultitem = $item;
2072: $resultgroup = $group;
2073: $resultlevel = $levelnames[$i];
2074: $resulttype = $$courseopt{$item.'.type'};
2075: $grpfound = 1;
2076: last;
2077: }
2078: }
2079: }
2080: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2081: }
1.201 www 2082:
1.63 bowersj2 2083:
2084:
1.562 damieng 2085: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2086: # All the parameters are references and are filled by the sub.
2087: #
1.566 damieng 2088: # @param {array reference} $ids - resource and map ids
2089: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2090: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2091: # @param {hash reference} $allparms - hash parameter name -> parameter title
2092: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2093: # @param {hash reference} $allmaps - hash map pc -> map src
2094: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2095: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2096: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2097: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2098: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2099: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608 raeburn 2100: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63 bowersj2 2101: sub extractResourceInformation {
2102: my $ids = shift;
2103: my $typep = shift;
2104: my $keyp = shift;
2105: my $allparms = shift;
2106: my $allparts = shift;
2107: my $allmaps = shift;
2108: my $mapp = shift;
2109: my $symbp = shift;
1.82 www 2110: my $maptitles=shift;
1.196 www 2111: my $uris=shift;
1.210 www 2112: my $keyorder=shift;
1.211 www 2113: my $defkeytype=shift;
1.603 raeburn 2114: my $pssymb=shift;
1.196 www 2115:
1.210 www 2116: my $keyordercnt=100;
1.63 bowersj2 2117:
1.196 www 2118: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 raeburn 2119: return unless(ref($navmap));
2120: my @allres;
2121: if ($pssymb ne '') {
2122: my $res = $navmap->getBySymb($pssymb);
2123: if (ref($res)) {
2124: @allres = ($res);
2125: }
2126: }
2127: if (!@allres) {
2128: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
2129: }
1.196 www 2130: foreach my $resource (@allres) {
1.480 amueller 2131: my $id=$resource->id();
1.196 www 2132: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2133: if ($mapid eq '0') { next; }
2134: $$ids[$#$ids+1]=$id;
2135: my $srcf=$resource->src();
2136: $srcf=~/\.(\w+)$/;
2137: $$typep{$id}=$1;
1.584 raeburn 2138: my $toolsymb;
2139: if ($srcf =~ /ext\.tool$/) {
2140: $toolsymb = $resource->symb();
2141: }
1.480 amueller 2142: $$keyp{$id}='';
1.196 www 2143: $$uris{$id}=$srcf;
1.512 foxr 2144:
1.584 raeburn 2145: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2146: next if ($key!~/^parameter_/);
1.363 albertel 2147:
1.209 www 2148: # Hidden parameters
1.584 raeburn 2149: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2150: #
2151: # allparms is a hash of parameter names
2152: #
1.584 raeburn 2153: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2154: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2155: my ($display,$parmdis);
2156: $display = &standard_parameter_names($name);
2157: if ($display eq '') {
1.584 raeburn 2158: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2159: $parmdis = $display;
2160: $parmdis =~ s/\s*\[Part.*$//g;
2161: } else {
2162: $parmdis = &mt($display);
2163: }
2164: $$allparms{$name}=$parmdis;
2165: if (ref($defkeytype)) {
2166: $$defkeytype{$name}=
1.584 raeburn 2167: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2168: }
2169: }
1.363 albertel 2170:
1.209 www 2171: #
2172: # allparts is a hash of all parts
2173: #
1.584 raeburn 2174: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2175: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2176: #
2177: # Remember all keys going with this resource
2178: #
1.480 amueller 2179: if ($$keyp{$id}) {
2180: $$keyp{$id}.=','.$key;
2181: } else {
2182: $$keyp{$id}=$key;
2183: }
1.210 www 2184: #
2185: # Put in order
1.446 bisitz 2186: #
1.480 amueller 2187: unless ($$keyorder{$key}) {
2188: $$keyorder{$key}=$keyordercnt;
2189: $keyordercnt++;
2190: }
1.473 amueller 2191: }
2192:
2193:
1.480 amueller 2194: if (!exists($$mapp{$mapid})) {
2195: $$mapp{$id}=
2196: &Apache::lonnet::declutter($resource->enclosing_map_src());
2197: $$mapp{$mapid}=$$mapp{$id};
2198: $$allmaps{$mapid}=$$mapp{$id};
2199: if ($mapid eq '1') {
1.532 raeburn 2200: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2201: } else {
2202: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2203: }
2204: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2205: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2206: # Lines 1038 and 1114 which use $symbp{$mapid}
2207: # are commented out in rev. 1.57
1.473 amueller 2208: } else {
1.480 amueller 2209: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2210: }
1.480 amueller 2211: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2212: }
2213: }
2214:
1.582 raeburn 2215: sub get_recursive {
2216: my ($recurseup,$resdata,$what,$prefix) = @_;
2217: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2218: foreach my $item (@{$recurseup}) {
2219: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2220: if (defined($resdata->{$norecursechk})) {
2221: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2222: my $type = $resdata->{$norecursechk.'.type'};
2223: return [$resdata->{$norecursechk},$type,$item];
2224: } else {
2225: last;
2226: }
2227: }
2228: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2229: if (defined($resdata->{$recursechk})) {
2230: my $type = $resdata->{$recursechk.'.type'};
2231: return [$resdata->{$recursechk},$type,$item];
2232: }
2233: }
2234: }
2235: return;
2236: }
2237:
1.208 www 2238:
1.562 damieng 2239: # Tells if a parameter type is a date.
2240: #
2241: # @param {string} type - parameter type
2242: # @returns{boolean} - true if it is a date
1.213 www 2243: sub isdateparm {
2244: my $type=shift;
2245: return (($type=~/^date/) && (!($type eq 'date_interval')));
2246: }
2247:
1.589 raeburn 2248: # Determine if parameter type is specialized string type (i.e.,
2249: # not just string or string_yesno.
2250:
2251: sub is_specialstring {
2252: my $type=shift;
1.603 raeburn 2253: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2254: }
2255:
1.562 damieng 2256: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2257: #
1.581 raeburn 2258: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2259: sub parmmenu {
1.581 raeburn 2260: my ($r)=@_;
1.208 www 2261: $r->print(<<ENDSCRIPT);
2262: <script type="text/javascript">
1.454 bisitz 2263: // <![CDATA[
1.208 www 2264: function checkall(value, checkName) {
1.453 schualex 2265:
2266: var li = "_li";
2267: var displayOverview = "";
2268:
2269: if (value == false) {
2270: displayOverview = "none"
2271: }
2272:
1.562 damieng 2273: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2274: ele = document.forms.parmform.elements[i];
2275: if (ele.name == checkName) {
2276: document.forms.parmform.elements[i].checked=value;
2277: }
2278: }
2279: }
1.210 www 2280:
2281: function checkthis(thisvalue, checkName) {
1.562 damieng 2282: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2283: ele = document.forms.parmform.elements[i];
2284: if (ele.name == checkName) {
1.562 damieng 2285: if (ele.value == thisvalue) {
2286: document.forms.parmform.elements[i].checked=true;
2287: }
1.210 www 2288: }
2289: }
2290: }
2291:
2292: function checkdates() {
1.562 damieng 2293: checkthis('duedate','pscat');
2294: checkthis('opendate','pscat');
2295: checkthis('answerdate','pscat');
1.218 www 2296: }
2297:
2298: function checkdisset() {
1.562 damieng 2299: checkthis('discussend','pscat');
2300: checkthis('discusshide','pscat');
2301: checkthis('discussvote','pscat');
1.218 www 2302: }
2303:
2304: function checkcontdates() {
1.562 damieng 2305: checkthis('contentopen','pscat');
2306: checkthis('contentclose','pscat');
1.218 www 2307: }
1.446 bisitz 2308:
1.210 www 2309: function checkvisi() {
1.562 damieng 2310: checkthis('hiddenresource','pscat');
2311: checkthis('encrypturl','pscat');
2312: checkthis('problemstatus','pscat');
2313: checkthis('contentopen','pscat');
2314: checkthis('opendate','pscat');
1.210 www 2315: }
2316:
2317: function checkparts() {
1.562 damieng 2318: checkthis('hiddenparts','pscat');
2319: checkthis('display','pscat');
2320: checkthis('ordered','pscat');
1.210 www 2321: }
2322:
2323: function checkstandard() {
2324: checkall(false,'pscat');
1.562 damieng 2325: checkdates();
2326: checkthis('weight','pscat');
2327: checkthis('maxtries','pscat');
2328: checkthis('type','pscat');
2329: checkthis('problemstatus','pscat');
1.210 www 2330: }
2331:
1.454 bisitz 2332: // ]]>
1.208 www 2333: </script>
2334: ENDSCRIPT
1.453 schualex 2335:
1.491 bisitz 2336: $r->print('<hr />');
1.581 raeburn 2337: &shortCuts($r);
1.491 bisitz 2338: $r->print('<hr />');
1.453 schualex 2339: }
1.562 damieng 2340:
2341: # Returns parameter categories.
2342: #
2343: # @returns {hash} - category name -> title in English
1.465 amueller 2344: sub categories {
2345: return ('time_settings' => 'Time Settings',
2346: 'grading' => 'Grading',
2347: 'tries' => 'Tries',
2348: 'problem_appearance' => 'Problem Appearance',
2349: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2350: 'hiding' => 'Hiding',
2351: 'high_level_randomization' => 'High Level Randomization',
2352: 'slots' => 'Slots',
2353: 'file_submission' => 'File Submission',
2354: 'misc' => 'Miscellaneous' );
2355: }
2356:
1.562 damieng 2357: # Returns the category for each parameter.
2358: #
2359: # @returns {hash} - parameter name -> category name
1.465 amueller 2360: sub lookUpTableParameter {
2361:
2362: return (
2363: 'opendate' => 'time_settings',
2364: 'duedate' => 'time_settings',
2365: 'answerdate' => 'time_settings',
2366: 'interval' => 'time_settings',
2367: 'contentopen' => 'time_settings',
2368: 'contentclose' => 'time_settings',
2369: 'discussend' => 'time_settings',
1.560 damieng 2370: 'printstartdate' => 'time_settings',
2371: 'printenddate' => 'time_settings',
1.465 amueller 2372: 'weight' => 'grading',
2373: 'handgrade' => 'grading',
2374: 'maxtries' => 'tries',
2375: 'hinttries' => 'tries',
1.503 raeburn 2376: 'randomizeontries' => 'tries',
1.465 amueller 2377: 'type' => 'problem_appearance',
2378: 'problemstatus' => 'problem_appearance',
2379: 'display' => 'problem_appearance',
2380: 'ordered' => 'problem_appearance',
2381: 'numbubbles' => 'problem_appearance',
2382: 'tol' => 'behaviour_of_input_fields',
2383: 'sig' => 'behaviour_of_input_fields',
2384: 'turnoffunit' => 'behaviour_of_input_fields',
2385: 'hiddenresource' => 'hiding',
2386: 'hiddenparts' => 'hiding',
2387: 'discusshide' => 'hiding',
2388: 'buttonshide' => 'hiding',
2389: 'turnoffeditor' => 'hiding',
2390: 'encrypturl' => 'hiding',
1.587 raeburn 2391: 'deeplink' => 'hiding',
1.465 amueller 2392: 'randomorder' => 'high_level_randomization',
2393: 'randompick' => 'high_level_randomization',
2394: 'available' => 'slots',
2395: 'useslots' => 'slots',
2396: 'availablestudent' => 'slots',
2397: 'uploadedfiletypes' => 'file_submission',
2398: 'maxfilesize' => 'file_submission',
2399: 'cssfile' => 'misc',
2400: 'mapalias' => 'misc',
2401: 'acc' => 'misc',
2402: 'maxcollaborators' => 'misc',
2403: 'scoreformat' => 'misc',
1.514 raeburn 2404: 'lenient' => 'grading',
1.519 raeburn 2405: 'retrypartial' => 'tries',
1.521 raeburn 2406: 'discussvote' => 'misc',
1.584 raeburn 2407: 'examcode' => 'high_level_randomization',
1.575 raeburn 2408: );
1.465 amueller 2409: }
2410:
1.562 damieng 2411: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2412: #
2413: # @param {string} $name - parameter name
2414: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2415: sub whatIsMyCategory {
2416: my $name = shift;
2417: my $catList = shift;
2418: my @list;
2419: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2420: my $cat = $lookUpList{$name};
2421: if (defined($cat)) {
2422: if (!defined($$catList{$cat})){
2423: push @list, ($name);
2424: $$catList{$cat} = \@list;
2425: } else {
2426: push @{${$catList}{$cat}}, ($name);
2427: }
2428: } else {
2429: if (!defined($$catList{'misc'})){
2430: push @list, ($name);
2431: $$catList{'misc'} = \@list;
2432: } else {
2433: push @{${$catList}{'misc'}}, ($name);
2434: }
2435: }
2436: }
2437:
1.562 damieng 2438: # Sorts parameter names based on appearance order.
2439: #
2440: # @param {array reference} name - array reference of parameter names
2441: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2442: # @returns {Array} - array of parameter names
1.465 amueller 2443: sub keysindisplayorderCategory {
2444: my ($name,$keyorder)=@_;
2445: return sort {
1.473 amueller 2446: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2447: } ( @{$name});
2448: }
2449:
1.562 damieng 2450: # Returns a hash category name -> order, starting at 1 (integer)
2451: #
2452: # @returns {hash}
1.467 amueller 2453: sub category_order {
2454: return (
2455: 'time_settings' => 1,
2456: 'grading' => 2,
2457: 'tries' => 3,
2458: 'problem_appearance' => 4,
2459: 'hiding' => 5,
2460: 'behaviour_of_input_fields' => 6,
2461: 'high_level_randomization' => 7,
2462: 'slots' => 8,
2463: 'file_submission' => 9,
2464: 'misc' => 10
2465: );
2466:
2467: }
1.453 schualex 2468:
1.562 damieng 2469: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2470: #
2471: # @param {Apache2::RequestRec} $r - the Apache request
2472: # @param {hash reference} $allparms - hash parameter name -> parameter title
2473: # @param {array reference} $pscat - list of selected parameter names
2474: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2475: sub parmboxes {
2476: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2477: my %categories = &categories();
1.467 amueller 2478: my %category_order = &category_order();
1.465 amueller 2479: my %categoryList = (
2480: 'time_settings' => [],
2481: 'grading' => [],
2482: 'tries' => [],
2483: 'problem_appearance' => [],
2484: 'behaviour_of_input_fields' => [],
2485: 'hiding' => [],
2486: 'high_level_randomization' => [],
2487: 'slots' => [],
2488: 'file_submission' => [],
2489: 'misc' => [],
1.489 bisitz 2490: );
1.510 www 2491:
1.548 raeburn 2492: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2493: &whatIsMyCategory($tempparameter, \%categoryList);
2494: }
1.453 schualex 2495: #part to print the parm-list
1.536 raeburn 2496: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2497: next if (@{$categoryList{$key}} == 0);
2498: next if ($key eq '');
2499: $r->print('<div class="LC_Box LC_400Box">'
2500: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2501: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2502: next if ($tempkey eq '');
1.536 raeburn 2503: $r->print('<span class="LC_nobreak">'
2504: .'<label><input type="checkbox" name="pscat" '
2505: .'value="'.$tempkey.'" ');
2506: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2507: $r->print( ' checked="checked"');
2508: }
2509: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465 amueller 2510: : $tempkey)
1.536 raeburn 2511: .'</label></span><br />'."\n");
1.465 amueller 2512: }
1.536 raeburn 2513: $r->print('</div>');
1.465 amueller 2514: }
1.536 raeburn 2515: $r->print("\n");
1.453 schualex 2516: }
1.562 damieng 2517:
2518: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2519: #
1.562 damieng 2520: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2521: sub shortCuts {
1.581 raeburn 2522: my ($r)=@_;
1.453 schualex 2523:
1.491 bisitz 2524: # Parameter Selection
2525: $r->print(
2526: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2527: .&Apache::lonhtmlcommon::add_item_funclist(
2528: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2529: .&Apache::lonhtmlcommon::add_item_funclist(
2530: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2531: .&Apache::lonhtmlcommon::add_item_funclist(
2532: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2533: .&Apache::lonhtmlcommon::end_funclist()
2534: );
2535:
2536: # Add Selection for...
2537: $r->print(
2538: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2539: .&Apache::lonhtmlcommon::add_item_funclist(
2540: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2541: .&Apache::lonhtmlcommon::add_item_funclist(
2542: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2543: .&Apache::lonhtmlcommon::add_item_funclist(
2544: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2545: .&Apache::lonhtmlcommon::add_item_funclist(
2546: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2547: .&Apache::lonhtmlcommon::add_item_funclist(
2548: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2549: .&Apache::lonhtmlcommon::end_funclist()
2550: );
1.208 www 2551: }
2552:
1.562 damieng 2553: # Prints HTML to select parts to view (except for the title).
2554: # Used by table and overview modes.
2555: #
2556: # @param {Apache2::RequestRec} $r - the Apache request
2557: # @param {hash reference} $allparts - hash parameter part -> part title
2558: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2559: sub partmenu {
1.446 bisitz 2560: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2561: my $selsize = 1+scalar(keys(%{$allparts}));
2562: if ($selsize > 8) {
2563: $selsize = 8;
2564: }
1.446 bisitz 2565:
1.523 raeburn 2566: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2567: $r->print('<option value="all"');
1.562 damieng 2568: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2569: $r->print('>'.&mt('All Parts').'</option>');
2570: my %temphash=();
2571: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2572: foreach my $tempkey (sort {
1.560 damieng 2573: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2574: } keys(%{$allparts})) {
2575: unless ($tempkey =~ /\./) {
2576: $r->print('<option value="'.$tempkey.'"');
2577: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2578: $r->print(' selected="selected"');
2579: }
2580: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2581: }
1.208 www 2582: }
1.446 bisitz 2583: $r->print('</select>');
1.209 www 2584: }
2585:
1.562 damieng 2586: # Prints HTML to select a user and/or a group.
2587: # Used by table mode.
2588: #
2589: # @param {Apache2::RequestRec} $r - the Apache request
2590: # @param {string} $uname - selected user name
2591: # @param {string} $id - selected Student/Employee ID
2592: # @param {string} $udom - selected user domain
2593: # @param {string} $csec - selected section name
2594: # @param {string} $cgroup - selected group name
2595: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2596: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2597: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2598: sub usermenu {
1.553 raeburn 2599: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2600: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2601: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2602: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2603: function setCourseadv(form,caller) {
2604: if (caller.value == 'st') {
2605: form.courseadv.value = 'none';
2606: } else {
2607: form.courseadv.value = '';
2608: }
2609: return;
2610: }
2611: ENDJS
1.412 bisitz 2612:
1.596 raeburn 2613: my (%chkroles,$stuonly,$courseadv);
2614: if ($env{'form.userroles'} eq 'any') {
2615: $chkroles{'any'} = ' checked="checked"';
2616: } else {
2617: $chkroles{'st'} = ' checked="checked"';
2618: $courseadv = 'none';
2619: }
2620: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2621: if ($crstype eq 'Community') {
2622: $stuonly = &mt('member only');
2623: } else {
2624: $stuonly = &mt('student only');
2625: }
2626: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2627: &mt("User's role").': '.
2628: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2629: $stuonly.'</label> '.
2630: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2631: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2632: my $sections='';
1.300 albertel 2633: my %sectionhash = &Apache::loncommon::get_sections();
2634:
1.269 raeburn 2635: my $groups;
1.553 raeburn 2636: my %grouphash;
2637: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2638: %grouphash = &Apache::longroup::coursegroups();
2639: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2640: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2641: }
1.299 albertel 2642:
1.412 bisitz 2643: my $g_s_header='';
2644: my $g_s_footer='';
1.446 bisitz 2645:
1.552 raeburn 2646: my $currsec = $env{'request.course.sec'};
2647: if ($currsec) {
2648: $sections=&mt('Section:').' '.$currsec;
2649: if (%grouphash) {
2650: $sections .= ';'.(' ' x2);
2651: }
2652: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2653: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2654: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2655: $sections .= qq| onchange="group_or_section('csec')" |;
2656: }
2657: $sections .= '>';
1.548 raeburn 2658: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2659: $sections.='<option value="'.$section.'" '.
2660: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2661: '</option>';
1.209 www 2662: }
2663: $sections.='</select>';
1.269 raeburn 2664: }
1.412 bisitz 2665:
1.552 raeburn 2666: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2667: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2668: $sections .= qq|
2669: <script type="text/javascript">
1.454 bisitz 2670: // <![CDATA[
1.269 raeburn 2671: function group_or_section(caller) {
2672: if (caller == "cgroup") {
2673: if (document.parmform.cgroup.selectedIndex != 0) {
2674: document.parmform.csec.selectedIndex = 0;
2675: }
2676: } else {
2677: if (document.parmform.csec.selectedIndex != 0) {
2678: document.parmform.cgroup.selectedIndex = 0;
2679: }
2680: }
2681: }
1.454 bisitz 2682: // ]]>
1.269 raeburn 2683: </script>
2684: |;
1.554 raeburn 2685: } else {
1.269 raeburn 2686: $sections .= qq|
2687: <script type="text/javascript">
1.454 bisitz 2688: // <![CDATA[
1.269 raeburn 2689: function group_or_section(caller) {
2690: return;
2691: }
1.454 bisitz 2692: // ]]>
1.269 raeburn 2693: </script>
2694: |;
1.446 bisitz 2695: }
1.299 albertel 2696:
2697: if (%grouphash) {
1.597 raeburn 2698: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2699: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2700: $groups .= qq| onchange="group_or_section('cgroup')" |;
2701: }
2702: $groups .= '>';
1.548 raeburn 2703: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2704: $groups.='<option value="'.$grp.'" ';
2705: if ($grp eq $cgroup) {
2706: unless ((defined($uname)) && ($grp eq '')) {
2707: $groups .= 'selected="selected" ';
2708: }
2709: } elsif (!defined($cgroup)) {
2710: if (@{$usersgroups} == 1) {
2711: if ($grp eq $$usersgroups[0]) {
2712: $groups .= 'selected="selected" ';
2713: }
2714: }
2715: }
2716: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2717: }
2718: $groups.='</select>';
2719: }
1.412 bisitz 2720:
1.445 neumanie 2721: if (%sectionhash || %grouphash) {
1.446 bisitz 2722: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2723: $r->print($sections.$groups);
1.448 bisitz 2724: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 2725: } else {
2726: $r->print($sections);
1.445 neumanie 2727: }
1.446 bisitz 2728:
2729: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 2730: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 2731: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
2732: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 2733: ,$chooseopt));
1.209 www 2734: }
2735:
1.562 damieng 2736: # Prints HTML to select parameters from a list of all parameters.
2737: # Uses parmmenu and parmboxes.
2738: # Used by table and overview modes.
1.468 amueller 2739: #
1.562 damieng 2740: # @param {Apache2::RequestRec} $r - the Apache request
2741: # @param {hash reference} $allparms - hash parameter name -> parameter title
2742: # @param {array reference} $pscat - list of selected parameter names
2743: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2744: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 2745: sub displaymenu {
1.581 raeburn 2746: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 2747:
1.445 neumanie 2748: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 2749: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
2750:
1.581 raeburn 2751: &parmmenu($r);
1.536 raeburn 2752: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 2753: &parmboxes($r,$allparms,$pscat,$keyorder);
2754: $r->print(&Apache::loncommon::end_scrollbox());
2755:
2756: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 2757: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 2758:
1.209 www 2759: }
2760:
1.562 damieng 2761: # Prints HTML to select a map.
2762: # Used by table mode and overview mode.
2763: #
2764: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 2765: # @param {hash reference} $allmaps - hash map pc -> map src
2766: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 2767: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 2768: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610 raeburn 2769: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445 neumanie 2770: sub mapmenu {
1.610 raeburn 2771: my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468 amueller 2772: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 2773: my $navmap = Apache::lonnavmaps::navmap->new();
2774: my $tree=[];
2775: my $treeinfo={};
2776: if (defined($navmap)) {
1.499 raeburn 2777: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 2778: my $curRes;
2779: my $depth = 0;
1.468 amueller 2780: my %parent = ();
2781: my $startcount = 5;
2782: my $lastcontainer = $startcount;
2783: # preparing what is to show ...
1.461 neumanie 2784: while ($curRes = $it->next()) {
2785: if ($curRes == $it->BEGIN_MAP()) {
2786: $depth++;
1.468 amueller 2787: $parent{$depth}= $lastcontainer;
1.461 neumanie 2788: }
2789: if ($curRes == $it->END_MAP()) {
2790: $depth--;
1.468 amueller 2791: $lastcontainer = $parent{$depth};
1.461 neumanie 2792: }
2793: if (ref($curRes)) {
1.468 amueller 2794: my $symb = $curRes->symb();
2795: my $ressymb = $symb;
1.461 neumanie 2796: if (($curRes->is_sequence()) || ($curRes->is_page())) {
2797: my $type = 'sequence';
2798: if ($curRes->is_page()) {
2799: $type = 'page';
2800: }
2801: my $id= $curRes->id();
1.468 amueller 2802: my $srcf = $curRes->src();
2803: my $resource_name = &Apache::lonnet::gettitle($srcf);
2804: if(!exists($treeinfo->{$id})) {
2805: push(@$tree,$id);
1.473 amueller 2806: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 2807: $treeinfo->{$id} = {
1.461 neumanie 2808: depth => $depth,
2809: type => $type,
1.468 amueller 2810: name => $resource_name,
2811: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 2812: };
1.462 neumanie 2813: }
1.461 neumanie 2814: }
2815: }
2816: }
1.462 neumanie 2817: }
1.473 amueller 2818: # Show it ...
1.610 raeburn 2819: my $rowattr = ' id="mapmenu"';
2820: if ($parmlev eq 'general') {
2821: $rowattr .= ' style="display:none"';
2822: }
2823: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461 neumanie 2824: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
2825: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 2826: my $whitespace =
2827: '<img src="'
2828: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
2829: .'" alt="" />';
2830:
1.498 bisitz 2831: # Info about selectable folders/maps
2832: $r->print(
2833: '<div class="LC_info">'
1.508 www 2834: .&mt('You can only select maps and folders which have modifiable settings.')
2835: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 2836: .'</div>'
2837: );
2838:
1.536 raeburn 2839: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 2840: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 2841:
1.498 bisitz 2842: # Display row: "All Maps or Folders"
2843: $r->print(
1.523 raeburn 2844: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 2845: .'<td>'
2846: .'<label>'
2847: .'<input type="radio" name="pschp"'
1.497 bisitz 2848: );
2849: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 2850: $r->print(
2851: ' value="all" /> '.$icon.' '
2852: .&mt('All Maps or Folders')
2853: .'</label>'
2854: .'<hr /></td>'
2855: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2856: );
1.497 bisitz 2857:
1.532 raeburn 2858: # Display row: "Main Content"
1.468 amueller 2859: if (exists($$allmaps{1})) {
1.498 bisitz 2860: $r->print(
2861: &Apache::loncommon::start_data_table_row()
2862: .'<td>'
2863: .'<label>'
2864: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 2865: );
1.497 bisitz 2866: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 2867: $r->print(
2868: '/> '.$icon.' '
2869: .$$maptitles{1}
2870: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
2871: .'</label>'
2872: .'</td>'
2873: .&Apache::loncommon::end_data_table_row()
1.468 amueller 2874: );
2875: }
1.497 bisitz 2876:
2877: # Display rows for all course maps and folders
1.468 amueller 2878: foreach my $id (@{$tree}) {
2879: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 2880: # Indentation
1.468 amueller 2881: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 2882: my $indent;
2883: for (my $i = 0; $i < $depth; $i++) {
2884: $indent.= $whitespace;
2885: }
1.461 neumanie 2886: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 2887: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 2888: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
2889: }
1.468 amueller 2890: my $symb_name = $$symbp{$id};
2891: my ($front, $tail) = split (/___${resid}___/, $symb_name);
2892: $symb_name = $tail;
1.498 bisitz 2893: $r->print(
2894: &Apache::loncommon::start_data_table_row()
2895: .'<td>'
2896: .'<label>'
1.463 bisitz 2897: );
1.498 bisitz 2898: # Only offer radio button for folders/maps which can be parameterized
2899: if ($allmaps_inverted{$symb_name}) {
2900: $r->print(
2901: '<input type ="radio" name="pschp"'
2902: .' value="'.$allmaps_inverted{$symb_name}.'"'
2903: );
2904: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
2905: $r->print('/>');
2906: } else {
2907: $r->print($whitespace);
1.461 neumanie 2908: }
1.498 bisitz 2909: $r->print(
2910: $indent.$icon.' '
2911: .$treeinfo->{$id}->{name}
2912: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
2913: .'</label>'
2914: .'</td>'
2915: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2916: );
1.461 neumanie 2917: }
1.497 bisitz 2918:
1.523 raeburn 2919: $r->print(&Apache::loncommon::end_data_table().
2920: '<br style="line-height:2px;" />'.
2921: &Apache::loncommon::end_scrollbox());
1.209 www 2922: }
2923: }
2924:
1.563 damieng 2925: # Prints HTML to select the parameter level (resource, map/folder or course).
2926: # Used by table and overview modes.
2927: #
2928: # @param {Apache2::RequestRec} $r - the Apache request
2929: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
2930: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 2931: sub levelmenu {
1.446 bisitz 2932: my ($r,$alllevs,$parmlev)=@_;
2933:
1.548 raeburn 2934: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
2935: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 2936: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 2937: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
2938: $r->print('<option value="'.$$alllevs{$lev}.'"');
2939: if ($parmlev eq $$alllevs{$lev}) {
2940: $r->print(' selected="selected"');
2941: }
2942: $r->print('>'.&mt($lev).'</option>');
1.208 www 2943: }
1.446 bisitz 2944: $r->print("</select>");
1.208 www 2945: }
2946:
1.211 www 2947:
1.563 damieng 2948: # Returns HTML to select a section (with a select HTML element).
2949: # Used by overview mode.
2950: #
2951: # @param {array reference} $selectedsections - list of selected section ids
2952: # @returns {string}
1.211 www 2953: sub sectionmenu {
1.553 raeburn 2954: my ($selectedsections)=@_;
1.300 albertel 2955: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 2956: return '' if (!%sectionhash);
1.300 albertel 2957:
1.552 raeburn 2958: my (@possibles,$disabled);
2959: if ($env{'request.course.sec'} ne '') {
2960: @possibles = ($env{'request.course.sec'});
2961: $selectedsections = [$env{'request.course.sec'}];
2962: $disabled = ' disabled="disabled"';
2963: } else {
2964: @possibles = ('all',sort(keys(%sectionhash)));
2965: }
1.553 raeburn 2966: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 2967: foreach my $s (@possibles) {
1.553 raeburn 2968: $output .= ' <option value="'.$s.'"';
2969: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
2970: $output .= ' selected="selected"';
1.473 amueller 2971: }
1.553 raeburn 2972: $output .= '>'."$s</option>\n";
1.300 albertel 2973: }
1.553 raeburn 2974: $output .= "</select>\n";
2975: return $output;
1.269 raeburn 2976: }
2977:
1.563 damieng 2978: # Returns HTML to select a group (with a select HTML element).
2979: # Used by overview mode.
2980: #
2981: # @param {array reference} $selectedgroups - list of selected group names
2982: # @returns {string}
1.269 raeburn 2983: sub groupmenu {
1.553 raeburn 2984: my ($selectedgroups)=@_;
2985: my %grouphash;
2986: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2987: %grouphash = &Apache::longroup::coursegroups();
2988: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2989: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2990: }
2991: return '' if (!%grouphash);
1.299 albertel 2992:
1.553 raeburn 2993: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 2994: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 2995: $output .= ' <option value="'.$group.'"';
2996: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
2997: $output .= ' selected="selected"';
1.473 amueller 2998: }
1.553 raeburn 2999: $output .= '>'."$group</option>\n";
1.211 www 3000: }
1.553 raeburn 3001: $output .= "</select>\n";
3002: return $output;
1.211 www 3003: }
3004:
1.563 damieng 3005: # Returns an array with the given parameter split by comma.
3006: # Used by assessparms (table mode).
3007: #
3008: # @param {string} $keyp - the string to split
3009: # @returns {Array<string>}
1.210 www 3010: sub keysplit {
3011: my $keyp=shift;
3012: return (split(/\,/,$keyp));
3013: }
3014:
1.563 damieng 3015: # Returns the keys in $name, sorted using $keyorder.
3016: # Parameters are sorted by key, which means they are sorted by part first, then by name.
3017: # Used by assessparms (table mode) for resource level.
3018: #
3019: # @param {hash reference} $name - parameter key -> parameter name
3020: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3021: # @returns {Array<string>}
1.210 www 3022: sub keysinorder {
3023: my ($name,$keyorder)=@_;
3024: return sort {
1.560 damieng 3025: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 3026: } (keys(%{$name}));
1.210 www 3027: }
3028:
1.563 damieng 3029: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3030: # Used by assessparms (table mode) for map and general levels.
3031: #
3032: # @param {hash reference} $name - parameter key -> parameter name
3033: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3034: # @returns {Array<string>}
1.236 albertel 3035: sub keysinorder_bytype {
3036: my ($name,$keyorder)=@_;
3037: return sort {
1.563 damieng 3038: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3039: my $tb=(split('_',$b))[-1];
3040: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3041: return ($a cmp $b);
3042: }
3043: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3044: } (keys(%{$name}));
1.236 albertel 3045: }
3046:
1.563 damieng 3047: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3048: # Used by defaultsetter (parameter settings default actions).
3049: #
3050: # @param {hash reference} $name - hash parameter name -> parameter title
3051: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3052: # @returns {Array<string>}
1.211 www 3053: sub keysindisplayorder {
3054: my ($name,$keyorder)=@_;
3055: return sort {
1.560 damieng 3056: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3057: } (keys(%{$name}));
1.211 www 3058: }
3059:
1.563 damieng 3060: # Prints HTML with a choice to sort results by realm or student first.
3061: # Used by overview mode.
3062: #
3063: # @param {Apache2::RequestRec} $r - the Apache request
3064: # @param {string} $sortorder - realmstudent|studentrealm
1.608 raeburn 3065: # @param {string} $context - newoverview|overview
1.214 www 3066: sub sortmenu {
1.608 raeburn 3067: my ($r,$sortorder,$context)=@_;
3068: my %text;
3069: if ($context eq 'newoverview') {
3070: %text = &Apache::lonlocal::texthash (
3071: realmstudent => 'Sort by location in course first, then student (group/section)',
3072: studentrealm => 'Sort by student (group/section) first, then location in course',
3073: );
3074: } else {
3075: %text = &Apache::lonlocal::texthash (
3076: realmstudent => 'Sort by realm first, then student (group/section)',
3077: studentrealm => 'Sort by student (group/section) first, then realm',
3078: );
1.214 www 3079: }
1.608 raeburn 3080: my %sortchecked = (
3081: realmstudent => ' checked="checked"',
3082: studentrealm => '',
3083: );
1.214 www 3084: if ($sortorder eq 'studentrealm') {
1.608 raeburn 3085: $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
3086: $sortchecked{'realmstudent'} = '';
3087: }
3088: foreach my $sorttype ('realmstudent','studentrealm') {
3089: $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
3090: $text{$sorttype}.'</label>');
1.214 www 3091: }
3092: }
3093:
1.563 damieng 3094: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3095: #
3096: # @returns {hash}
1.211 www 3097: sub standardkeyorder {
3098: return ('parameter_0_opendate' => 1,
1.473 amueller 3099: 'parameter_0_duedate' => 2,
3100: 'parameter_0_answerdate' => 3,
3101: 'parameter_0_interval' => 4,
3102: 'parameter_0_weight' => 5,
3103: 'parameter_0_maxtries' => 6,
3104: 'parameter_0_hinttries' => 7,
3105: 'parameter_0_contentopen' => 8,
3106: 'parameter_0_contentclose' => 9,
3107: 'parameter_0_type' => 10,
3108: 'parameter_0_problemstatus' => 11,
3109: 'parameter_0_hiddenresource' => 12,
3110: 'parameter_0_hiddenparts' => 13,
3111: 'parameter_0_display' => 14,
3112: 'parameter_0_ordered' => 15,
3113: 'parameter_0_tol' => 16,
3114: 'parameter_0_sig' => 17,
3115: 'parameter_0_turnoffunit' => 18,
1.521 raeburn 3116: 'parameter_0_discussend' => 19,
3117: 'parameter_0_discusshide' => 20,
3118: 'parameter_0_discussvote' => 21,
1.560 damieng 3119: 'parameter_0_printstartdate' => 22,
3120: 'parameter_0_printenddate' => 23);
1.211 www 3121: }
3122:
1.59 matthew 3123:
1.560 damieng 3124: # Table mode UI.
1.563 damieng 3125: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3126: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3127: #
3128: # Parameters used from the request:
3129: # action - handler action (see handler), usermenu is checking for value 'settable'
3130: # cgroup - selected group
3131: # command - 'set': direct access to table mode for a resource
3132: # csec - selected section
3133: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3134: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3135: # id - student/employee ID
3136: # parmlev - selected level (full|map|general)
3137: # part - selected part (unused ?)
3138: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3139: # pres_type - &&&-separated parameter types
3140: # pres_value - &&&-separated parameter values
3141: # prevvisit - '1' if the user has submitted the form before
3142: # pscat (multiple values) - selected parameter names
1.566 damieng 3143: # pschp - selected map pc, or 'all'
1.563 damieng 3144: # psprt (multiple values) - list of selected parameter parts
3145: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3146: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3147: # symb - resource symb (when a single resource is selected)
3148: # udom - selected user domain
3149: # uname - selected user name
3150: # url - used only with command 'set', the resource url
3151: #
3152: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3153: # @param $parm_permission - ref to hash of permissions
3154: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3155: sub assessparms {
1.1 www 3156:
1.568 raeburn 3157: my ($r,$parm_permission) = @_;
1.201 www 3158:
1.512 foxr 3159:
3160: # -------------------------------------------------------- Variable declaration
1.566 damieng 3161: my @ids=(); # resource and map ids
3162: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3163: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3164: my %typep=(); # hash resource/map id -> resource type (file extension)
3165: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3166: my %uris=(); # hash resource/map id -> resource src
3167: my %maptitles=(); # hash map pc or src -> map title
3168: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3169: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3170: my %alllevs=(); # hash English level title -> value
3171:
3172: my $uname; # selected user name
3173: my $udom; # selected user domain
3174: my $uhome; # server with the user's files, or 'no_host'
3175: my $csec; # selected section name
3176: my $cgroup; # selected group name
3177: my @usersgroups = (); # list of the user groups
1.582 raeburn 3178: my $numreclinks = 0;
1.446 bisitz 3179:
1.190 albertel 3180: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3181:
1.57 albertel 3182: $alllevs{'Resource Level'}='full';
1.215 www 3183: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3184: $alllevs{'Course Level'}='general';
3185:
1.563 damieng 3186: my %allparms; # hash parameter name -> parameter title
3187: my %allparts; # hash parameter part -> part title
1.512 foxr 3188: # ------------------------------------------------------------------------------
3189:
1.210 www 3190: #
3191: # Order in which these parameters will be displayed
3192: #
1.211 www 3193: my %keyorder=&standardkeyorder();
3194:
1.512 foxr 3195: # @ids=();
3196: # %symbp=(); # These seem defined above already.
3197: # %typep=();
1.43 albertel 3198:
3199: my $message='';
3200:
1.190 albertel 3201: $csec=$env{'form.csec'};
1.552 raeburn 3202: if ($env{'request.course.sec'} ne '') {
3203: $csec = $env{'request.course.sec'};
3204: }
3205:
1.553 raeburn 3206: # Check group privs.
1.269 raeburn 3207: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3208: my $noeditgrp;
3209: if ($cgroup ne '') {
3210: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3211: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3212: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3213: $noeditgrp = 1;
3214: }
3215: }
3216: }
1.188 www 3217:
1.190 albertel 3218: if ($udom=$env{'form.udom'}) {
3219: } elsif ($udom=$env{'request.role.domain'}) {
3220: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3221: } else {
1.473 amueller 3222: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3223: }
1.468 amueller 3224:
1.43 albertel 3225:
1.134 albertel 3226: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3227: my $pschp=$env{'form.pschp'};
1.506 www 3228:
3229:
1.134 albertel 3230: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3231: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3232: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3233:
1.43 albertel 3234: my $pssymb='';
1.57 albertel 3235: my $parmlev='';
1.446 bisitz 3236:
1.190 albertel 3237: unless ($env{'form.parmlev'}) {
1.57 albertel 3238: $parmlev = 'map';
3239: } else {
1.190 albertel 3240: $parmlev = $env{'form.parmlev'};
1.57 albertel 3241: }
1.26 www 3242:
1.29 www 3243: # ----------------------------------------------- Was this started from grades?
3244:
1.560 damieng 3245: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3246: (!$env{'form.dis'})) {
1.473 amueller 3247: my $url=$env{'form.url'};
3248: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3249: $pssymb=&Apache::lonnet::symbread($url);
3250: if (!@pscat) { @pscat=('all'); }
3251: $pschp='';
1.57 albertel 3252: $parmlev = 'full';
1.190 albertel 3253: } elsif ($env{'form.symb'}) {
1.473 amueller 3254: $pssymb=$env{'form.symb'};
3255: if (!@pscat) { @pscat=('all'); }
3256: $pschp='';
1.57 albertel 3257: $parmlev = 'full';
1.43 albertel 3258: } else {
1.473 amueller 3259: $env{'form.url'}='';
1.43 albertel 3260: }
3261:
1.190 albertel 3262: my $id=$env{'form.id'};
1.43 albertel 3263: if (($id) && ($udom)) {
1.555 raeburn 3264: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3265: if ($uname) {
3266: $id='';
3267: } else {
3268: $message=
1.540 bisitz 3269: '<p class="LC_warning">'.
3270: &mt('Unknown ID [_1] at domain [_2]',
3271: "'".$id."'","'".$udom."'").
3272: '</p>';
1.473 amueller 3273: }
1.43 albertel 3274: } else {
1.473 amueller 3275: $uname=$env{'form.uname'};
1.43 albertel 3276: }
3277: unless ($udom) { $uname=''; }
3278: $uhome='';
3279: if ($uname) {
1.473 amueller 3280: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3281: if ($uhome eq 'no_host') {
1.473 amueller 3282: $message=
1.540 bisitz 3283: '<p class="LC_warning">'.
3284: &mt('Unknown user [_1] at domain [_2]',
3285: "'".$uname."'","'".$udom."'").
3286: '</p>';
1.473 amueller 3287: $uname='';
1.12 www 3288: } else {
1.473 amueller 3289: $csec=&Apache::lonnet::getsection($udom,$uname,
3290: $env{'request.course.id'});
3291: if ($csec eq '-1') {
1.596 raeburn 3292: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3293: if ($env{'form.userroles'} eq 'any') {
3294: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3295: $csec = $env{'request.course.sec'};
3296: $message = '<span class="LC_info">';
3297: if ($crstype eq 'Community') {
3298: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3299: $uname,$udom);
3300: } else {
3301: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3302: $uname,$udom);
3303: }
3304: $message .= '</span>';
3305: } else {
3306: my @possroles = ('in','ep','ta','cr');
3307: if ($crstype eq 'Community') {
3308: unshift(@possroles,'co');
3309: } else {
3310: unshift(@possroles,'cc');
3311: }
3312: my %not_student_roles =
3313: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3314: \@possroles,[$udom],1,1);
3315: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3316: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3317: my %sections_by_role;
3318: foreach my $role (keys(%not_student_roles)) {
3319: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3320: my ($rolename,$sec) = ($1,$2);
3321: if ($rolename =~ m{^cr/}) {
3322: $rolename = 'cr';
3323: }
3324: push(@{$sections_by_role{$rolename}},$sec);
3325: }
3326: }
3327: my $numroles = scalar(keys(%sections_by_role));
3328: if ($numroles) {
3329: foreach my $role (@possroles) {
3330: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3331: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3332: $csec = $secs[0];
3333: last;
3334: }
3335: }
3336: }
3337: if ($csec eq '-1') {
3338: $message = '<span class="LC_warning">';
3339: if ($crstype eq 'Community') {
3340: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3341: $uname,$udom);
3342: } else {
3343: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3344: $uname,$udom);
3345: }
3346: $message .= '</span>';
3347: $uname='';
3348: if ($env{'request.course.sec'} ne '') {
3349: $csec=$env{'request.course.sec'};
3350: } else {
3351: $csec=$env{'form.csec'};
3352: }
3353: $cgroup=$env{'form.cgroup'};
3354: } else {
3355: $message = '<span class="LC_info">';
3356: if ($crstype eq 'Community') {
3357: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3358: $uname,$udom);
3359: } else {
3360: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3361: $uname,$udom);
3362: }
3363: $message .= '</span>';
3364: }
3365: }
1.594 raeburn 3366: } else {
1.596 raeburn 3367: $message = '<span class="LC_warning">';
3368: if ($crstype eq 'Community') {
3369: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3370: $uname,$udom);
3371: } else {
3372: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3373: $uname,$udom);
3374: }
3375: $message .= '</span>';
3376: $uname='';
3377: if ($env{'request.course.sec'} ne '') {
3378: $csec=$env{'request.course.sec'};
3379: } else {
3380: $csec=$env{'form.csec'};
3381: }
3382: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3383: }
3384: } elsif ($env{'request.course.sec'} ne '') {
3385: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3386: $message='<span class="LC_warning">'.
1.594 raeburn 3387: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3388: $uname,$udom,$env{'request.course.sec'}).
3389: '</span>';
3390: $uname='';
3391: $csec=$env{'request.course.sec'};
3392: }
1.269 raeburn 3393: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3394: }
3395: if ($uname ne '') {
1.473 amueller 3396: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3397: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3398: $message .= "\n<p>\n".&mt('Full Name').': '
3399: .$name{'firstname'}.' '.$name{'middlename'}.' '
3400: .$name{'lastname'}.' '.$name{'generation'}
3401: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3402: @usersgroups = &Apache::lonnet::get_users_groups(
3403: $udom,$uname,$env{'request.course.id'});
3404: if (@usersgroups > 0) {
3405: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3406: $cgroup = $usersgroups[0];
3407: }
3408: } else {
3409: $cgroup = '';
1.297 raeburn 3410: }
1.269 raeburn 3411: }
1.12 www 3412: }
1.43 albertel 3413: }
1.2 www 3414:
1.43 albertel 3415: unless ($csec) { $csec=''; }
1.269 raeburn 3416: unless ($cgroup) { $cgroup=''; }
1.12 www 3417:
1.14 www 3418: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3419: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3420: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 3421: \%keyorder,undef,$pssymb);
1.63 bowersj2 3422:
1.582 raeburn 3423: %allmaps_inverted = reverse(%allmaps);
3424:
1.57 albertel 3425: $mapp{'0.0'} = '';
3426: $symbp{'0.0'} = '';
1.99 albertel 3427:
1.14 www 3428: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3429: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3430: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3431: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3432: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3433: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3434: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3435: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3436: my ($got_chostname,$chostname,$cmajor,$cminor);
3437: my $totalstored = 0;
1.605 raeburn 3438: my $totalskippeduser = 0;
1.546 raeburn 3439: my $now = time;
1.473 amueller 3440: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3441: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3442: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3443: next if ($csec ne $env{'request.course.sec'});
3444: }
1.556 raeburn 3445: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3446: next if ($noeditgrp);
1.605 raeburn 3447: } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
3448: if ($uname eq '') {
3449: $totalskippeduser ++;
3450: next;
3451: }
1.557 raeburn 3452: }
3453: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3454: $namematch = 'maplevelrecurse';
3455: }
1.556 raeburn 3456: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3457: my (@ok_slots,@fail_slots,@del_slots);
3458: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3459: my ($level,@all) =
3460: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3461: $csec,$cgroup,$courseopt);
3462: foreach my $slot_name (split(/:/,$values[$i])) {
3463: next if ($slot_name eq '');
3464: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3465: push(@ok_slots,$slot_name);
3466:
3467: } else {
3468: push(@fail_slots,$slot_name);
3469: }
3470: }
3471: if (@ok_slots) {
3472: $values[$i] = join(':',@ok_slots);
3473: } else {
3474: $values[$i] = '';
3475: }
3476: if ($all[$level] ne '') {
3477: my @existing = split(/:/,$all[$level]);
3478: foreach my $slot_name (@existing) {
3479: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3480: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3481: push(@del_slots,$slot_name);
3482: }
3483: }
3484: }
3485: }
1.554 raeburn 3486: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3487: $name = $1;
1.533 raeburn 3488: my $val = $values[$i];
1.549 raeburn 3489: my $valmatch = '';
1.533 raeburn 3490: if ($name eq 'examcode') {
1.544 raeburn 3491: if (&Apache::lonnet::validCODE($values[$i])) {
3492: $val = 'valid';
3493: }
1.546 raeburn 3494: } elsif ($name eq 'printstartdate') {
3495: if ($val =~ /^\d+$/) {
3496: if ($val > $now) {
3497: $val = 'future';
3498: }
3499: }
3500: } elsif ($name eq 'printenddate') {
3501: if ($val =~ /^\d+$/) {
3502: if ($val < $now) {
3503: $val = 'past';
3504: }
3505: }
1.549 raeburn 3506: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3507: my $stringtype = &get_stringtype($name);
3508: my $stringmatch = &standard_string_matches($stringtype);
3509: if (ref($stringmatch) eq 'ARRAY') {
3510: foreach my $item (@{$stringmatch}) {
3511: if (ref($item) eq 'ARRAY') {
3512: my ($regexpname,$pattern) = @{$item};
3513: if ($pattern ne '') {
3514: if ($val =~ /$pattern/) {
3515: $valmatch = $regexpname;
3516: $val = '';
3517: last;
3518: }
3519: }
3520: }
3521: }
3522: }
1.554 raeburn 3523: } elsif ($name eq 'interval') {
3524: my $intervaltype = &get_intervaltype($name);
3525: my $intervalmatch = &standard_interval_matches($intervaltype);
3526: if (ref($intervalmatch) eq 'ARRAY') {
3527: foreach my $item (@{$intervalmatch}) {
3528: if (ref($item) eq 'ARRAY') {
3529: my ($regexpname,$pattern) = @{$item};
3530: if ($pattern ne '') {
3531: if ($val =~ /$pattern/) {
3532: $valmatch = $regexpname;
3533: $val = '';
3534: last;
3535: }
3536: }
3537: }
3538: }
3539: }
1.533 raeburn 3540: }
1.504 raeburn 3541: $needsrelease =
1.557 raeburn 3542: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3543: if ($needsrelease) {
1.505 raeburn 3544: unless ($got_chostname) {
1.514 raeburn 3545: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3546: $got_chostname = 1;
1.546 raeburn 3547: }
1.557 raeburn 3548: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3549: $needsrelease,
3550: $cmajor,$cminor);
1.500 raeburn 3551: }
1.437 raeburn 3552: }
1.504 raeburn 3553: if ($needsnewer) {
1.557 raeburn 3554: undef($namematch);
3555: } else {
3556: my $currneeded;
3557: if ($needsrelease) {
3558: $currneeded = $needsrelease;
3559: }
3560: if ($namematch) {
3561: $needsrelease =
3562: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3563: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3564: unless ($got_chostname) {
3565: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3566: $got_chostname = 1;
3567: }
3568: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3569: $needsrelease,
3570: $cmajor,$cminor);
3571: } else {
3572: undef($namematch);
3573: }
3574: }
3575: }
3576: if ($needsnewer) {
3577: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3578: $cminor,$needsrelease);
3579: } else {
3580: $message.=&storeparm(split(/\&/,$markers[$i]),
3581: $values[$i],
3582: $types[$i],
3583: $uname,$udom,$csec,$cgroup);
3584: $totalstored ++;
3585: }
1.473 amueller 3586: }
1.68 www 3587: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3588: if ($totalstored) {
3589: $message.='<p class="LC_warning">'
1.605 raeburn 3590: .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
3591: .'<br />'
1.504 raeburn 3592: .&mt('Changes can take up to 10 minutes before being active for all students.')
3593: .&Apache::loncommon::help_open_topic('Caching')
3594: .'</p>';
1.605 raeburn 3595: } else {
3596: $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
3597: }
3598: if ($totalskippeduser) {
3599: $message .= '<p class="LC_warning">';
3600: if ($uhome eq 'no_host') {
3601: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
3602: $totalskippeduser);
3603: } elsif ($env{'form.userroles'} eq 'any') {
3604: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
3605: $totalskippeduser);
3606: } else {
3607: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
3608: $totalskippeduser);
3609: }
3610: $message .= '</p>';
1.504 raeburn 3611: }
1.68 www 3612: }
1.584 raeburn 3613:
1.57 albertel 3614: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3615: if ($pscat[0] eq "all") {
3616: @pscat = (keys(%allparms));
3617: }
3618: if (!@pscat) {
3619: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3620: };
3621: if ($psprt[0] eq "all" || !@psprt) {
3622: @psprt = (keys(%allparts));
3623: }
1.2 www 3624: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3625:
1.531 raeburn 3626: my $crstype = &Apache::loncommon::course_type();
3627: &startpage($r,$pssymb,$crstype);
1.57 albertel 3628:
1.548 raeburn 3629: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3630: 'date_interval','int','float','string','string_lenient',
3631: 'string_examcode','string_deeplink','string_discussvote',
3632: 'string_useslots','string_problemstatus','string_ip',
3633: 'string_questiontype') {
1.473 amueller 3634: $r->print('<input type="hidden" value="'.
1.563 damieng 3635: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3636: '" name="recent_'.$item.'" />');
1.44 albertel 3637: }
1.446 bisitz 3638:
1.459 bisitz 3639: # ----- Start Parameter Selection
3640:
1.606 raeburn 3641: # Hide parm selection and possibly table?
3642: my ($tablejs,$tabledivsty);
3643: if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
3644: ($env{'form.dis'}) && ($pssymb eq '')) {
3645: $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
3646: $tabledivsty = ' style="display:none"';
3647: }
1.459 bisitz 3648: $r->print(<<ENDPARMSELSCRIPT);
3649: <script type="text/javascript">
3650: // <![CDATA[
3651: function parmsel_show() {
1.562 damieng 3652: document.getElementById('parmsel').style.display = "";
3653: document.getElementById('parmsellink').style.display = "none";
1.606 raeburn 3654: $tablejs
1.459 bisitz 3655: }
3656: // ]]>
3657: </script>
3658: ENDPARMSELSCRIPT
1.474 amueller 3659:
1.445 neumanie 3660: if (!$pssymb) {
1.563 damieng 3661: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3662: my $parmselhiddenstyle=' style="display:none"';
3663: if($env{'form.hideparmsel'} eq 'hidden') {
3664: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3665: } else {
3666: $r->print('<div id="parmsel">');
3667: }
3668:
1.491 bisitz 3669: # Step 1
1.523 raeburn 3670: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3671: $r->print('
1.474 amueller 3672: <script type="text/javascript">
1.523 raeburn 3673: // <![CDATA['.
3674: &showhide_js().'
1.474 amueller 3675: // ]]>
3676: </script>
1.523 raeburn 3677: ');
3678: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3679: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3680: $r->print(&Apache::lonhtmlcommon::row_closure());
1.610 raeburn 3681: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491 bisitz 3682: $r->print(&Apache::lonhtmlcommon::row_closure());
3683: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3684: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3685: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3686: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3687:
3688: # Step 2
1.523 raeburn 3689: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3690: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3691:
3692: # Step 3
1.523 raeburn 3693: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3694: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3695: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3696: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3697: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3698:
3699: # Update Display Button
1.486 www 3700: $r->print('<p>'
3701: .'<input type="submit" name="dis"'
1.511 www 3702: .' value="'.&mt('Update Display').'" />'
1.486 www 3703: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3704: .'</p>');
3705: $r->print('</div>');
1.491 bisitz 3706:
1.486 www 3707: # Offer link to display parameter selection again
3708: $r->print('<p id="parmsellink"');
3709: if ($env{'form.hideparmsel'} ne 'hidden') {
3710: $r->print($parmselhiddenstyle);
3711: }
3712: $r->print('>'
3713: .'<a href="javascript:parmsel_show()">'
3714: .&mt('Change Parameter Selection')
3715: .'</a>'
3716: .'</p>');
1.44 albertel 3717: } else {
1.478 amueller 3718: # parameter screen for a single resource.
1.486 www 3719: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3720: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3721: $r->print(&mt('Specific Resource: [_1] ([_2])',
3722: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3723: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 3724: '<br />');
3725: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
3726: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3727: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3728: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3729: $r->print(&Apache::lonhtmlcommon::end_pick_box());
3730: $r->print('<p>'
1.459 bisitz 3731: .'<input type="submit" name="dis"'
1.511 www 3732: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 3733: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 3734: .'</p>');
1.459 bisitz 3735: }
1.478 amueller 3736:
1.486 www 3737: # ----- End Parameter Selection
1.57 albertel 3738:
1.459 bisitz 3739: # Display Messages
3740: $r->print('<div>'.$message.'</div>');
1.210 www 3741:
1.57 albertel 3742:
3743: my @temp_pscat;
3744: map {
3745: my $cat = $_;
3746: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
3747: } @pscat;
3748:
3749: @pscat = @temp_pscat;
3750:
1.548 raeburn 3751:
1.209 www 3752: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 3753: # ----------------------------------------------------------------- Start Table
1.57 albertel 3754: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 3755: my $csuname=$env{'user.name'};
3756: my $csudom=$env{'user.domain'};
1.568 raeburn 3757: my $readonly = 1;
3758: if ($parm_permission->{'edit'}) {
3759: undef($readonly);
3760: }
1.606 raeburn 3761: $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57 albertel 3762:
1.203 www 3763: if ($parmlev eq 'full') {
1.506 www 3764: #
3765: # This produces the cascading table output of parameters
3766: #
1.578 raeburn 3767: my $coursespan=$csec?8:5;
3768: my $userspan=3;
1.560 damieng 3769: if ($cgroup ne '') {
1.578 raeburn 3770: $coursespan += 3;
1.560 damieng 3771: }
1.473 amueller 3772:
1.560 damieng 3773: $r->print(&Apache::loncommon::start_data_table());
3774: #
3775: # This produces the headers
3776: #
3777: $r->print('<tr><td colspan="5"></td>');
3778: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
3779: if ($uname) {
1.473 amueller 3780: if (@usersgroups > 1) {
1.560 damieng 3781: $userspan ++;
3782: }
3783: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
3784: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
3785: }
3786: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 3787: 'pie' => "Parameter in Effect",
3788: 'csv' => "Current Session Value",
1.472 amueller 3789: 'rl' => "Resource Level",
1.473 amueller 3790: 'ic' => 'in Course',
3791: 'aut' => "Assessment URL and Title",
3792: 'type' => 'Type',
3793: 'emof' => "Enclosing Map or Folder",
3794: 'part' => 'Part',
1.472 amueller 3795: 'pn' => 'Parameter Name',
1.473 amueller 3796: 'def' => 'default',
3797: 'femof' => 'from Enclosing Map or Folder',
3798: 'gen' => 'general',
3799: 'foremf' => 'for Enclosing Map or Folder',
3800: 'fr' => 'for Resource'
3801: );
1.560 damieng 3802: $r->print(<<ENDTABLETWO);
1.419 bisitz 3803: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 3804: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 3805: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 3806: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 3807:
1.10 www 3808: ENDTABLETWO
1.560 damieng 3809: if ($csec) {
1.578 raeburn 3810: $r->print('<th colspan="3">'.
1.560 damieng 3811: &mt("in Section")." $csec</th>");
3812: }
3813: if ($cgroup) {
1.578 raeburn 3814: $r->print('<th colspan="3">'.
1.472 amueller 3815: &mt("in Group")." $cgroup</th>");
1.560 damieng 3816: }
3817: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 3818: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
3819: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 3820: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 3821: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 3822: ENDTABLEHEADFOUR
1.57 albertel 3823:
1.560 damieng 3824: if ($csec) {
1.578 raeburn 3825: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3826: }
1.473 amueller 3827:
1.560 damieng 3828: if ($cgroup) {
1.578 raeburn 3829: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3830: }
3831:
3832: if ($uname) {
3833: if (@usersgroups > 1) {
3834: $r->print('<th>'.&mt('Control by other group?').'</th>');
3835: }
1.578 raeburn 3836: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3837: }
3838:
3839: $r->print('</tr>');
1.506 www 3840: #
3841: # Done with the headers
3842: #
1.560 damieng 3843: my $defbgone='';
3844: my $defbgtwo='';
3845: my $defbgthree = '';
1.57 albertel 3846:
1.560 damieng 3847: foreach my $rid (@ids) {
1.57 albertel 3848:
3849: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 3850: if ((!$pssymb &&
1.560 damieng 3851: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
3852: ||
3853: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 3854: # ------------------------------------------------------ Entry for one resource
1.473 amueller 3855: if ($defbgone eq '#E0E099') {
3856: $defbgone='#E0E0DD';
1.57 albertel 3857: } else {
1.419 bisitz 3858: $defbgone='#E0E099';
1.57 albertel 3859: }
1.419 bisitz 3860: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 3861: $defbgtwo='#FFFFDD';
1.57 albertel 3862: } else {
1.473 amueller 3863: $defbgtwo='#FFFF99';
1.57 albertel 3864: }
1.419 bisitz 3865: if ($defbgthree eq '#FFBB99') {
3866: $defbgthree='#FFBBDD';
1.269 raeburn 3867: } else {
1.419 bisitz 3868: $defbgthree='#FFBB99';
1.269 raeburn 3869: }
3870:
1.57 albertel 3871: my $thistitle='';
3872: my %name= ();
3873: undef %name;
3874: my %part= ();
3875: my %display=();
3876: my %type= ();
3877: my %default=();
1.196 www 3878: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3879: my $toolsymb;
3880: if ($uri =~ /ext\.tool$/) {
3881: $toolsymb = $symbp{$rid};
3882: }
1.57 albertel 3883:
1.506 www 3884: my $filter=$env{'form.filter'};
1.548 raeburn 3885: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 3886: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 3887: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 3888: # We may only want certain parameters listed
3889: if ($filter) {
3890: unless ($filter=~/\Q$parmname\E/) { next; }
3891: }
3892: $name{$tempkeyp}=$parmname;
1.584 raeburn 3893: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 3894:
1.584 raeburn 3895: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 3896: if ($allparms{$name{$tempkeyp}} ne '') {
3897: my $identifier;
3898: if ($parmdis =~ /(\s*\[Part.*)$/) {
3899: $identifier = $1;
3900: }
3901: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3902: } else {
3903: $display{$tempkeyp} = $parmdis;
3904: }
3905: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3906: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 3907: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
3908: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
3909: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 3910: }
3911: }
1.548 raeburn 3912: my $totalparms=scalar(keys(%name));
1.57 albertel 3913: if ($totalparms>0) {
1.560 damieng 3914: my $firstrow=1;
1.473 amueller 3915: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 3916: my $navmap = Apache::lonnavmaps::navmap->new();
3917: my @recurseup;
3918: if (ref($navmap) && $mapp{$rid}) {
3919: @recurseup = $navmap->recurseup_maps($mapp{$rid});
3920: }
1.419 bisitz 3921: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 3922: ' rowspan='.$totalparms.
1.419 bisitz 3923: '><tt><font size="-1">'.
1.57 albertel 3924: join(' / ',split(/\//,$uri)).
3925: '</font></tt><p><b>'.
1.154 albertel 3926: "<a href=\"javascript:openWindow('".
1.473 amueller 3927: &Apache::lonnet::clutter($uri).'?symb='.
3928: &escape($symbp{$rid}).
1.336 albertel 3929: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
3930: " target=\"_self\">$title");
1.57 albertel 3931:
3932: if ($thistitle) {
1.473 amueller 3933: $r->print(' ('.$thistitle.')');
1.57 albertel 3934: }
3935: $r->print('</a></b></td>');
1.419 bisitz 3936: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 3937: ' rowspan='.$totalparms.'>'.$typep{$rid}.
3938: '</td>');
3939:
1.419 bisitz 3940: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 3941: ' rowspan='.$totalparms.
1.238 www 3942: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 3943: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 3944: unless ($firstrow) {
3945: $r->print('<tr>');
3946: } else {
3947: undef $firstrow;
3948: }
1.548 raeburn 3949: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 3950: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 3951: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 3952: $cgroup,\@usersgroups,$noeditgrp,$readonly,
3953: \@recurseup,\%maptitles,\%allmaps_inverted,
3954: \$numreclinks);
1.57 albertel 3955: }
3956: }
3957: }
3958: } # end foreach ids
1.43 albertel 3959: # -------------------------------------------------- End entry for one resource
1.517 www 3960: $r->print(&Apache::loncommon::end_data_table);
1.203 www 3961: } # end of full
1.57 albertel 3962: #--------------------------------------------------- Entry for parm level map
3963: if ($parmlev eq 'map') {
1.419 bisitz 3964: my $defbgone = '#E0E099';
3965: my $defbgtwo = '#FFFF99';
3966: my $defbgthree = '#FFBB99';
1.57 albertel 3967:
3968: my %maplist;
3969:
3970: if ($pschp eq 'all') {
1.446 bisitz 3971: %maplist = %allmaps;
1.57 albertel 3972: } else {
3973: %maplist = ($pschp => $mapp{$pschp});
3974: }
3975:
3976: #-------------------------------------------- for each map, gather information
3977: my $mapid;
1.607 raeburn 3978: foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60 albertel 3979: my $maptitle = $maplist{$mapid};
1.57 albertel 3980:
3981: #----------------------- loop through ids and get all parameter types for map
3982: #----------------------------------------- and associated information
3983: my %name = ();
3984: my %part = ();
3985: my %display = ();
3986: my %type = ();
3987: my %default = ();
3988: my $map = 0;
3989:
1.473 amueller 3990: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 3991:
1.548 raeburn 3992: foreach my $id (@ids) {
3993: ($map)=($id =~ /([\d]*?)\./);
3994: my $rid = $id;
1.446 bisitz 3995:
1.57 albertel 3996: # $r->print("$mapid:$map: $rid <br /> \n");
3997:
1.560 damieng 3998: if ($map eq $mapid) {
1.473 amueller 3999: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4000: my $toolsymb;
4001: if ($uri =~ /ext\.tool$/) {
4002: $toolsymb = $symbp{$rid};
4003: }
1.582 raeburn 4004:
1.57 albertel 4005: # $r->print("Keys: $keyp{$rid} <br />\n");
4006:
4007: #--------------------------------------------------------------------
4008: # @catmarker contains list of all possible parameters including part #s
4009: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4010: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4011: # When storing information, store as part 0
4012: # When requesting information, request from full part
4013: #-------------------------------------------------------------------
1.548 raeburn 4014: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4015: my $tempkeyp = $fullkeyp;
4016: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 4017:
1.548 raeburn 4018: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4019: $part{$tempkeyp}="0";
1.584 raeburn 4020: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4021: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4022: if ($allparms{$name{$tempkeyp}} ne '') {
4023: my $identifier;
4024: if ($parmdis =~ /(\s*\[Part.*)$/) {
4025: $identifier = $1;
4026: }
4027: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4028: } else {
4029: $display{$tempkeyp} = $parmdis;
4030: }
4031: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4032: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4033: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4034: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4035: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 4036: }
4037: } # end loop through keys
1.560 damieng 4038: }
1.57 albertel 4039: } # end loop through ids
1.446 bisitz 4040:
1.57 albertel 4041: #---------------------------------------------------- print header information
1.133 www 4042: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 4043: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 4044: my $tmp="";
1.57 albertel 4045: if ($uname) {
1.473 amueller 4046: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 4047: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
4048: &mt('in')." \n";
1.57 albertel 4049: } else {
1.401 bisitz 4050: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 4051: }
1.269 raeburn 4052: if ($cgroup) {
1.401 bisitz 4053: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
4054: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4055: $csec = '';
4056: } elsif ($csec) {
1.401 bisitz 4057: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
4058: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4059: }
1.401 bisitz 4060: $r->print('<div align="center"><h4>'
4061: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 4062: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 4063: ,$tmp
4064: ,'<font color="red"><i>'.$coursename.'</i></font>'
4065: )
4066: ."<br /></h4>\n"
1.422 bisitz 4067: );
1.57 albertel 4068: #---------------------------------------------------------------- print table
1.419 bisitz 4069: $r->print('<p>'.&Apache::loncommon::start_data_table()
4070: .&Apache::loncommon::start_data_table_header_row()
4071: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 4072: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4073: .'<th>'.&mt('Parameter in Effect').'</th>'
4074: .&Apache::loncommon::end_data_table_header_row()
4075: );
1.57 albertel 4076:
1.582 raeburn 4077: my $navmap = Apache::lonnavmaps::navmap->new();
4078: my @recurseup;
4079: if (ref($navmap)) {
4080: my $mapres = $navmap->getByMapPc($mapid);
4081: if (ref($mapres)) {
4082: @recurseup = $navmap->recurseup_maps($mapres->src());
4083: }
4084: }
4085:
4086:
1.548 raeburn 4087: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4088: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4089: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4090: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4091: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4092: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4093: \$numreclinks);
1.57 albertel 4094: }
1.422 bisitz 4095: $r->print(&Apache::loncommon::end_data_table().'</p>'
4096: .'</div>'
4097: );
1.57 albertel 4098: } # end each map
4099: } # end of $parmlev eq map
4100: #--------------------------------- Entry for parm level general (Course level)
4101: if ($parmlev eq 'general') {
1.473 amueller 4102: my $defbgone = '#E0E099';
1.419 bisitz 4103: my $defbgtwo = '#FFFF99';
4104: my $defbgthree = '#FFBB99';
1.57 albertel 4105:
4106: #-------------------------------------------- for each map, gather information
4107: my $mapid="0.0";
4108: #----------------------- loop through ids and get all parameter types for map
4109: #----------------------------------------- and associated information
4110: my %name = ();
4111: my %part = ();
4112: my %display = ();
4113: my %type = ();
4114: my %default = ();
1.446 bisitz 4115:
1.548 raeburn 4116: foreach $id (@ids) {
4117: my $rid = $id;
1.446 bisitz 4118:
1.196 www 4119: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4120: my $toolsymb;
4121: if ($uri =~ /ext\.tool$/) {
4122: $toolsymb = $symbp{$rid};
4123: }
1.57 albertel 4124:
4125: #--------------------------------------------------------------------
4126: # @catmarker contains list of all possible parameters including part #s
4127: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4128: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4129: # When storing information, store as part 0
4130: # When requesting information, request from full part
4131: #-------------------------------------------------------------------
1.548 raeburn 4132: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4133: my $tempkeyp = $fullkeyp;
4134: $tempkeyp =~ s/_\w+_/_0_/;
4135: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4136: $part{$tempkeyp}="0";
1.584 raeburn 4137: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4138: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4139: if ($allparms{$name{$tempkeyp}} ne '') {
4140: my $identifier;
4141: if ($parmdis =~ /(\s*\[Part.*)$/) {
4142: $identifier = $1;
4143: }
4144: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4145: } else {
4146: $display{$tempkeyp} = $parmdis;
4147: }
4148: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4149: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4150: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4151: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4152: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4153: }
1.57 albertel 4154: } # end loop through keys
4155: } # end loop through ids
1.446 bisitz 4156:
1.57 albertel 4157: #---------------------------------------------------- print header information
1.473 amueller 4158: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4159: $r->print(<<ENDMAPONE);
1.419 bisitz 4160: <center>
4161: <h4>$setdef
1.135 albertel 4162: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4163: ENDMAPONE
4164: if ($uname) {
1.473 amueller 4165: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4166: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4167: } else {
1.135 albertel 4168: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4169: }
1.446 bisitz 4170:
1.135 albertel 4171: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4172: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4173: $r->print("</h4>\n");
1.57 albertel 4174: #---------------------------------------------------------------- print table
1.419 bisitz 4175: $r->print('<p>'.&Apache::loncommon::start_data_table()
4176: .&Apache::loncommon::start_data_table_header_row()
4177: .'<th>'.&mt('Parameter Name').'</th>'
4178: .'<th>'.&mt('Default Value').'</th>'
4179: .'<th>'.&mt('Parameter in Effect').'</th>'
4180: .&Apache::loncommon::end_data_table_header_row()
4181: );
1.57 albertel 4182:
1.548 raeburn 4183: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4184: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4185: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4186: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4187: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4188: $readonly);
1.57 albertel 4189: }
1.419 bisitz 4190: $r->print(&Apache::loncommon::end_data_table()
4191: .'</p>'
4192: .'</center>'
4193: );
1.57 albertel 4194: } # end of $parmlev eq general
1.606 raeburn 4195: $r->print('</div>');
1.43 albertel 4196: }
1.507 www 4197: $r->print('</form>');
1.582 raeburn 4198: if ($numreclinks) {
4199: $r->print(<<"END");
4200: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4201: <input type="hidden" name="pschp" />
4202: <input type="hidden" name="pscat" />
4203: <input type="hidden" name="psprt" />
4204: <input type="hidden" name="hideparmsel" value="hidden" />
4205: </form>
4206: <script type="text/javascript">
4207: function pjumprec(rid,name,part) {
4208: document.forms.recurseform.pschp.value = rid;
4209: document.forms.recurseform.pscat.value = name;
4210: document.forms.recurseform.psprt.value = part;
4211: document.forms.recurseform.submit();
4212: return false;
4213: }
4214: </script>
4215: END
4216: }
1.507 www 4217: &endSettingsScreen($r);
4218: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4219: } # end sub assessparms
1.30 www 4220:
1.560 damieng 4221:
4222:
1.120 www 4223: ##################################################
1.560 damieng 4224: # OVERVIEW MODE
1.207 www 4225: ##################################################
1.124 www 4226:
1.563 damieng 4227: my $tableopen; # boolean, true if HTML table is already opened
4228:
4229: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4230: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4231: # @returns {string}
1.124 www 4232: sub tablestart {
1.576 raeburn 4233: my ($readonly,$is_map) = @_;
1.124 www 4234: if ($tableopen) {
1.552 raeburn 4235: return '';
1.124 www 4236: } else {
1.552 raeburn 4237: $tableopen=1;
4238: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4239: if ($readonly) {
4240: $output .= '<th>'.&mt('Current value').'</th>';
4241: } else {
1.576 raeburn 4242: $output .= '<th>'.&mt('Delete').'</th>'.
4243: '<th>'.&mt('Set to ...').'</th>';
4244: if ($is_map) {
4245: $output .= '<th>'.&mt('Recursive?').'</th>';
4246: }
1.552 raeburn 4247: }
4248: $output .= '</tr>';
4249: return $output;
1.124 www 4250: }
4251: }
4252:
1.563 damieng 4253: # Returns HTML with the HTML table end tag, unless the table is not opened.
4254: # @returns {string}
1.124 www 4255: sub tableend {
4256: if ($tableopen) {
1.560 damieng 4257: $tableopen=0;
4258: return &Apache::loncommon::end_data_table();
1.124 www 4259: } else {
1.560 damieng 4260: return'';
1.124 www 4261: }
4262: }
4263:
1.563 damieng 4264: # Reads course and user information.
4265: # 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).
4266: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4267: # If the context is looking for a list, returns a list with the scalar data and the class list.
4268: # @param {string} $crs - course number
4269: # @param {string} $dom - course domain
4270: # @returns {hash reference|Array}
1.207 www 4271: sub readdata {
4272: my ($crs,$dom)=@_;
4273: # Read coursedata
4274: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4275: # Read userdata
4276:
4277: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4278: foreach my $user (keys(%$classlist)) {
4279: if ($user=~/^($match_username)\:($match_domain)$/) {
4280: my ($tuname,$tudom)=($1,$2);
4281: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4282: foreach my $userkey (keys(%{$useropt})) {
4283: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4284: my $newkey=$userkey;
1.548 raeburn 4285: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4286: $$resourcedata{$newkey}=$$useropt{$userkey};
4287: }
4288: }
1.473 amueller 4289: }
4290: }
1.552 raeburn 4291: if (wantarray) {
4292: return ($resourcedata,$classlist);
4293: } else {
4294: return $resourcedata;
4295: }
1.207 www 4296: }
4297:
4298:
1.563 damieng 4299: # Stores parameter data, using form parameters directly.
4300: #
4301: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.588 raeburn 4302: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563 damieng 4303: # del_* - remove a parameter
4304: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4305: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4306: # key_* - date values
4307: # days_* - for date intervals
4308: # hours_* - for date intervals
4309: # minutes_* - for date intervals
4310: # seconds_* - for date intervals
4311: # done_* - for date intervals
4312: # typeof_* - parameter type
4313: #
4314: # @param {Apache2::RequestRec} $r - the Apache request
4315: # @param {string} $crs - course number
4316: # @param {string} $dom - course domain
1.208 www 4317: sub storedata {
4318: my ($r,$crs,$dom)=@_;
1.207 www 4319: # Set userlevel immediately
4320: # Do an intermediate store of course level
4321: my $olddata=&readdata($crs,$dom);
1.124 www 4322: my %newdata=();
4323: undef %newdata;
4324: my @deldata=();
1.576 raeburn 4325: my @delrec=();
4326: my @delnonrec=();
1.124 www 4327: undef @deldata;
1.504 raeburn 4328: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4329: my $now = time;
1.560 damieng 4330: foreach my $key (keys(%env)) {
4331: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4332: my $cmd=$1;
4333: my $thiskey=$2;
1.576 raeburn 4334: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588 raeburn 4335: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576 raeburn 4336: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4337: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4338: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4339: $altkey = $thiskey;
4340: $altkey =~ s/\Q___(all)\E/___(rec)/;
4341: if ($env{'form.rec_'.$thiskey}) {
4342: $recursive = 1;
4343: }
4344: }
4345: }
1.560 damieng 4346: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4347: if ($tuname) {
1.576 raeburn 4348: $tkey=$thiskey;
1.560 damieng 4349: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4350: if ($altkey) {
4351: $tkeynonrec = $tkey;
4352: $tkeyrec = $altkey;
4353: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4354: }
1.560 damieng 4355: }
4356: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4357: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4358: if ($cmd eq 'set') {
4359: $data=$env{$key};
4360: $valmatch = '';
4361: $valchk = $data;
4362: $typeof=$env{'form.typeof_'.$thiskey};
4363: $text = &mt('Saved modified parameter for');
4364: if ($typeof eq 'string_questiontype') {
4365: $name = 'type';
1.588 raeburn 4366: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4367: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4368: my $stringmatch = &standard_string_matches($typeof);
4369: if (ref($stringmatch) eq 'ARRAY') {
4370: foreach my $item (@{$stringmatch}) {
4371: if (ref($item) eq 'ARRAY') {
4372: my ($regexpname,$pattern) = @{$item};
4373: if ($pattern ne '') {
4374: if ($data =~ /$pattern/) {
4375: $valmatch = $regexpname;
4376: $valchk = '';
4377: last;
4378: }
1.560 damieng 4379: }
1.549 raeburn 4380: }
4381: }
4382: }
1.563 damieng 4383: } elsif ($typeof eq 'string_discussvote') {
4384: $name = 'discussvote';
4385: } elsif ($typeof eq 'string_examcode') {
4386: $name = 'examcode';
4387: if (&Apache::lonnet::validCODE($data)) {
4388: $valchk = 'valid';
4389: }
4390: } elsif ($typeof eq 'string_yesno') {
4391: if ($thiskey =~ /\.retrypartial$/) {
4392: $name = 'retrypartial';
4393: }
1.549 raeburn 4394: }
1.563 damieng 4395: } elsif ($cmd eq 'datepointer') {
4396: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4397: $typeof=$env{'form.typeof_'.$thiskey};
4398: $text = &mt('Saved modified date for');
4399: if ($typeof eq 'date_start') {
4400: if ($thiskey =~ /\.printstartdate$/) {
4401: $name = 'printstartdate';
4402: if (($data) && ($data > $now)) {
4403: $valchk = 'future';
4404: }
1.560 damieng 4405: }
1.563 damieng 4406: } elsif ($typeof eq 'date_end') {
4407: if ($thiskey =~ /\.printenddate$/) {
4408: $name = 'printenddate';
4409: if (($data) && ($data < $now)) {
4410: $valchk = 'past';
4411: }
1.560 damieng 4412: }
1.504 raeburn 4413: }
1.563 damieng 4414: } elsif ($cmd eq 'dateinterval') {
4415: $data=&get_date_interval_from_form($thiskey);
4416: if ($thiskey =~ /\.interval$/) {
4417: $name = 'interval';
4418: my $intervaltype = &get_intervaltype($name);
4419: my $intervalmatch = &standard_interval_matches($intervaltype);
4420: if (ref($intervalmatch) eq 'ARRAY') {
4421: foreach my $item (@{$intervalmatch}) {
4422: if (ref($item) eq 'ARRAY') {
4423: my ($regexpname,$pattern) = @{$item};
4424: if ($pattern ne '') {
4425: if ($data =~ /$pattern/) {
4426: $valmatch = $regexpname;
4427: $valchk = '';
4428: last;
4429: }
1.560 damieng 4430: }
1.554 raeburn 4431: }
4432: }
4433: }
4434: }
1.563 damieng 4435: $typeof=$env{'form.typeof_'.$thiskey};
4436: $text = &mt('Saved modified date for');
1.554 raeburn 4437: }
1.576 raeburn 4438: if ($recursive) {
1.563 damieng 4439: $namematch = 'maplevelrecurse';
1.560 damieng 4440: }
1.563 damieng 4441: if (($name ne '') || ($namematch ne '')) {
4442: my ($needsrelease,$needsnewer);
4443: if ($name ne '') {
4444: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4445: if ($needsrelease) {
4446: unless ($got_chostname) {
1.563 damieng 4447: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4448: $got_chostname = 1;
4449: }
1.563 damieng 4450: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4451: $needsrelease,
4452: $cmajor,$cminor);
4453: }
4454: }
4455: if ($namematch ne '') {
4456: if ($needsnewer) {
4457: undef($namematch);
1.560 damieng 4458: } else {
1.563 damieng 4459: my $currneeded;
4460: if ($needsrelease) {
4461: $currneeded = $needsrelease;
4462: }
4463: $needsrelease =
4464: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4465: if (($needsrelease) &&
4466: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4467: unless ($got_chostname) {
4468: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4469: $got_chostname = 1;
4470: }
4471: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4472: $namematch, $needsrelease,$cmajor,$cminor);
4473: } else {
4474: undef($namematch);
4475: }
1.560 damieng 4476: }
1.557 raeburn 4477: }
1.563 damieng 4478: if ($needsnewer) {
4479: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4480: $chostname,$cmajor,
4481: $cminor,$needsrelease));
4482: next;
4483: }
1.504 raeburn 4484: }
1.576 raeburn 4485: my ($reconlychg,$haschange,$storekey);
4486: if ($tuname) {
4487: my $ustorekey;
4488: if ($altkey) {
4489: if ($recursive) {
4490: if (exists($$olddata{$thiskey})) {
4491: if ($$olddata{$thiskey} eq $data) {
4492: $reconlychg = 1;
4493: }
4494: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4495: }
4496: if (exists($$olddata{$altkey})) {
4497: if (defined($data) && $$olddata{$altkey} ne $data) {
4498: $haschange = 1;
4499: }
4500: } elsif ((!$reconlychg) && ($data ne '')) {
4501: $haschange = 1;
4502: }
4503: $ustorekey = $tkeyrec;
4504: } else {
4505: if (exists($$olddata{$altkey})) {
4506: if ($$olddata{$altkey} eq $data) {
4507: $reconlychg = 1;
4508: }
4509: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4510: }
4511: if (exists($$olddata{$thiskey})) {
4512: if (defined($data) && $$olddata{$thiskey} ne $data) {
4513: $haschange = 1;
4514: }
4515: } elsif ((!$reconlychg) && ($data ne '')) {
4516: $haschange = 1;
4517: }
4518: $ustorekey = $tkeynonrec;
4519: }
4520: } else {
4521: if (exists($$olddata{$tkey})) {
4522: if (defined($data) && $$olddata{$tkey} ne $data) {
4523: $haschange = 1;
4524: }
4525: $ustorekey = $tkey;
4526: }
4527: }
4528: if ($haschange || $reconlychg) {
4529: unless ($env{'form.del_'.$thiskey}) {
4530: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4531: $ustorekey.'.type' => $typeof},
4532: $tudom,$tuname) eq 'ok') {
4533: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4534: $r->print('<br />'.$text.' '.
4535: &Apache::loncommon::plainname($tuname,$tudom));
4536: } else {
4537: $r->print('<div class="LC_error">'.
4538: &mt('Error saving parameters').'</div>');
4539: }
4540: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4541: }
4542: }
4543: } else {
4544: if ($altkey) {
4545: if ($recursive) {
4546: if (exists($$olddata{$thiskey})) {
4547: if ($$olddata{$thiskey} eq $data) {
4548: $reconlychg = 1;
4549: }
4550: push(@delnonrec,($thiskey,$thiskey.'.type'));
4551: }
4552: if (exists($$olddata{$altkey})) {
4553: if (defined($data) && $$olddata{$altkey} ne $data) {
4554: $haschange = 1;
4555: }
4556: } elsif (($data ne '') && (!$reconlychg)) {
4557: $haschange = 1;
4558: }
4559: $storekey = $altkey;
1.563 damieng 4560: } else {
1.576 raeburn 4561: if (exists($$olddata{$altkey})) {
4562: if ($$olddata{$altkey} eq $data) {
4563: $reconlychg = 1;
4564: }
4565: push(@delrec,($altkey,$altkey.'.type'));
4566: }
4567: if (exists($$olddata{$thiskey})) {
4568: if (defined($data) && $$olddata{$thiskey} ne $data) {
4569: $haschange = 1;
4570: }
4571: } elsif (($data ne '') && (!$reconlychg)) {
4572: $haschange = 1;
4573: }
4574: $storekey = $thiskey;
1.563 damieng 4575: }
1.560 damieng 4576: } else {
1.576 raeburn 4577: if (defined($data) && $$olddata{$thiskey} ne $data) {
4578: $haschange = 1;
4579: $storekey = $thiskey;
4580: }
4581: }
4582: }
4583: if ($reconlychg || $haschange) {
4584: unless ($env{'form.del_'.$thiskey}) {
4585: $newdata{$storekey}=$data;
4586: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4587: }
4588: }
4589: } elsif ($cmd eq 'del') {
4590: if ($tuname) {
1.576 raeburn 4591: my $error;
4592: if ($altkey) {
4593: if (exists($$olddata{$altkey})) {
4594: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4595: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4596: if ($recursive) {
4597: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4598: }
4599: } elsif ($recursive) {
4600: $error = 1;
4601: }
4602: }
4603: if (exists($$olddata{$thiskey})) {
4604: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4605: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4606: unless ($recursive) {
4607: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4608: }
4609: } elsif (!$recursive) {
4610: $error = 1;
4611: }
4612: }
1.560 damieng 4613: } else {
1.576 raeburn 4614: if (exists($$olddata{$thiskey})) {
4615: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4616: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4617: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4618: } else {
4619: $error = 1;
4620: }
4621: }
4622: }
4623: if ($error) {
1.560 damieng 4624: $r->print('<div class="LC_error">'.
4625: &mt('Error deleting parameters').'</div>');
4626: }
4627: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4628: } else {
1.576 raeburn 4629: if ($altkey) {
4630: if (exists($$olddata{$altkey})) {
4631: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4632: push(@deldata,($altkey,$altkey.'.type'));
4633: }
4634: }
4635: if (exists($$olddata{$thiskey})) {
4636: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4637: push(@deldata,($thiskey,$thiskey.'.type'));
4638: }
4639: }
4640: } elsif (exists($$olddata{$thiskey})) {
4641: push(@deldata,($thiskey,$thiskey.'.type'));
4642: }
1.560 damieng 4643: }
1.473 amueller 4644: }
4645: }
4646: }
1.207 www 4647: # Store all course level
1.144 www 4648: my $delentries=$#deldata+1;
1.576 raeburn 4649: my @alldels;
4650: if (@delrec) {
4651: push(@alldels,@delrec);
4652: }
4653: if (@delnonrec) {
4654: push(@alldels,@delnonrec);
4655: }
4656: if (@deldata) {
4657: push(@alldels,@deldata);
4658: }
1.548 raeburn 4659: my @newdatakeys=keys(%newdata);
1.144 www 4660: my $putentries=$#newdatakeys+1;
1.576 raeburn 4661: my ($delresult,$devalidate);
4662: if (@alldels) {
4663: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4664: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4665: &log_parmset(\%loghash,1);
1.576 raeburn 4666: if ($delentries) {
4667: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4668: }
4669: } elsif ($delentries) {
1.560 damieng 4670: $r->print('<div class="LC_error">'.
4671: &mt('Error deleting parameters').'</div>');
4672: }
1.576 raeburn 4673: $devalidate = 1;
1.144 www 4674: }
4675: if ($putentries) {
1.560 damieng 4676: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4677: &log_parmset(\%newdata,0);
4678: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4679: } else {
4680: $r->print('<div class="LC_error">'.
4681: &mt('Error saving parameters').'</div>');
4682: }
1.576 raeburn 4683: $devalidate = 1;
4684: }
4685: if ($devalidate) {
1.560 damieng 4686: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4687: }
1.208 www 4688: }
1.207 www 4689:
1.563 damieng 4690: # Returns the username and domain from a key created in readdata from a resourcedata key.
4691: #
4692: # @param {string} $key - the key
4693: # @returns {Array}
1.208 www 4694: sub extractuser {
4695: my $key=shift;
1.350 albertel 4696: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4697: }
1.206 www 4698:
1.563 damieng 4699: # Parses a parameter key and returns the components.
4700: #
4701: # @param {string} $key -
4702: # @param {hash reference} $listdata -
4703: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4704: sub parse_listdata_key {
4705: my ($key,$listdata) = @_;
4706: # split into student/section affected, and
4707: # the realm (folder/resource part and parameter
1.446 bisitz 4708: my ($student,$realm) =
1.473 amueller 4709: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4710: # if course wide student would be undefined
4711: if (!defined($student)) {
1.560 damieng 4712: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4713: }
4714: # strip off the .type if it's not the Question type parameter
4715: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4716: $realm=~s/\.type//;
1.381 albertel 4717: }
4718: # split into resource+part and parameter name
1.388 albertel 4719: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4720: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4721: return ($student,$res,$part,$parm);
4722: }
4723:
1.563 damieng 4724: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
4725: #
4726: # @param {Apache2::RequestRec} $r - the Apache request
4727: # @param {hash reference} $resourcedata - parameter data returned by readdata
4728: # @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
4729: # @param {string} $sortorder - realmstudent|studentrealm
4730: # @param {string} $caller - name of the calling sub (overview|newoverview)
4731: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 4732: # @param {boolean} $readonly - true if editing not allowed
1.608 raeburn 4733: # @param {string} $parmlev - full|map
4734: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order
4735: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 4736: # @returns{integer} - number of $listdata parameters processed
1.208 www 4737: sub listdata {
1.608 raeburn 4738: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552 raeburn 4739:
1.207 www 4740: # Start list output
1.206 www 4741:
1.122 www 4742: my $oldsection='';
4743: my $oldrealm='';
4744: my $oldpart='';
1.123 www 4745: my $pointer=0;
1.124 www 4746: $tableopen=0;
1.145 www 4747: my $foundkeys=0;
1.248 albertel 4748: my %keyorder=&standardkeyorder();
1.594 raeburn 4749: my $readonlyall = $readonly;
1.381 albertel 4750:
1.552 raeburn 4751: my ($secidx,%grouphash);
4752: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4753: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 4754: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4755: %grouphash = &Apache::longroup::coursegroups();
4756: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 4757: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 4758: }
1.552 raeburn 4759: }
4760:
1.576 raeburn 4761: foreach my $key (sort {
1.560 damieng 4762: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
4763: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608 raeburn 4764: my ($aid,$bid);
4765: if ($caller eq 'newoverview') {
4766: if (ref($hash_for_realm) eq 'HASH') {
4767: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4768: my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4769: my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4770: $aid = $hash_for_realm->{$aurl};
4771: $bid = $hash_for_realm->{$burl};
4772: } elsif ($parmlev eq 'full') {
4773: $aid = $hash_for_realm->{$ares};
4774: $bid = $hash_for_realm->{$bres};
4775: }
4776: }
4777: }
1.381 albertel 4778:
1.560 damieng 4779: # get the numerical order for the param
4780: $aparm=$keyorder{'parameter_0_'.$aparm};
4781: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 4782:
1.560 damieng 4783: my $result=0;
1.381 albertel 4784:
1.560 damieng 4785: if ($sortorder eq 'realmstudent') {
1.381 albertel 4786: if ($ares ne $bres ) {
1.608 raeburn 4787: if ($caller eq 'newoverview') {
4788: if (ref($hash_for_realm) eq 'HASH') {
4789: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4790: $result = ($aid <=> $bid);
4791: } elsif ($parmlev eq 'full') {
4792: $result = ($aid <=> $bid);
4793: } else {
4794: $result = ($ares cmp $bres);
4795: }
4796: } else {
4797: $result = ($ares cmp $bres);
4798: }
4799: } else {
4800: $result = ($ares cmp $bres);
4801: }
1.446 bisitz 4802: } elsif ($astudent ne $bstudent) {
1.560 damieng 4803: $result = ($astudent cmp $bstudent);
4804: } elsif ($apart ne $bpart ) {
4805: $result = ($apart cmp $bpart);
4806: }
4807: } else {
4808: if ($astudent ne $bstudent) {
4809: $result = ($astudent cmp $bstudent);
4810: } elsif ($ares ne $bres ) {
1.608 raeburn 4811: if ($caller eq 'newoverview') {
4812: if (ref($hash_for_realm) eq 'HASH') {
4813: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4814: $result = ($aid <=> $bid);
4815: } elsif ($parmlev eq 'full') {
4816: $result = ($aid <=> $bid);
4817: } else {
4818: $result = ($ares cmp $bres);
4819: }
4820: } else {
4821: $result = ($ares cmp $bres);
4822: }
4823: } else {
4824: $result = ($ares cmp $bres);
4825: }
1.560 damieng 4826: } elsif ($apart ne $bpart ) {
4827: $result = ($apart cmp $bpart);
4828: }
1.473 amueller 4829: }
1.446 bisitz 4830:
1.560 damieng 4831: if (!$result) {
1.381 albertel 4832: if (defined($aparm) && defined($bparm)) {
1.560 damieng 4833: $result = ($aparm <=> $bparm);
1.381 albertel 4834: } elsif (defined($aparm)) {
1.560 damieng 4835: $result = -1;
1.381 albertel 4836: } elsif (defined($bparm)) {
1.560 damieng 4837: $result = 1;
4838: }
1.473 amueller 4839: }
1.381 albertel 4840:
1.560 damieng 4841: $result;
4842:
1.576 raeburn 4843: } keys(%{$listdata})) { # foreach my $key
4844: my $thiskey = $key;
1.560 damieng 4845: if ($$listdata{$thiskey.'.type'}) {
4846: my $thistype=$$listdata{$thiskey.'.type'};
4847: if ($$resourcedata{$thiskey.'.type'}) {
4848: $thistype=$$resourcedata{$thiskey.'.type'};
4849: }
4850: my ($middle,$part,$name)=
1.572 damieng 4851: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 4852: my $section=&mt('All Students');
1.594 raeburn 4853: $readonly = $readonlyall;
1.599 raeburn 4854: my $userscope;
1.576 raeburn 4855: my $showval = $$resourcedata{$thiskey};
1.560 damieng 4856: if ($middle=~/^\[(.*)\]/) {
4857: my $issection=$1;
4858: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
4859: my ($stuname,$studom) = ($1,$2);
4860: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4861: if (ref($classlist) eq 'HASH') {
4862: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
4863: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
4864: }
4865: }
4866: }
4867: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 4868: $userscope = 1;
1.560 damieng 4869: } else {
4870: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4871: if (exists($grouphash{$issection})) {
4872: $section=&mt('Group').': '.$issection;
4873: } elsif ($issection eq $env{'request.course.sec'}) {
4874: $section = &mt('Section').': '.$issection;
4875: } else {
4876: next;
1.552 raeburn 4877: }
1.560 damieng 4878: } else {
4879: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 4880: }
4881: }
1.560 damieng 4882: $middle=~s/^\[(.*)\]//;
4883: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4884: $readonly = 1;
4885: }
4886: $middle=~s/\.+$//;
4887: $middle=~s/^\.+//;
4888: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 4889: my ($is_map,$is_recursive,$mapurl,$maplevel);
4890: if ($caller eq 'overview') {
4891: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
4892: $mapurl = $1;
4893: $maplevel = $2;
4894: $is_map = 1;
4895: }
4896: } elsif ($caller eq 'newoverview') {
4897: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
4898: $mapurl = $1;
4899: $maplevel = $2;
4900: $is_map = 1;
4901: }
4902: }
4903: if ($is_map) {
1.560 damieng 4904: my $leveltitle = &mt('Folder/Map');
1.615 ! raeburn 4905: my $title = &Apache::lonnet::gettitle($mapurl);
1.608 raeburn 4906: if (ref($hash_for_realm) eq 'HASH') {
4907: if ($hash_for_realm->{$mapurl} eq '1') {
4908: $title = &mt('Main Content');
4909: }
4910: }
1.576 raeburn 4911: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
4912: if ($caller eq 'newoverview') {
4913: my $altkey = $thiskey;
4914: $altkey =~ s/\Q___(all)\E/___(rec)/;
4915: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
4916: $is_recursive = 1;
4917: if ($$resourcedata{$altkey.'.type'}) {
4918: $thistype=$$resourcedata{$altkey.'.type'};
4919: }
4920: $showval = $$resourcedata{$altkey};
4921: }
4922: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
4923: $thiskey =~ s/\Q___(rec)\E/___(all)/;
4924: $is_recursive = 1;
4925: }
1.560 damieng 4926: }
1.608 raeburn 4927: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560 damieng 4928: } elsif ($middle) {
4929: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609 raeburn 4930: next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560 damieng 4931: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
4932: ': '.&Apache::lonnet::gettitle($middle).
4933: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
4934: $id.')</span></span>';
4935: }
4936: if ($sortorder eq 'realmstudent') {
4937: if ($realm ne $oldrealm) {
4938: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
4939: $oldrealm=$realm;
4940: $oldsection='';
4941: }
4942: if ($section ne $oldsection) {
4943: $r->print(&tableend()."\n<h2>$section</h2>");
4944: $oldsection=$section;
4945: $oldpart='';
4946: }
1.552 raeburn 4947: } else {
1.560 damieng 4948: if ($section ne $oldsection) {
4949: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
4950: $oldsection=$section;
4951: $oldrealm='';
4952: }
4953: if ($realm ne $oldrealm) {
4954: $r->print(&tableend()."\n<h2>$realm</h2>");
4955: $oldrealm=$realm;
4956: $oldpart='';
1.552 raeburn 4957: }
4958: }
1.560 damieng 4959: if ($part ne $oldpart) {
4960: $r->print(&tableend().
4961: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
4962: $oldpart=$part;
1.556 raeburn 4963: }
1.560 damieng 4964: #
4965: # Ready to print
4966: #
1.470 raeburn 4967: my $parmitem = &standard_parameter_names($name);
1.576 raeburn 4968: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 4969: &Apache::loncommon::start_data_table_row().
4970: '<td><b>'.&mt($parmitem).
4971: '</b></td>');
4972: unless ($readonly) {
1.599 raeburn 4973: my $disabled;
4974: if (($name eq 'availablestudent') &&
4975: (($showval eq '') || ($userscope))) {
4976: $disabled = ' disabled="disabled"';
4977: }
1.560 damieng 4978: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 4979: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 4980: }
4981: $r->print('<td>');
4982: $foundkeys++;
4983: if (&isdateparm($thistype)) {
4984: my $jskey='key_'.$pointer;
4985: my $state;
4986: $pointer++;
4987: if ($readonly) {
4988: $state = 'disabled';
4989: }
4990: $r->print(
4991: &Apache::lonhtmlcommon::date_setter('parmform',
4992: $jskey,
1.576 raeburn 4993: $showval,
1.560 damieng 4994: '',1,$state));
4995: unless ($readonly) {
4996: $r->print(
4997: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 4998: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 4999: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 5000: &date_sanity_info($showval)
1.560 damieng 5001: );
5002: }
5003: } elsif ($thistype eq 'date_interval') {
5004: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 5005: $showval,$readonly));
1.560 damieng 5006: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 5007: if ($name eq 'availablestudent') {
5008: $readonly = 1;
5009: }
1.560 damieng 5010: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 5011: $showval,$name,$readonly));
1.560 damieng 5012: } else {
1.576 raeburn 5013: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 5014: }
1.560 damieng 5015: unless ($readonly) {
5016: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
5017: $thistype.'" />');
1.552 raeburn 5018: }
1.576 raeburn 5019: $r->print('</td>');
5020: if ($is_map) {
5021: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
5022: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
5023: } else {
5024: my ($disabled,$recon,$recoff);
5025: if ($readonly) {
5026: $disabled = ' disabled="disabled"';
5027: }
5028: if ($is_recursive) {
5029: $recon = ' checked="checked"';
5030: } else {
5031: $recoff = ' checked="checked"';
5032: }
5033: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
5034: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
5035: }
5036: }
5037: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 5038: }
1.121 www 5039: }
1.208 www 5040: return $foundkeys;
5041: }
5042:
1.563 damieng 5043: # Returns a string representing the interval, directly using form data matching the given key.
5044: # The returned string may also include information related to proctored exams.
5045: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
5046: #
5047: # @param {string} $key - suffix for form fields related to the interval
5048: # @returns {string}
1.385 albertel 5049: sub get_date_interval_from_form {
5050: my ($key) = @_;
5051: my $seconds = 0;
1.611 raeburn 5052: my $numnotnull = 0;
1.385 albertel 5053: foreach my $which (['days', 86400],
1.473 amueller 5054: ['hours', 3600],
5055: ['minutes', 60],
5056: ['seconds', 1]) {
1.560 damieng 5057: my ($name, $factor) = @{ $which };
5058: if (defined($env{'form.'.$name.'_'.$key})) {
1.611 raeburn 5059: unless ($env{'form.'.$name.'_'.$key} eq '') {
5060: $numnotnull ++;
5061: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
5062: }
1.560 damieng 5063: }
1.473 amueller 5064: }
1.560 damieng 5065: if (($key =~ /\.interval$/) &&
5066: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 5067: if ($env{'form.done_'.$key.'_buttontext'}) {
5068: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
5069: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
5070: if ($env{'form.done_'.$key} eq '_done_proctor') {
5071: $seconds .= '_proctor';
5072: }
5073: } else {
5074: $seconds .= $env{'form.done_'.$key};
5075: }
5076: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 5077: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 5078: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
5079: }
1.554 raeburn 5080: }
1.611 raeburn 5081: return if (!$numnotnull);
1.385 albertel 5082: return $seconds;
5083: }
5084:
5085:
1.563 damieng 5086: # Returns HTML to enter a text value for a parameter.
5087: #
5088: # @param {string} $thiskey - parameter key
5089: # @param {string} $showval - the current value
5090: # @param {boolean} $readonly - true if the field should not be made editable
5091: # @returns {string}
1.383 albertel 5092: sub default_selector {
1.552 raeburn 5093: my ($thiskey, $showval, $readonly) = @_;
5094: my $disabled;
5095: if ($readonly) {
5096: $disabled = ' disabled="disabled"';
5097: }
5098: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 5099: }
5100:
1.563 damieng 5101: # Returns HTML to enter allow/deny rules related to IP addresses.
5102: #
5103: # @param {string} $thiskey - parameter key
5104: # @param {string} $showval - the current value
5105: # @param {boolean} $readonly - true if the fields should not be made editable
5106: # @returns {string}
1.549 raeburn 5107: sub string_ip_selector {
1.552 raeburn 5108: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 5109: my %access = (
5110: allow => [],
5111: deny => [],
5112: );
5113: if ($showval ne '') {
5114: my @current;
5115: if ($showval =~ /,/) {
5116: @current = split(/,/,$showval);
5117: } else {
5118: @current = ($showval);
5119: }
5120: foreach my $item (@current) {
5121: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
5122: push(@{$access{'deny'}},$1);
5123: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
5124: push(@{$access{'allow'}},$item);
5125: }
5126: }
5127: }
5128: if (!@{$access{'allow'}}) {
5129: @{$access{'allow'}} = ('');
5130: }
5131: if (!@{$access{'deny'}}) {
5132: @{$access{'deny'}} = ('');
5133: }
1.552 raeburn 5134: my ($disabled,$addmore);
1.567 raeburn 5135: if ($readonly) {
1.552 raeburn 5136: $disabled=' disabled="disabled"';
5137: } else {
5138: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5139: }
1.549 raeburn 5140: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5141: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5142: foreach my $acctype ('allow','deny') {
5143: $output .= '
5144: <td valign="top">
5145: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5146: <div class="LC_string_ipacc_inner">'."\n";
5147: my $num = 0;
5148: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5149: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5150: if ($num > 0) {
5151: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5152: }
5153: $output .= '</div>'."\n";
5154: $num ++;
5155: }
5156: $output .= '
1.552 raeburn 5157: </div>'.$addmore.'
1.549 raeburn 5158: </div>
5159: </td>';
5160: }
5161: $output .= '
5162: </tr>
5163: </table>'."\n";
5164: return $output;
5165: }
5166:
1.588 raeburn 5167: sub string_deeplink_selector {
5168: my ($thiskey, $showval, $readonly) = @_;
1.597 raeburn 5169: my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601 raeburn 5170: %selectnull,%domlti,%crslti,@possmenus);
1.613 raeburn 5171: @components = ('state','others','listing','scope','protect','menus','target');
1.588 raeburn 5172: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5173: state => 'Access status',
5174: others => 'Hide other resources',
1.588 raeburn 5175: listing => 'In Contents and/or Gradebook',
5176: scope => 'Access scope for link',
1.601 raeburn 5177: protect => 'Link protection',
1.597 raeburn 5178: menus => 'Menu Items Displayed',
1.613 raeburn 5179: target => 'Embedded?',
1.588 raeburn 5180: );
5181: %options = (
1.601 raeburn 5182: state => ['only','off','both'],
5183: others => ['hide','unhide'],
1.588 raeburn 5184: listing => ['full','absent','grades','details','datestatus'],
5185: scope => ['res','map','rec'],
1.601 raeburn 5186: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5187: menus => ['std','colls'],
1.613 raeburn 5188: target => ['_self','_top'],
1.588 raeburn 5189: );
5190: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5191: only => 'deep only',
5192: off => 'deeplink off',
5193: both => 'regular + deep',
5194: hide => 'Hidden',
5195: unhide => 'Unhidden',
1.588 raeburn 5196: full => 'Listed (linked) in both',
5197: absent => 'Not listed',
5198: grades => 'Listed in grades only',
5199: details => 'Listed (unlinked) in both',
5200: datestatus => 'Listed (unlinked) inc. status in both',
5201: res => 'resource only',
5202: map => 'enclosing map/folder',
5203: rec => 'recursive map/folder',
1.601 raeburn 5204: none => 'not in use',
5205: key => 'key access',
5206: ltic => 'LTI access (course)',
5207: ltid => 'LTI access (domain)' ,
1.597 raeburn 5208: std => 'Standard (all menus)',
5209: colls => 'Numbered collection',
1.614 raeburn 5210: _self => 'Embedded',
1.613 raeburn 5211: _top => 'Not embedded',
1.597 raeburn 5212: );
5213: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5214: ltic => 'Select Launcher',
5215: ltid => 'Select Launcher',
1.597 raeburn 5216: colls => 'Select',
1.588 raeburn 5217: );
5218: if ($showval =~ /,/) {
1.597 raeburn 5219: %values=();
1.588 raeburn 5220: @current = split(/,/,$showval);
1.601 raeburn 5221: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5222: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5223: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5224: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5225: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5226: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613 raeburn 5227: ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.588 raeburn 5228: } else {
1.601 raeburn 5229: $defaults{'state'} = 'off',
5230: $defaults{'others'} = 'unhide',
1.588 raeburn 5231: $defaults{'listing'} = 'full';
5232: $defaults{'scope'} = 'res';
1.601 raeburn 5233: $defaults{'protect'} = 'none';
1.597 raeburn 5234: $defaults{'menus'} = '0';
1.613 raeburn 5235: $defaults{'target'} = '_top';
1.588 raeburn 5236: }
5237: my $disabled;
5238: if ($readonly) {
5239: $disabled=' disabled="disabled"';
5240: }
1.601 raeburn 5241: my %courselti =
5242: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
5243: $env{'course.'.$env{'request.course.id'}.'.domain'});
5244: foreach my $item (keys(%courselti)) {
5245: if (ref($courselti{$item}) eq 'HASH') {
5246: $crslti{$item} = $courselti{$item}{'name'};
5247: }
5248: }
5249: my %lti =
1.588 raeburn 5250: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 5251: 'linkprot');
1.588 raeburn 5252: foreach my $item (keys(%lti)) {
1.604 raeburn 5253: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
5254: $domlti{$item} = $lti{$item}{'name'};
1.588 raeburn 5255: }
5256: }
1.597 raeburn 5257: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5258: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5259: my ($num,$value) = split(/\%/,$item);
5260: if ($num =~ /^\d+$/) {
5261: push(@possmenus,$num);
5262: }
5263: }
5264: }
5265:
1.588 raeburn 5266: my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597 raeburn 5267: foreach my $item (@components) {
1.588 raeburn 5268: $output .= '<th>'.$titles{$item}.'</th>';
5269: }
5270: $output .= '</tr><tr>';
5271: foreach my $item (@components) {
5272: $output .= '<td>';
1.601 raeburn 5273: if (($item eq 'protect') || ($item eq 'menus')) {
1.588 raeburn 5274: my $selected = $values{$item};
5275: foreach my $option (@{$options{$item}}) {
1.601 raeburn 5276: if ($item eq 'protect') {
5277: if ($option eq 'ltid') {
5278: next unless (keys(%domlti));
5279: } elsif ($option eq 'ltic') {
5280: next unless (keys(%crslti));
5281: }
1.597 raeburn 5282: } elsif (($item eq 'menus') && ($option eq 'colls')) {
5283: next unless (@possmenus);
1.588 raeburn 5284: }
5285: my $checked;
1.597 raeburn 5286: if ($item eq 'menus') {
5287: if (($selected =~ /^\d+$/) && (@possmenus) &&
5288: (grep(/^\Q$selected\E$/,@possmenus))) {
5289: if ($option eq 'colls') {
5290: $checked = ' checked="checked"';
5291: }
5292: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
5293: $checked = ' checked="checked"';
5294: }
5295: } elsif ($selected =~ /^\Q$option\E/) {
1.588 raeburn 5296: $checked = ' checked="checked"';
5297: }
5298: my $onclick;
5299: unless ($readonly) {
5300: my $esc_key = &js_escape($thiskey);
5301: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
5302: }
5303: $output .= '<span class="LC_nobreak"><label>'.
5304: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
5305: $optiontext{$option}.'</label>';
1.601 raeburn 5306: if (($item eq 'protect') && ($option eq 'key')) {
1.588 raeburn 5307: my $visibility="hidden";
5308: my $currkey;
5309: if ($checked) {
5310: $visibility = "text";
5311: $currkey = (split(/\:/,$values{$item}))[1];
5312: }
5313: $output .= ' '.
1.597 raeburn 5314: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601 raeburn 5315: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588 raeburn 5316: my $display="none";
1.597 raeburn 5317: my ($current,$blankcheck,@possibles);
1.588 raeburn 5318: if ($checked) {
5319: $display = 'inline-block';
1.601 raeburn 5320: if (($option eq 'ltic') || ($option eq 'ltid')) {
1.597 raeburn 5321: $current = (split(/\:/,$selected))[1];
5322: } else {
5323: $current = $selected;
5324: }
1.588 raeburn 5325: } else {
5326: $blankcheck = ' selected="selected"';
5327: }
1.601 raeburn 5328: if ($option eq 'ltid') {
5329: @possibles = keys(%domlti);
5330: } elsif ($option eq 'ltic') {
5331: @possibles = keys(%crslti);
1.597 raeburn 5332: } else {
5333: @possibles = @possmenus;
5334: }
1.588 raeburn 5335: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
5336: ' style="display: '.$display.'"> <select name="'.
1.597 raeburn 5337: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
5338: if (@possibles > 1) {
5339: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
5340: '</option>'."\n";
5341: }
5342: foreach my $poss (sort { $a <=> $b } @possibles) {
1.588 raeburn 5343: my $selected;
1.597 raeburn 5344: if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588 raeburn 5345: $selected = ' selected="selected"';
5346: }
1.597 raeburn 5347: my $shown = $poss;
1.601 raeburn 5348: if ($option eq 'ltid') {
5349: $shown = $domlti{$poss};
5350: } elsif ($option eq 'ltic') {
5351: $shown = $crslti{$poss};
1.597 raeburn 5352: }
5353: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588 raeburn 5354: }
5355: $output .= '</select></div>';
5356: }
5357: $output .= '</span> ';
5358: }
5359: } else {
5360: my $selected = $values{$item};
5361: my $defsel;
5362: if ($selected eq '') {
5363: $defsel = ' selected="selected"';
5364: }
5365: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
5366: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
5367: foreach my $option (@{$options{$item}}) {
5368: $output .= '<option value="'.$option.'"';
5369: if ($option eq $selected) {
5370: $output .= ' selected="selected"';
5371: }
5372: $output .= '>'.$optiontext{$option}.'</option>';
5373: }
5374: $output .= '</select>';
5375: }
5376: $output .= '</td>';
5377: }
5378: $output .= '</tr></table>'."\n";
5379: return $output;
5380: }
5381:
1.560 damieng 5382:
5383: { # block using some constants related to parameter types (overview mode)
5384:
1.446 bisitz 5385: my %strings =
1.383 albertel 5386: (
5387: 'string_yesno'
5388: => [[ 'yes', 'Yes' ],
1.560 damieng 5389: [ 'no', 'No' ]],
1.383 albertel 5390: 'string_problemstatus'
5391: => [[ 'yes', 'Yes' ],
1.473 amueller 5392: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5393: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5394: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5395: 'string_questiontype'
5396: => [[ 'problem', 'Standard Problem'],
5397: [ 'survey', 'Survey'],
5398: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5399: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5400: [ 'anonsurvey', 'Anonymous Survey'],
5401: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5402: [ 'practice', 'Practice'],
5403: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5404: 'string_lenient'
5405: => [['yes', 'Yes' ],
5406: [ 'no', 'No' ],
1.549 raeburn 5407: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5408: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5409: 'string_discussvote'
5410: => [['yes','Yes'],
5411: ['notended','Yes, unless discussion ended'],
5412: ['no','No']],
1.549 raeburn 5413: 'string_ip'
5414: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5415: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5416: 'string_deeplink'
1.613 raeburn 5417: => [['on','Set choices for link protection, resource listing, access scope, shown menu items, and embedding']],
1.587 raeburn 5418: );
5419:
1.383 albertel 5420:
1.549 raeburn 5421: my %stringmatches = (
5422: 'string_lenient'
5423: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5424: 'string_ip'
5425: => [['_allowfrom_','[^\!]+'],
5426: ['_denyfrom_','\!']],
1.588 raeburn 5427: 'string_deeplink'
1.613 raeburn 5428: => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top)$']],
1.549 raeburn 5429: );
5430:
5431: my %stringtypes = (
5432: type => 'string_questiontype',
5433: lenient => 'string_lenient',
5434: retrypartial => 'string_yesno',
5435: discussvote => 'string_discussvote',
5436: examcode => 'string_examcode',
5437: acc => 'string_ip',
1.587 raeburn 5438: deeplink => 'string_deeplink',
1.549 raeburn 5439: );
5440:
1.563 damieng 5441: # Returns the possible values and titles for a given string type, or undef if there are none.
5442: # Used by courseprefs.
5443: #
5444: # @param {string} $string_type - a parameter type for strings
5445: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5446: sub standard_string_options {
5447: my ($string_type) = @_;
5448: if (ref($strings{$string_type}) eq 'ARRAY') {
5449: return $strings{$string_type};
5450: }
5451: return;
5452: }
1.383 albertel 5453:
1.563 damieng 5454: # Returns regular expressions to match kinds of string types, or undef if there are none.
5455: #
5456: # @param {string} $string_type - a parameter type for strings
5457: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5458: sub standard_string_matches {
5459: my ($string_type) = @_;
5460: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5461: return $stringmatches{$string_type};
5462: }
5463: return;
5464: }
5465:
1.563 damieng 5466: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5467: #
5468: # @param {string} $name - parameter name
5469: # @returns {string}
1.549 raeburn 5470: sub get_stringtype {
5471: my ($name) = @_;
5472: if (exists($stringtypes{$name})) {
5473: return $stringtypes{$name};
5474: }
5475: return;
5476: }
5477:
1.563 damieng 5478: # Returns HTML to edit a string parameter.
5479: #
5480: # @param {string} $thistype - parameter type
5481: # @param {string} $thiskey - parameter key
5482: # @param {string} $showval - parameter current value
5483: # @param {string} $name - parameter name
5484: # @param {boolean} $readonly - true if the values should not be made editable
5485: # @returns {string}
1.383 albertel 5486: sub string_selector {
1.552 raeburn 5487: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5488:
1.383 albertel 5489: if (!exists($strings{$thistype})) {
1.552 raeburn 5490: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5491: }
5492:
1.504 raeburn 5493: my %skiptype;
1.514 raeburn 5494: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5495: ($thistype eq 'string_lenient') ||
5496: ($thistype eq 'string_discussvote') ||
5497: ($thistype eq 'string_ip') ||
1.588 raeburn 5498: ($thistype eq 'string_deeplink') ||
1.560 damieng 5499: ($name eq 'retrypartial')) {
1.504 raeburn 5500: my ($got_chostname,$chostname,$cmajor,$cminor);
5501: foreach my $possibilities (@{ $strings{$thistype} }) {
5502: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5503: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5504: my $parmmatch;
5505: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5506: foreach my $item (@{$stringmatches{$thistype}}) {
5507: if (ref($item) eq 'ARRAY') {
5508: if ($parmval eq $item->[0]) {
5509: $parmmatch = $parmval;
5510: $parmval = '';
5511: last;
5512: }
5513: }
5514: }
5515: }
5516: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5517: if ($needsrelease) {
5518: unless ($got_chostname) {
1.514 raeburn 5519: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5520: $got_chostname = 1;
5521: }
1.557 raeburn 5522: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5523: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5524: if ($needsnewer) {
1.549 raeburn 5525: if ($parmmatch ne '') {
5526: $skiptype{$parmmatch} = 1;
5527: } elsif ($parmval ne '') {
5528: $skiptype{$parmval} = 1;
5529: }
1.504 raeburn 5530: }
5531: }
5532: }
5533: }
1.549 raeburn 5534:
5535: if ($thistype eq 'string_ip') {
1.552 raeburn 5536: return &string_ip_selector($thiskey,$showval,$readonly);
1.588 raeburn 5537: } elsif ($thistype eq 'string_deeplink') {
5538: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5539: }
1.504 raeburn 5540:
1.552 raeburn 5541: my ($result,$disabled);
5542:
5543: if ($readonly) {
5544: $disabled = ' disabled="disabled"';
5545: }
1.504 raeburn 5546: my $numinrow = 3;
5547: if ($thistype eq 'string_problemstatus') {
5548: $numinrow = 2;
5549: } elsif ($thistype eq 'string_questiontype') {
5550: if (keys(%skiptype) > 0) {
5551: $numinrow = 4;
5552: }
5553: }
5554: my $rem;
5555: if (ref($strings{$thistype}) eq 'ARRAY') {
5556: my $i=0;
5557: foreach my $possibilities (@{ $strings{$thistype} }) {
5558: next unless (ref($possibilities) eq 'ARRAY');
5559: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5560: next if ($skiptype{$name});
1.504 raeburn 5561: $rem = $i%($numinrow);
5562: if ($rem == 0) {
5563: if ($i > 0) {
5564: $result .= '</tr>';
5565: }
5566: $result .= '<tr>';
5567: }
1.549 raeburn 5568: my $colspan;
5569: if ($i == @{ $strings{$thistype} }-1) {
5570: $rem = @{ $strings{$thistype} }%($numinrow);
5571: if ($rem) {
5572: my $colsleft = $numinrow - $rem;
5573: if ($colsleft) {
5574: $colspan = $colsleft+1;
5575: $colspan = ' colspan="'.$colspan.'"';
5576: }
5577: }
5578: }
5579: my ($add,$onchange,$css_class);
5580: if ($thistype eq 'string_lenient') {
5581: if ($name eq 'weighted') {
5582: my $display;
5583: my %relatives = &Apache::lonlocal::texthash(
5584: corrchkd => 'Correct (checked)',
5585: corrunchkd => 'Correct (unchecked)',
5586: incorrchkd => 'Incorrect (checked)',
5587: incorrunchkd => 'Incorrect (unchecked)',
5588: );
5589: my %textval = (
5590: corrchkd => '1.0',
5591: corrunchkd => '1.0',
5592: incorrchkd => '0.0',
5593: incorrunchkd => '0.0',
5594: );
5595: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
5596: $textval{'corrchkd'} = $1;
5597: $textval{'corrunchkd'} = $2;
5598: $textval{'incorrchkd'} = $3;
5599: $textval{'incorrunchkd'} = $4;
5600: $display = 'inline';
5601: $showval = $name;
5602: } else {
5603: $display = 'none';
5604: }
5605: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
5606: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
5607: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
5608: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
5609: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 5610: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 5611: '</td></tr>';
5612: }
5613: $add .= '</table></div>'."\n";
5614: }
5615: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
5616: $css_class = ' class="LC_lenient_radio"';
5617: }
5618: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 5619: '<span class="LC_nobreak"><label>'.
5620: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 5621: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 5622: if ($showval eq $name) {
5623: $result .= ' checked="checked"';
5624: }
1.549 raeburn 5625: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 5626: $i++;
5627: }
5628: $result .= '</tr>';
1.473 amueller 5629: }
1.504 raeburn 5630: if ($result) {
5631: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 5632: }
5633: return $result;
5634: }
5635:
1.554 raeburn 5636: my %intervals =
5637: (
5638: 'date_interval'
5639: => [[ 'done', 'Yes' ],
1.558 raeburn 5640: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 5641: [ '', 'No' ]],
5642: );
5643:
5644: my %intervalmatches = (
5645: 'date_interval'
1.559 raeburn 5646: => [['done','\d+_done(|\:[^\:]+\:)$'],
5647: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 5648: );
5649:
5650: my %intervaltypes = (
5651: interval => 'date_interval',
5652: );
5653:
1.563 damieng 5654: # Returns regular expressions to match kinds of interval type, or undef if there are none.
5655: #
5656: # @param {string} $interval_type - a parameter type for intervals
5657: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 5658: sub standard_interval_matches {
5659: my ($interval_type) = @_;
5660: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
5661: return $intervalmatches{$interval_type};
5662: }
5663: return;
5664: }
5665:
1.563 damieng 5666: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
5667: #
5668: # @param {string} $name - parameter name
5669: # @returns {string}
1.554 raeburn 5670: sub get_intervaltype {
5671: my ($name) = @_;
5672: if (exists($intervaltypes{$name})) {
5673: return $intervaltypes{$name};
5674: }
5675: return;
5676: }
5677:
1.563 damieng 5678: # Returns the possible values and titles for a given interval type, or undef if there are none.
5679: # Used by courseprefs.
5680: #
5681: # @param {string} $interval_type - a parameter type for intervals
5682: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 5683: sub standard_interval_options {
5684: my ($interval_type) = @_;
5685: if (ref($intervals{$interval_type}) eq 'ARRAY') {
5686: return $intervals{$interval_type};
5687: }
5688: return;
5689: }
5690:
1.563 damieng 5691: # Returns HTML to edit a date interval parameter.
5692: #
5693: # @param {string} $thiskey - parameter key
5694: # @param {string} $name - parameter name
5695: # @param {string} $showval - parameter current value
5696: # @param {boolean} $readonly - true if the values should not be made editable
5697: # @returns {string}
1.554 raeburn 5698: sub date_interval_selector {
5699: my ($thiskey, $name, $showval, $readonly) = @_;
5700: my ($result,%skipval);
5701: if ($name eq 'interval') {
5702: my $intervaltype = &get_intervaltype($name);
5703: my ($got_chostname,$chostname,$cmajor,$cminor);
5704: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
5705: next unless (ref($possibilities) eq 'ARRAY');
5706: my ($parmval, $description) = @{ $possibilities };
5707: my $parmmatch;
5708: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
5709: foreach my $item (@{$intervalmatches{$intervaltype}}) {
5710: if (ref($item) eq 'ARRAY') {
5711: if ($parmval eq $item->[0]) {
5712: $parmmatch = $parmval;
5713: $parmval = '';
5714: last;
5715: }
5716: }
5717: }
5718: }
5719: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
5720: if ($needsrelease) {
5721: unless ($got_chostname) {
5722: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
5723: $got_chostname = 1;
5724: }
1.557 raeburn 5725: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 5726: $needsrelease,$cmajor,$cminor);
5727: if ($needsnewer) {
5728: if ($parmmatch ne '') {
5729: $skipval{$parmmatch} = 1;
5730: } elsif ($parmval ne '') {
5731: $skipval{$parmval} = 1;
5732: }
5733: }
5734: }
5735: }
5736: }
5737:
5738: my $currval = $showval;
5739: foreach my $which (['days', 86400, 31],
5740: ['hours', 3600, 23],
5741: ['minutes', 60, 59],
5742: ['seconds', 1, 59]) {
1.560 damieng 5743: my ($name, $factor, $max) = @{ $which };
5744: my $amount = int($showval/$factor);
5745: $showval %= $factor;
5746: my %select = ((map {$_ => $_} (0..$max)),
5747: 'select_form_order' => [0..$max]);
1.611 raeburn 5748: if ($currval eq '') {
5749: unshift(@{$select{'select_form_order'}},'');
5750: $select{''} = '';
5751: $amount = '';
5752: }
1.560 damieng 5753: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
5754: \%select,'',$readonly);
5755: $result .= ' '.&mt($name);
1.554 raeburn 5756: }
5757: if ($name eq 'interval') {
5758: unless ($skipval{'done'}) {
5759: my $checkedon = '';
1.611 raeburn 5760: my $checkedoff = '';
1.558 raeburn 5761: my $checkedproc = '';
5762: my $currproctorkey = '';
5763: my $currprocdisplay = 'hidden';
1.559 raeburn 5764: my $currdonetext = &mt('Done');
5765: if ($currval =~ /^(?:\d+)_done$/) {
5766: $checkedon = ' checked="checked"';
5767: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
5768: $currdonetext = $1;
1.554 raeburn 5769: $checkedon = ' checked="checked"';
1.558 raeburn 5770: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
5771: $currproctorkey = $1;
5772: $checkedproc = ' checked="checked"';
5773: $currprocdisplay = 'text';
1.559 raeburn 5774: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
5775: $currdonetext = $1;
5776: $currproctorkey = $2;
5777: $checkedproc = ' checked="checked"';
5778: $currprocdisplay = 'text';
1.611 raeburn 5779: } elsif ($currval ne '') {
5780: $checkedoff = ' checked="checked"';
5781: } else {
5782: $currdonetext = '';
1.554 raeburn 5783: }
1.558 raeburn 5784: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 5785: my $disabled;
5786: if ($readonly) {
5787: $disabled = ' disabled="disabled"';
5788: }
1.558 raeburn 5789: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 5790: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 5791: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 5792: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 5793: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 5794: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 5795: &mt('Yes, with proctor key').'</label>'.
5796: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 5797: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 5798: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611 raeburn 5799: '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
5800: &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 5801: }
5802: }
5803: unless ($readonly) {
5804: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
5805: }
5806: return $result;
5807: }
5808:
1.563 damieng 5809: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
5810: #
5811: # @param {string} $name - parameter name
5812: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
5813: # @param {string} $value - parameter value
5814: # @param {string} $chostname - course server name
5815: # @param {integer} $cmajor - major version number
5816: # @param {integer} $cminor - minor version number
5817: # @param {string} $needsrelease - release version needed (major.minor)
5818: # @returns {string}
1.549 raeburn 5819: sub oldversion_warning {
1.557 raeburn 5820: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
5821: my $standard_name = &standard_parameter_names($name);
5822: if ($namematch) {
5823: my $level = &standard_parameter_levels($namematch);
5824: my $msg = '';
5825: if ($level) {
5826: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
5827: $standard_name,'<b>','</b>','"'.$level.'"');
5828: } else {
5829: $msg = &mt('[_1] was [_2]not[_3] set.',
5830: $standard_name,'<b>','</b>');
5831: }
5832: return '<p class="LC_warning">'.$msg.'<br />'.
5833: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5834: $cmajor.'.'.$cminor,$chostname,
5835: $needsrelease).
5836: '</p>';
5837: }
1.549 raeburn 5838: my $desc;
5839: my $stringtype = &get_stringtype($name);
5840: if ($stringtype ne '') {
5841: if ($name eq 'examcode') {
5842: $desc = $value;
5843: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
5844: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
5845: next unless (ref($possibilities) eq 'ARRAY');
5846: my ($parmval, $description) = @{ $possibilities };
5847: my $parmmatch;
5848: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
5849: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
5850: if (ref($item) eq 'ARRAY') {
5851: my ($regexpname,$pattern) = @{$item};
5852: if ($parmval eq $regexpname) {
5853: if ($value =~ /$pattern/) {
5854: $desc = $description;
5855: $parmmatch = 1;
5856: last;
5857: }
5858: }
5859: }
5860: }
5861: last if ($parmmatch);
5862: } elsif ($parmval eq $value) {
5863: $desc = $description;
5864: last;
5865: }
5866: }
5867: }
5868: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
5869: my $now = time;
5870: if ($value =~ /^\d+$/) {
5871: if ($name eq 'printstartdate') {
5872: if ($value > $now) {
5873: $desc = &Apache::lonlocal::locallocaltime($value);
5874: }
5875: } elsif ($name eq 'printenddate') {
5876: if ($value < $now) {
5877: $desc = &Apache::lonlocal::locallocaltime($value);
5878: }
5879: }
5880: }
5881: }
5882: return '<p class="LC_warning">'.
1.557 raeburn 5883: &mt('[_1] was [_2]not[_3] set to [_4].',
5884: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
5885: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5886: $cmajor.'.'.$cminor,$chostname,
5887: $needsrelease).
5888: '</p>';
1.549 raeburn 5889: }
5890:
1.560 damieng 5891: } # end of block using some constants related to parameter types
5892:
1.549 raeburn 5893:
1.563 damieng 5894:
5895: # Shifts all start and end dates in the current course by $shift.
1.389 www 5896: #
1.563 damieng 5897: # @param {integer} $shift - time to shift, in seconds
5898: # @returns {string} - error name or 'ok'
1.389 www 5899: sub dateshift {
1.594 raeburn 5900: my ($shift,$numchanges)=@_;
1.389 www 5901: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5902: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 5903: my $sec = $env{'request.course.sec'};
1.595 raeburn 5904: my $secgrpregex;
5905: if ($sec ne '') {
5906: my @groups;
5907: if ($env{'request.course.groups'} ne '') {
5908: @groups = split(/:/,$env{'request.course.groups'});
5909: }
5910: if (@groups) {
5911: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
5912: } else {
5913: $secgrpregex = $sec;
5914: }
5915: }
1.389 www 5916: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
5917: # ugly retro fix for broken version of types
1.548 raeburn 5918: foreach my $key (keys(%data)) {
1.389 www 5919: if ($key=~/\wtype$/) {
5920: my $newkey=$key;
5921: $newkey=~s/type$/\.type/;
5922: $data{$newkey}=$data{$key};
5923: delete $data{$key};
5924: }
5925: }
1.391 www 5926: my %storecontent=();
1.389 www 5927: # go through all parameters and look for dates
1.548 raeburn 5928: foreach my $key (keys(%data)) {
1.389 www 5929: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 5930: if ($sec ne '') {
1.595 raeburn 5931: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 5932: }
1.389 www 5933: my $newdate=$data{$key}+$shift;
1.594 raeburn 5934: $$numchanges ++;
1.391 www 5935: $storecontent{$key}=$newdate;
1.389 www 5936: }
5937: }
1.391 www 5938: my $reply=&Apache::lonnet::cput
5939: ('resourcedata',\%storecontent,$dom,$crs);
5940: if ($reply eq 'ok') {
5941: &log_parmset(\%storecontent);
5942: }
5943: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
5944: return $reply;
1.389 www 5945: }
5946:
1.563 damieng 5947: # Overview mode UI to edit course parameters.
5948: #
5949: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 5950: sub newoverview {
1.568 raeburn 5951: my ($r,$parm_permission) = @_;
1.280 albertel 5952:
1.208 www 5953: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5954: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 5955: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 5956: my $readonly = 1;
5957: if ($parm_permission->{'edit'}) {
5958: undef($readonly);
5959: }
1.414 droeschl 5960: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 5961: text=>"Overview Mode"});
1.523 raeburn 5962:
5963: my %loaditems = (
1.549 raeburn 5964: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 5965: );
5966: my $js = '
5967: <script type="text/javascript">
5968: // <![CDATA[
5969: '.
5970: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
5971: &showhide_js()."\n".
1.549 raeburn 5972: &toggleparmtextbox_js()."\n".
5973: &validateparms_js()."\n".
5974: &ipacc_boxes_js()."\n".
1.558 raeburn 5975: &done_proctor_js()."\n".
1.588 raeburn 5976: &deeplink_js()."\n".
1.523 raeburn 5977: '// ]]>
5978: </script>
5979: ';
1.549 raeburn 5980:
1.523 raeburn 5981: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
5982: {'add_entries' => \%loaditems,});
1.298 albertel 5983: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 5984: $r->print($start_page.$breadcrumbs);
1.531 raeburn 5985: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 5986: $r->print(<<ENDOVER);
1.549 raeburn 5987: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208 www 5988: ENDOVER
1.211 www 5989: my @ids=();
5990: my %typep=();
5991: my %keyp=();
5992: my %allparms=();
5993: my %allparts=();
5994: my %allmaps=();
5995: my %mapp=();
5996: my %symbp=();
5997: my %maptitles=();
5998: my %uris=();
5999: my %keyorder=&standardkeyorder();
6000: my %defkeytype=();
6001:
6002: my %alllevs=();
6003: $alllevs{'Resource Level'}='full';
1.215 www 6004: $alllevs{'Map/Folder Level'}='map';
1.211 www 6005: $alllevs{'Course Level'}='general';
6006:
6007: my $csec=$env{'form.csec'};
1.269 raeburn 6008: my $cgroup=$env{'form.cgroup'};
1.211 www 6009:
6010: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
6011: my $pschp=$env{'form.pschp'};
1.506 www 6012:
1.211 www 6013: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 6014: if (!@psprt) { $psprt[0]='all'; }
1.211 www 6015:
1.446 bisitz 6016: my @selected_sections =
1.473 amueller 6017: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 6018: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 6019: foreach my $sec (@selected_sections) {
6020: if ($sec eq 'all') {
1.211 www 6021: @selected_sections = ('all');
6022: }
6023: }
1.552 raeburn 6024: if ($env{'request.course.sec'} ne '') {
6025: @selected_sections = ($env{'request.course.sec'});
6026: }
1.269 raeburn 6027: my @selected_groups =
6028: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 6029:
6030: my $pssymb='';
6031: my $parmlev='';
1.446 bisitz 6032:
1.211 www 6033: unless ($env{'form.parmlev'}) {
6034: $parmlev = 'map';
6035: } else {
6036: $parmlev = $env{'form.parmlev'};
6037: }
6038:
1.446 bisitz 6039: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 6040: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 6041: \%keyorder,\%defkeytype,$pssymb);
1.211 www 6042:
1.374 albertel 6043: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 6044: @psprt = keys(%allparts);
1.374 albertel 6045: }
1.211 www 6046: # Menu to select levels, etc
6047:
1.456 bisitz 6048: $r->print('<div class="LC_Box">');
1.445 neumanie 6049: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 6050: $r->print('<div>');
1.523 raeburn 6051: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 6052: &levelmenu($r,\%alllevs,$parmlev);
1.610 raeburn 6053: $r->print(&Apache::lonhtmlcommon::row_closure());
6054: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447 bisitz 6055: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6056: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6057: $r->print('</div></div>');
1.446 bisitz 6058:
1.456 bisitz 6059: $r->print('<div class="LC_Box">');
1.452 bisitz 6060: $r->print('<div>');
1.581 raeburn 6061: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 6062: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 6063: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 6064: my $sectionselector = §ionmenu(\@selected_sections);
6065: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 6066: $r->print('<table>'.
1.553 raeburn 6067: '<tr><th>'.&mt('Parts').'</th>');
6068: if ($sectionselector) {
6069: $r->print('<th>'.&mt('Section(s)').'</th>');
6070: }
6071: if ($groupselector) {
6072: $r->print('<th>'.&mt('Group(s)').'</th>');
6073: }
6074: $r->print('</tr><tr><td>');
1.211 www 6075: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 6076: $r->print('</td>');
6077: if ($sectionselector) {
6078: $r->print('<td>'.$sectionselector.'</td>');
6079: }
6080: if ($groupselector) {
6081: $r->print('<td>'.$groupselector.'</td>');
6082: }
6083: $r->print('</tr></table>');
1.447 bisitz 6084: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6085: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6086: $r->print('</div></div>');
6087:
1.456 bisitz 6088: $r->print('<div class="LC_Box">');
1.452 bisitz 6089: $r->print('<div>');
1.214 www 6090: my $sortorder=$env{'form.sortorder'};
6091: unless ($sortorder) { $sortorder='realmstudent'; }
1.612 raeburn 6092: &sortmenu($r,$sortorder,'newoverview');
1.445 neumanie 6093: $r->print('</div></div>');
1.446 bisitz 6094:
1.214 www 6095: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446 bisitz 6096:
1.211 www 6097: # Build the list data hash from the specified parms
6098:
6099: my $listdata;
6100: %{$listdata}=();
6101:
6102: foreach my $cat (@pscat) {
1.269 raeburn 6103: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
6104: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 6105: }
6106:
1.212 www 6107: if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211 www 6108:
1.481 amueller 6109: if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211 www 6110:
6111: # Read modified data
6112:
1.481 amueller 6113: my $resourcedata=&readdata($crs,$dom);
1.211 www 6114:
6115: # List data
6116:
1.608 raeburn 6117: my $hash_for_realm;
6118: if (($parmlev eq 'map') && (keys(%allmaps))) {
6119: %{$hash_for_realm} = reverse(%allmaps);
6120: } elsif (($parmlev eq 'full') && (keys(%symbp))) {
6121: for (my $i=0; $i<@ids; $i++) {
6122: $hash_for_realm->{$symbp{$ids[$i]}} = $i;
6123: }
6124: }
6125: &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568 raeburn 6126: }
6127: $r->print(&tableend());
6128: unless ($readonly) {
6129: $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211 www 6130: }
1.568 raeburn 6131: $r->print('</form>');
1.507 www 6132: &endSettingsScreen($r);
6133: $r->print(&Apache::loncommon::end_page());
1.208 www 6134: }
6135:
1.563 damieng 6136: # Fills $listdata with parameter information.
6137: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
6138: # The non-type value is always 1.
6139: #
6140: # @param {string} $cat - parameter name
1.566 damieng 6141: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 6142: # @param {string} $parmlev - selected level value (full|map|general), or ''
6143: # @param {hash reference} $listdata - the parameter data that will be modified
6144: # @param {array reference} $psprt - selected parts
6145: # @param {array reference} $selections - selected sections
6146: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6147: # @param {hash reference} $allmaps - hash map pc -> map src
6148: # @param {array reference} $ids - resource and map ids
6149: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6150: sub secgroup_lister {
6151: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6152: foreach my $item (@{$selections}) {
6153: foreach my $part (@{$psprt}) {
6154: my $rootparmkey=$env{'request.course.id'};
6155: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6156: $rootparmkey.='.['.$item.']';
6157: }
6158: if ($parmlev eq 'general') {
6159: # course-level parameter
6160: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6161: $$listdata{$newparmkey}=1;
6162: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6163: } elsif ($parmlev eq 'map') {
6164: # map-level parameter
1.548 raeburn 6165: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6166: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6167: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6168: $$listdata{$newparmkey}=1;
6169: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6170: }
6171: } else {
6172: # resource-level parameter
6173: foreach my $rid (@{$ids}) {
6174: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6175: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6176: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6177: $$listdata{$newparmkey}=1;
6178: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6179: }
6180: }
6181: }
6182: }
6183: }
6184:
1.563 damieng 6185: # UI to edit parameter settings starting with a list of all existing parameters.
6186: # (called by setoverview action)
6187: #
6188: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6189: sub overview {
1.568 raeburn 6190: my ($r,$parm_permission) = @_;
1.208 www 6191: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6192: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6193: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6194: my $readonly = 1;
6195: if ($parm_permission->{'edit'}) {
6196: undef($readonly);
6197: }
1.549 raeburn 6198: my $js = '<script type="text/javascript">'."\n".
6199: '// <![CDATA['."\n".
6200: &toggleparmtextbox_js()."\n".
6201: &validateparms_js()."\n".
6202: &ipacc_boxes_js()."\n".
1.558 raeburn 6203: &done_proctor_js()."\n".
1.588 raeburn 6204: &deeplink_js()."\n".
1.549 raeburn 6205: '// ]]>'."\n".
6206: '</script>'."\n";
1.414 droeschl 6207: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6208: text=>"Overview Mode"});
1.549 raeburn 6209: my %loaditems = (
6210: 'onload' => "showHideLenient();",
6211: );
6212:
6213: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6214: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6215: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6216: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6217: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6218:
1.208 www 6219: # Store modified
6220:
1.568 raeburn 6221: unless ($readonly) {
6222: &storedata($r,$crs,$dom);
6223: }
1.208 www 6224:
6225: # Read modified data
6226:
1.552 raeburn 6227: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6228:
1.214 www 6229:
6230: my $sortorder=$env{'form.sortorder'};
6231: unless ($sortorder) { $sortorder='realmstudent'; }
1.608 raeburn 6232: &sortmenu($r,$sortorder,'overview');
1.214 www 6233:
1.568 raeburn 6234: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6235:
6236: if ($readonly) {
6237: $r->print('<p>'.$submitbutton.'</p>');
6238: }
6239:
1.208 www 6240: # List data
6241:
1.568 raeburn 6242: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6243: $r->print(&tableend().'<p>');
6244: if ($foundkeys) {
6245: unless ($readonly) {
6246: $r->print('<p>'.$submitbutton.'</p>');
6247: }
6248: } else {
6249: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6250: }
6251: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6252: }
1.121 www 6253:
1.560 damieng 6254: # Unused sub.
1.563 damieng 6255: #
6256: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6257: sub clean_parameters {
6258: my ($r) = @_;
6259: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6260: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6261:
1.414 droeschl 6262: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6263: text=>"Clean Parameters"});
1.333 albertel 6264: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6265: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6266: $r->print(<<ENDOVER);
6267: $start_page
6268: $breadcrumbs
6269: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6270: ENDOVER
6271: # Store modified
6272:
6273: &storedata($r,$crs,$dom);
6274:
6275: # Read modified data
6276:
6277: my $resourcedata=&readdata($crs,$dom);
6278:
6279: # List data
6280:
6281: $r->print('<h3>'.
1.473 amueller 6282: &mt('These parameters refer to resources that do not exist.').
6283: '</h3>'.
6284: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6285: '<br />');
1.333 albertel 6286: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6287: '<tr>'.
6288: '<th>'.&mt('Delete').'</th>'.
6289: '<th>'.&mt('Parameter').'</th>'.
6290: '</tr>');
1.333 albertel 6291: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6292: next if (!exists($resourcedata->{$thiskey.'.type'})
6293: && $thiskey=~/\.type$/);
6294: my %data = &parse_key($thiskey);
6295: if (1) { #exists($data{'realm_exists'})
6296: #&& !$data{'realm_exists'}) {
6297: $r->print(&Apache::loncommon::start_data_table_row().
6298: '<tr>'.
6299: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6300:
6301: $r->print('<td>');
6302: my $display_value = $resourcedata->{$thiskey};
6303: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6304: $display_value =
6305: &Apache::lonlocal::locallocaltime($display_value);
6306: }
1.470 raeburn 6307: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6308: $parmitem = &mt($parmitem);
1.560 damieng 6309: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6310: $parmitem,$resourcedata->{$thiskey}));
6311: $r->print('<br />');
6312: if ($data{'scope_type'} eq 'all') {
6313: $r->print(&mt('All users'));
6314: } elsif ($data{'scope_type'} eq 'user') {
6315: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6316: } elsif ($data{'scope_type'} eq 'secgroup') {
6317: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6318: }
6319: $r->print('<br />');
6320: if ($data{'realm_type'} eq 'all') {
6321: $r->print(&mt('All Resources'));
6322: } elsif ($data{'realm_type'} eq 'folder') {
6323: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6324: } elsif ($data{'realm_type'} eq 'symb') {
6325: my ($map,$resid,$url) =
6326: &Apache::lonnet::decode_symb($data{'realm'});
6327: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6328: $url.' <br /> ',
6329: $resid.' <br /> ',$map));
6330: }
6331: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6332: $r->print('</td></tr>');
6333:
1.473 amueller 6334: }
1.333 albertel 6335: }
6336: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6337: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6338: '</p></form>');
6339: &endSettingsScreen($r);
6340: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6341: }
6342:
1.563 damieng 6343: # UI to shift all dates (called by dateshift1 action).
6344: # Used by overview mode.
6345: #
6346: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6347: sub date_shift_one {
6348: my ($r) = @_;
6349: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6350: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6351: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6352: my $sec = $env{'request.course.sec'};
1.414 droeschl 6353: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6354: text=>"Shifting Dates"});
1.594 raeburn 6355: my $submit_text = &mt('Shift all dates accordingly');
6356: if ($sec ne '') {
1.595 raeburn 6357: my @groups;
6358: if ($env{'request.course.groups'} ne '') {
6359: @groups = split(/:/,$env{'request.course.groups'});
6360: }
6361: if (@groups) {
6362: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6363: } else {
6364: $submit_text = &mt("Shift dates set just for your section, accordingly");
6365: }
1.594 raeburn 6366: }
1.390 www 6367: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6368: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6369: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6370: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6371: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6372: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6373: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6374: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6375: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6376: 'timeshifted',
6377: $env{'form.timebase'},,
6378: '').
6379: '</td></tr></table>'.
6380: '<input type="hidden" name="action" value="dateshift2" />'.
6381: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6382: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6383: &endSettingsScreen($r);
1.390 www 6384: $r->print(&Apache::loncommon::end_page());
6385: }
6386:
1.563 damieng 6387: # UI to shift all dates (second form).
6388: #
6389: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6390: sub date_shift_two {
6391: my ($r) = @_;
6392: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6393: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6394: my $sec = $env{'request.course.sec'};
1.531 raeburn 6395: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6396: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6397: text=>"Shifting Dates"});
1.390 www 6398: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6399: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6400: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6401: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6402: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6403: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6404: if ($sec ne '') {
1.595 raeburn 6405: my @groups;
6406: if ($env{'request.course.groups'} ne '') {
6407: @groups = split(/:/,$env{'request.course.groups'});
6408: }
6409: if (@groups) {
6410: $r->print('<p>'.
6411: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6412: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6413: &Apache::lonlocal::locallocaltime($timeshifted)).
6414: '</p>');
6415: } else {
6416: $r->print('<p>'.
6417: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6418: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6419: &Apache::lonlocal::locallocaltime($timeshifted)).
6420: '</p>');
6421: }
1.594 raeburn 6422: } else {
6423: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6424: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6425: &Apache::lonlocal::locallocaltime($timeshifted)).
6426: '</p>');
6427: }
1.390 www 6428: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6429: my $numchanges = 0;
6430: my $result = &dateshift($delta,\$numchanges);
6431: if ($result eq 'ok') {
6432: $r->print(
6433: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6434: $numchanges)));
6435: } elsif ($result eq 'con_delayed') {
6436: $r->print(
6437: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6438: $numchanges)));
6439: } else {
6440: $r->print(
6441: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6442: }
1.543 bisitz 6443: $r->print(
6444: '<br /><br />'.
6445: &Apache::lonhtmlcommon::actionbox(
6446: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6447: &endSettingsScreen($r);
1.390 www 6448: $r->print(&Apache::loncommon::end_page());
6449: }
6450:
1.563 damieng 6451: # Returns the different components of a resourcedata key.
6452: # Keys: scope_type, scope, realm_type, realm, realm_title,
6453: # realm_exists, parameter_part, parameter_name.
6454: # Was used by clean_parameters (which is unused).
6455: #
6456: # @param {string} $key - the parameter key
6457: # @returns {hash}
1.333 albertel 6458: sub parse_key {
6459: my ($key) = @_;
6460: my %data;
6461: my ($middle,$part,$name)=
1.572 damieng 6462: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6463: $data{'scope_type'} = 'all';
6464: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6465: $data{'scope'} = $1;
6466: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6467: $data{'scope_type'} = 'user';
6468: $data{'scope'} = [$1,$2];
6469: } else {
1.581 raeburn 6470: $data{'scope_type'} = 'secgroup';
1.560 damieng 6471: }
6472: $middle=~s/^\[(.*)\]//;
1.333 albertel 6473: }
6474: $middle=~s/\.+$//;
6475: $middle=~s/^\.+//;
6476: $data{'realm_type'}='all';
6477: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6478: $data{'realm'} = $1;
6479: $data{'realm_type'} = 'folder';
6480: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6481: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6482: } elsif ($middle) {
1.560 damieng 6483: $data{'realm'} = $middle;
6484: $data{'realm_type'} = 'symb';
6485: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6486: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6487: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6488: }
1.446 bisitz 6489:
1.333 albertel 6490: $data{'parameter_part'} = $part;
6491: $data{'parameter_name'} = $name;
6492:
6493: return %data;
6494: }
6495:
1.239 raeburn 6496:
1.563 damieng 6497: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6498: sub header {
1.507 www 6499: return &Apache::loncommon::start_page('Settings');
1.416 jms 6500: }
1.193 albertel 6501:
6502:
6503:
1.560 damieng 6504: ##################################################
6505: # MAIN MENU
6506: ##################################################
6507:
1.563 damieng 6508: # Content and problem settings main menu.
6509: #
6510: # @param {Apache2::RequestRec} $r - the Apache request
6511: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 6512: sub print_main_menu {
6513: my ($r,$parm_permission)=@_;
6514: #
1.414 droeschl 6515: $r->print(&header());
1.507 www 6516: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 6517: my $crstype = &Apache::loncommon::course_type();
6518: my $lc_crstype = lc($crstype);
6519:
6520: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 6521: $r->print(<<ENDMAINFORMHEAD);
6522: <form method="post" enctype="multipart/form-data"
6523: action="/adm/parmset" name="studentform">
6524: ENDMAINFORMHEAD
6525: #
1.195 albertel 6526: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6527: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 6528: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 6529: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 6530: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 6531: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
6532: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 6533: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
6534: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
6535: '/'.$env{'request.course.sec'});
6536: }
1.568 raeburn 6537: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
6538: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
6539: '/'.$env{'request.course.sec'});
6540: }
6541: my (%linktext,%linktitle,%url);
6542: if ($parm_permission->{'edit'}) {
6543: %linktext = (
6544: newoverview => 'Edit Resource Parameters - Overview Mode',
6545: settable => 'Edit Resource Parameters - Table Mode',
6546: setoverview => 'Modify Resource Parameters - Overview Mode',
6547: );
6548: %linktitle = (
6549: newoverview => 'Set/Modify resource parameters in overview mode.',
6550: settable => 'Set/Modify resource parameters in table mode.',
6551: setoverview => 'Set/Modify existing resource parameters in overview mode.',
6552: );
6553: } else {
6554: %linktext = (
6555: newoverview => 'View Resource Parameters - Overview Mode',
6556: settable => 'View Resource Parameters - Table Mode',
6557: setoverview => 'View Resource Parameters - Overview Mode',
6558: );
6559: %linktitle = (
6560: newoverview => 'Display resource parameters in overview mode.',
6561: settable => 'Display resource parameters in table mode.',
6562: setoverview => 'Display existing resource parameters in overview mode.',
6563: );
6564: }
6565: if ($mgr) {
6566: $linktext{'resettimes'} = 'Reset Student Access Times';
6567: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
6568: $url{'resettimes'} = '/adm/helper/resettimes.helper';
6569: } elsif ($vgr) {
6570: $linktext{'resettimes'} = 'Display Student Access Times',
6571: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
6572: $url{'resettimes'} = '/adm/accesstimes';
6573: }
1.193 albertel 6574: my @menu =
1.507 www 6575: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 6576: items => [
6577: { linktext => 'Portfolio Metadata',
6578: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 6579: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 6580: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 6581: icon =>'contact-new.png' ,
6582: },
1.568 raeburn 6583: { linktext => $linktext{'resettimes'},
6584: url => $url{'resettimes'},
6585: permission => ($vgr || $mgr),
6586: linktitle => $linktitle{'resettimes'},
6587: icon => 'start-here.png',
1.473 amueller 6588: },
1.520 raeburn 6589: { linktext => 'Blocking Communication/Resource Access',
6590: url => '/adm/setblock',
1.568 raeburn 6591: permission => ($vcb || $dcm),
1.520 raeburn 6592: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
6593: icon => 'comblock.png',
6594: },
1.473 amueller 6595: { linktext => 'Set Parameter Setting Default Actions',
6596: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 6597: permission => $parm_permission->{'setdefaults'},
1.473 amueller 6598: linktitle =>'Set default actions for parameters.' ,
6599: icon => 'folder-new.png' ,
6600: }]},
6601: { categorytitle => 'New and Existing Parameter Settings for Resources',
6602: items => [
6603: { linktext => 'Edit Resource Parameters - Helper Mode',
6604: url => '/adm/helper/parameter.helper',
1.568 raeburn 6605: permission => $parm_permission->{'helper'},
1.473 amueller 6606: linktitle =>'Set/Modify resource parameters in helper mode.' ,
6607: icon => 'dialog-information.png' ,
6608: #help => 'Parameter_Helper',
6609: },
1.568 raeburn 6610: { linktext => $linktext{'newoverview'},
1.473 amueller 6611: url => '/adm/parmset?action=newoverview',
1.568 raeburn 6612: permission => $parm_permission->{'newoverview'},
6613: linktitle => $linktitle{'newoverview'},
6614: icon => 'edit-find.png',
1.473 amueller 6615: #help => 'Parameter_Overview',
6616: },
1.568 raeburn 6617: { linktext => $linktext{'settable'},
1.473 amueller 6618: url => '/adm/parmset?action=settable',
1.568 raeburn 6619: permission => $parm_permission->{'settable'},
6620: linktitle => $linktitle{'settable'},
6621: icon => 'edit-copy.png',
1.473 amueller 6622: #help => 'Table_Mode',
6623: }]},
1.417 droeschl 6624: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 6625: items => [
1.570 raeburn 6626: { linktext => $linktext{'setoverview'},
1.473 amueller 6627: url => '/adm/parmset?action=setoverview',
1.568 raeburn 6628: permission => $parm_permission->{'setoverview'},
6629: linktitle => $linktitle{'setoverview'},
6630: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 6631: #help => 'Parameter_Overview',
6632: },
6633: { linktext => 'Change Log',
6634: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 6635: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 6636: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 6637: icon => 'document-properties.png',
1.473 amueller 6638: }]}
1.193 albertel 6639: );
1.414 droeschl 6640: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 6641: $r->print('</form>');
1.507 www 6642: &endSettingsScreen($r);
1.539 raeburn 6643: $r->print(&Apache::loncommon::end_page());
1.193 albertel 6644: return;
6645: }
1.414 droeschl 6646:
1.416 jms 6647:
6648:
1.560 damieng 6649: ##################################################
6650: # PORTFOLIO METADATA
6651: ##################################################
6652:
1.563 damieng 6653: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
6654: # It looks like field titles are not localized.
6655: #
6656: # @param {Apache2::RequestRec} $r - the Apache request
6657: # @param {string} $field_name - metadata field name
6658: # @param {string} $field_text - metadata field title, in English unless manually added
6659: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 6660: sub output_row {
1.347 banghart 6661: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 6662: my $output;
1.263 banghart 6663: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
6664: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 6665: if (!defined($options)) {
1.254 banghart 6666: $options = 'active,stuadd';
1.261 banghart 6667: $values = '';
1.252 banghart 6668: }
1.337 banghart 6669: if (!($options =~ /deleted/)) {
6670: my @options= ( ['active', 'Show to student'],
1.418 schafran 6671: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 6672: ['choices','Provide choices for students to select from']);
1.473 amueller 6673: # ['onlyone','Student may select only one choice']);
1.337 banghart 6674: if ($added_flag) {
6675: push @options,['deleted', 'Delete Metadata Field'];
6676: }
1.351 banghart 6677: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 6678: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 6679: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 6680: foreach my $opt (@options) {
1.560 damieng 6681: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
6682: $output .= &Apache::loncommon::continue_data_table_row();
6683: $output .= '<td>'.(' ' x 5).'<label>
6684: <input type="checkbox" name="'.
6685: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
6686: &mt($opt->[1]).'</label></td>';
6687: $output .= &Apache::loncommon::end_data_table_row();
6688: }
1.351 banghart 6689: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 6690: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 6691: $output .= &Apache::loncommon::end_data_table_row();
6692: my $multiple_checked;
6693: my $single_checked;
6694: if ($options =~ m/onlyone/) {
1.422 bisitz 6695: $multiple_checked = '';
1.423 bisitz 6696: $single_checked = ' checked="checked"';
1.351 banghart 6697: } else {
1.423 bisitz 6698: $multiple_checked = ' checked="checked"';
1.422 bisitz 6699: $single_checked = '';
1.351 banghart 6700: }
1.560 damieng 6701: $output .= &Apache::loncommon::continue_data_table_row();
6702: $output .= '<td>'.(' ' x 10).'
6703: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
6704: '.&mt('Student may select multiple choices from list').'</td>';
6705: $output .= &Apache::loncommon::end_data_table_row();
6706: $output .= &Apache::loncommon::continue_data_table_row();
6707: $output .= '<td>'.(' ' x 10).'
6708: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
6709: '.&mt('Student may select only one choice from list').'</td>';
6710: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 6711: }
6712: return ($output);
6713: }
1.416 jms 6714:
6715:
1.560 damieng 6716: # UI to order portfolio metadata fields.
1.563 damieng 6717: # Currently useless because addmetafield does not work.
6718: #
6719: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 6720: sub order_meta_fields {
6721: my ($r)=@_;
6722: my $idx = 1;
6723: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6724: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6725: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 6726: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 6727: &Apache::lonhtmlcommon::add_breadcrumb(
6728: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6729: text=>"Add Metadata Field"});
1.560 damieng 6730: &Apache::lonhtmlcommon::add_breadcrumb(
6731: {href=>"/adm/parmset?action=setrestrictmeta",
6732: text=>"Restrict Metadata"},
6733: {text=>"Order Metadata"});
1.345 banghart 6734: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 6735: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 6736: if ($env{'form.storeorder'}) {
6737: my $newpos = $env{'form.newpos'} - 1;
6738: my $currentpos = $env{'form.currentpos'} - 1;
6739: my @neworder = ();
1.548 raeburn 6740: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6741: my $i;
1.341 banghart 6742: if ($newpos > $currentpos) {
1.340 banghart 6743: # moving stuff up
6744: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 6745: $neworder[$i]=$oldorder[$i];
1.340 banghart 6746: }
6747: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 6748: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 6749: }
6750: $neworder[$newpos]=$oldorder[$currentpos];
6751: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 6752: $neworder[$i]=$oldorder[$i];
1.340 banghart 6753: }
6754: } else {
6755: # moving stuff down
1.473 amueller 6756: for ($i=0;$i<$newpos;$i++) {
6757: $neworder[$i]=$oldorder[$i];
6758: }
6759: $neworder[$newpos]=$oldorder[$currentpos];
6760: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
6761: $neworder[$i]=$oldorder[$i-1];
6762: }
6763: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
6764: $neworder[$i]=$oldorder[$i];
6765: }
1.340 banghart 6766: }
1.560 damieng 6767: my $ordered_fields = join ",", @neworder;
1.343 banghart 6768: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 6769: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6770: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 6771: }
1.357 raeburn 6772: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 6773: my $ordered_fields;
1.548 raeburn 6774: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6775: if (!@fields_in_order) {
6776: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 6777: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 6778: push @fields_in_order, $key;
1.341 banghart 6779: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 6780: }
1.341 banghart 6781: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 6782: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6783: }
1.340 banghart 6784: $r->print('<table>');
6785: my $num_fields = scalar(@fields_in_order);
6786: foreach my $key (@fields_in_order) {
6787: $r->print('<tr><td>');
6788: $r->print('<form method="post" action="">');
1.537 bisitz 6789: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 6790: for (my $i = 1;$i le $num_fields;$i ++) {
6791: if ($i eq $idx) {
6792: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
6793: } else {
6794: $r->print('<option value="'.$i.'">'.$i.'</option>');
6795: }
6796: }
6797: $r->print('</select></td><td>');
6798: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
6799: $r->print('<input type="hidden" name="storeorder" value="true" />');
6800: $r->print('</form>');
6801: $r->print($$fields{$key}.'</td></tr>');
6802: $idx ++;
6803: }
6804: $r->print('</table>');
1.507 www 6805: &endSettingsScreen($r);
1.340 banghart 6806: return 'ok';
6807: }
1.416 jms 6808:
6809:
1.563 damieng 6810: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
6811: # @returns {string}
1.359 banghart 6812: sub continue {
6813: my $output;
6814: $output .= '<form action="" method="post">';
6815: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 6816: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 6817: return ($output);
6818: }
1.416 jms 6819:
6820:
1.563 damieng 6821: # UI to add a metadata field.
6822: # Currenly does not work because of an HTML error (the field is not visible).
6823: #
6824: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 6825: sub addmetafield {
6826: my ($r)=@_;
1.414 droeschl 6827: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6828: text=>"Add Metadata Field"});
1.334 banghart 6829: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
6830: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 6831: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6832: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6833: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6834: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 6835: if (exists($env{'form.undelete'})) {
1.358 banghart 6836: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 6837: foreach my $meta_field(@meta_fields) {
6838: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
6839: $options =~ s/deleted//;
6840: $options =~ s/,,/,/;
6841: my $put_result = &Apache::lonnet::put('environment',
6842: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 6843:
1.586 raeburn 6844: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
6845: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
6846: '</strong>',$put_result).
6847: '<br />');
1.339 banghart 6848: }
1.359 banghart 6849: $r->print(&continue());
1.339 banghart 6850: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 6851: my $meta_field = $env{'form.fieldname'};
6852: my $display_field = $env{'form.fieldname'};
6853: $meta_field =~ s/\W/_/g;
1.338 banghart 6854: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 6855: my $put_result = &Apache::lonnet::put('environment',
6856: {'metadata.'.$meta_field.'.values'=>"",
6857: 'metadata.'.$meta_field.'.added'=>"$display_field",
6858: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 6859: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
6860: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
6861: '<br />');
1.359 banghart 6862: $r->print(&continue());
1.335 banghart 6863: } else {
1.357 raeburn 6864: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 6865: if ($fields) {
1.586 raeburn 6866: $r->print(&mt('You may undelete previously deleted fields.').
6867: '<br />'.
6868: &mt('Check those you wish to undelete and click Undelete.').
6869: '<br />');
1.339 banghart 6870: $r->print('<form method="post" action="">');
6871: foreach my $key(keys(%$fields)) {
1.581 raeburn 6872: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 6873: }
1.586 raeburn 6874: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 6875: $r->print('</form>');
6876: }
1.586 raeburn 6877: $r->print('<hr />'.
6878: &mt('[_1]Or[_2] you may enter a new metadata field name.',
6879: '<strong>','</strong>').
1.581 raeburn 6880: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 6881: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 6882: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 6883: $r->print('</form>');
1.334 banghart 6884: }
1.507 www 6885: &endSettingsScreen($r);
1.334 banghart 6886: }
1.416 jms 6887:
6888:
6889:
1.560 damieng 6890: # Display or save portfolio metadata.
1.563 damieng 6891: #
6892: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 6893: sub setrestrictmeta {
1.240 banghart 6894: my ($r)=@_;
1.242 banghart 6895: my $next_meta;
1.244 banghart 6896: my $output;
1.245 banghart 6897: my $item_num;
1.246 banghart 6898: my $put_result;
1.414 droeschl 6899: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 6900: text=>"Restrict Metadata"});
1.280 albertel 6901: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 6902: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 6903: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6904: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6905: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6906: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 6907: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 6908: my $save_field = '';
1.586 raeburn 6909: my %lt = &Apache::lonlocal::texthash(
6910: addm => 'Add Metadata Field',
6911: ordm => 'Order Metadata Fields',
6912: save => 'Save',
6913: );
1.259 banghart 6914: if ($env{'form.restrictmeta'}) {
1.254 banghart 6915: foreach my $field (sort(keys(%env))) {
1.252 banghart 6916: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 6917: my $options;
1.252 banghart 6918: my $meta_field = $1;
6919: my $meta_key = $2;
1.253 banghart 6920: if ($save_field ne $meta_field) {
1.252 banghart 6921: $save_field = $meta_field;
1.473 amueller 6922: if ($env{'form.'.$meta_field.'_stuadd'}) {
6923: $options.='stuadd,';
6924: }
6925: if ($env{'form.'.$meta_field.'_choices'}) {
6926: $options.='choices,';
6927: }
6928: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
6929: $options.='onlyone,';
6930: }
6931: if ($env{'form.'.$meta_field.'_active'}) {
6932: $options.='active,';
6933: }
6934: if ($env{'form.'.$meta_field.'_deleted'}) {
6935: $options.='deleted,';
6936: }
1.259 banghart 6937: my $name = $save_field;
1.560 damieng 6938: $put_result = &Apache::lonnet::put('environment',
6939: {'metadata.'.$meta_field.'.options'=>$options,
6940: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
6941: },$dom,$crs);
1.252 banghart 6942: }
6943: }
6944: }
6945: }
1.296 albertel 6946: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 6947: {'freshen_cache' => 1});
1.335 banghart 6948: # Get the default metadata fields
1.258 albertel 6949: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 6950: # Now get possible added metadata fields
1.357 raeburn 6951: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 6952: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 6953: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 6954: if ($field ne 'courserestricted') {
1.586 raeburn 6955: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 6956: }
1.255 banghart 6957: }
1.351 banghart 6958: my $buttons = (<<ENDButtons);
1.586 raeburn 6959: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 6960: </form><br />
6961: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 6962: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 6963: </form>
6964: <br />
6965: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 6966: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 6967: ENDButtons
1.337 banghart 6968: my $added_flag = 1;
1.335 banghart 6969: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 6970: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 6971: }
1.347 banghart 6972: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 6973: $r->print(<<ENDenv);
1.259 banghart 6974: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 6975: $output
1.351 banghart 6976: $buttons
1.340 banghart 6977: </form>
1.244 banghart 6978: ENDenv
1.507 www 6979: &endSettingsScreen($r);
1.280 albertel 6980: $r->print(&Apache::loncommon::end_page());
1.240 banghart 6981: return 'ok';
6982: }
1.416 jms 6983:
6984:
1.563 damieng 6985: # Returns metadata fields that have been manually added.
6986: #
6987: # @param {string} $cid - course id
6988: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 6989: sub get_added_meta_fieldnames {
1.357 raeburn 6990: my ($cid) = @_;
1.335 banghart 6991: my %fields;
6992: foreach my $key(%env) {
1.357 raeburn 6993: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 6994: my $field_name = $1;
6995: my ($display_field_name) = $env{$key};
6996: $fields{$field_name} = $display_field_name;
6997: }
6998: }
6999: return \%fields;
7000: }
1.416 jms 7001:
7002:
1.563 damieng 7003: # Returns metadata fields that have been manually added and deleted.
7004: #
7005: # @param {string} $cid - course id
7006: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 7007: sub get_deleted_meta_fieldnames {
1.357 raeburn 7008: my ($cid) = @_;
1.339 banghart 7009: my %fields;
7010: foreach my $key(%env) {
1.357 raeburn 7011: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 7012: my $field_name = $1;
7013: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
7014: my ($display_field_name) = $env{$key};
7015: $fields{$field_name} = $display_field_name;
7016: }
7017: }
7018: }
7019: return \%fields;
7020: }
1.560 damieng 7021:
7022:
7023: ##################################################
7024: # PARAMETER SETTINGS DEFAULT ACTIONS
7025: ##################################################
7026:
7027: # UI to change parameter setting default actions
1.563 damieng 7028: #
7029: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 7030: sub defaultsetter {
1.280 albertel 7031: my ($r) = @_;
7032:
1.414 droeschl 7033: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 7034: text=>"Set Defaults"});
1.531 raeburn 7035: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7036: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
7037: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 7038: my $start_page =
1.531 raeburn 7039: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 7040: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 7041: $r->print($start_page.$breadcrumbs);
1.531 raeburn 7042: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 7043: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 7044:
1.221 www 7045: my @ids=();
7046: my %typep=();
7047: my %keyp=();
7048: my %allparms=();
7049: my %allparts=();
7050: my %allmaps=();
7051: my %mapp=();
7052: my %symbp=();
7053: my %maptitles=();
7054: my %uris=();
7055: my %keyorder=&standardkeyorder();
7056: my %defkeytype=();
7057:
1.446 bisitz 7058: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 7059: \%mapp, \%symbp,\%maptitles,\%uris,
7060: \%keyorder,\%defkeytype);
1.224 www 7061: if ($env{'form.storerules'}) {
1.560 damieng 7062: my %newrules=();
7063: my @delrules=();
7064: my %triggers=();
7065: foreach my $key (keys(%env)) {
1.225 albertel 7066: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 7067: my $tempkey=$1;
7068: my $action=$env{$key};
1.226 www 7069: if ($action) {
1.560 damieng 7070: $newrules{$tempkey.'_action'}=$action;
7071: if ($action ne 'default') {
7072: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
7073: $triggers{$whichparm}.=$tempkey.':';
7074: }
7075: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
7076: if (&isdateparm($defkeytype{$tempkey})) {
7077: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
7078: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
7079: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
7080: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
7081: } else {
7082: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
7083: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
7084: }
7085: } else {
7086: push(@delrules,$tempkey.'_action');
7087: push(@delrules,$tempkey.'_type');
7088: push(@delrules,$tempkey.'_hours');
7089: push(@delrules,$tempkey.'_min');
7090: push(@delrules,$tempkey.'_sec');
7091: push(@delrules,$tempkey.'_value');
7092: }
1.473 amueller 7093: }
7094: }
1.560 damieng 7095: foreach my $key (keys(%allparms)) {
7096: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 7097: }
1.560 damieng 7098: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
7099: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
7100: &resetrulescache();
1.224 www 7101: }
1.227 www 7102: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 7103: 'hours' => 'Hours',
7104: 'min' => 'Minutes',
7105: 'sec' => 'Seconds',
7106: 'yes' => 'Yes',
7107: 'no' => 'No');
1.222 www 7108: my @standardoptions=('','default');
7109: my @standarddisplay=('',&mt('Default value when manually setting'));
7110: my @dateoptions=('','default');
7111: my @datedisplay=('',&mt('Default value when manually setting'));
7112: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7113: unless ($tempkey) { next; }
7114: push @standardoptions,'when_setting_'.$tempkey;
7115: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
7116: if (&isdateparm($defkeytype{$tempkey})) {
7117: push @dateoptions,'later_than_'.$tempkey;
7118: push @datedisplay,&mt('Automatically set later than ').$tempkey;
7119: push @dateoptions,'earlier_than_'.$tempkey;
7120: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
7121: }
1.222 www 7122: }
1.563 damieng 7123: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
7124: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 7125: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 7126: &Apache::loncommon::start_data_table_header_row().
7127: "<th>".&mt('Rule for parameter').'</th><th>'.
7128: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
7129: &Apache::loncommon::end_data_table_header_row());
1.221 www 7130: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7131: unless ($tempkey) { next; }
7132: $r->print("\n".&Apache::loncommon::start_data_table_row().
7133: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
7134: my $action=&rulescache($tempkey.'_action');
7135: $r->print('<select name="'.$tempkey.'_action">');
7136: if (&isdateparm($defkeytype{$tempkey})) {
7137: for (my $i=0;$i<=$#dateoptions;$i++) {
7138: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
7139: $r->print("\n<option value='$dateoptions[$i]'".
7140: ($dateoptions[$i] eq $action?' selected="selected"':'').
7141: ">$datedisplay[$i]</option>");
7142: }
7143: } else {
7144: for (my $i=0;$i<=$#standardoptions;$i++) {
7145: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
7146: $r->print("\n<option value='$standardoptions[$i]'".
7147: ($standardoptions[$i] eq $action?' selected="selected"':'').
7148: ">$standarddisplay[$i]</option>");
7149: }
1.473 amueller 7150: }
1.560 damieng 7151: $r->print('</select>');
7152: unless (&isdateparm($defkeytype{$tempkey})) {
7153: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7154: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7155: }
1.560 damieng 7156: $r->print("\n</td><td>\n");
1.222 www 7157:
1.221 www 7158: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7159: my $days=&rulescache($tempkey.'_days');
7160: my $hours=&rulescache($tempkey.'_hours');
7161: my $min=&rulescache($tempkey.'_min');
7162: my $sec=&rulescache($tempkey.'_sec');
7163: $r->print(<<ENDINPUTDATE);
7164: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7165: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7166: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7167: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7168: ENDINPUTDATE
1.560 damieng 7169: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7170: my $yeschecked='';
7171: my $nochecked='';
7172: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7173: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7174:
7175: $r->print(<<ENDYESNO);
7176: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7177: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7178: ENDYESNO
1.221 www 7179: } else {
1.560 damieng 7180: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7181: }
1.318 albertel 7182: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7183: }
1.318 albertel 7184: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7185: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7186: &mt('Save').'" /></form>'."\n");
7187: &endSettingsScreen($r);
7188: $r->print(&Apache::loncommon::end_page());
1.220 www 7189: return;
7190: }
1.193 albertel 7191:
1.560 damieng 7192: ##################################################
7193: # PARAMETER CHANGES LOG
7194: ##################################################
7195:
1.563 damieng 7196: # Returns some info for a parameter log entry.
7197: # Returned entries:
7198: # $realm - HTML title for the parameter level and resource
7199: # $section - parameter section
7200: # $name - parameter name
7201: # $part - parameter part
7202: # $what - $part.'.'.$name
7203: # $middle - resource symb ?
7204: # $uname - user name (same as given)
7205: # $udom - user domain (same as given)
7206: # $issection - section or group name
7207: # $realmdescription - title for the parameter level and resource (without using HTML)
7208: #
7209: # @param {string} $key - parameter log key
7210: # @param {string} $uname - user name
7211: # @param {string} $udom - user domain
7212: # @param {boolean} $typeflag - .type log entry
7213: # @returns {Array}
1.290 www 7214: sub components {
1.581 raeburn 7215: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7216:
7217: if ($typeflag) {
1.560 damieng 7218: $key=~s/\.type$//;
1.290 www 7219: }
1.330 albertel 7220:
7221: my ($middle,$part,$name)=
1.572 damieng 7222: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7223: my $issection;
1.330 albertel 7224:
1.290 www 7225: my $section=&mt('All Students');
7226: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7227: $issection=$1;
7228: $section=&mt('Group/Section').': '.$issection;
7229: $middle=~s/^\[(.*)\]//;
1.290 www 7230: }
7231: $middle=~s/\.+$//;
7232: $middle=~s/^\.+//;
1.291 www 7233: if ($uname) {
1.560 damieng 7234: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7235: $issection='';
1.291 www 7236: }
1.316 albertel 7237: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7238: my $realmdescription=&mt('all resources');
1.556 raeburn 7239: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7240: my $mapurl = $1;
7241: my $maplevel = $2;
7242: my $leveltitle = &mt('Folder/Map');
7243: if ($maplevel eq 'rec') {
7244: $leveltitle = &mt('Recursive');
7245: }
1.560 damieng 7246: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7247: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7248: $mapurl.')</span></span>';
7249: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7250: } elsif ($middle) {
7251: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7252: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7253: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7254: ' in '.$map.' id: '.$id.')</span></span>';
7255: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7256: }
1.291 www 7257: my $what=$part.'.'.$name;
1.330 albertel 7258: return ($realm,$section,$name,$part,
1.473 amueller 7259: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7260: }
1.293 www 7261:
1.563 damieng 7262: my %standard_parms; # hash parameter name -> parameter title (not localized)
7263: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7264:
1.563 damieng 7265: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7266: sub load_parameter_names {
1.583 raeburn 7267: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7268: while (my $configline=<$config>) {
1.560 damieng 7269: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7270: chomp($configline);
7271: my ($short,$plain)=split(/:/,$configline);
7272: my (undef,$name,$type)=split(/\&/,$short,3);
7273: if ($type eq 'display') {
7274: $standard_parms{$name} = $plain;
1.469 raeburn 7275: } elsif ($type eq 'type') {
1.560 damieng 7276: $standard_parms_types{$name} = $plain;
1.469 raeburn 7277: }
1.328 albertel 7278: }
7279: close($config);
7280: $standard_parms{'int_pos'} = 'Positive Integer';
7281: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7282: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7283: }
7284:
1.563 damieng 7285: # Returns a parameter title for standard parameters, the name for others.
7286: #
7287: # @param {string} $name - parameter name
7288: # @returns {string}
1.292 www 7289: sub standard_parameter_names {
7290: my ($name)=@_;
1.328 albertel 7291: if (!%standard_parms) {
1.560 damieng 7292: &load_parameter_names();
1.328 albertel 7293: }
1.292 www 7294: if ($standard_parms{$name}) {
1.560 damieng 7295: return $standard_parms{$name};
1.446 bisitz 7296: } else {
1.560 damieng 7297: return $name;
1.292 www 7298: }
7299: }
1.290 www 7300:
1.563 damieng 7301: # Returns a parameter type for standard parameters, undef for others.
7302: #
7303: # @param {string} $name - parameter name
7304: # @returns {string}
1.469 raeburn 7305: sub standard_parameter_types {
7306: my ($name)=@_;
7307: if (!%standard_parms_types) {
7308: &load_parameter_names();
7309: }
7310: if ($standard_parms_types{$name}) {
7311: return $standard_parms_types{$name};
7312: }
7313: return;
7314: }
1.309 www 7315:
1.563 damieng 7316: # Returns a parameter level title (not localized) from the parameter level name.
7317: #
7318: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7319: # @returns {string}
1.557 raeburn 7320: sub standard_parameter_levels {
7321: my ($name)=@_;
7322: my %levels = (
7323: 'resourcelevel' => 'a single resource',
7324: 'maplevel' => 'the enclosing map/folder',
7325: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7326: 'courselevel' => 'the general (course) level',
7327: );
7328: if ($levels{$name}) {
7329: return $levels{$name};
7330: }
7331: return;
7332: }
7333:
1.560 damieng 7334: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7335: #
7336: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7337: sub parm_change_log {
1.568 raeburn 7338: my ($r,$parm_permission)=@_;
1.531 raeburn 7339: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7340: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7341: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7342: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7343: text=>"Parameter Change Log"});
1.522 raeburn 7344: my $js = '<script type="text/javascript">'."\n".
7345: '// <![CDATA['."\n".
7346: &Apache::loncommon::display_filter_js('parmslog')."\n".
7347: '// ]]>'."\n".
7348: '</script>'."\n";
7349: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7350: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7351: &startSettingsScreen($r,'parmset',$crstype);
7352: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7353:
1.301 www 7354: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7355:
1.522 raeburn 7356: $r->print('<div class="LC_left_float">'.
7357: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7358: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7359: method="post" name="parameterlog">');
1.446 bisitz 7360:
1.311 albertel 7361: my %saveable_parameters = ('show' => 'scalar',);
7362: &Apache::loncommon::store_course_settings('parameter_log',
7363: \%saveable_parameters);
7364: &Apache::loncommon::restore_course_settings('parameter_log',
7365: \%saveable_parameters);
1.522 raeburn 7366: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7367: '<input type="submit" value="'.&mt('Display').'" />'.
7368: '</form></fieldset></div><br clear="all" />');
1.301 www 7369:
1.568 raeburn 7370: my $readonly = 1;
7371: if ($parm_permission->{'edit'}) {
7372: undef($readonly);
7373: }
1.531 raeburn 7374: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7375: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7376: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7377: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7378: unless ($readonly) {
7379: $r->print('<th>'.&mt('Announce').'</th>');
7380: }
7381: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7382: my $shown=0;
1.349 www 7383: my $folder='';
7384: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7385: my $last='';
7386: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7387: &GDBM_READER(),0640)) {
7388: $last=$hash{'last_known'};
7389: untie(%hash);
7390: }
7391: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7392: }
1.595 raeburn 7393: my $numgroups = 0;
7394: my @groups;
7395: if ($env{'request.course.groups'} ne '') {
7396: @groups = split(/:/,$env{'request.course.groups'});
7397: $numgroups = scalar(@groups);
7398: }
1.560 damieng 7399: foreach my $id (sort {
7400: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7401: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7402: }
7403: my $aid = (split('00000',$a))[-1];
7404: my $bid = (split('00000',$b))[-1];
7405: return $bid<=>$aid;
1.473 amueller 7406: } (keys(%parmlog))) {
1.294 www 7407: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7408: my $count = 0;
7409: my $time =
7410: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7411: my $plainname =
7412: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7413: $parmlog{$id}{'exe_udom'});
7414: my $about_me_link =
7415: &Apache::loncommon::aboutmewrapper($plainname,
7416: $parmlog{$id}{'exe_uname'},
7417: $parmlog{$id}{'exe_udom'});
7418: my $send_msg_link='';
1.568 raeburn 7419: if ((!$readonly) &&
7420: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7421: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7422: $send_msg_link ='<br />'.
7423: &Apache::loncommon::messagewrapper(&mt('Send message'),
7424: $parmlog{$id}{'exe_uname'},
7425: $parmlog{$id}{'exe_udom'});
7426: }
7427: my $row_start=&Apache::loncommon::start_data_table_row();
7428: my $makenewrow=0;
7429: my %istype=();
7430: my $output;
7431: foreach my $changed (reverse(sort(@changes))) {
7432: my $value=$parmlog{$id}{'logentry'}{$changed};
7433: my $typeflag = ($changed =~/\.type$/ &&
7434: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7435: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7436: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7437: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7438: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7439: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7440: if ($uname ne '') {
7441: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7442: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7443: }
7444: }
7445: if ($env{'form.displayfilter'} eq 'currentfolder') {
7446: if ($folder) {
7447: if ($middle!~/^\Q$folder\E/) { next; }
7448: }
7449: }
7450: if ($typeflag) {
7451: $istype{$parmname}=$value;
7452: if (!$env{'form.includetypes'}) { next; }
7453: }
7454: $count++;
7455: if ($makenewrow) {
7456: $output .= $row_start;
7457: } else {
7458: $makenewrow=1;
7459: }
1.470 raeburn 7460: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7461: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7462: &mt($parmitem).'</td><td>'.
7463: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7464: my $stillactive=0;
7465: if ($parmlog{$id}{'delflag'}) {
7466: $output .= &mt('Deleted');
7467: } else {
7468: if ($typeflag) {
1.470 raeburn 7469: my $parmitem = &standard_parameter_names($value);
7470: $parmitem = &mt($parmitem);
1.560 damieng 7471: $output .= &mt('Type: [_1]',$parmitem);
7472: } else {
1.584 raeburn 7473: my $toolsymb;
7474: if ($middle =~ /ext\.tool$/) {
7475: $toolsymb = $middle;
7476: }
1.560 damieng 7477: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7478: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7479: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7480: my $showvalue = $value;
7481: if ($istype{$parmname} eq '') {
7482: my $type = &standard_parameter_types($parmname);
7483: if ($type ne '') {
7484: if (&isdateparm($type)) {
7485: $showvalue =
7486: &Apache::lonlocal::locallocaltime($value);
7487: }
7488: }
7489: } else {
1.560 damieng 7490: if (&isdateparm($istype{$parmname})) {
7491: $showvalue = &Apache::lonlocal::locallocaltime($value);
7492: }
1.469 raeburn 7493: }
7494: $output .= $showvalue;
1.560 damieng 7495: if ($value ne $all[$level]) {
7496: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7497: } else {
7498: $stillactive=1;
7499: }
7500: }
1.473 amueller 7501: }
1.568 raeburn 7502: $output .= '</td>';
7503:
7504: unless ($readonly) {
7505: $output .= '<td>';
7506: if ($stillactive) {
7507: my $parmitem = &standard_parameter_names($parmname);
7508: $parmitem = &mt($parmitem);
7509: my $title=&mt('Changed [_1]',$parmitem);
7510: my $description=&mt('Changed [_1] for [_2] to [_3]',
7511: $parmitem,$realmdescription,
7512: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
7513: if (($uname) && ($udom)) {
7514: $output .=
7515: &Apache::loncommon::messagewrapper('Notify User',
7516: $uname,$udom,$title,
7517: $description);
7518: } else {
7519: $output .=
7520: &Apache::lonrss::course_blog_link($id,$title,
7521: $description);
7522: }
1.560 damieng 7523: }
1.568 raeburn 7524: $output .= '</td>';
1.560 damieng 7525: }
1.568 raeburn 7526: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 7527: }
1.560 damieng 7528: if ($env{'form.displayfilter'} eq 'containing') {
7529: my $wholeentry=$about_me_link.':'.
7530: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
7531: $output;
7532: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 7533: }
1.349 www 7534: if ($count) {
1.560 damieng 7535: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
7536: <td rowspan="'.$count.'">'.$about_me_link.
7537: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
7538: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
7539: $send_msg_link.'</td>'.$output);
7540: $shown++;
7541: }
7542: if (!($env{'form.show'} eq &mt('all')
7543: || $shown<=$env{'form.show'})) { last; }
1.286 www 7544: }
1.301 www 7545: $r->print(&Apache::loncommon::end_data_table());
1.507 www 7546: &endSettingsScreen($r);
1.284 www 7547: $r->print(&Apache::loncommon::end_page());
7548: }
7549:
1.560 damieng 7550: ##################################################
7551: # MISC !
7552: ##################################################
7553:
1.563 damieng 7554: # Stores slot information.
1.560 damieng 7555: # Used by table UI
1.563 damieng 7556: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7557: #
7558: # @param {string} $slot_name - slot name
7559: # @param {string} $cdom - course domain
7560: # @param {string} $cnum - course number
7561: # @param {string} $symb - resource symb
7562: # @param {string} $uname - user name
7563: # @param {string} $udom - user domain
7564: # @returns {string} - 'ok' or error name
1.437 raeburn 7565: sub update_slots {
7566: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
7567: my %slot=&Apache::lonnet::get_slot($slot_name);
7568: if (!keys(%slot)) {
7569: return 'error: slot does not exist';
7570: }
7571: my $max=$slot{'maxspace'};
7572: if (!defined($max)) { $max=99999; }
7573:
7574: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
7575: "^$slot_name\0");
7576: my ($tmp)=%consumed;
7577: if ($tmp=~/^error: 2 / ) {
7578: return 'error: unable to determine current slot status';
7579: }
7580: my $last=0;
7581: foreach my $key (keys(%consumed)) {
7582: my $num=(split('\0',$key))[1];
7583: if ($num > $last) { $last=$num; }
7584: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7585: return 'ok';
7586: }
7587: }
7588:
7589: if (scalar(keys(%consumed)) >= $max) {
7590: return 'error: no space left in slot';
7591: }
7592: my $wanted=$last+1;
7593:
7594: my %reservation=('name' => $uname.':'.$udom,
7595: 'timestamp' => time,
7596: 'symb' => $symb);
7597:
7598: my $success=&Apache::lonnet::newput('slot_reservations',
7599: {"$slot_name\0$wanted" =>
7600: \%reservation},
7601: $cdom, $cnum);
1.438 raeburn 7602: if ($success eq 'ok') {
7603: my %storehash = (
7604: symb => $symb,
7605: slot => $slot_name,
7606: action => 'reserve',
7607: context => 'parameter',
7608: );
1.526 raeburn 7609: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7610: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 7611:
1.526 raeburn 7612: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7613: '',$uname,$udom,$uname,$udom);
1.438 raeburn 7614: }
1.437 raeburn 7615: return $success;
7616: }
7617:
1.563 damieng 7618: # Deletes a slot reservation.
1.560 damieng 7619: # Used by table UI
1.563 damieng 7620: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7621: #
7622: # @param {string} $slot_name - slot name
7623: # @param {string} $cdom - course domain
7624: # @param {string} $cnum - course number
7625: # @param {string} $uname - user name
7626: # @param {string} $udom - user domain
7627: # @param {string} $symb - resource symb
7628: # @returns {string} - 'ok' or error name
1.437 raeburn 7629: sub delete_slots {
7630: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
7631: my $delresult;
7632: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
7633: $cnum, "^$slot_name\0");
7634: if (&Apache::lonnet::error(%consumed)) {
7635: return 'error: unable to determine current slot status';
7636: }
7637: my ($tmp)=%consumed;
7638: if ($tmp=~/^error: 2 /) {
7639: return 'error: unable to determine current slot status';
7640: }
7641: foreach my $key (keys(%consumed)) {
7642: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7643: my $num=(split('\0',$key))[1];
7644: my $entry = $slot_name.'\0'.$num;
7645: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
7646: $cdom,$cnum);
7647: if ($delresult eq 'ok') {
7648: my %storehash = (
7649: symb => $symb,
7650: slot => $slot_name,
7651: action => 'release',
7652: context => 'parameter',
7653: );
1.526 raeburn 7654: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7655: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 7656: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7657: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 7658: }
7659: }
7660: }
7661: return $delresult;
7662: }
7663:
1.563 damieng 7664: # Returns true if there is a current course.
1.560 damieng 7665: # Used by handler
1.563 damieng 7666: #
7667: # @returns {boolean}
1.355 albertel 7668: sub check_for_course_info {
7669: my $navmap = Apache::lonnavmaps::navmap->new();
7670: return 1 if ($navmap);
7671: return 0;
7672: }
7673:
1.563 damieng 7674: # Returns the current course host and host LON-CAPA version.
7675: #
7676: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 7677: sub parameter_release_vars {
1.504 raeburn 7678: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7679: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
7680: my $chostname = &Apache::lonnet::hostname($chome);
7681: my ($cmajor,$cminor) =
7682: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
7683: return ($chostname,$cmajor,$cminor);
7684: }
7685:
1.563 damieng 7686: # Checks if the course host version can handle a parameter required version,
7687: # and if it does, stores the release needed for the course.
7688: #
7689: # @param {string} $name - parameter name
7690: # @param {string} $value - parameter value
7691: # @param {string} $valmatch - name of the test used for checking the value
7692: # @param {string} $namematch - name of the test used for checking the name
7693: # @param {string} $needsrelease - version needed by the parameter, major.minor
7694: # @param {integer} $cmajor - course major version number
7695: # @param {integer} $cminor - course minor version number
7696: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 7697: sub parameter_releasecheck {
1.557 raeburn 7698: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 7699: my $needsnewer;
7700: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
7701: if (($cmajor < $needsmajor) ||
7702: ($cmajor == $needsmajor && $cminor < $needsminor)) {
7703: $needsnewer = 1;
1.557 raeburn 7704: } elsif ($name) {
7705: if ($valmatch) {
7706: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
7707: } elsif ($value) {
7708: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
7709: }
7710: } elsif ($namematch) {
7711: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 7712: }
7713: return $needsnewer;
7714: }
7715:
1.568 raeburn 7716: sub get_permission {
7717: my %permission;
7718: my $allowed = 0;
7719: return (\%permission,$allowed) unless ($env{'request.course.id'});
7720: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
7721: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
7722: $env{'request.course.sec'}))) {
7723: %permission= (
7724: 'edit' => 1,
7725: 'set' => 1,
7726: 'setoverview' => 1,
7727: 'addmetadata' => 1,
7728: 'ordermetadata' => 1,
7729: 'setrestrictmeta' => 1,
7730: 'newoverview' => 1,
7731: 'setdefaults' => 1,
7732: 'settable' => 1,
7733: 'parameterchangelog' => 1,
7734: 'cleanparameters' => 1,
7735: 'dateshift1' => 1,
7736: 'dateshift2' => 1,
7737: 'helper' => 1,
7738: );
7739: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
7740: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
7741: $env{'request.course.sec'}))) {
7742: %permission = (
7743: 'set' => 1,
7744: 'settable' => 1,
7745: 'newoverview' => 1,
7746: 'setoverview' => 1,
7747: 'parameterchangelog' => 1,
7748: );
7749: }
7750: foreach my $perm (values(%permission)) {
7751: if ($perm) { $allowed=1; last; }
7752: }
7753: return (\%permission,$allowed);
7754: }
7755:
1.560 damieng 7756: ##################################################
7757: # HANDLER
7758: ##################################################
7759:
7760: # Main handler for lonparmset.
7761: # Sub called based on request parameters action and command:
7762: # no command or action: print_main_menu
7763: # command 'set': assessparms (direct access to table mode for a resource)
7764: # (this can also be accessed simply with the symb parameter)
7765: # action 'setoverview': overview (display all existing parameter settings)
7766: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
7767: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
7768: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
7769: # action 'newoverview': newoverview (overview mode)
7770: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
7771: # action 'settable': assessparms (table mode)
7772: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
7773: # blog postings, user notification changes)
7774: # action 'cleanparameters': clean_parameters (unused)
7775: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
7776: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 7777: sub handler {
1.43 albertel 7778: my $r=shift;
1.30 www 7779:
1.376 albertel 7780: &reset_caches();
7781:
1.414 droeschl 7782: &Apache::loncommon::content_type($r,'text/html');
7783: $r->send_http_header;
7784: return OK if $r->header_only;
7785:
1.193 albertel 7786: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 7787: ['action','state',
1.205 www 7788: 'pres_marker',
7789: 'pres_value',
1.206 www 7790: 'pres_type',
1.506 www 7791: 'filter','part',
1.390 www 7792: 'udom','uname','symb','serial','timebase']);
1.131 www 7793:
1.83 bowersj2 7794:
1.193 albertel 7795: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 7796: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 7797: text=>"Content and Problem Settings",
1.473 amueller 7798: faq=>10,
7799: bug=>'Instructor Interface',
1.442 droeschl 7800: help =>
7801: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 7802:
1.30 www 7803: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 7804: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 7805: my $exists = &check_for_course_info();
7806:
1.568 raeburn 7807: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 7808: #
7809: # Main switch on form.action and form.state, as appropriate
7810: #
7811: # Check first if coming from someone else headed directly for
7812: # the table mode
1.568 raeburn 7813: if (($parm_permission->{'set'}) &&
7814: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
7815: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
7816: &assessparms($r,$parm_permission);
1.193 albertel 7817: } elsif (! exists($env{'form.action'})) {
7818: &print_main_menu($r,$parm_permission);
1.568 raeburn 7819: } elsif (!$parm_permission->{$env{'form.action'}}) {
7820: &print_main_menu($r,$parm_permission);
1.414 droeschl 7821: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 7822: &overview($r,$parm_permission);
1.560 damieng 7823: } elsif ($env{'form.action'} eq 'addmetadata') {
7824: &addmetafield($r);
7825: } elsif ($env{'form.action'} eq 'ordermetadata') {
7826: &order_meta_fields($r);
1.414 droeschl 7827: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 7828: &setrestrictmeta($r);
1.414 droeschl 7829: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 7830: &newoverview($r,$parm_permission);
1.414 droeschl 7831: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 7832: &defaultsetter($r);
7833: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 7834: &assessparms($r,$parm_permission);
1.414 droeschl 7835: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 7836: &parm_change_log($r,$parm_permission);
1.414 droeschl 7837: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 7838: &clean_parameters($r);
1.414 droeschl 7839: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 7840: &date_shift_one($r);
1.414 droeschl 7841: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 7842: &date_shift_two($r);
1.446 bisitz 7843: }
1.43 albertel 7844: } else {
1.1 www 7845: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 7846: if ($exists) {
7847: $env{'user.error.msg'}=
7848: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
7849: } else {
7850: $env{'user.error.msg'}=
7851: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
7852: }
7853: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 7854: }
1.376 albertel 7855: &reset_caches();
7856:
1.43 albertel 7857: return OK;
1.1 www 7858: }
7859:
7860: 1;
7861: __END__
7862:
7863:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>