Annotation of loncom/interface/lonparmset.pm, revision 1.622
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.622 ! raeburn 4: # $Id: lonparmset.pm,v 1.621 2023/12/22 13:38:02 raeburn Exp $
1.40 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.59 matthew 28: ###################################################################
29: ###################################################################
30:
31: =pod
32:
33: =head1 NAME
34:
35: lonparmset - Handler to set parameters for assessments and course
36:
37: =head1 SYNOPSIS
38:
1.579 raeburn 39: lonparmset provides an interface to setting content parameters in a
40: course.
1.560 damieng 41:
42: It contains all the code for the "Content and Problem Settings" UI, except
43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
44: and lonblockingmenu.pm.
1.59 matthew 45:
46: =head1 DESCRIPTION
47:
48: This module sets coursewide and assessment parameters.
49:
50: =head1 INTERNAL SUBROUTINES
51:
1.416 jms 52: =over
1.59 matthew 53:
1.416 jms 54: =item parmval()
1.59 matthew 55:
56: Figure out a cascading parameter.
57:
1.71 albertel 58: Inputs: $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162 albertel 59: $id - a bighash Id number
1.71 albertel 60: $def - the resource's default value 'stupid emacs
61:
1.556 raeburn 62: Returns: A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71 albertel 63:
1.556 raeburn 64: 18 - General Course
65: 17 - Map or Folder level in course (recursive)
66: 16 - Map or Folder level in course (non-recursive)
67: 15 - resource default
68: 14 - map default
69: 13 - resource level in course
70: 12 - General for section
71: 11 - Map or Folder level for section (recursive)
72: 10 - Map or Folder level for section (non-recursive)
73: 9 - resource level in section
74: 8 - General for group
75: 7 - Map or Folder level for group (recursive)
76: 6 - Map or Folder level for group (non-recursive)
77: 5 - resource level in group
78: 4 - General for specific student
79: 3 - Map or Folder level for specific student (recursive)
80: 2 - Map or Folder level for specific student (non-recursive)
1.71 albertel 81: 1 - resource level for specific student
1.2 www 82:
1.416 jms 83: =item parmval_by_symb()
84:
85: =item reset_caches()
86:
87: =item cacheparmhash()
88:
89: =item parmhash()
90:
91: =item symbcache()
92:
93: =item preset_defaults()
94:
95: =item date_sanity_info()
96:
97: =item storeparm()
98:
99: Store a parameter by symb
100:
101: Takes
102: - symb
103: - name of parameter
104: - level
105: - new value
106: - new type
107: - username
108: - userdomain
109:
110: =item log_parmset()
111:
112: =item storeparm_by_symb_inner()
113:
114: =item valout()
115:
116: Format a value for output.
117:
118: Inputs: $value, $type, $editable
119:
120: Returns: $value, formatted for output. If $type indicates it is a date,
121: localtime($value) is returned.
122: $editable will return an icon to click on
123:
124: =item plink()
125:
126: Produces a link anchor.
127:
128: Inputs: $type,$dis,$value,$marker,$return,$call
129:
130: Returns: scalar with html code for a link which will envoke the
131: javascript function 'pjump'.
132:
133: =item page_js()
134:
135: =item startpage()
136:
137: =item print_row()
138:
139: =item print_td()
140:
1.580 raeburn 141: =item check_other_groups()
1.416 jms 142:
143: =item parm_control_group()
144:
145: =item extractResourceInformation() :
146:
1.512 foxr 147: extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416 jms 148:
1.542 raeburn 149: Input: See list below
150:
151: =over 4
1.416 jms 152:
1.512 foxr 153: =item * B<env{'user.name'}> : Current username
1.416 jms 154:
1.512 foxr 155: =item * B<env{'user.domain'}> : Domain of current user.
1.416 jms 156:
1.542 raeburn 157: =item * B<env{"request.course.fn"}> : Course
158:
159: =back
1.416 jms 160:
1.512 foxr 161: Outputs: See list below:
1.416 jms 162:
1.542 raeburn 163: =over 4
164:
1.512 foxr 165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416 jms 166:
1.512 foxr 167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416 jms 168:
1.512 foxr 169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416 jms 170:
1.512 foxr 171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416 jms 172:
1.512 foxr 173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
174:
175: =item * B<allmaps> (out) : hash, ???
1.416 jms 176:
177: =item * B<mapp> : ??
178:
179: =item * B<symbp> : hash, id->full sym?
180:
1.512 foxr 181: =item * B<maptitles>
182:
183: =item * B<uris>
1.416 jms 184:
1.512 foxr 185: =item * B<keyorder>
186:
187: =item * B<defkeytype>
1.416 jms 188:
1.542 raeburn 189: =back
190:
1.416 jms 191: =item isdateparm()
192:
193: =item parmmenu()
194:
195: =item partmenu()
196:
197: =item usermenu()
198:
199: =item displaymenu()
200:
201: =item mapmenu()
202:
203: =item levelmenu()
204:
205: =item sectionmenu()
206:
207: =item keysplit()
208:
209: =item keysinorder()
210:
211: =item keysinorder_bytype()
212:
213: =item keysindisplayorder()
214:
215: =item standardkeyorder()
216:
217: =item assessparms() :
218:
219: Show assessment data and parameters. This is a large routine that should
220: be simplified and shortened... someday.
221:
1.513 foxr 222: Inputs: $r - the Apache request object.
223:
1.416 jms 224: Returns: nothing
225:
226: Variables used (guessed by Jeremy):
227:
1.542 raeburn 228: =over
229:
1.416 jms 230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
231:
232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
233:
234: =item * B<@catmarker> contains list of all possible parameters including part #s
235:
236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
237:
238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
239: When storing information, store as part 0
240: When requesting information, request from full part
241:
1.542 raeburn 242: =back
243:
1.416 jms 244: =item tablestart()
245:
246: =item tableend()
247:
248: =item extractuser()
249:
250: =item parse_listdata_key()
251:
252: =item listdata()
253:
254: =item date_interval_selector()
255:
256: =item get_date_interval_from_form()
257:
258: =item default_selector()
259:
260: =item string_selector()
261:
262: =item dateshift()
263:
264: =item newoverview()
265:
266: =item secgroup_lister()
267:
268: =item overview()
269:
270: =item clean_parameters()
271:
272: =item date_shift_one()
273:
274: =item date_shift_two()
275:
276: =item parse_key()
277:
278: =item header()
279:
280: Output html header for page
281:
282: =item print_main_menu()
283:
284: =item output_row()
285:
286: Set portfolio metadata
287:
288: =item order_meta_fields()
289:
290: =item addmetafield()
291:
292: =item setrestrictmeta()
293:
294: =item get_added_meta_fieldnames()
295:
296: =item get_deleted_meta_fieldnames()
297:
298: =item defaultsetter()
299:
300: =item components()
301:
302: =item load_parameter_names()
303:
304: =item parm_change_log()
305:
306: =item handler() :
307:
1.450 raeburn 308: Main handler. Calls &assessparms subroutine.
1.416 jms 309:
310: =back
311:
1.59 matthew 312: =cut
313:
1.416 jms 314: ###################################################################
315: ###################################################################
316:
317: package Apache::lonparmset;
318:
319: use strict;
320: use Apache::lonnet;
321: use Apache::Constants qw(:common :http REDIRECT);
322: use Apache::lonhtmlcommon();
323: use Apache::loncommon;
324: use GDBM_File;
325: use Apache::lonhomework;
326: use Apache::lonxml;
327: use Apache::lonlocal;
328: use Apache::lonnavmaps;
329: use Apache::longroup;
330: use Apache::lonrss;
1.506 www 331: use HTML::Entities;
1.617 raeburn 332: use Text::Wrap();
1.416 jms 333: use LONCAPA qw(:DEFAULT :match);
334:
335:
1.560 damieng 336: ##################################################
337: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
338: ##################################################
339:
340: # Page header
1.561 damieng 341: #
342: # @param {Apache2::RequestRec} $r - Apache request object
343: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
344: # @param {string} $crstype - course type ('Community' for community settings)
1.507 www 345: sub startSettingsScreen {
1.531 raeburn 346: my ($r,$mode,$crstype)=@_;
1.507 www 347:
1.531 raeburn 348: my $tabtext = &mt('Course Settings');
349: if ($crstype eq 'Community') {
350: $tabtext = &mt('Community Settings');
351: }
1.507 www 352: $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
353: $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b> '.
1.531 raeburn 354: $tabtext.
1.507 www 355: ' </b></a></li>');
356:
1.523 raeburn 357: $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507 www 358: &mt('Content and Problem Settings').'</b></a></li>');
359: $r->print("\n".'</ul>'."\n");
1.523 raeburn 360: $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507 www 361: }
362:
1.560 damieng 363: # Page footer
1.507 www 364: sub endSettingsScreen {
365: my ($r)=@_;
366: $r->print('</div></div></div>');
367: }
368:
369:
370:
1.560 damieng 371: ##################################################
1.563 damieng 372: # (mostly) TABLE MODE
1.560 damieng 373: # (parmval is also used for the log of parameter changes)
374: ##################################################
375:
1.566 damieng 376: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561 damieng 377: #
378: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 379: # @param {string} $id - resource id or map pc
1.561 damieng 380: # @param {string} $def - the resource's default value for this parameter
381: # @param {string} $uname - user name
382: # @param {string} $udom - user domain
383: # @param {string} $csec - section name
384: # @param {string} $cgroup - group name
385: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
386: # @returns {Array}
1.2 www 387: sub parmval {
1.275 raeburn 388: my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
389: return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
390: $cgroup,$courseopt);
1.201 www 391: }
392:
1.561 damieng 393: # Returns an array containing
394: # - the most specific level that is defined for that parameter (integer)
395: # - an array with the level as index and the parameter value as value (when defined)
396: # (level 1 is the most specific and will have precedence)
397: #
398: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 399: # @param {string} $symb - resource symb or map src
1.561 damieng 400: # @param {string} $def - the resource's default value for this parameter
401: # @param {string} $uname - user name
402: # @param {string} $udom - user domain
403: # @param {string} $csec - section name
404: # @param {string} $cgroup - group name
405: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
406: # @returns {Array}
1.201 www 407: sub parmval_by_symb {
1.275 raeburn 408: my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200 www 409:
1.352 albertel 410: my $useropt;
411: if ($uname ne '' && $udom ne '') {
1.561 damieng 412: $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352 albertel 413: }
1.200 www 414:
1.8 www 415: my $result='';
1.44 albertel 416: my @outpar=();
1.2 www 417: # ----------------------------------------------------- Cascading lookup scheme
1.446 bisitz 418: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 419: $map = &Apache::lonnet::deversion($map);
1.561 damieng 420:
421: # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
422: # any change should be reflected there.
423:
1.201 www 424: my $symbparm=$symb.'.'.$what;
1.556 raeburn 425: my $recurseparm=$map.'___(rec).'.$what;
1.201 www 426: my $mapparm=$map.'___(all).'.$what;
1.10 www 427:
1.269 raeburn 428: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
429: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 430: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 431: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
432:
1.190 albertel 433: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
434: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 435: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 436: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
437:
438: my $courselevel=$env{'request.course.id'}.'.'.$what;
439: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 440: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 441: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2 www 442:
1.11 www 443:
1.182 albertel 444: # --------------------------------------------------------- first, check course
1.11 www 445:
1.561 damieng 446: # 18 - General Course
1.200 www 447: if (defined($$courseopt{$courselevel})) {
1.556 raeburn 448: $outpar[18]=$$courseopt{$courselevel};
449: $result=18;
450: }
451:
1.561 damieng 452: # 17 - Map or Folder level in course (recursive)
1.556 raeburn 453: if (defined($$courseopt{$courseleveli})) {
454: $outpar[17]=$$courseopt{$courseleveli};
455: $result=17;
1.43 albertel 456: }
1.11 www 457:
1.561 damieng 458: # 16 - Map or Folder level in course (non-recursive)
1.200 www 459: if (defined($$courseopt{$courselevelm})) {
1.556 raeburn 460: $outpar[16]=$$courseopt{$courselevelm};
461: $result=16;
1.43 albertel 462: }
1.11 www 463:
1.182 albertel 464: # ------------------------------------------------------- second, check default
465:
1.561 damieng 466: # 15 - resource default
1.556 raeburn 467: if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182 albertel 468:
469: # ------------------------------------------------------ third, check map parms
470:
1.556 raeburn 471:
1.561 damieng 472: # 14 - map default
1.376 albertel 473: my $thisparm=&parmhash($symbparm);
1.556 raeburn 474: if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182 albertel 475:
1.561 damieng 476: # 13 - resource level in course
1.200 www 477: if (defined($$courseopt{$courselevelr})) {
1.556 raeburn 478: $outpar[13]=$$courseopt{$courselevelr};
479: $result=13;
1.43 albertel 480: }
1.11 www 481:
1.182 albertel 482: # ------------------------------------------------------ fourth, back to course
1.352 albertel 483: if ($csec ne '') {
1.561 damieng 484: # 12 - General for section
1.200 www 485: if (defined($$courseopt{$seclevel})) {
1.556 raeburn 486: $outpar[12]=$$courseopt{$seclevel};
487: $result=12;
488: }
1.561 damieng 489: # 11 - Map or Folder level for section (recursive)
1.556 raeburn 490: if (defined($$courseopt{$secleveli})) {
491: $outpar[11]=$$courseopt{$secleveli};
492: $result=11;
493: }
1.561 damieng 494: # 10 - Map or Folder level for section (non-recursive)
1.200 www 495: if (defined($$courseopt{$seclevelm})) {
1.556 raeburn 496: $outpar[10]=$$courseopt{$seclevelm};
497: $result=10;
498: }
1.561 damieng 499: # 9 - resource level in section
1.200 www 500: if (defined($$courseopt{$seclevelr})) {
1.556 raeburn 501: $outpar[9]=$$courseopt{$seclevelr};
502: $result=9;
503: }
1.43 albertel 504: }
1.275 raeburn 505: # ------------------------------------------------------ fifth, check course group
1.352 albertel 506: if ($cgroup ne '') {
1.561 damieng 507: # 8 - General for group
1.269 raeburn 508: if (defined($$courseopt{$grplevel})) {
1.556 raeburn 509: $outpar[8]=$$courseopt{$grplevel};
510: $result=8;
511: }
1.561 damieng 512: # 7 - Map or Folder level for group (recursive)
1.556 raeburn 513: if (defined($$courseopt{$grpleveli})) {
514: $outpar[7]=$$courseopt{$grpleveli};
515: $result=7;
1.269 raeburn 516: }
1.561 damieng 517: # 6 - Map or Folder level for group (non-recursive)
1.269 raeburn 518: if (defined($$courseopt{$grplevelm})) {
1.556 raeburn 519: $outpar[6]=$$courseopt{$grplevelm};
520: $result=6;
1.269 raeburn 521: }
1.561 damieng 522: # 5 - resource level in group
1.269 raeburn 523: if (defined($$courseopt{$grplevelr})) {
1.556 raeburn 524: $outpar[5]=$$courseopt{$grplevelr};
525: $result=5;
1.269 raeburn 526: }
527: }
1.11 www 528:
1.556 raeburn 529: # ---------------------------------------------------------- sixth, check user
1.11 www 530:
1.352 albertel 531: if ($uname ne '') {
1.561 damieng 532: # 4 - General for specific student
533: if (defined($$useropt{$courselevel})) {
534: $outpar[4]=$$useropt{$courselevel};
535: $result=4;
536: }
1.556 raeburn 537:
1.561 damieng 538: # 3 - Map or Folder level for specific student (recursive)
539: if (defined($$useropt{$courseleveli})) {
540: $outpar[3]=$$useropt{$courseleveli};
541: $result=3;
542: }
1.473 amueller 543:
1.561 damieng 544: # 2 - Map or Folder level for specific student (non-recursive)
545: if (defined($$useropt{$courselevelm})) {
546: $outpar[2]=$$useropt{$courselevelm};
547: $result=2;
548: }
1.473 amueller 549:
1.561 damieng 550: # 1 - resource level for specific student
551: if (defined($$useropt{$courselevelr})) {
552: $outpar[1]=$$useropt{$courselevelr};
553: $result=1;
554: }
1.43 albertel 555: }
1.44 albertel 556: return ($result,@outpar);
1.2 www 557: }
558:
1.198 www 559:
560:
1.376 albertel 561: # --- Caches local to lonparmset
562:
1.446 bisitz 563:
1.561 damieng 564: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376 albertel 565: sub reset_caches {
566: &resetparmhash();
567: &resetsymbcache();
568: &resetrulescache();
1.203 www 569: }
570:
1.561 damieng 571: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
572: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376 albertel 573: {
1.561 damieng 574: my $parmhashid; # course identifier, to initialize the cache only once for a course
575: my %parmhash; # the parameter cache
576: # reset map parameter hash
1.376 albertel 577: sub resetparmhash {
1.560 damieng 578: undef($parmhashid);
579: undef(%parmhash);
1.376 albertel 580: }
1.446 bisitz 581:
1.561 damieng 582: # dump the _parms.db database into %parmhash
1.376 albertel 583: sub cacheparmhash {
1.560 damieng 584: if ($parmhashid eq $env{'request.course.fn'}) { return; }
585: my %parmhashfile;
586: if (tie(%parmhashfile,'GDBM_File',
587: $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
588: %parmhash=%parmhashfile;
589: untie(%parmhashfile);
590: $parmhashid=$env{'request.course.fn'};
591: }
1.201 www 592: }
1.446 bisitz 593:
1.561 damieng 594: # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376 albertel 595: sub parmhash {
1.560 damieng 596: my ($id) = @_;
597: &cacheparmhash();
598: return $parmhash{$id};
1.376 albertel 599: }
1.560 damieng 600: }
1.376 albertel 601:
1.566 damieng 602: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446 bisitz 603: {
1.561 damieng 604: my $symbsid; # course identifier, to initialize the cache only once for a course
605: my %symbs; # hash id->symb
606: # reset the id->symb cache
1.376 albertel 607: sub resetsymbcache {
1.560 damieng 608: undef($symbsid);
609: undef(%symbs);
1.376 albertel 610: }
1.446 bisitz 611:
1.566 damieng 612: # returns the resource symb or map src corresponding to a resource id or map pc
613: # (using lonnavmaps and a cache)
1.376 albertel 614: sub symbcache {
1.560 damieng 615: my $id=shift;
616: if ($symbsid ne $env{'request.course.id'}) {
617: undef(%symbs);
618: }
619: if (!$symbs{$id}) {
620: my $navmap = Apache::lonnavmaps::navmap->new();
621: if ($id=~/\./) {
622: my $resource=$navmap->getById($id);
623: $symbs{$id}=$resource->symb();
624: } else {
625: my $resource=$navmap->getByMapPc($id);
626: $symbs{$id}=&Apache::lonnet::declutter($resource->src());
627: }
628: $symbsid=$env{'request.course.id'};
1.473 amueller 629: }
1.560 damieng 630: return $symbs{$id};
1.473 amueller 631: }
1.560 damieng 632: }
1.201 www 633:
1.561 damieng 634: # cache for parameter default actions (stored in parmdefactions.db)
1.446 bisitz 635: {
1.561 damieng 636: my $rulesid; # course identifier, to initialize the cache only once for a course
637: my %rules; # parameter default actions hash
1.376 albertel 638: sub resetrulescache {
1.560 damieng 639: undef($rulesid);
640: undef(%rules);
1.376 albertel 641: }
1.446 bisitz 642:
1.561 damieng 643: # returns the value for a given key in the parameter default action hash
1.376 albertel 644: sub rulescache {
1.560 damieng 645: my $id=shift;
646: if ($rulesid ne $env{'request.course.id'}
647: && !defined($rules{$id})) {
648: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
649: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
650: %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
651: $rulesid=$env{'request.course.id'};
652: }
653: return $rules{$id};
1.221 www 654: }
655: }
656:
1.416 jms 657:
1.561 damieng 658: # Returns the values of the parameter type default action
659: # "default value when manually setting".
660: # If none is defined, ('','','','','') is returned.
661: #
662: # @param {string} $type - parameter type
663: # @returns {Array<string>} - (hours, min, sec, value)
1.229 www 664: sub preset_defaults {
665: my $type=shift;
666: if (&rulescache($type.'_action') eq 'default') {
1.560 damieng 667: # yes, there is something
668: return (&rulescache($type.'_hours'),
669: &rulescache($type.'_min'),
670: &rulescache($type.'_sec'),
671: &rulescache($type.'_value'));
1.229 www 672: } else {
1.560 damieng 673: # nothing there or something else
674: return ('','','','','');
1.229 www 675: }
676: }
677:
1.416 jms 678:
1.561 damieng 679: # Checks that a date is after enrollment start date and before
680: # enrollment end date.
681: # Returns HTML with a warning if it is not, or the empty string otherwise.
682: # This is used by both overview and table modes.
683: #
684: # @param {integer} $checkdate - the date to check.
685: # @returns {string} - HTML possibly containing a localized warning message.
1.277 www 686: sub date_sanity_info {
687: my $checkdate=shift;
688: unless ($checkdate) { return ''; }
689: my $result='';
690: my $crsprefix='course.'.$env{'request.course.id'}.'.';
691: if ($env{$crsprefix.'default_enrollment_end_date'}) {
692: if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413 bisitz 693: $result.='<div class="LC_warning">'
694: .&mt('After course enrollment end!')
695: .'</div>';
1.277 www 696: }
697: }
698: if ($env{$crsprefix.'default_enrollment_start_date'}) {
699: if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413 bisitz 700: $result.='<div class="LC_warning">'
701: .&mt('Before course enrollment start!')
702: .'</div>';
1.277 www 703: }
704: }
1.413 bisitz 705: # Preparation for additional warnings about dates in the past/future.
706: # An improved, more context sensitive version is recommended,
707: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
708: # if ($checkdate<time) {
709: # $result.='<div class="LC_info">'
710: # .'('.&mt('in the past').')'
711: # .'</div>';
712: # }
713: # if ($checkdate>time) {
714: # $result.='<div class="LC_info">'
715: # .'('.&mt('in the future').')'
716: # .'</div>';
717: # }
1.277 www 718: return $result;
719: }
1.561 damieng 720:
721:
722: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186 www 723: #
1.566 damieng 724: # @param {string} $sresid - resource id or map pc
1.565 damieng 725: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 726: # @param {integer} $snum - level
727: # @param {string} $nval - new value
728: # @param {string} $ntype - new type
729: # @param {string} $uname - username
730: # @param {string} $udom - userdomain
731: # @param {string} $csec - section name
732: # @param {string} $cgroup - group name
1.186 www 733: sub storeparm {
1.269 raeburn 734: my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275 raeburn 735: &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197 www 736: }
737:
1.561 damieng 738: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
739:
740: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
741: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
742: #
1.566 damieng 743: # @param {string} $symb - resource symb or map src
1.565 damieng 744: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 745: # @param {integer} $snum - level
746: # @param {string} $nval - new value
747: # @param {string} $ntype - new type
748: # @param {string} $uname - username
749: # @param {string} $udom - userdomain
750: # @param {string} $csec - section name
751: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
752: # @param {string} $cgroup - group name
1.197 www 753: sub storeparm_by_symb {
1.275 raeburn 754: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226 www 755: unless ($recflag) {
1.560 damieng 756: # first time call
757: %recstack=();
758: $recflag=1;
1.226 www 759: }
1.560 damieng 760: # store parameter
1.226 www 761: &storeparm_by_symb_inner
1.473 amueller 762: ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560 damieng 763: # don't do anything if parameter was reset
1.266 www 764: unless ($nval) { return; }
1.226 www 765: my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560 damieng 766: # remember that this was set
1.226 www 767: $recstack{$parm}=1;
1.560 damieng 768: # what does this trigger?
1.226 www 769: foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560 damieng 770: # don't backfire
771: unless ((!$triggered) || ($recstack{$triggered})) {
772: my $action=&rulescache($triggered.'_action');
773: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
774: # set triggered parameter on same level
775: my $newspnam=$prefix.$triggered;
776: my $newvalue='';
777: my $active=1;
778: if ($action=~/^when\_setting/) {
779: # are there restrictions?
780: if (&rulescache($triggered.'_triggervalue')=~/\w/) {
781: $active=0;
1.565 damieng 782: foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560 damieng 783: if (lc($possiblevalue) eq lc($nval)) { $active=1; }
784: }
785: }
786: $newvalue=&rulescache($triggered.'_value');
787: } else {
788: my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
789: if ($action=~/^later\_than/) {
790: $newvalue=$nval+$totalsecs;
791: } else {
792: $newvalue=$nval-$totalsecs;
793: }
794: }
795: if ($active) {
796: &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
797: $uname,$udom,$csec,$recflag,$cgroup);
798: }
799: }
1.226 www 800: }
801: return '';
802: }
803:
1.561 damieng 804: # Adds all given arguments to the course parameter log.
805: # @returns {string} - the answer to the lonnet query.
1.293 www 806: sub log_parmset {
1.525 raeburn 807: return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284 www 808: }
809:
1.561 damieng 810: # Store a parameter value and type by symb, without using the parameter default actions.
811: # Expire related sheets.
812: #
1.566 damieng 813: # @param {string} $symb - resource symb or map src
1.561 damieng 814: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
815: # @param {integer} $snum - level
816: # @param {string} $nval - new value
817: # @param {string} $ntype - new type
818: # @param {string} $uname - username
819: # @param {string} $udom - userdomain
820: # @param {string} $csec - section name
821: # @param {string} $cgroup - group name
822: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226 www 823: sub storeparm_by_symb_inner {
1.197 www 824: # ---------------------------------------------------------- Get symb, map, etc
1.269 raeburn 825: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197 www 826: # ---------------------------------------------------------- Construct prefixes
1.186 www 827: $spnam=~s/\_([^\_]+)$/\.$1/;
1.446 bisitz 828: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 829: $map = &Apache::lonnet::deversion($map);
830:
1.197 www 831: my $symbparm=$symb.'.'.$spnam;
1.556 raeburn 832: my $recurseparm=$map.'___(rec).'.$spnam;
1.197 www 833: my $mapparm=$map.'___(all).'.$spnam;
834:
1.269 raeburn 835: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
836: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 837: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 838: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
839:
1.190 albertel 840: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
841: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 842: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 843: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446 bisitz 844:
1.190 albertel 845: my $courselevel=$env{'request.course.id'}.'.'.$spnam;
846: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 847: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 848: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446 bisitz 849:
1.186 www 850: my $storeunder='';
1.578 raeburn 851: my $possreplace='';
1.556 raeburn 852: if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578 raeburn 853: if (($snum==17) || ($snum==3)) {
854: $storeunder=$courseleveli;
855: $possreplace=$courselevelm;
856: }
857: if (($snum==16) || ($snum==2)) {
858: $storeunder=$courselevelm;
859: $possreplace=$courseleveli;
860: }
1.556 raeburn 861: if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
862: if ($snum==12) { $storeunder=$seclevel; }
1.578 raeburn 863: if ($snum==11) {
864: $storeunder=$secleveli;
865: $possreplace=$seclevelm;
866: }
867: if ($snum==10) {
868: $storeunder=$seclevelm;
869: $possreplace=$secleveli;
870: }
1.556 raeburn 871: if ($snum==9) { $storeunder=$seclevelr; }
872: if ($snum==8) { $storeunder=$grplevel; }
1.578 raeburn 873: if ($snum==7) {
874: $storeunder=$grpleveli;
875: $possreplace=$grplevelm;
876: }
877: if ($snum==6) {
878: $storeunder=$grplevelm;
879: $possreplace=$grpleveli;
880: }
1.556 raeburn 881: if ($snum==5) { $storeunder=$grplevelr; }
1.269 raeburn 882:
1.446 bisitz 883:
1.186 www 884: my $delete;
885: if ($nval eq '') { $delete=1;}
886: my %storecontent = ($storeunder => $nval,
1.473 amueller 887: $storeunder.'.type' => $ntype);
1.186 www 888: my $reply='';
1.560 damieng 889:
1.556 raeburn 890: if ($snum>4) {
1.186 www 891: # ---------------------------------------------------------------- Store Course
892: #
1.560 damieng 893: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
894: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
895: # Expire sheets
896: &Apache::lonnet::expirespread('','','studentcalc');
897: if (($snum==13) || ($snum==9) || ($snum==5)) {
898: &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578 raeburn 899: } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560 damieng 900: &Apache::lonnet::expirespread('','','assesscalc',$map);
901: } else {
902: &Apache::lonnet::expirespread('','','assesscalc');
903: }
904: # Store parameter
905: if ($delete) {
906: $reply=&Apache::lonnet::del
907: ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
908: &log_parmset(\%storecontent,1);
909: } else {
910: $reply=&Apache::lonnet::cput
911: ('resourcedata',\%storecontent,$cdom,$cnum);
912: &log_parmset(\%storecontent);
1.578 raeburn 913: if ($possreplace) {
914: my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
915: if (ref($resdata) eq 'HASH') {
916: if (exists($resdata->{$possreplace})) {
917: if (&Apache::lonnet::del
918: ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
919: &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);
920: }
921: }
922: }
923: }
1.560 damieng 924: }
925: &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186 www 926: } else {
927: # ------------------------------------------------------------------ Store User
928: #
1.560 damieng 929: # Expire sheets
930: &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
931: if ($snum==1) {
932: &Apache::lonnet::expirespread
933: ($uname,$udom,'assesscalc',$symb);
1.578 raeburn 934: } elsif (($snum==2) || ($snum==3)) {
1.560 damieng 935: &Apache::lonnet::expirespread
936: ($uname,$udom,'assesscalc',$map);
937: } else {
938: &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
939: }
940: # Store parameter
941: if ($delete) {
942: $reply=&Apache::lonnet::del
943: ('resourcedata',[keys(%storecontent)],$udom,$uname);
944: &log_parmset(\%storecontent,1,$uname,$udom);
945: } else {
946: $reply=&Apache::lonnet::cput
947: ('resourcedata',\%storecontent,$udom,$uname);
948: &log_parmset(\%storecontent,0,$uname,$udom);
1.578 raeburn 949: if ($possreplace) {
950: my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
951: if (ref($resdata) eq 'HASH') {
952: if (exists($resdata->{$possreplace})) {
953: if (&Apache::lonnet::del
954: ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
955: &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
956: $uname,$udom);
957: }
958: }
959: }
960: }
1.560 damieng 961: }
962: &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186 www 963: }
1.446 bisitz 964:
1.186 www 965: if ($reply=~/^error\:(.*)/) {
1.560 damieng 966: return "<span class=\"LC_error\">Write Error: $1</span>";
1.186 www 967: }
968: return '';
969: }
970:
1.9 www 971:
1.561 damieng 972: # Returns HTML with the value of the given parameter,
973: # using a readable format for dates, and
974: # a warning if there is a problem with a date.
975: # Used by table mode.
976: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
977: #
978: # @param {string} $value - the parameter value
979: # @param {string} $type - the parameter type
980: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9 www 981: sub valout {
1.600 raeburn 982: my ($value,$type,$editable)=@_;
1.59 matthew 983: my $result = '';
984: # Values of zero are valid.
985: if (! $value && $value ne '0') {
1.528 bisitz 986: if ($editable) {
987: $result =
988: '<img src="/res/adm/pages/editmap.png"'
989: .' alt="'.&mt('Change').'"'
1.539 raeburn 990: .' title="'.&mt('Change').'" style="border:0;" />';
1.528 bisitz 991: } else {
992: $result=' ';
993: }
1.59 matthew 994: } else {
1.622 ! raeburn 995: if (($type eq 'date_interval') || ($type eq 'string_grace')) {
! 996: if ($type eq 'string_grace') {
! 997: my @items;
! 998: if ($value =~ /,/) {
! 999: @items = split(/,/,$value);
1.558 raeburn 1000: } else {
1.622 ! raeburn 1001: @items = ($value);
! 1002: }
! 1003: foreach my $item (@items) {
! 1004: if ($item =~ /^\d+:(0|1)\.?\d*:(0|1)$/) {
! 1005: my ($totalsecs,$fraction,$grad) = split(/:/,$item);
! 1006: $result .= &interval_to_humanstr($totalsecs);
! 1007: if (($fraction >=0) && ($fraction <=1)) {
! 1008: $result .= ' | '.$fraction.' '.&mt('pts');
! 1009: if ($grad == 1) {
! 1010: $result .= ' ('.&mt('gradual').')';
! 1011: }
! 1012: }
! 1013: $result .= ', ';
! 1014: }
! 1015: }
! 1016: $result =~ s/, $//;
! 1017: } else {
! 1018: my ($totalsecs,$donesuffix) = split(/_/,$value,2);
! 1019: $result = &interval_to_humanstr($totalsecs);
! 1020: my ($usesdone,$donebuttontext,$proctor,$secretkey);
! 1021: if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
! 1022: $donebuttontext = $1;
! 1023: (undef,$proctor,$secretkey) = split(/_/,$2);
! 1024: $usesdone = 'done';
! 1025: } elsif ($donesuffix =~ /^done(|_.+)$/) {
! 1026: $donebuttontext = &mt('Done');
! 1027: ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
! 1028: }
! 1029: if ($usesdone eq 'done') {
! 1030: if ($secretkey) {
! 1031: $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
! 1032: } else {
! 1033: $result .= ' + "'.$donebuttontext.'"';
! 1034: }
1.559 raeburn 1035: }
1.554 raeburn 1036: }
1.213 www 1037: } elsif (&isdateparm($type)) {
1.361 albertel 1038: $result = &Apache::lonlocal::locallocaltime($value).
1.560 damieng 1039: &date_sanity_info($value);
1.59 matthew 1040: } else {
1041: $result = $value;
1.517 www 1042: $result=~s/\,/\, /gs;
1.560 damieng 1043: $result = &HTML::Entities::encode($result,'"<>&');
1.59 matthew 1044: }
1045: }
1046: return $result;
1.9 www 1047: }
1048:
1.622 ! raeburn 1049: sub interval_to_humanstr {
! 1050: my ($totalsecs) = @_;
! 1051: my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
! 1052: my @timer;
! 1053: $year=$year-70;
! 1054: $mday--;
! 1055: if ($year) {
! 1056: push(@timer,&mt('[quant,_1,yr]',$year));
! 1057: }
! 1058: if ($mon) {
! 1059: push(@timer,&mt('[quant,_1,mth]',$mon));
! 1060: }
! 1061: if ($mday) {
! 1062: push(@timer,&mt('[quant,_1,day]',$mday));
! 1063: }
! 1064: if ($hour) {
! 1065: push(@timer,&mt('[quant,_1,hr]',$hour));
! 1066: }
! 1067: if ($min) {
! 1068: push(@timer,&mt('[quant,_1,min]',$min));
! 1069: }
! 1070: if ($sec) {
! 1071: push(@timer,&mt('[quant,_1,sec]',$sec));
! 1072: }
! 1073: if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
! 1074: push(@timer,&mt('[quant,_1,sec]',0));
! 1075: }
! 1076: return '<span style="white-space:nowrap">'.join('</span>, <span style="white-space:nowrap">',@timer).'</span>';
! 1077: }
1.59 matthew 1078:
1.561 damieng 1079: # Returns HTML containing a link on a parameter value, for table mode.
1080: # The link uses the javascript function 'pjump'.
1081: #
1082: # @param {string} $type - parameter type
1083: # @param {string} $dis - dialog title for editing the parameter value and type
1084: # @param {string} $value - parameter value
1085: # @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.
1086: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
1087: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588 raeburn 1088: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
1089: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5 www 1090: sub plink {
1.588 raeburn 1091: my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23 www 1092: my $winvalue=$value;
1093: unless ($winvalue) {
1.592 raeburn 1094: if (&isdateparm($type) || (&is_specialstring($type))) {
1.190 albertel 1095: $winvalue=$env{'form.recent_'.$type};
1.591 raeburn 1096: } elsif ($type eq 'string_yesno') {
1097: if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
1098: $winvalue=$env{'form.recent_string'};
1099: }
1.23 www 1100: } else {
1.190 albertel 1101: $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23 www 1102: }
1103: }
1.229 www 1104: my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
1105: my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
1106: unless (defined($winvalue)) { $winvalue=$val; }
1.593 raeburn 1107: my $valout = &valout($value,$type,1);
1.429 raeburn 1108: my $unencmarker = $marker;
1.378 albertel 1109: foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588 raeburn 1110: \$hour, \$min, \$sec, \$extra) {
1.560 damieng 1111: $$item = &HTML::Entities::encode($$item,'"<>&');
1112: $$item =~ s/\'/\\\'/g;
1.378 albertel 1113: }
1.429 raeburn 1114: return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473 amueller 1115: '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588 raeburn 1116: .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578 raeburn 1117: $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
1118: &mt('recursive').'</td></tr>' : '').'</table>';
1119:
1.5 www 1120: }
1121:
1.561 damieng 1122: # Javascript for table mode.
1.280 albertel 1123: sub page_js {
1124:
1.81 www 1125: my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88 matthew 1126: my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280 albertel 1127:
1128: return(<<ENDJS);
1129: <script type="text/javascript">
1.454 bisitz 1130: // <![CDATA[
1.44 albertel 1131:
1.88 matthew 1132: $pjump_def
1.44 albertel 1133:
1134: function psub() {
1.591 raeburn 1135: var specstring = /^string_!(yesno|any)/i;
1.44 albertel 1136: if (document.parmform.pres_marker.value!='') {
1137: document.parmform.action+='#'+document.parmform.pres_marker.value;
1138: var typedef=new Array();
1139: typedef=document.parmform.pres_type.value.split('_');
1.562 damieng 1140: if (document.parmform.pres_type.value!='') {
1.589 raeburn 1141: if ((typedef[0]=='date') ||
1.591 raeburn 1142: (specstring.test(document.parmform.pres_type.value))) {
1.562 damieng 1143: eval('document.parmform.recent_'+
1144: document.parmform.pres_type.value+
1145: '.value=document.parmform.pres_value.value;');
1146: } else {
1147: eval('document.parmform.recent_'+typedef[0]+
1148: '.value=document.parmform.pres_value.value;');
1149: }
1.44 albertel 1150: }
1151: document.parmform.submit();
1152: } else {
1153: document.parmform.pres_value.value='';
1154: document.parmform.pres_marker.value='';
1155: }
1156: }
1157:
1.57 albertel 1158: function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
1159: var options = "width=" + w + ",height=" + h + ",";
1160: options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
1161: options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
1162: var newWin = window.open(url, wdwName, options);
1163: newWin.focus();
1164: }
1.523 raeburn 1165:
1.454 bisitz 1166: // ]]>
1.523 raeburn 1167:
1.44 albertel 1168: </script>
1.81 www 1169: $selscript
1.280 albertel 1170: ENDJS
1171:
1172: }
1.507 www 1173:
1.561 damieng 1174: # Javascript to show or hide the map selection (function showHide_courseContent),
1175: # for table and overview modes.
1.523 raeburn 1176: sub showhide_js {
1177: return <<"COURSECONTENTSCRIPT";
1178:
1179: function showHide_courseContent() {
1180: var parmlevValue=document.getElementById("parmlev").value;
1181: if (parmlevValue == 'general') {
1182: document.getElementById('mapmenu').style.display="none";
1183: } else {
1184: if ((parmlevValue == "full") || (parmlevValue == "map")) {
1185: document.getElementById('mapmenu').style.display ="";
1186: } else {
1187: document.getElementById('mapmenu').style.display="none";
1188: }
1189: }
1190: return;
1191: }
1192:
1193: COURSECONTENTSCRIPT
1194: }
1195:
1.561 damieng 1196: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549 raeburn 1197: sub toggleparmtextbox_js {
1198: return <<"ENDSCRIPT";
1199:
1200: if (!document.getElementsByClassName) {
1201: function getElementsByClassName(node, classname) {
1202: var a = [];
1203: var re = new RegExp('(^| )'+classname+'( |$)');
1204: var els = node.getElementsByTagName("*");
1205: for(var i=0,j=els.length; i<j; i++)
1206: if(re.test(els[i].className))a.push(els[i]);
1207: return a;
1208: }
1209: }
1210:
1211: function showHideLenient() {
1212: var lenients;
1213: var setRegExp = /^set_/;
1214: if (document.getElementsByClassName) {
1215: lenients = document.getElementsByClassName('LC_lenient_radio');
1216: } else {
1217: lenients = getElementsByClassName(document.body,'LC_lenient_radio');
1218: }
1219: if (lenients != 'undefined') {
1220: for (var i=0; i<lenients.length; i++) {
1221: if (lenients[i].checked) {
1222: if (lenients[i].value == 'weighted') {
1223: if (setRegExp.test(lenients[i].name)) {
1224: var identifier = lenients[i].name.replace(setRegExp,'');
1225: toggleParmTextbox(document.parmform,identifier);
1226: }
1227: }
1228: }
1229: }
1230: }
1231: return;
1232: }
1233:
1234: function toggleParmTextbox(form,key) {
1235: var divfortext = document.getElementById('LC_parmtext_'+key);
1236: if (divfortext) {
1237: var caller = form.elements['set_'+key];
1238: if (caller.length) {
1239: for (i=0; i<caller.length; i++) {
1240: if (caller[i].checked) {
1241: if (caller[i].value == 'weighted') {
1242: divfortext.style.display = 'inline';
1243: } else {
1244: divfortext.style.display = 'none';
1245: }
1246: }
1247: }
1248: }
1249: }
1250: return;
1251: }
1252:
1253: ENDSCRIPT
1254: }
1255:
1.561 damieng 1256: # Javascript function validateParms, for overview mode
1.549 raeburn 1257: sub validateparms_js {
1258: return <<'ENDSCRIPT';
1259:
1260: function validateParms() {
1261: var textRegExp = /^settext_/;
1262: var tailLenient = /\.lenient$/;
1263: var patternRelWeight = /^\-?[\d.]+$/;
1264: var patternLenientStd = /^(yes|no|default)$/;
1.597 raeburn 1265: var ipRegExp = /^setip/;
1.549 raeburn 1266: var ipallowRegExp = /^setipallow_/;
1267: var ipdenyRegExp = /^setipdeny_/;
1.622 ! raeburn 1268: var graceRegExp = /^setgrace_/;
1.597 raeburn 1269: var deeplinkRegExp = /^deeplink_/;
1.601 raeburn 1270: var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;
1271: var dlLinkProtectRegExp = /^deeplink_protect_/;
1272: var dlLtidRegExp = /^deeplink_ltid_/;
1273: var dlLticRegExp = /^deeplink_ltic_/;
1.597 raeburn 1274: var dlKeyRegExp = /^deeplink_key_/;
1275: var dlMenusRegExp = /^deeplink_menus_/;
1276: var dlCollsRegExp = /^deeplink_colls_/;
1.613 raeburn 1277: var dlTargetRegExp = /^deeplink_target_/;
1.616 raeburn 1278: var dlExitRegExp = /^deeplink_exit_/;
1279: var dlExitTextRegExp = /^deeplink_exittext_/;
1.549 raeburn 1280: var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1.616 raeburn 1281: var numelements = document.parmform.elements.length;
1282: if ((typeof(numelements) != 'undefined') && (numelements != null)) {
1283: if (numelements) {
1284: for (i=0; i<numelements; i++) {
1.549 raeburn 1285: var name=document.parmform.elements[i].name;
1.588 raeburn 1286: if (textRegExp.test(name)) {
1.549 raeburn 1287: var identifier = name.replace(textRegExp,'');
1288: if (tailLenient.test(identifier)) {
1289: if (document.parmform.elements['set_'+identifier].length) {
1290: for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
1291: if (document.parmform.elements['set_'+identifier][j].checked) {
1292: if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
1293: var relweight = document.parmform.elements[i].value;
1294: relweight = relweight.replace(/^\s+|\s+$/g,'');
1295: if (!patternRelWeight.test(relweight)) {
1296: relweight = '0.0';
1297: }
1298: if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
1299: document.parmform.elements['set_'+identifier][j].value = relweight;
1300: } else {
1301: document.parmform.elements['set_'+identifier][j].value += ','+relweight;
1302: }
1303: }
1304: break;
1305: }
1306: }
1307: }
1308: }
1.597 raeburn 1309: } else if (ipRegExp.test(name)) {
1310: if (ipallowRegExp.test(name)) {
1311: var identifier = name.replace(ipallowRegExp,'');
1312: var possallow = document.parmform.elements[i].value;
1313: possallow = possallow.replace(/^\s+|\s+$/g,'');
1314: if (patternIP.test(possallow)) {
1315: if (document.parmform.elements['set_'+identifier].value) {
1316: possallow = ','+possallow;
1317: }
1318: document.parmform.elements['set_'+identifier].value += possallow;
1319: }
1320: } else if (ipdenyRegExp.test(name)) {
1321: var identifier = name.replace(ipdenyRegExp,'');
1322: var possdeny = document.parmform.elements[i].value;
1323: possdeny = possdeny.replace(/^\s+|\s+$/g,'');
1324: if (patternIP.test(possdeny)) {
1325: possdeny = '!'+possdeny;
1326: if (document.parmform.elements['set_'+identifier].value) {
1327: possdeny = ','+possdeny;
1328: }
1329: document.parmform.elements['set_'+identifier].value += possdeny;
1.588 raeburn 1330: }
1331: }
1332: } else if (deeplinkRegExp.test(name)) {
1.597 raeburn 1333: if (dlListScopeRegExp.test(name)) {
1334: var identifier = name.replace(dlListScopeRegExp,'');
1335: var idx = document.parmform.elements[i].selectedIndex;
1336: if (idx > 0) {
1337: var possdeeplink = document.parmform.elements[i].options[idx].value
1338: possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
1339: if (document.parmform.elements['set_'+identifier].value) {
1340: possdeeplink = ','+possdeeplink;
1341: }
1342: document.parmform.elements['set_'+identifier].value += possdeeplink;
1343: }
1.601 raeburn 1344: } else if (dlLinkProtectRegExp.test(name)) {
1.597 raeburn 1345: if (document.parmform.elements[i].checked) {
1.601 raeburn 1346: var identifier = name.replace(dlLinkProtectRegExp,'');
1.597 raeburn 1347: var posslinkurl = document.parmform.elements[i].value;
1348: posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
1349: if (document.parmform.elements['set_'+identifier].value) {
1350: posslinkurl = ','+posslinkurl;
1351: }
1352: document.parmform.elements['set_'+identifier].value += posslinkurl;
1353: }
1.601 raeburn 1354: } else if (dlLtidRegExp.test(name)) {
1355: var identifier = name.replace(dlLtidRegExp,'');
1356: if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
1357: var possltid = document.parmform.elements[i].value;
1358: possltid = possltid.replace(/\D+/g,'');
1359: if (possltid.length) {
1.597 raeburn 1360: if (document.parmform.elements['set_'+identifier].value) {
1.601 raeburn 1361: possltid = ':'+possltid;
1.597 raeburn 1362: }
1.601 raeburn 1363: document.parmform.elements['set_'+identifier].value += possltid;
1.597 raeburn 1364: } else {
1365: document.parmform.elements['set_'+identifier].value = '';
1.601 raeburn 1366: 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 1367: return false;
1368: }
1369: }
1.601 raeburn 1370: } else if (dlLticRegExp.test(name)) {
1371: var identifier = name.replace(dlLticRegExp,'');
1372: if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
1373: var possltic = document.parmform.elements[i].value;
1374: possltic = possltic.replace(/\D+/g,'');
1375: if (possltic.length) {
1376: if (document.parmform.elements['set_'+identifier].value) {
1377: possltic = ':'+possltic;
1378: }
1379: document.parmform.elements['set_'+identifier].value += possltic;
1380: } else {
1381: document.parmform.elements['set_'+identifier].value = '';
1382: 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.");
1383: return false;
1384: }
1385: }
1.597 raeburn 1386: } else if (dlKeyRegExp.test(name)) {
1387: var identifier = name.replace(dlKeyRegExp,'');
1.601 raeburn 1388: if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597 raeburn 1389: var posskey = document.parmform.elements[i].value;
1390: posskey = posskey.replace(/^\s+|\s+$/g,'');
1391: var origlength = posskey.length;
1392: posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
1393: var newlength = posskey.length;
1394: if (newlength > 0) {
1395: var change = origlength - newlength;
1396: if (change) {
1397: alert(change+' disallowed character(s) removed from deeplink key');
1398: }
1399: if (document.parmform.elements['set_'+identifier].value) {
1400: posskey = ':'+posskey;
1401: }
1402: document.parmform.elements['set_'+identifier].value += posskey;
1403: } else {
1404: document.parmform.elements['set_'+identifier].value = '';
1405: if (newlength < origlength) {
1406: 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_.!@#$%^&*()+=-");
1407: } else {
1408: alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
1409: }
1410: return false;
1411: }
1412: }
1413: } else if (dlMenusRegExp.test(name)) {
1414: if (document.parmform.elements[i].checked) {
1415: var identifier = name.replace(dlMenusRegExp,'');
1416: var posslinkmenu = document.parmform.elements[i].value;
1417: posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
1418: if (posslinkmenu == 'std') {
1419: posslinkmenu = '0';
1420: if (document.parmform.elements['set_'+identifier].value) {
1421: posslinkmenu = ','+posslinkmenu;
1422: }
1423: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1424: }
1425: }
1426: } else if (dlCollsRegExp.test(name)) {
1427: var identifier = name.replace(dlCollsRegExp,'');
1428: if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
1429: var posslinkmenu = document.parmform.elements[i].value;
1430: if (document.parmform.elements['set_'+identifier].value) {
1431: posslinkmenu = ','+posslinkmenu;
1432: }
1433: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1434: }
1.614 raeburn 1435: } else if (dlTargetRegExp.test(name)) {
1436: var identifier = name.replace(dlTargetRegExp,'');
1.613 raeburn 1437: var idx = document.parmform.elements[i].selectedIndex;
1438: if (idx > 0) {
1.616 raeburn 1439: var linktarget = document.parmform.elements[i].options[idx].value
1440: linktarget = linktarget.replace(/^\s+|\s+$/g,'');
1441: if (document.parmform.elements['set_'+identifier].value) {
1442: linktarget = ','+linktarget;
1443: }
1444: document.parmform.elements['set_'+identifier].value += linktarget;
1445: }
1446: } else if (dlExitRegExp.test(name)) {
1447: if (document.parmform.elements[i].checked) {
1448: var identifier = name.replace(dlExitRegExp,'');
1449: var posslinkexit = document.parmform.elements[i].value;
1450: posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');
1.613 raeburn 1451: if (document.parmform.elements['set_'+identifier].value) {
1.616 raeburn 1452: posslinkexit = ','+posslinkexit;
1453: }
1454: document.parmform.elements['set_'+identifier].value += posslinkexit;
1455: }
1456: } else if (dlExitTextRegExp.test(name)) {
1457: var identifier = name.replace(dlExitTextRegExp,'');
1458: if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
1459: (isRadioSet('deeplink_exit_'+identifier,'url'))) {
1460: var posstext = document.parmform.elements[i].value;
1461: posstext = posstext.replace(/^\s+|\s+$/g,'');
1462: var origlength = posstext.length;
1463: posstext = posstext.replace(/[:;'",]/g,'');
1464: var newlength = posstext.length;
1465: if (newlength > 0) {
1466: var change = origlength - newlength;
1467: if (change) {
1468: alert(change+' disallowed character(s) removed from Exit Button text');
1469: }
1470: if (posstext !== 'Exit Tool') {
1471: posstext = ':'+posstext;
1472: document.parmform.elements['set_'+identifier].value += posstext;
1473: }
1474: } else {
1475: document.parmform.elements['set_'+identifier].value = '';
1476: if (newlength < origlength) {
1477: alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");
1478: } else {
1479: alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");
1480: }
1481: return false;
1.613 raeburn 1482: }
1483: }
1.549 raeburn 1484: }
1.622 ! raeburn 1485: } else if (graceRegExp.test(name)) {
! 1486: var identifier = name.replace(graceRegExp,'');
! 1487: var divElem = document.parmform.elements[i].closest('div');
! 1488: var timeSels = divElem.getElementsByTagName("select");
! 1489: var total = 0;
! 1490: if (timeSels.length) {
! 1491: for (var j=0; j<timeSels.length; j++) {
! 1492: var sname = timeSels[j].getAttribute('name');
! 1493: var poss = parseInt(timeSels[j].options[timeSels[j].selectedIndex].value);
! 1494: if (sname == 'days_'+identifier) {
! 1495: if ((poss > 0) && (poss <= 31)) {
! 1496: total += (poss * 86400);
! 1497: }
! 1498: } else if (sname == 'hours_'+identifier) {
! 1499: if ((poss > 0) && (poss < 24)) {
! 1500: total += (poss * 3600);
! 1501: }
! 1502: } else if (sname == 'minutes_'+identifier) {
! 1503: if ((poss > 0) && (poss < 60)) {
! 1504: total += (poss * 60);
! 1505: }
! 1506: } else if (sname == 'seconds_'+identifier) {
! 1507: if ((poss > 0) && (poss < 60)) {
! 1508: total += poss;
! 1509: }
! 1510: }
! 1511: }
! 1512: }
! 1513: var inputElems = divElem.getElementsByTagName("input");
! 1514: var frac = '';
! 1515: var grad = '';
! 1516: if (inputElems.length) {
! 1517: for (var j=0; j<inputElems.length; j++) {
! 1518: var iname = inputElems[j].getAttribute('name');
! 1519: if (iname == 'frac_'+identifier) {
! 1520: var ival = inputElems[j].value;
! 1521: ival.trim();
! 1522: var poss = parseFloat(ival);
! 1523: if ((typeof poss === 'number') && (!isNaN(poss))) {
! 1524: if ((poss => 0) && (poss <= 1)) {
! 1525: frac = poss;
! 1526: }
! 1527: }
! 1528: } else if (iname == 'grad_'+identifier) {
! 1529: if (inputElems[j].checked) {
! 1530: grad = 1;
! 1531: } else {
! 1532: grad = 0;
! 1533: }
! 1534: }
! 1535: }
! 1536: }
! 1537: document.parmform.elements[i].value = total+':'+frac+':'+grad;
! 1538: if (document.parmform.elements['set_'+identifier].value) {
! 1539: document.parmform.elements['set_'+identifier].value += ',';
! 1540: }
! 1541: document.parmform.elements['set_'+identifier].value += document.parmform.elements[i].value;
1.549 raeburn 1542: }
1543: }
1544: }
1545: }
1546: return true;
1547: }
1548:
1.597 raeburn 1549: function isRadioSet(name,expected) {
1550: var menuitems = document.getElementsByName(name);
1551: var radioLength = menuitems.length;
1552: result = false;
1553: if (radioLength > 1) {
1554: for (var j=0; j<radioLength; j++) {
1555: if (menuitems[j].checked) {
1556: if (menuitems[j].value == expected) {
1557: result = true;
1558: break;
1559: }
1560: }
1561: }
1562: }
1563: return result;
1564: }
1565:
1.549 raeburn 1566: ENDSCRIPT
1567: }
1568:
1.561 damieng 1569: # Javascript initialization, for overview mode
1.549 raeburn 1570: sub ipacc_boxes_js {
1571: my $remove = &mt('Remove');
1572: return <<"END";
1573: \$(document).ready(function() {
1574: var wrapper = \$(".LC_string_ipacc_wrap");
1575: var add_button = \$(".LC_add_ipacc_button");
1576: var ipaccRegExp = /^LC_string_ipacc_/;
1577:
1578: \$(add_button).click(function(e){
1579: e.preventDefault();
1580: var identifier = \$(this).closest("div").attr("id");
1581: identifier = identifier.replace(ipaccRegExp,'');
1.551 raeburn 1582: \$(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 1583: });
1584:
1585: \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
1586: e.preventDefault(); \$(this).closest("div").remove();
1587: })
1588: });
1589:
1590:
1591: END
1592: }
1593:
1.622 ! raeburn 1594: sub grace_js {
! 1595: my %lt = &grace_titles();
! 1596: &js_escape(\%lt);
! 1597: my $overdue = '<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
! 1598: foreach my $which (['days', 86400, 31],
! 1599: ['hours', 3600, 23],
! 1600: ['minutes', 60, 59],
! 1601: ['seconds', 1, 59]) {
! 1602: my ($name, $factor, $max) = @{ $which };
! 1603: my %select = ((map {$_ => $_} (0..$max)),
! 1604: 'select_form_order' => [0..$max]);
! 1605: my $selector = &Apache::loncommon::select_form('',$name."_'+identifier+'",
! 1606: \%select);
! 1607: $selector =~ s/([\r\n\f]+)//g;
! 1608: $overdue .= $selector.' '.$lt{$name}.(' 'x2).' ';
! 1609: }
! 1610: $overdue .= '</fieldset>';
! 1611: return <<"END";
! 1612: \$(document).ready(function() {
! 1613: var wrapper = \$(".LC_string_grace_wrap");
! 1614: var add_button = \$(".LC_add_grace_button");
! 1615: var graceRegExp = /^LC_string_grace_/;
! 1616:
! 1617: \$(add_button).click(function(e){
! 1618: e.preventDefault();
! 1619: var identifier = \$(this).closest("div").attr("id");
! 1620: identifier = identifier.replace(graceRegExp,'');
! 1621: \$(this).closest('div').find('.LC_string_grace_inner').append('<div><input type="hidden" name="setgrace_'+identifier+'" value="" />$overdue<fieldset class="LC_grace"><legend>$lt{scor}</legend><input type="text" size="3" name="frac_'+identifier+'" value="" /> <label><input type="checkbox" value="1" name="grad_'+identifier+'" />$lt{grad}</label></fieldset><a href="#" class="LC_remove_grace">$lt{remo}</a></div>');
! 1622: });
! 1623:
! 1624: \$(wrapper).delegate(".LC_remove_grace","click", function(e){
! 1625: e.preventDefault(); \$(this).closest("div").remove();
! 1626: })
! 1627: });
! 1628:
! 1629:
! 1630: END
! 1631: }
! 1632:
1.561 damieng 1633: # Javascript function toggleSecret, for overview mode.
1.558 raeburn 1634: sub done_proctor_js {
1.611 raeburn 1635: my $defaultdone = &mt('Done');
1636: &js_escape(\$defaultdone);
1.558 raeburn 1637: return <<"END";
1638: function toggleSecret(form,radio,key) {
1639: var radios = form[radio+key];
1640: if (radios.length) {
1641: for (var i=0; i<radios.length; i++) {
1642: if (radios[i].checked) {
1643: if (radios[i].value == '_done_proctor') {
1644: if (document.getElementById('done_'+key+'_proctorkey')) {
1645: document.getElementById('done_'+key+'_proctorkey').type='text';
1646: }
1647: } else {
1648: if (document.getElementById('done_'+key+'_proctorkey')) {
1649: document.getElementById('done_'+key+'_proctorkey').type='hidden';
1650: document.getElementById('done_'+key+'_proctorkey').value='';
1651: }
1652: }
1.611 raeburn 1653: if (document.getElementById('done_'+key+'_buttontext')) {
1654: if (radios[i].value == '') {
1655: document.getElementById('done_'+key+'_buttontext').value = '';
1656: } else {
1657: if (document.getElementById('done_'+key+'_buttontext').value == '') {
1658: document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
1659: }
1660: }
1661: }
1.558 raeburn 1662: }
1663: }
1664: }
1665: }
1666: END
1667:
1668: }
1669:
1.588 raeburn 1670: # Javascript function toggle
1671: sub deeplink_js {
1672: return <<"END";
1673: function toggleDeepLink(form,item,key) {
1674: var radios = form['deeplink_'+item+'_'+key];
1675: if (radios.length) {
1676: var keybox;
1677: if (document.getElementById('deeplink_key_'+item+'_'+key)) {
1678: keybox = document.getElementById('deeplink_key_'+item+'_'+key);
1679: }
1.601 raeburn 1680: var divoptions = new Array();
1681: if (item == 'protect') {
1682: divoptions = ['ltic','ltid'];
1.597 raeburn 1683: } else {
1684: if (item == 'menus') {
1.601 raeburn 1685: divoptions = ['colls'];
1.597 raeburn 1686: }
1687: }
1.601 raeburn 1688: var seldivs = new Array();
1689: if ((item == 'protect') || (item == 'menus')) {
1690: for (var i=0; i<divoptions.length; i++) {
1691: if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
1692: seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
1693: } else {
1694: seldivs[i] = '';
1695: }
1696: }
1.588 raeburn 1697: }
1698: for (var i=0; i<radios.length; i++) {
1699: if (radios[i].checked) {
1.601 raeburn 1700: if ((item == 'protect') || (item == 'menus')) {
1701: for (var j=0; j<seldivs.length; j++) {
1702: if (radios[i].value == divoptions[j]) {
1703: if (seldivs[j] != '') {
1704: seldivs[j].style.display = 'inline-block';
1705: }
1706: if (item == 'protect') {
1707: keybox.type = 'hidden';
1708: keybox.value = '';
1709: }
1710: } else {
1711: if (seldivs[j] != '') {
1712: seldivs[j].style.display = 'none';
1713: form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
1714: }
1715: }
1.597 raeburn 1716: }
1.601 raeburn 1717: if (item == 'protect') {
1.597 raeburn 1718: if (radios[i].value == 'key') {
1719: keybox.type = 'text';
1720: } else {
1721: keybox.type = 'hidden';
1722: }
1.588 raeburn 1723: }
1.616 raeburn 1724: } else if (item == 'exit') {
1725: if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
1726: if (radios[i].value == 'no') {
1727: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';
1728: if (document.getElementById('deeplink_exittext_'+key)) {
1729: if (document.getElementById('deeplink_exittext_'+key).value != '') {
1730: document.getElementById('deeplink_exittext_'+key).value = '';
1731: }
1732: }
1733: } else {
1734: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
1735: if (document.getElementById('deeplink_exittext_'+key)) {
1736: if (document.getElementById('deeplink_exittext_'+key).value == '') {
1737: document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
1738: }
1739: }
1740: }
1741: }
1.588 raeburn 1742: }
1743: }
1744: }
1745: }
1746: }
1747: END
1748:
1749: }
1750:
1.561 damieng 1751: # Prints HTML page start for table mode.
1752: # @param {Apache2::RequestRec} $r - the Apache request
1753: # @param {string} $psymb - resource symb
1754: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280 albertel 1755: sub startpage {
1.531 raeburn 1756: my ($r,$psymb,$crstype) = @_;
1.281 albertel 1757:
1.515 raeburn 1758: my %loaditems = (
1759: 'onload' => "group_or_section('cgroup')",
1760: );
1761: if (!$psymb) {
1.523 raeburn 1762: $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515 raeburn 1763: }
1.280 albertel 1764:
1.560 damieng 1765: if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
1766: (!$env{'form.dis'})) || ($env{'form.symb'})) {
1767: &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
1768: text=>"Problem Parameters"});
1.414 droeschl 1769: } else {
1.560 damieng 1770: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1771: text=>"Table Mode",
1772: help => 'Course_Setting_Parameters'});
1.414 droeschl 1773: }
1.523 raeburn 1774: my $js = &page_js().'
1775: <script type="text/javascript">
1776: // <![CDATA[
1777: '.
1778: &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
1779: // ]]>
1780: </script>
1781: ';
1.446 bisitz 1782: my $start_page =
1.523 raeburn 1783: &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
1784: {'add_entries' => \%loaditems,});
1.446 bisitz 1785: my $breadcrumbs =
1.473 amueller 1786: &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506 www 1787: my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
1788: my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507 www 1789: $r->print($start_page.$breadcrumbs);
1.531 raeburn 1790: &startSettingsScreen($r,'parmset',$crstype);
1.280 albertel 1791: $r->print(<<ENDHEAD);
1.193 albertel 1792: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419 bisitz 1793: <input type="hidden" value="" name="pres_value" />
1794: <input type="hidden" value="" name="pres_type" />
1795: <input type="hidden" value="" name="pres_marker" />
1796: <input type="hidden" value="1" name="prevvisit" />
1.506 www 1797: <input type="hidden" value="$escfilter" name="filter" />
1798: <input type="hidden" value="$escpart" name="part" />
1.44 albertel 1799: ENDHEAD
1800: }
1801:
1.209 www 1802:
1.561 damieng 1803: # Prints a row for table mode (except for the tr start).
1804: # Every time a hash reference is passed, a single entry is used, so print_row
1805: # could just use these values, but why make it simple when it can be complicated ?
1806: #
1807: # @param {Apache2::RequestRec} $r - the Apache request
1808: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
1809: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
1810: # @param {hash reference} $name - parameter key -> parameter name
1.566 damieng 1811: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561 damieng 1812: # @param {string} $rid - resource id
1813: # @param {hash reference} $default - parameter key -> resource parameter default value
1814: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
1815: # @param {hash reference} $display - parameter key -> full title for the parameter
1816: # @param {string} $defbgone - user level and other levels background color
1817: # @param {string} $defbgtwo - section level background color, also used for part number
1818: # @param {string} $defbgthree - group level background color
1819: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1820: # @param {string} $uname - user name
1821: # @param {string} $udom - user domain
1822: # @param {string} $csec - section name
1823: # @param {string} $cgroup - group name
1824: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1825: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582 raeburn 1826: # @param {boolean} $readonly - true if no editing allowed.
1827: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
1828: # @param {hash reference} - $maptitles - - hash map id or src -> map title
1829: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
1830: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set
1.44 albertel 1831: sub print_row {
1.201 www 1832: my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568 raeburn 1833: $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582 raeburn 1834: $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275 raeburn 1835: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1836: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1837: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582 raeburn 1838: my $numlinks = 0;
1.553 raeburn 1839:
1.560 damieng 1840: # get the values for the parameter in cascading order
1841: # empty levels will remain empty
1.44 albertel 1842: my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473 amueller 1843: $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1844: # get the type for the parameters
1845: # problem: these may not be set for all levels
1.66 www 1846: my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275 raeburn 1847: $$name{$which}.'.type',$rid,
1.473 amueller 1848: $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1849: # cascade down manually
1.182 albertel 1850: my $cascadetype=$$defaulttype{$which};
1.556 raeburn 1851: for (my $i=18;$i>0;$i--) {
1.560 damieng 1852: if ($typeoutpar[$i]) {
1.66 www 1853: $cascadetype=$typeoutpar[$i];
1.560 damieng 1854: } else {
1.66 www 1855: $typeoutpar[$i]=$cascadetype;
1856: }
1857: }
1.57 albertel 1858: my $parm=$$display{$which};
1859:
1.203 www 1860: if ($parmlev eq 'full') {
1.419 bisitz 1861: $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506 www 1862: .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433 raeburn 1863: } else {
1.57 albertel 1864: $parm=~s|\[.*\]\s||g;
1865: }
1.231 www 1866: my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
1867: if ($automatic) {
1.560 damieng 1868: $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231 www 1869: }
1.619 raeburn 1870: my $advice;
1871: if ((ref($name) eq 'HASH') && ($name->{$which} eq 'mapalias') &&
1872: (ref($symbp) eq 'HASH') && ($parmlev eq 'full')) {
1873: if ($symbp->{$rid} =~ m{^uploaded/}) {
1874: if ($result == 14) {
1875: $advice = &mt('Use Course Editor to modify this.');
1876: } else {
1877: $advice = &mt('Use Course Editor to set this.');
1878: }
1879: } else {
1880: if ($result == 14) {
1881: $advice = &mt('Use Resource Assembly Tool to modify this.');
1882: } else {
1883: $advice = &mt('Use Resource Assembly Tool to set this.');
1884: }
1885: }
1886: $parm .= '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
1887: }
1.427 bisitz 1888: $r->print('<td>'.$parm.'</td>');
1.446 bisitz 1889:
1.44 albertel 1890: my $thismarker=$which;
1891: $thismarker=~s/^parameter\_//;
1892: my $mprefix=$rid.'&'.$thismarker.'&';
1.582 raeburn 1893: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1894: my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588 raeburn 1895: $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582 raeburn 1896: if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
1897: if ($result eq '') {
1898: $recurse_check = 1;
1899: } elsif (($uname ne '') && ($result > 3)) {
1900: $recurse_check = 1;
1901: } elsif (($cgroup ne '') && ($result > 7)) {
1902: $recurse_check = 1;
1903: } elsif (($csec ne '') && ($result > 11)) {
1904: $recurse_check = 1;
1905: } elsif ($result > 17) {
1906: $recurse_check = 1;
1907: }
1908: if ($recurse_check) {
1909: my $what = $$part{$which}.'.'.$$name{$which};
1910: my $prefix;
1911: if (($uname ne '') && ($udom ne '')) {
1912: my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1913: $prefix = $env{'request.course.id'};
1914: $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
1915: if (ref($recursinfo) eq 'ARRAY') {
1916: $effparm_rec = 1;
1917: $effparm_level = &mt('user: [_1]',$uname);
1918: }
1919: }
1920: if (($cgroup ne '') && (!$effparm_rec)) {
1921: $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
1922: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1923: if (ref($recursinfo) eq 'ARRAY') {
1924: $effparm_rec = 1;
1925: $effparm_level = &mt('group: [_1]',$cgroup);
1926: }
1927: }
1928: if (($csec ne '') && (!$effparm_rec)) {
1929: $prefix = $env{'request.course.id'}.'.['.$csec.']';
1930: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1931: if (ref($recursinfo) eq 'ARRAY') {
1932: $effparm_rec = 1;
1933: $effparm_level = &mt('section: [_1]',$csec);
1934: }
1935: }
1936: if (!$effparm_rec) {
1937: $prefix = $env{'request.course.id'};
1938: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1939: if (ref($recursinfo) eq 'ARRAY') {
1940: $effparm_rec = 1;
1941: }
1942: }
1943: }
1944: }
1945: if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
1946: $effparm_rec = 1;
1947: }
1948: if ((!$effparm_rec) &&
1949: (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) &&
1950: ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578 raeburn 1951: $effparm_rec = 1;
1952: }
1.588 raeburn 1953: if ($parmname eq 'deeplink') {
1.601 raeburn 1954: my ($domltistr,$crsltistr);
1.588 raeburn 1955: my %lti =
1956: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 1957: 'linkprot');
1.601 raeburn 1958: if (keys(%lti)) {
1959: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1.604 raeburn 1960: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
1961: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588 raeburn 1962: }
1963: }
1.601 raeburn 1964: $domltistr =~ s/,$//;
1965: if ($domltistr) {
1966: $extra = 'ltid_'.$domltistr;
1967: }
1.588 raeburn 1968: }
1.620 raeburn 1969: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider');
1.601 raeburn 1970: if (keys(%courselti)) {
1971: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
1972: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
1973: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
1974: }
1975: }
1976: $crsltistr =~ s/,$//;
1977: if ($crsltistr) {
1978: if ($extra) {
1979: $extra .= '&';
1980: }
1981: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 1982: }
1983: }
1.597 raeburn 1984: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
1985: my @colls;
1986: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
1987: my ($num,$value) = split(/\%/,$item);
1988: if ($num =~ /^\d+$/) {
1989: push(@colls,$num);
1990: }
1991: }
1992: if (@colls) {
1993: if ($extra) {
1994: $extra .= '&';
1995: }
1996: $extra .= 'menus_'.join(',',@colls);
1997: }
1998: }
1.588 raeburn 1999: }
1.57 albertel 2000: if ($parmlev eq 'general') {
2001: if ($uname) {
1.588 raeburn 2002: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 2003: } elsif ($cgroup) {
1.588 raeburn 2004: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 2005: } elsif ($csec) {
1.588 raeburn 2006: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 2007: } else {
1.588 raeburn 2008: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 2009: }
2010: } elsif ($parmlev eq 'map') {
2011: if ($uname) {
1.588 raeburn 2012: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 2013: } elsif ($cgroup) {
1.588 raeburn 2014: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 2015: } elsif ($csec) {
1.588 raeburn 2016: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 2017: } else {
1.588 raeburn 2018: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 2019: }
2020: } else {
1.275 raeburn 2021: if ($uname) {
2022: if (@{$usersgroups} > 1) {
1.582 raeburn 2023: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 2024: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 2025: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 2026: if (($coursereply) && ($result > 4)) {
1.275 raeburn 2027: if (defined($controlgrp)) {
2028: if ($cgroup ne $controlgrp) {
1.582 raeburn 2029: $eff_groupparm = $grp_parm;
2030: undef($result);
2031: undef($effparm_rec);
2032: if ($grp_is_rec) {
2033: $effparm_rec = 1;
2034: }
1.275 raeburn 2035: }
2036: }
2037: }
2038: }
2039: }
1.57 albertel 2040:
1.588 raeburn 2041: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2042: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
2043: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2044: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2045: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 2046:
2047: if ($csec) {
1.588 raeburn 2048: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2049: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
2050: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 2051: }
1.269 raeburn 2052:
2053: if ($cgroup) {
1.588 raeburn 2054: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
2055: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
2056: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 2057: }
1.446 bisitz 2058:
1.548 raeburn 2059: if ($uname) {
1.275 raeburn 2060: if ($othergrp) {
2061: $r->print($othergrp);
2062: }
1.588 raeburn 2063: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2064: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
2065: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 2066: }
1.57 albertel 2067: } # end of $parmlev if/else
1.582 raeburn 2068: if (ref($recursinfo) eq 'ARRAY') {
2069: my $rectitle = &mt('recursive');
2070: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
2071: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
2072: $rectitle = &mt('set in: [_1]','"'.
2073: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
2074: "'$parmname','$$part{$which}'".');">'.
2075: $maptitles->{$recursinfo->[2]}.'</a>"');
2076:
2077: $numlinks ++;
2078: }
2079: }
2080: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 2081: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 2082: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
2083: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
2084: $effparm_level.'</span></td>');
2085: } else {
2086: if ($result) {
1.593 raeburn 2087: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 2088: }
2089: if ($eff_groupparm) {
2090: $effective_parm = $eff_groupparm;
2091: }
2092: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
2093: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
2094: '</span>':'').'</td>');
2095: }
1.203 www 2096: if ($parmlev eq 'full') {
1.136 albertel 2097: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 2098: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 2099: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 2100: if (!defined($sessionvaltype)) {
2101: $sessionvaltype=$$defaulttype{$which};
2102: }
1.419 bisitz 2103: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 2104: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 2105: '</font></td>');
1.136 albertel 2106: }
1.44 albertel 2107: $r->print('</tr>');
1.57 albertel 2108: $r->print("\n");
1.582 raeburn 2109: if (($numlinks) && (ref($reclinks))) {
2110: $$reclinks = $numlinks;
2111: }
1.44 albertel 2112: }
1.59 matthew 2113:
1.561 damieng 2114: # Prints a cell for table mode.
2115: #
2116: # FIXME: some of these parameter names are uninspired ($which and $value)
2117: # Also, it would make more sense to pass the display for this cell rather
2118: # than the full display hash and the key to use.
2119: #
2120: # @param {Apache2::RequestRec} $r - the Apache request
2121: # @param {integer} $which - level
2122: # @param {string} $defbg - cell background color
2123: # @param {integer} $result - the most specific level that is defined for that parameter
2124: # @param {array reference} $outpar - array level -> parameter value (when defined)
2125: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
2126: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
2127: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
2128: # @param {hash reference} $display - parameter key -> full title for the parameter
2129: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 2130: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 2131: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 2132: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 2133: sub print_td {
1.578 raeburn 2134: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 2135: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 2136: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
2137: $ineffect = 0;
2138: $currval = $$outpar[$which];
2139: $currtype = $$typeoutpar[$which];
2140: $currlevel = $which;
2141: if (($result) && ($result == $which)) {
2142: $ineffect = 1;
2143: }
2144: if ($ismaplevel) {
2145: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
2146: if (($result) && ($result == $which)) {
2147: $recursive = 1;
2148: }
2149: } elsif ($$outpar[$which+1] ne '') {
2150: $recursive = 1;
2151: $currlevel = $which+1;
2152: $currval = $$outpar[$currlevel];
2153: $currtype = $$typeoutpar[$currlevel];
2154: if (($result) && ($result == $currlevel)) {
2155: $ineffect = 1;
2156: }
2157: }
2158: }
2159: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 2160: ';" align="center">');
1.437 raeburn 2161: my $nolink = 0;
1.568 raeburn 2162: if ($readonly) {
1.552 raeburn 2163: $nolink = 1;
1.568 raeburn 2164: } else {
1.578 raeburn 2165: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 2166: $nolink = 1;
1.568 raeburn 2167: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 2168: $nolink = 1;
1.568 raeburn 2169: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
2170: if ($noeditgrp) {
2171: $nolink = 1;
2172: }
2173: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 2174: $nolink = 1;
1.568 raeburn 2175: } elsif ($mprefix =~ /examcode\&$/) {
2176: unless ($which == 2) {
2177: $nolink = 1;
2178: }
1.533 raeburn 2179: }
1.437 raeburn 2180: }
2181: if ($nolink) {
1.577 raeburn 2182: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 2183: $r->print(&valout($currval,$currtype));
1.114 www 2184: } else {
1.578 raeburn 2185: $r->print(&plink($currtype,
2186: $$display{$value},$currval,
1.588 raeburn 2187: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
2188: $extra));
1.114 www 2189: }
2190: $r->print('</td>'."\n");
1.57 albertel 2191: }
2192:
1.561 damieng 2193: # Returns HTML and other info for the cell added when a user is selected
2194: # and that user is in several groups. This is the cell with the title "Control by other group".
2195: #
2196: # @param {string} $what - parameter part.'.'.parameter name
2197: # @param {string} $rid - resource id
2198: # @param {string} $cgroup - group name
2199: # @param {string} $defbg - cell background color
2200: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2201: # @param {integer} $result - level
2202: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 2203: # @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 2204: sub check_other_groups {
2205: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 2206: my $courseid = $env{'request.course.id'};
2207: my $output;
2208: my $symb = &symbcache($rid);
2209: my $symbparm=$symb.'.'.$what;
2210: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 2211: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 2212: my $mapparm=$map.'___(all).'.$what;
2213: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 2214: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
2215: $recurseparm,$what,$courseopt);
1.275 raeburn 2216: my $bgcolor = $defbg;
1.582 raeburn 2217: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2218: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2219: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2220: if ($result > 3) {
1.419 bisitz 2221: $bgcolor = '#AAFFAA';
1.275 raeburn 2222: }
1.593 raeburn 2223: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2224: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2225: if ($resultgroup && $resultlevel) {
1.582 raeburn 2226: if ($resultlevel eq 'recursive') {
2227: $resultlevel = 'map/folder';
2228: $grp_is_rec = 1;
2229: }
2230: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2231: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2232:
1.275 raeburn 2233: } else {
2234: $output .= ' ';
2235: }
2236: $output .= '</td>';
2237: } else {
1.419 bisitz 2238: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2239: }
1.582 raeburn 2240: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2241: }
2242:
1.561 damieng 2243: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2244: # Used by check_other_groups.
1.561 damieng 2245: #
2246: # @param {string} $courseid - the course id
2247: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2248: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2249: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2250: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2251: # @param {string} $what - parameter part.'.'.parameter name
2252: # @param {hash reference} $courseopt - course parameters hash
2253: # @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 2254: sub parm_control_group {
1.556 raeburn 2255: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2256: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2257: my $grpfound = 0;
1.556 raeburn 2258: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2259: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2260: foreach my $group (@{$usersgroups}) {
2261: if ($grpfound) { last; }
2262: for (my $i=0; $i<@levels; $i++) {
2263: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2264: if (defined($$courseopt{$item})) {
2265: $coursereply = $$courseopt{$item};
2266: $resultitem = $item;
2267: $resultgroup = $group;
2268: $resultlevel = $levelnames[$i];
2269: $resulttype = $$courseopt{$item.'.type'};
2270: $grpfound = 1;
2271: last;
2272: }
2273: }
2274: }
2275: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2276: }
1.201 www 2277:
1.63 bowersj2 2278:
2279:
1.562 damieng 2280: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2281: # All the parameters are references and are filled by the sub.
2282: #
1.566 damieng 2283: # @param {array reference} $ids - resource and map ids
2284: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2285: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2286: # @param {hash reference} $allparms - hash parameter name -> parameter title
2287: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2288: # @param {hash reference} $allmaps - hash map pc -> map src
2289: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2290: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2291: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2292: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2293: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2294: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608 raeburn 2295: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63 bowersj2 2296: sub extractResourceInformation {
2297: my $ids = shift;
2298: my $typep = shift;
2299: my $keyp = shift;
2300: my $allparms = shift;
2301: my $allparts = shift;
2302: my $allmaps = shift;
2303: my $mapp = shift;
2304: my $symbp = shift;
1.82 www 2305: my $maptitles=shift;
1.196 www 2306: my $uris=shift;
1.210 www 2307: my $keyorder=shift;
1.211 www 2308: my $defkeytype=shift;
1.603 raeburn 2309: my $pssymb=shift;
1.196 www 2310:
1.210 www 2311: my $keyordercnt=100;
1.63 bowersj2 2312:
1.196 www 2313: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 raeburn 2314: return unless(ref($navmap));
2315: my @allres;
2316: if ($pssymb ne '') {
2317: my $res = $navmap->getBySymb($pssymb);
2318: if (ref($res)) {
2319: @allres = ($res);
2320: }
2321: }
2322: if (!@allres) {
2323: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
2324: }
1.196 www 2325: foreach my $resource (@allres) {
1.480 amueller 2326: my $id=$resource->id();
1.196 www 2327: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2328: if ($mapid eq '0') { next; }
2329: $$ids[$#$ids+1]=$id;
2330: my $srcf=$resource->src();
2331: $srcf=~/\.(\w+)$/;
2332: $$typep{$id}=$1;
1.584 raeburn 2333: my $toolsymb;
2334: if ($srcf =~ /ext\.tool$/) {
2335: $toolsymb = $resource->symb();
2336: }
1.480 amueller 2337: $$keyp{$id}='';
1.196 www 2338: $$uris{$id}=$srcf;
1.512 foxr 2339:
1.584 raeburn 2340: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2341: next if ($key!~/^parameter_/);
1.363 albertel 2342:
1.209 www 2343: # Hidden parameters
1.584 raeburn 2344: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2345: #
2346: # allparms is a hash of parameter names
2347: #
1.584 raeburn 2348: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2349: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2350: my ($display,$parmdis);
2351: $display = &standard_parameter_names($name);
2352: if ($display eq '') {
1.584 raeburn 2353: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2354: $parmdis = $display;
2355: $parmdis =~ s/\s*\[Part.*$//g;
2356: } else {
2357: $parmdis = &mt($display);
2358: }
2359: $$allparms{$name}=$parmdis;
2360: if (ref($defkeytype)) {
2361: $$defkeytype{$name}=
1.584 raeburn 2362: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2363: }
2364: }
1.363 albertel 2365:
1.209 www 2366: #
2367: # allparts is a hash of all parts
2368: #
1.584 raeburn 2369: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2370: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2371: #
2372: # Remember all keys going with this resource
2373: #
1.480 amueller 2374: if ($$keyp{$id}) {
2375: $$keyp{$id}.=','.$key;
2376: } else {
2377: $$keyp{$id}=$key;
2378: }
1.210 www 2379: #
2380: # Put in order
1.446 bisitz 2381: #
1.480 amueller 2382: unless ($$keyorder{$key}) {
2383: $$keyorder{$key}=$keyordercnt;
2384: $keyordercnt++;
2385: }
1.473 amueller 2386: }
2387:
2388:
1.480 amueller 2389: if (!exists($$mapp{$mapid})) {
2390: $$mapp{$id}=
2391: &Apache::lonnet::declutter($resource->enclosing_map_src());
2392: $$mapp{$mapid}=$$mapp{$id};
2393: $$allmaps{$mapid}=$$mapp{$id};
2394: if ($mapid eq '1') {
1.532 raeburn 2395: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2396: } else {
2397: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2398: }
2399: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2400: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2401: # Lines 1038 and 1114 which use $symbp{$mapid}
2402: # are commented out in rev. 1.57
1.473 amueller 2403: } else {
1.480 amueller 2404: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2405: }
1.480 amueller 2406: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2407: }
2408: }
2409:
1.582 raeburn 2410: sub get_recursive {
2411: my ($recurseup,$resdata,$what,$prefix) = @_;
2412: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2413: foreach my $item (@{$recurseup}) {
2414: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2415: if (defined($resdata->{$norecursechk})) {
2416: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2417: my $type = $resdata->{$norecursechk.'.type'};
2418: return [$resdata->{$norecursechk},$type,$item];
2419: } else {
2420: last;
2421: }
2422: }
2423: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2424: if (defined($resdata->{$recursechk})) {
2425: my $type = $resdata->{$recursechk.'.type'};
2426: return [$resdata->{$recursechk},$type,$item];
2427: }
2428: }
2429: }
2430: return;
2431: }
2432:
1.208 www 2433:
1.562 damieng 2434: # Tells if a parameter type is a date.
2435: #
2436: # @param {string} type - parameter type
2437: # @returns{boolean} - true if it is a date
1.213 www 2438: sub isdateparm {
2439: my $type=shift;
2440: return (($type=~/^date/) && (!($type eq 'date_interval')));
2441: }
2442:
1.589 raeburn 2443: # Determine if parameter type is specialized string type (i.e.,
2444: # not just string or string_yesno.
2445:
2446: sub is_specialstring {
2447: my $type=shift;
1.603 raeburn 2448: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2449: }
2450:
1.562 damieng 2451: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2452: #
1.581 raeburn 2453: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2454: sub parmmenu {
1.581 raeburn 2455: my ($r)=@_;
1.208 www 2456: $r->print(<<ENDSCRIPT);
2457: <script type="text/javascript">
1.454 bisitz 2458: // <![CDATA[
1.208 www 2459: function checkall(value, checkName) {
1.453 schualex 2460:
2461: var li = "_li";
2462: var displayOverview = "";
2463:
2464: if (value == false) {
2465: displayOverview = "none"
2466: }
2467:
1.562 damieng 2468: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2469: ele = document.forms.parmform.elements[i];
2470: if (ele.name == checkName) {
2471: document.forms.parmform.elements[i].checked=value;
2472: }
2473: }
2474: }
1.210 www 2475:
2476: function checkthis(thisvalue, checkName) {
1.562 damieng 2477: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2478: ele = document.forms.parmform.elements[i];
2479: if (ele.name == checkName) {
1.562 damieng 2480: if (ele.value == thisvalue) {
2481: document.forms.parmform.elements[i].checked=true;
2482: }
1.210 www 2483: }
2484: }
2485: }
2486:
2487: function checkdates() {
1.562 damieng 2488: checkthis('duedate','pscat');
2489: checkthis('opendate','pscat');
2490: checkthis('answerdate','pscat');
1.218 www 2491: }
2492:
2493: function checkdisset() {
1.562 damieng 2494: checkthis('discussend','pscat');
2495: checkthis('discusshide','pscat');
2496: checkthis('discussvote','pscat');
1.218 www 2497: }
2498:
2499: function checkcontdates() {
1.562 damieng 2500: checkthis('contentopen','pscat');
2501: checkthis('contentclose','pscat');
1.218 www 2502: }
1.446 bisitz 2503:
1.210 www 2504: function checkvisi() {
1.562 damieng 2505: checkthis('hiddenresource','pscat');
2506: checkthis('encrypturl','pscat');
2507: checkthis('problemstatus','pscat');
2508: checkthis('contentopen','pscat');
2509: checkthis('opendate','pscat');
1.210 www 2510: }
2511:
2512: function checkparts() {
1.562 damieng 2513: checkthis('hiddenparts','pscat');
2514: checkthis('display','pscat');
2515: checkthis('ordered','pscat');
1.210 www 2516: }
2517:
2518: function checkstandard() {
2519: checkall(false,'pscat');
1.562 damieng 2520: checkdates();
2521: checkthis('weight','pscat');
2522: checkthis('maxtries','pscat');
2523: checkthis('type','pscat');
2524: checkthis('problemstatus','pscat');
1.210 www 2525: }
2526:
1.454 bisitz 2527: // ]]>
1.208 www 2528: </script>
2529: ENDSCRIPT
1.453 schualex 2530:
1.491 bisitz 2531: $r->print('<hr />');
1.581 raeburn 2532: &shortCuts($r);
1.491 bisitz 2533: $r->print('<hr />');
1.453 schualex 2534: }
1.562 damieng 2535:
2536: # Returns parameter categories.
2537: #
2538: # @returns {hash} - category name -> title in English
1.465 amueller 2539: sub categories {
2540: return ('time_settings' => 'Time Settings',
2541: 'grading' => 'Grading',
2542: 'tries' => 'Tries',
2543: 'problem_appearance' => 'Problem Appearance',
2544: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2545: 'hiding' => 'Hiding',
2546: 'high_level_randomization' => 'High Level Randomization',
2547: 'slots' => 'Slots',
2548: 'file_submission' => 'File Submission',
2549: 'misc' => 'Miscellaneous' );
2550: }
2551:
1.562 damieng 2552: # Returns the category for each parameter.
2553: #
2554: # @returns {hash} - parameter name -> category name
1.465 amueller 2555: sub lookUpTableParameter {
2556:
2557: return (
2558: 'opendate' => 'time_settings',
2559: 'duedate' => 'time_settings',
2560: 'answerdate' => 'time_settings',
1.622 ! raeburn 2561: 'grace' => 'time_settings',
1.465 amueller 2562: 'interval' => 'time_settings',
2563: 'contentopen' => 'time_settings',
2564: 'contentclose' => 'time_settings',
2565: 'discussend' => 'time_settings',
1.560 damieng 2566: 'printstartdate' => 'time_settings',
2567: 'printenddate' => 'time_settings',
1.465 amueller 2568: 'weight' => 'grading',
2569: 'handgrade' => 'grading',
2570: 'maxtries' => 'tries',
2571: 'hinttries' => 'tries',
1.503 raeburn 2572: 'randomizeontries' => 'tries',
1.465 amueller 2573: 'type' => 'problem_appearance',
2574: 'problemstatus' => 'problem_appearance',
2575: 'display' => 'problem_appearance',
2576: 'ordered' => 'problem_appearance',
2577: 'numbubbles' => 'problem_appearance',
2578: 'tol' => 'behaviour_of_input_fields',
2579: 'sig' => 'behaviour_of_input_fields',
2580: 'turnoffunit' => 'behaviour_of_input_fields',
2581: 'hiddenresource' => 'hiding',
2582: 'hiddenparts' => 'hiding',
2583: 'discusshide' => 'hiding',
2584: 'buttonshide' => 'hiding',
2585: 'turnoffeditor' => 'hiding',
2586: 'encrypturl' => 'hiding',
1.587 raeburn 2587: 'deeplink' => 'hiding',
1.465 amueller 2588: 'randomorder' => 'high_level_randomization',
2589: 'randompick' => 'high_level_randomization',
2590: 'available' => 'slots',
2591: 'useslots' => 'slots',
2592: 'availablestudent' => 'slots',
2593: 'uploadedfiletypes' => 'file_submission',
2594: 'maxfilesize' => 'file_submission',
2595: 'cssfile' => 'misc',
2596: 'mapalias' => 'misc',
2597: 'acc' => 'misc',
2598: 'maxcollaborators' => 'misc',
2599: 'scoreformat' => 'misc',
1.514 raeburn 2600: 'lenient' => 'grading',
1.519 raeburn 2601: 'retrypartial' => 'tries',
1.521 raeburn 2602: 'discussvote' => 'misc',
1.621 raeburn 2603: 'texdisplay' => 'misc',
1.584 raeburn 2604: 'examcode' => 'high_level_randomization',
1.575 raeburn 2605: );
1.465 amueller 2606: }
2607:
1.562 damieng 2608: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2609: #
2610: # @param {string} $name - parameter name
2611: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2612: sub whatIsMyCategory {
2613: my $name = shift;
2614: my $catList = shift;
2615: my @list;
2616: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2617: my $cat = $lookUpList{$name};
2618: if (defined($cat)) {
2619: if (!defined($$catList{$cat})){
2620: push @list, ($name);
2621: $$catList{$cat} = \@list;
2622: } else {
2623: push @{${$catList}{$cat}}, ($name);
2624: }
2625: } else {
2626: if (!defined($$catList{'misc'})){
2627: push @list, ($name);
2628: $$catList{'misc'} = \@list;
2629: } else {
2630: push @{${$catList}{'misc'}}, ($name);
2631: }
2632: }
2633: }
2634:
1.562 damieng 2635: # Sorts parameter names based on appearance order.
2636: #
2637: # @param {array reference} name - array reference of parameter names
2638: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2639: # @returns {Array} - array of parameter names
1.465 amueller 2640: sub keysindisplayorderCategory {
2641: my ($name,$keyorder)=@_;
2642: return sort {
1.473 amueller 2643: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2644: } ( @{$name});
2645: }
2646:
1.562 damieng 2647: # Returns a hash category name -> order, starting at 1 (integer)
2648: #
2649: # @returns {hash}
1.467 amueller 2650: sub category_order {
2651: return (
2652: 'time_settings' => 1,
2653: 'grading' => 2,
2654: 'tries' => 3,
2655: 'problem_appearance' => 4,
2656: 'hiding' => 5,
2657: 'behaviour_of_input_fields' => 6,
2658: 'high_level_randomization' => 7,
2659: 'slots' => 8,
2660: 'file_submission' => 9,
2661: 'misc' => 10
2662: );
2663:
2664: }
1.453 schualex 2665:
1.562 damieng 2666: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2667: #
2668: # @param {Apache2::RequestRec} $r - the Apache request
2669: # @param {hash reference} $allparms - hash parameter name -> parameter title
2670: # @param {array reference} $pscat - list of selected parameter names
2671: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2672: sub parmboxes {
2673: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2674: my %categories = &categories();
1.467 amueller 2675: my %category_order = &category_order();
1.465 amueller 2676: my %categoryList = (
2677: 'time_settings' => [],
2678: 'grading' => [],
2679: 'tries' => [],
2680: 'problem_appearance' => [],
2681: 'behaviour_of_input_fields' => [],
2682: 'hiding' => [],
2683: 'high_level_randomization' => [],
2684: 'slots' => [],
2685: 'file_submission' => [],
2686: 'misc' => [],
1.489 bisitz 2687: );
1.510 www 2688:
1.548 raeburn 2689: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2690: &whatIsMyCategory($tempparameter, \%categoryList);
2691: }
1.453 schualex 2692: #part to print the parm-list
1.618 raeburn 2693: $Text::Wrap::columns=60;
2694: $Text::Wrap::separator='<br />';
1.536 raeburn 2695: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2696: next if (@{$categoryList{$key}} == 0);
2697: next if ($key eq '');
2698: $r->print('<div class="LC_Box LC_400Box">'
2699: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2700: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2701: next if ($tempkey eq '');
1.536 raeburn 2702: $r->print('<span class="LC_nobreak">'
2703: .'<label><input type="checkbox" name="pscat" '
2704: .'value="'.$tempkey.'" ');
2705: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2706: $r->print( ' checked="checked"');
2707: }
1.617 raeburn 2708: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ?
2709: Text::Wrap::wrap('',' 'x4,$$allparms{$tempkey})
2710: : $tempkey)
1.536 raeburn 2711: .'</label></span><br />'."\n");
1.465 amueller 2712: }
1.536 raeburn 2713: $r->print('</div>');
1.465 amueller 2714: }
1.536 raeburn 2715: $r->print("\n");
1.453 schualex 2716: }
1.562 damieng 2717:
2718: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2719: #
1.562 damieng 2720: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2721: sub shortCuts {
1.581 raeburn 2722: my ($r)=@_;
1.453 schualex 2723:
1.491 bisitz 2724: # Parameter Selection
2725: $r->print(
2726: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2727: .&Apache::lonhtmlcommon::add_item_funclist(
2728: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2729: .&Apache::lonhtmlcommon::add_item_funclist(
2730: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2731: .&Apache::lonhtmlcommon::add_item_funclist(
2732: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2733: .&Apache::lonhtmlcommon::end_funclist()
2734: );
2735:
2736: # Add Selection for...
2737: $r->print(
2738: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2739: .&Apache::lonhtmlcommon::add_item_funclist(
2740: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2741: .&Apache::lonhtmlcommon::add_item_funclist(
2742: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2743: .&Apache::lonhtmlcommon::add_item_funclist(
2744: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2745: .&Apache::lonhtmlcommon::add_item_funclist(
2746: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2747: .&Apache::lonhtmlcommon::add_item_funclist(
2748: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2749: .&Apache::lonhtmlcommon::end_funclist()
2750: );
1.208 www 2751: }
2752:
1.562 damieng 2753: # Prints HTML to select parts to view (except for the title).
2754: # Used by table and overview modes.
2755: #
2756: # @param {Apache2::RequestRec} $r - the Apache request
2757: # @param {hash reference} $allparts - hash parameter part -> part title
2758: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2759: sub partmenu {
1.446 bisitz 2760: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2761: my $selsize = 1+scalar(keys(%{$allparts}));
2762: if ($selsize > 8) {
2763: $selsize = 8;
2764: }
1.446 bisitz 2765:
1.523 raeburn 2766: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2767: $r->print('<option value="all"');
1.562 damieng 2768: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2769: $r->print('>'.&mt('All Parts').'</option>');
2770: my %temphash=();
2771: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2772: foreach my $tempkey (sort {
1.560 damieng 2773: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2774: } keys(%{$allparts})) {
2775: unless ($tempkey =~ /\./) {
2776: $r->print('<option value="'.$tempkey.'"');
2777: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2778: $r->print(' selected="selected"');
2779: }
2780: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2781: }
1.208 www 2782: }
1.446 bisitz 2783: $r->print('</select>');
1.209 www 2784: }
2785:
1.562 damieng 2786: # Prints HTML to select a user and/or a group.
2787: # Used by table mode.
2788: #
2789: # @param {Apache2::RequestRec} $r - the Apache request
2790: # @param {string} $uname - selected user name
2791: # @param {string} $id - selected Student/Employee ID
2792: # @param {string} $udom - selected user domain
2793: # @param {string} $csec - selected section name
2794: # @param {string} $cgroup - selected group name
2795: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2796: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2797: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2798: sub usermenu {
1.553 raeburn 2799: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2800: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2801: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2802: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2803: function setCourseadv(form,caller) {
2804: if (caller.value == 'st') {
2805: form.courseadv.value = 'none';
2806: } else {
2807: form.courseadv.value = '';
2808: }
2809: return;
2810: }
2811: ENDJS
1.412 bisitz 2812:
1.596 raeburn 2813: my (%chkroles,$stuonly,$courseadv);
2814: if ($env{'form.userroles'} eq 'any') {
2815: $chkroles{'any'} = ' checked="checked"';
2816: } else {
2817: $chkroles{'st'} = ' checked="checked"';
2818: $courseadv = 'none';
2819: }
2820: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2821: if ($crstype eq 'Community') {
2822: $stuonly = &mt('member only');
2823: } else {
2824: $stuonly = &mt('student only');
2825: }
2826: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2827: &mt("User's role").': '.
2828: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2829: $stuonly.'</label> '.
2830: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2831: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2832: my $sections='';
1.300 albertel 2833: my %sectionhash = &Apache::loncommon::get_sections();
2834:
1.269 raeburn 2835: my $groups;
1.553 raeburn 2836: my %grouphash;
2837: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2838: %grouphash = &Apache::longroup::coursegroups();
2839: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2840: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2841: }
1.299 albertel 2842:
1.412 bisitz 2843: my $g_s_header='';
2844: my $g_s_footer='';
1.446 bisitz 2845:
1.552 raeburn 2846: my $currsec = $env{'request.course.sec'};
2847: if ($currsec) {
2848: $sections=&mt('Section:').' '.$currsec;
2849: if (%grouphash) {
2850: $sections .= ';'.(' ' x2);
2851: }
2852: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2853: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2854: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2855: $sections .= qq| onchange="group_or_section('csec')" |;
2856: }
2857: $sections .= '>';
1.548 raeburn 2858: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2859: $sections.='<option value="'.$section.'" '.
2860: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2861: '</option>';
1.209 www 2862: }
2863: $sections.='</select>';
1.269 raeburn 2864: }
1.412 bisitz 2865:
1.552 raeburn 2866: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2867: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2868: $sections .= qq|
2869: <script type="text/javascript">
1.454 bisitz 2870: // <![CDATA[
1.269 raeburn 2871: function group_or_section(caller) {
2872: if (caller == "cgroup") {
2873: if (document.parmform.cgroup.selectedIndex != 0) {
2874: document.parmform.csec.selectedIndex = 0;
2875: }
2876: } else {
2877: if (document.parmform.csec.selectedIndex != 0) {
2878: document.parmform.cgroup.selectedIndex = 0;
2879: }
2880: }
2881: }
1.454 bisitz 2882: // ]]>
1.269 raeburn 2883: </script>
2884: |;
1.554 raeburn 2885: } else {
1.269 raeburn 2886: $sections .= qq|
2887: <script type="text/javascript">
1.454 bisitz 2888: // <![CDATA[
1.269 raeburn 2889: function group_or_section(caller) {
2890: return;
2891: }
1.454 bisitz 2892: // ]]>
1.269 raeburn 2893: </script>
2894: |;
1.446 bisitz 2895: }
1.299 albertel 2896:
2897: if (%grouphash) {
1.597 raeburn 2898: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2899: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2900: $groups .= qq| onchange="group_or_section('cgroup')" |;
2901: }
2902: $groups .= '>';
1.548 raeburn 2903: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2904: $groups.='<option value="'.$grp.'" ';
2905: if ($grp eq $cgroup) {
2906: unless ((defined($uname)) && ($grp eq '')) {
2907: $groups .= 'selected="selected" ';
2908: }
2909: } elsif (!defined($cgroup)) {
2910: if (@{$usersgroups} == 1) {
2911: if ($grp eq $$usersgroups[0]) {
2912: $groups .= 'selected="selected" ';
2913: }
2914: }
2915: }
2916: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2917: }
2918: $groups.='</select>';
2919: }
1.412 bisitz 2920:
1.445 neumanie 2921: if (%sectionhash || %grouphash) {
1.446 bisitz 2922: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2923: $r->print($sections.$groups);
1.448 bisitz 2924: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 2925: } else {
2926: $r->print($sections);
1.445 neumanie 2927: }
1.446 bisitz 2928:
2929: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 2930: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 2931: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
2932: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 2933: ,$chooseopt));
1.209 www 2934: }
2935:
1.562 damieng 2936: # Prints HTML to select parameters from a list of all parameters.
2937: # Uses parmmenu and parmboxes.
2938: # Used by table and overview modes.
1.468 amueller 2939: #
1.562 damieng 2940: # @param {Apache2::RequestRec} $r - the Apache request
2941: # @param {hash reference} $allparms - hash parameter name -> parameter title
2942: # @param {array reference} $pscat - list of selected parameter names
2943: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2944: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 2945: sub displaymenu {
1.581 raeburn 2946: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 2947:
1.445 neumanie 2948: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 2949: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
2950:
1.581 raeburn 2951: &parmmenu($r);
1.536 raeburn 2952: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 2953: &parmboxes($r,$allparms,$pscat,$keyorder);
2954: $r->print(&Apache::loncommon::end_scrollbox());
2955:
2956: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 2957: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 2958:
1.209 www 2959: }
2960:
1.562 damieng 2961: # Prints HTML to select a map.
2962: # Used by table mode and overview mode.
2963: #
2964: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 2965: # @param {hash reference} $allmaps - hash map pc -> map src
2966: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 2967: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 2968: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610 raeburn 2969: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445 neumanie 2970: sub mapmenu {
1.610 raeburn 2971: my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468 amueller 2972: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 2973: my $navmap = Apache::lonnavmaps::navmap->new();
2974: my $tree=[];
2975: my $treeinfo={};
2976: if (defined($navmap)) {
1.499 raeburn 2977: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 2978: my $curRes;
2979: my $depth = 0;
1.468 amueller 2980: my %parent = ();
2981: my $startcount = 5;
2982: my $lastcontainer = $startcount;
2983: # preparing what is to show ...
1.461 neumanie 2984: while ($curRes = $it->next()) {
2985: if ($curRes == $it->BEGIN_MAP()) {
2986: $depth++;
1.468 amueller 2987: $parent{$depth}= $lastcontainer;
1.461 neumanie 2988: }
2989: if ($curRes == $it->END_MAP()) {
2990: $depth--;
1.468 amueller 2991: $lastcontainer = $parent{$depth};
1.461 neumanie 2992: }
2993: if (ref($curRes)) {
1.468 amueller 2994: my $symb = $curRes->symb();
2995: my $ressymb = $symb;
1.461 neumanie 2996: if (($curRes->is_sequence()) || ($curRes->is_page())) {
2997: my $type = 'sequence';
2998: if ($curRes->is_page()) {
2999: $type = 'page';
3000: }
3001: my $id= $curRes->id();
1.468 amueller 3002: my $srcf = $curRes->src();
3003: my $resource_name = &Apache::lonnet::gettitle($srcf);
3004: if(!exists($treeinfo->{$id})) {
3005: push(@$tree,$id);
1.473 amueller 3006: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 3007: $treeinfo->{$id} = {
1.461 neumanie 3008: depth => $depth,
3009: type => $type,
1.468 amueller 3010: name => $resource_name,
3011: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 3012: };
1.462 neumanie 3013: }
1.461 neumanie 3014: }
3015: }
3016: }
1.462 neumanie 3017: }
1.473 amueller 3018: # Show it ...
1.610 raeburn 3019: my $rowattr = ' id="mapmenu"';
3020: if ($parmlev eq 'general') {
3021: $rowattr .= ' style="display:none"';
3022: }
3023: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461 neumanie 3024: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
3025: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 3026: my $whitespace =
3027: '<img src="'
3028: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
3029: .'" alt="" />';
3030:
1.498 bisitz 3031: # Info about selectable folders/maps
3032: $r->print(
3033: '<div class="LC_info">'
1.508 www 3034: .&mt('You can only select maps and folders which have modifiable settings.')
3035: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 3036: .'</div>'
3037: );
3038:
1.536 raeburn 3039: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 3040: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 3041:
1.498 bisitz 3042: # Display row: "All Maps or Folders"
3043: $r->print(
1.523 raeburn 3044: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 3045: .'<td>'
3046: .'<label>'
3047: .'<input type="radio" name="pschp"'
1.497 bisitz 3048: );
3049: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 3050: $r->print(
3051: ' value="all" /> '.$icon.' '
3052: .&mt('All Maps or Folders')
3053: .'</label>'
3054: .'<hr /></td>'
3055: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 3056: );
1.497 bisitz 3057:
1.532 raeburn 3058: # Display row: "Main Content"
1.468 amueller 3059: if (exists($$allmaps{1})) {
1.498 bisitz 3060: $r->print(
3061: &Apache::loncommon::start_data_table_row()
3062: .'<td>'
3063: .'<label>'
3064: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 3065: );
1.497 bisitz 3066: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 3067: $r->print(
3068: '/> '.$icon.' '
3069: .$$maptitles{1}
3070: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
3071: .'</label>'
3072: .'</td>'
3073: .&Apache::loncommon::end_data_table_row()
1.468 amueller 3074: );
3075: }
1.497 bisitz 3076:
3077: # Display rows for all course maps and folders
1.468 amueller 3078: foreach my $id (@{$tree}) {
3079: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 3080: # Indentation
1.468 amueller 3081: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 3082: my $indent;
3083: for (my $i = 0; $i < $depth; $i++) {
3084: $indent.= $whitespace;
3085: }
1.461 neumanie 3086: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 3087: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 3088: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
3089: }
1.468 amueller 3090: my $symb_name = $$symbp{$id};
3091: my ($front, $tail) = split (/___${resid}___/, $symb_name);
3092: $symb_name = $tail;
1.498 bisitz 3093: $r->print(
3094: &Apache::loncommon::start_data_table_row()
3095: .'<td>'
3096: .'<label>'
1.463 bisitz 3097: );
1.498 bisitz 3098: # Only offer radio button for folders/maps which can be parameterized
3099: if ($allmaps_inverted{$symb_name}) {
3100: $r->print(
3101: '<input type ="radio" name="pschp"'
3102: .' value="'.$allmaps_inverted{$symb_name}.'"'
3103: );
3104: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
3105: $r->print('/>');
3106: } else {
3107: $r->print($whitespace);
1.461 neumanie 3108: }
1.498 bisitz 3109: $r->print(
3110: $indent.$icon.' '
3111: .$treeinfo->{$id}->{name}
3112: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
3113: .'</label>'
3114: .'</td>'
3115: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 3116: );
1.461 neumanie 3117: }
1.497 bisitz 3118:
1.523 raeburn 3119: $r->print(&Apache::loncommon::end_data_table().
3120: '<br style="line-height:2px;" />'.
3121: &Apache::loncommon::end_scrollbox());
1.209 www 3122: }
3123: }
3124:
1.563 damieng 3125: # Prints HTML to select the parameter level (resource, map/folder or course).
3126: # Used by table and overview modes.
3127: #
3128: # @param {Apache2::RequestRec} $r - the Apache request
3129: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
3130: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 3131: sub levelmenu {
1.446 bisitz 3132: my ($r,$alllevs,$parmlev)=@_;
3133:
1.548 raeburn 3134: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
3135: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 3136: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 3137: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
3138: $r->print('<option value="'.$$alllevs{$lev}.'"');
3139: if ($parmlev eq $$alllevs{$lev}) {
3140: $r->print(' selected="selected"');
3141: }
3142: $r->print('>'.&mt($lev).'</option>');
1.208 www 3143: }
1.446 bisitz 3144: $r->print("</select>");
1.208 www 3145: }
3146:
1.211 www 3147:
1.563 damieng 3148: # Returns HTML to select a section (with a select HTML element).
3149: # Used by overview mode.
3150: #
3151: # @param {array reference} $selectedsections - list of selected section ids
3152: # @returns {string}
1.211 www 3153: sub sectionmenu {
1.553 raeburn 3154: my ($selectedsections)=@_;
1.300 albertel 3155: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 3156: return '' if (!%sectionhash);
1.300 albertel 3157:
1.552 raeburn 3158: my (@possibles,$disabled);
3159: if ($env{'request.course.sec'} ne '') {
3160: @possibles = ($env{'request.course.sec'});
3161: $selectedsections = [$env{'request.course.sec'}];
3162: $disabled = ' disabled="disabled"';
3163: } else {
3164: @possibles = ('all',sort(keys(%sectionhash)));
3165: }
1.553 raeburn 3166: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 3167: foreach my $s (@possibles) {
1.553 raeburn 3168: $output .= ' <option value="'.$s.'"';
3169: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
3170: $output .= ' selected="selected"';
1.473 amueller 3171: }
1.553 raeburn 3172: $output .= '>'."$s</option>\n";
1.300 albertel 3173: }
1.553 raeburn 3174: $output .= "</select>\n";
3175: return $output;
1.269 raeburn 3176: }
3177:
1.563 damieng 3178: # Returns HTML to select a group (with a select HTML element).
3179: # Used by overview mode.
3180: #
3181: # @param {array reference} $selectedgroups - list of selected group names
3182: # @returns {string}
1.269 raeburn 3183: sub groupmenu {
1.553 raeburn 3184: my ($selectedgroups)=@_;
3185: my %grouphash;
3186: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3187: %grouphash = &Apache::longroup::coursegroups();
3188: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 3189: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 3190: }
3191: return '' if (!%grouphash);
1.299 albertel 3192:
1.553 raeburn 3193: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 3194: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 3195: $output .= ' <option value="'.$group.'"';
3196: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
3197: $output .= ' selected="selected"';
1.473 amueller 3198: }
1.553 raeburn 3199: $output .= '>'."$group</option>\n";
1.211 www 3200: }
1.553 raeburn 3201: $output .= "</select>\n";
3202: return $output;
1.211 www 3203: }
3204:
1.563 damieng 3205: # Returns an array with the given parameter split by comma.
3206: # Used by assessparms (table mode).
3207: #
3208: # @param {string} $keyp - the string to split
3209: # @returns {Array<string>}
1.210 www 3210: sub keysplit {
3211: my $keyp=shift;
3212: return (split(/\,/,$keyp));
3213: }
3214:
1.563 damieng 3215: # Returns the keys in $name, sorted using $keyorder.
3216: # Parameters are sorted by key, which means they are sorted by part first, then by name.
3217: # Used by assessparms (table mode) for resource level.
3218: #
3219: # @param {hash reference} $name - parameter key -> parameter name
3220: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3221: # @returns {Array<string>}
1.210 www 3222: sub keysinorder {
3223: my ($name,$keyorder)=@_;
3224: return sort {
1.560 damieng 3225: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 3226: } (keys(%{$name}));
1.210 www 3227: }
3228:
1.563 damieng 3229: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3230: # Used by assessparms (table mode) for map and general levels.
3231: #
3232: # @param {hash reference} $name - parameter key -> parameter name
3233: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3234: # @returns {Array<string>}
1.236 albertel 3235: sub keysinorder_bytype {
3236: my ($name,$keyorder)=@_;
3237: return sort {
1.563 damieng 3238: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3239: my $tb=(split('_',$b))[-1];
3240: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3241: return ($a cmp $b);
3242: }
3243: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3244: } (keys(%{$name}));
1.236 albertel 3245: }
3246:
1.563 damieng 3247: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3248: # Used by defaultsetter (parameter settings default actions).
3249: #
3250: # @param {hash reference} $name - hash parameter name -> parameter title
3251: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3252: # @returns {Array<string>}
1.211 www 3253: sub keysindisplayorder {
3254: my ($name,$keyorder)=@_;
3255: return sort {
1.560 damieng 3256: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3257: } (keys(%{$name}));
1.211 www 3258: }
3259:
1.563 damieng 3260: # Prints HTML with a choice to sort results by realm or student first.
3261: # Used by overview mode.
3262: #
3263: # @param {Apache2::RequestRec} $r - the Apache request
3264: # @param {string} $sortorder - realmstudent|studentrealm
1.608 raeburn 3265: # @param {string} $context - newoverview|overview
1.214 www 3266: sub sortmenu {
1.608 raeburn 3267: my ($r,$sortorder,$context)=@_;
3268: my %text;
3269: if ($context eq 'newoverview') {
3270: %text = &Apache::lonlocal::texthash (
3271: realmstudent => 'Sort by location in course first, then student (group/section)',
3272: studentrealm => 'Sort by student (group/section) first, then location in course',
3273: );
3274: } else {
3275: %text = &Apache::lonlocal::texthash (
3276: realmstudent => 'Sort by realm first, then student (group/section)',
3277: studentrealm => 'Sort by student (group/section) first, then realm',
3278: );
1.214 www 3279: }
1.608 raeburn 3280: my %sortchecked = (
3281: realmstudent => ' checked="checked"',
3282: studentrealm => '',
3283: );
1.214 www 3284: if ($sortorder eq 'studentrealm') {
1.608 raeburn 3285: $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
3286: $sortchecked{'realmstudent'} = '';
3287: }
3288: foreach my $sorttype ('realmstudent','studentrealm') {
3289: $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
3290: $text{$sorttype}.'</label>');
1.214 www 3291: }
3292: }
3293:
1.563 damieng 3294: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3295: #
3296: # @returns {hash}
1.211 www 3297: sub standardkeyorder {
3298: return ('parameter_0_opendate' => 1,
1.473 amueller 3299: 'parameter_0_duedate' => 2,
3300: 'parameter_0_answerdate' => 3,
1.622 ! raeburn 3301: 'parameter_0_grace' => 4,
! 3302: 'parameter_0_interval' => 5,
! 3303: 'parameter_0_weight' => 6,
! 3304: 'parameter_0_maxtries' => 7,
! 3305: 'parameter_0_hinttries' => 8,
! 3306: 'parameter_0_contentopen' => 9,
! 3307: 'parameter_0_contentclose' => 10,
! 3308: 'parameter_0_type' => 11,
! 3309: 'parameter_0_problemstatus' => 12,
! 3310: 'parameter_0_hiddenresource' => 13,
! 3311: 'parameter_0_hiddenparts' => 14,
! 3312: 'parameter_0_display' => 15,
! 3313: 'parameter_0_ordered' => 16,
! 3314: 'parameter_0_tol' => 17,
! 3315: 'parameter_0_sig' => 18,
! 3316: 'parameter_0_turnoffunit' => 19,
! 3317: 'parameter_0_discussend' => 20,
! 3318: 'parameter_0_discusshide' => 21,
! 3319: 'parameter_0_discussvote' => 22,
! 3320: 'parameter_0_printstartdate' => 23,
! 3321: 'parameter_0_printenddate' => 24);
1.211 www 3322: }
3323:
1.59 matthew 3324:
1.560 damieng 3325: # Table mode UI.
1.563 damieng 3326: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3327: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3328: #
3329: # Parameters used from the request:
3330: # action - handler action (see handler), usermenu is checking for value 'settable'
3331: # cgroup - selected group
3332: # command - 'set': direct access to table mode for a resource
3333: # csec - selected section
3334: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3335: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3336: # id - student/employee ID
3337: # parmlev - selected level (full|map|general)
3338: # part - selected part (unused ?)
3339: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3340: # pres_type - &&&-separated parameter types
3341: # pres_value - &&&-separated parameter values
3342: # prevvisit - '1' if the user has submitted the form before
3343: # pscat (multiple values) - selected parameter names
1.566 damieng 3344: # pschp - selected map pc, or 'all'
1.563 damieng 3345: # psprt (multiple values) - list of selected parameter parts
3346: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3347: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3348: # symb - resource symb (when a single resource is selected)
3349: # udom - selected user domain
3350: # uname - selected user name
3351: # url - used only with command 'set', the resource url
3352: #
3353: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3354: # @param $parm_permission - ref to hash of permissions
3355: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3356: sub assessparms {
1.1 www 3357:
1.568 raeburn 3358: my ($r,$parm_permission) = @_;
1.201 www 3359:
1.512 foxr 3360:
3361: # -------------------------------------------------------- Variable declaration
1.566 damieng 3362: my @ids=(); # resource and map ids
3363: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3364: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3365: my %typep=(); # hash resource/map id -> resource type (file extension)
3366: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3367: my %uris=(); # hash resource/map id -> resource src
3368: my %maptitles=(); # hash map pc or src -> map title
3369: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3370: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3371: my %alllevs=(); # hash English level title -> value
3372:
3373: my $uname; # selected user name
3374: my $udom; # selected user domain
3375: my $uhome; # server with the user's files, or 'no_host'
3376: my $csec; # selected section name
3377: my $cgroup; # selected group name
3378: my @usersgroups = (); # list of the user groups
1.582 raeburn 3379: my $numreclinks = 0;
1.446 bisitz 3380:
1.190 albertel 3381: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3382:
1.57 albertel 3383: $alllevs{'Resource Level'}='full';
1.215 www 3384: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3385: $alllevs{'Course Level'}='general';
3386:
1.563 damieng 3387: my %allparms; # hash parameter name -> parameter title
3388: my %allparts; # hash parameter part -> part title
1.512 foxr 3389: # ------------------------------------------------------------------------------
3390:
1.210 www 3391: #
3392: # Order in which these parameters will be displayed
3393: #
1.211 www 3394: my %keyorder=&standardkeyorder();
3395:
1.512 foxr 3396: # @ids=();
3397: # %symbp=(); # These seem defined above already.
3398: # %typep=();
1.43 albertel 3399:
3400: my $message='';
3401:
1.190 albertel 3402: $csec=$env{'form.csec'};
1.552 raeburn 3403: if ($env{'request.course.sec'} ne '') {
3404: $csec = $env{'request.course.sec'};
3405: }
3406:
1.553 raeburn 3407: # Check group privs.
1.269 raeburn 3408: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3409: my $noeditgrp;
3410: if ($cgroup ne '') {
3411: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3412: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3413: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3414: $noeditgrp = 1;
3415: }
3416: }
3417: }
1.188 www 3418:
1.190 albertel 3419: if ($udom=$env{'form.udom'}) {
3420: } elsif ($udom=$env{'request.role.domain'}) {
3421: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3422: } else {
1.473 amueller 3423: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3424: }
1.468 amueller 3425:
1.43 albertel 3426:
1.134 albertel 3427: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3428: my $pschp=$env{'form.pschp'};
1.506 www 3429:
3430:
1.134 albertel 3431: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3432: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3433: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3434:
1.43 albertel 3435: my $pssymb='';
1.57 albertel 3436: my $parmlev='';
1.446 bisitz 3437:
1.190 albertel 3438: unless ($env{'form.parmlev'}) {
1.57 albertel 3439: $parmlev = 'map';
3440: } else {
1.190 albertel 3441: $parmlev = $env{'form.parmlev'};
1.57 albertel 3442: }
1.26 www 3443:
1.29 www 3444: # ----------------------------------------------- Was this started from grades?
3445:
1.560 damieng 3446: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3447: (!$env{'form.dis'})) {
1.473 amueller 3448: my $url=$env{'form.url'};
3449: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3450: $pssymb=&Apache::lonnet::symbread($url);
3451: if (!@pscat) { @pscat=('all'); }
3452: $pschp='';
1.57 albertel 3453: $parmlev = 'full';
1.190 albertel 3454: } elsif ($env{'form.symb'}) {
1.473 amueller 3455: $pssymb=$env{'form.symb'};
3456: if (!@pscat) { @pscat=('all'); }
3457: $pschp='';
1.57 albertel 3458: $parmlev = 'full';
1.43 albertel 3459: } else {
1.473 amueller 3460: $env{'form.url'}='';
1.43 albertel 3461: }
3462:
1.190 albertel 3463: my $id=$env{'form.id'};
1.43 albertel 3464: if (($id) && ($udom)) {
1.555 raeburn 3465: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3466: if ($uname) {
3467: $id='';
3468: } else {
3469: $message=
1.540 bisitz 3470: '<p class="LC_warning">'.
3471: &mt('Unknown ID [_1] at domain [_2]',
3472: "'".$id."'","'".$udom."'").
3473: '</p>';
1.473 amueller 3474: }
1.43 albertel 3475: } else {
1.473 amueller 3476: $uname=$env{'form.uname'};
1.43 albertel 3477: }
3478: unless ($udom) { $uname=''; }
3479: $uhome='';
3480: if ($uname) {
1.473 amueller 3481: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3482: if ($uhome eq 'no_host') {
1.473 amueller 3483: $message=
1.540 bisitz 3484: '<p class="LC_warning">'.
3485: &mt('Unknown user [_1] at domain [_2]',
3486: "'".$uname."'","'".$udom."'").
3487: '</p>';
1.473 amueller 3488: $uname='';
1.12 www 3489: } else {
1.473 amueller 3490: $csec=&Apache::lonnet::getsection($udom,$uname,
3491: $env{'request.course.id'});
3492: if ($csec eq '-1') {
1.596 raeburn 3493: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3494: if ($env{'form.userroles'} eq 'any') {
3495: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3496: $csec = $env{'request.course.sec'};
3497: $message = '<span class="LC_info">';
3498: if ($crstype eq 'Community') {
3499: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3500: $uname,$udom);
3501: } else {
3502: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3503: $uname,$udom);
3504: }
3505: $message .= '</span>';
3506: } else {
3507: my @possroles = ('in','ep','ta','cr');
3508: if ($crstype eq 'Community') {
3509: unshift(@possroles,'co');
3510: } else {
3511: unshift(@possroles,'cc');
3512: }
3513: my %not_student_roles =
3514: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3515: \@possroles,[$udom],1,1);
3516: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3517: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3518: my %sections_by_role;
3519: foreach my $role (keys(%not_student_roles)) {
3520: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3521: my ($rolename,$sec) = ($1,$2);
3522: if ($rolename =~ m{^cr/}) {
3523: $rolename = 'cr';
3524: }
3525: push(@{$sections_by_role{$rolename}},$sec);
3526: }
3527: }
3528: my $numroles = scalar(keys(%sections_by_role));
3529: if ($numroles) {
3530: foreach my $role (@possroles) {
3531: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3532: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3533: $csec = $secs[0];
3534: last;
3535: }
3536: }
3537: }
3538: if ($csec eq '-1') {
3539: $message = '<span class="LC_warning">';
3540: if ($crstype eq 'Community') {
3541: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3542: $uname,$udom);
3543: } else {
3544: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3545: $uname,$udom);
3546: }
3547: $message .= '</span>';
3548: $uname='';
3549: if ($env{'request.course.sec'} ne '') {
3550: $csec=$env{'request.course.sec'};
3551: } else {
3552: $csec=$env{'form.csec'};
3553: }
3554: $cgroup=$env{'form.cgroup'};
3555: } else {
3556: $message = '<span class="LC_info">';
3557: if ($crstype eq 'Community') {
3558: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3559: $uname,$udom);
3560: } else {
3561: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3562: $uname,$udom);
3563: }
3564: $message .= '</span>';
3565: }
3566: }
1.594 raeburn 3567: } else {
1.596 raeburn 3568: $message = '<span class="LC_warning">';
3569: if ($crstype eq 'Community') {
3570: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3571: $uname,$udom);
3572: } else {
3573: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3574: $uname,$udom);
3575: }
3576: $message .= '</span>';
3577: $uname='';
3578: if ($env{'request.course.sec'} ne '') {
3579: $csec=$env{'request.course.sec'};
3580: } else {
3581: $csec=$env{'form.csec'};
3582: }
3583: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3584: }
3585: } elsif ($env{'request.course.sec'} ne '') {
3586: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3587: $message='<span class="LC_warning">'.
1.594 raeburn 3588: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3589: $uname,$udom,$env{'request.course.sec'}).
3590: '</span>';
3591: $uname='';
3592: $csec=$env{'request.course.sec'};
3593: }
1.269 raeburn 3594: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3595: }
3596: if ($uname ne '') {
1.473 amueller 3597: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3598: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3599: $message .= "\n<p>\n".&mt('Full Name').': '
3600: .$name{'firstname'}.' '.$name{'middlename'}.' '
3601: .$name{'lastname'}.' '.$name{'generation'}
3602: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3603: @usersgroups = &Apache::lonnet::get_users_groups(
3604: $udom,$uname,$env{'request.course.id'});
3605: if (@usersgroups > 0) {
3606: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3607: $cgroup = $usersgroups[0];
3608: }
3609: } else {
3610: $cgroup = '';
1.297 raeburn 3611: }
1.269 raeburn 3612: }
1.12 www 3613: }
1.43 albertel 3614: }
1.2 www 3615:
1.43 albertel 3616: unless ($csec) { $csec=''; }
1.269 raeburn 3617: unless ($cgroup) { $cgroup=''; }
1.12 www 3618:
1.14 www 3619: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3620: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3621: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 3622: \%keyorder,undef,$pssymb);
1.63 bowersj2 3623:
1.582 raeburn 3624: %allmaps_inverted = reverse(%allmaps);
3625:
1.57 albertel 3626: $mapp{'0.0'} = '';
3627: $symbp{'0.0'} = '';
1.99 albertel 3628:
1.14 www 3629: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3630: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3631: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3632: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3633: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3634: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3635: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3636: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3637: my ($got_chostname,$chostname,$cmajor,$cminor);
3638: my $totalstored = 0;
1.605 raeburn 3639: my $totalskippeduser = 0;
1.546 raeburn 3640: my $now = time;
1.473 amueller 3641: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3642: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3643: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3644: next if ($csec ne $env{'request.course.sec'});
3645: }
1.556 raeburn 3646: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3647: next if ($noeditgrp);
1.605 raeburn 3648: } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
3649: if ($uname eq '') {
3650: $totalskippeduser ++;
3651: next;
3652: }
1.557 raeburn 3653: }
3654: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3655: $namematch = 'maplevelrecurse';
3656: }
1.556 raeburn 3657: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3658: my (@ok_slots,@fail_slots,@del_slots);
3659: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3660: my ($level,@all) =
3661: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3662: $csec,$cgroup,$courseopt);
3663: foreach my $slot_name (split(/:/,$values[$i])) {
3664: next if ($slot_name eq '');
3665: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3666: push(@ok_slots,$slot_name);
3667:
3668: } else {
3669: push(@fail_slots,$slot_name);
3670: }
3671: }
3672: if (@ok_slots) {
3673: $values[$i] = join(':',@ok_slots);
3674: } else {
3675: $values[$i] = '';
3676: }
3677: if ($all[$level] ne '') {
3678: my @existing = split(/:/,$all[$level]);
3679: foreach my $slot_name (@existing) {
3680: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3681: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3682: push(@del_slots,$slot_name);
3683: }
3684: }
3685: }
3686: }
1.554 raeburn 3687: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3688: $name = $1;
1.533 raeburn 3689: my $val = $values[$i];
1.549 raeburn 3690: my $valmatch = '';
1.533 raeburn 3691: if ($name eq 'examcode') {
1.544 raeburn 3692: if (&Apache::lonnet::validCODE($values[$i])) {
3693: $val = 'valid';
3694: }
1.546 raeburn 3695: } elsif ($name eq 'printstartdate') {
3696: if ($val =~ /^\d+$/) {
3697: if ($val > $now) {
3698: $val = 'future';
3699: }
3700: }
3701: } elsif ($name eq 'printenddate') {
3702: if ($val =~ /^\d+$/) {
3703: if ($val < $now) {
3704: $val = 'past';
3705: }
3706: }
1.549 raeburn 3707: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3708: my $stringtype = &get_stringtype($name);
3709: my $stringmatch = &standard_string_matches($stringtype);
3710: if (ref($stringmatch) eq 'ARRAY') {
3711: foreach my $item (@{$stringmatch}) {
3712: if (ref($item) eq 'ARRAY') {
3713: my ($regexpname,$pattern) = @{$item};
3714: if ($pattern ne '') {
3715: if ($val =~ /$pattern/) {
3716: $valmatch = $regexpname;
3717: $val = '';
3718: last;
3719: }
3720: }
3721: }
3722: }
3723: }
1.554 raeburn 3724: } elsif ($name eq 'interval') {
3725: my $intervaltype = &get_intervaltype($name);
3726: my $intervalmatch = &standard_interval_matches($intervaltype);
3727: if (ref($intervalmatch) eq 'ARRAY') {
3728: foreach my $item (@{$intervalmatch}) {
3729: if (ref($item) eq 'ARRAY') {
3730: my ($regexpname,$pattern) = @{$item};
3731: if ($pattern ne '') {
3732: if ($val =~ /$pattern/) {
3733: $valmatch = $regexpname;
3734: $val = '';
3735: last;
3736: }
3737: }
3738: }
3739: }
3740: }
1.533 raeburn 3741: }
1.504 raeburn 3742: $needsrelease =
1.557 raeburn 3743: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3744: if ($needsrelease) {
1.505 raeburn 3745: unless ($got_chostname) {
1.514 raeburn 3746: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3747: $got_chostname = 1;
1.546 raeburn 3748: }
1.557 raeburn 3749: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3750: $needsrelease,
3751: $cmajor,$cminor);
1.500 raeburn 3752: }
1.437 raeburn 3753: }
1.504 raeburn 3754: if ($needsnewer) {
1.557 raeburn 3755: undef($namematch);
3756: } else {
3757: my $currneeded;
3758: if ($needsrelease) {
3759: $currneeded = $needsrelease;
3760: }
3761: if ($namematch) {
3762: $needsrelease =
3763: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3764: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3765: unless ($got_chostname) {
3766: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3767: $got_chostname = 1;
3768: }
3769: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3770: $needsrelease,
3771: $cmajor,$cminor);
3772: } else {
3773: undef($namematch);
3774: }
3775: }
3776: }
3777: if ($needsnewer) {
3778: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3779: $cminor,$needsrelease);
3780: } else {
3781: $message.=&storeparm(split(/\&/,$markers[$i]),
3782: $values[$i],
3783: $types[$i],
3784: $uname,$udom,$csec,$cgroup);
3785: $totalstored ++;
3786: }
1.473 amueller 3787: }
1.68 www 3788: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3789: if ($totalstored) {
3790: $message.='<p class="LC_warning">'
1.605 raeburn 3791: .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
3792: .'<br />'
1.504 raeburn 3793: .&mt('Changes can take up to 10 minutes before being active for all students.')
3794: .&Apache::loncommon::help_open_topic('Caching')
3795: .'</p>';
1.605 raeburn 3796: } else {
3797: $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
3798: }
3799: if ($totalskippeduser) {
3800: $message .= '<p class="LC_warning">';
3801: if ($uhome eq 'no_host') {
3802: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
3803: $totalskippeduser);
3804: } elsif ($env{'form.userroles'} eq 'any') {
3805: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
3806: $totalskippeduser);
3807: } else {
3808: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
3809: $totalskippeduser);
3810: }
3811: $message .= '</p>';
1.504 raeburn 3812: }
1.68 www 3813: }
1.584 raeburn 3814:
1.57 albertel 3815: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3816: if ($pscat[0] eq "all") {
3817: @pscat = (keys(%allparms));
3818: }
3819: if (!@pscat) {
3820: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3821: };
3822: if ($psprt[0] eq "all" || !@psprt) {
3823: @psprt = (keys(%allparts));
3824: }
1.2 www 3825: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3826:
1.531 raeburn 3827: my $crstype = &Apache::loncommon::course_type();
3828: &startpage($r,$pssymb,$crstype);
1.57 albertel 3829:
1.548 raeburn 3830: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3831: 'date_interval','int','float','string','string_lenient',
3832: 'string_examcode','string_deeplink','string_discussvote',
3833: 'string_useslots','string_problemstatus','string_ip',
1.622 ! raeburn 3834: 'string_questiontype','string_tex','string_grace') {
1.473 amueller 3835: $r->print('<input type="hidden" value="'.
1.563 damieng 3836: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3837: '" name="recent_'.$item.'" />');
1.44 albertel 3838: }
1.446 bisitz 3839:
1.459 bisitz 3840: # ----- Start Parameter Selection
3841:
1.606 raeburn 3842: # Hide parm selection and possibly table?
3843: my ($tablejs,$tabledivsty);
3844: if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
3845: ($env{'form.dis'}) && ($pssymb eq '')) {
3846: $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
3847: $tabledivsty = ' style="display:none"';
3848: }
1.459 bisitz 3849: $r->print(<<ENDPARMSELSCRIPT);
3850: <script type="text/javascript">
3851: // <![CDATA[
3852: function parmsel_show() {
1.562 damieng 3853: document.getElementById('parmsel').style.display = "";
3854: document.getElementById('parmsellink').style.display = "none";
1.606 raeburn 3855: $tablejs
1.459 bisitz 3856: }
3857: // ]]>
3858: </script>
3859: ENDPARMSELSCRIPT
1.474 amueller 3860:
1.445 neumanie 3861: if (!$pssymb) {
1.563 damieng 3862: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3863: my $parmselhiddenstyle=' style="display:none"';
3864: if($env{'form.hideparmsel'} eq 'hidden') {
3865: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3866: } else {
3867: $r->print('<div id="parmsel">');
3868: }
3869:
1.491 bisitz 3870: # Step 1
1.523 raeburn 3871: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3872: $r->print('
1.474 amueller 3873: <script type="text/javascript">
1.523 raeburn 3874: // <![CDATA['.
3875: &showhide_js().'
1.474 amueller 3876: // ]]>
3877: </script>
1.523 raeburn 3878: ');
3879: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3880: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3881: $r->print(&Apache::lonhtmlcommon::row_closure());
1.610 raeburn 3882: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491 bisitz 3883: $r->print(&Apache::lonhtmlcommon::row_closure());
3884: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3885: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3886: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3887: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3888:
3889: # Step 2
1.523 raeburn 3890: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3891: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3892:
3893: # Step 3
1.523 raeburn 3894: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3895: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3896: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3897: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3898: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3899:
3900: # Update Display Button
1.486 www 3901: $r->print('<p>'
3902: .'<input type="submit" name="dis"'
1.511 www 3903: .' value="'.&mt('Update Display').'" />'
1.486 www 3904: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3905: .'</p>');
3906: $r->print('</div>');
1.491 bisitz 3907:
1.486 www 3908: # Offer link to display parameter selection again
3909: $r->print('<p id="parmsellink"');
3910: if ($env{'form.hideparmsel'} ne 'hidden') {
3911: $r->print($parmselhiddenstyle);
3912: }
3913: $r->print('>'
3914: .'<a href="javascript:parmsel_show()">'
3915: .&mt('Change Parameter Selection')
3916: .'</a>'
3917: .'</p>');
1.44 albertel 3918: } else {
1.478 amueller 3919: # parameter screen for a single resource.
1.486 www 3920: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3921: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3922: $r->print(&mt('Specific Resource: [_1] ([_2])',
3923: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3924: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 3925: '<br />');
3926: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
3927: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3928: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3929: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3930: $r->print(&Apache::lonhtmlcommon::end_pick_box());
3931: $r->print('<p>'
1.459 bisitz 3932: .'<input type="submit" name="dis"'
1.511 www 3933: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 3934: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 3935: .'</p>');
1.459 bisitz 3936: }
1.478 amueller 3937:
1.486 www 3938: # ----- End Parameter Selection
1.57 albertel 3939:
1.459 bisitz 3940: # Display Messages
3941: $r->print('<div>'.$message.'</div>');
1.210 www 3942:
1.57 albertel 3943:
3944: my @temp_pscat;
3945: map {
3946: my $cat = $_;
3947: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
3948: } @pscat;
3949:
3950: @pscat = @temp_pscat;
3951:
1.548 raeburn 3952:
1.209 www 3953: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 3954: # ----------------------------------------------------------------- Start Table
1.57 albertel 3955: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 3956: my $csuname=$env{'user.name'};
3957: my $csudom=$env{'user.domain'};
1.568 raeburn 3958: my $readonly = 1;
3959: if ($parm_permission->{'edit'}) {
3960: undef($readonly);
3961: }
1.606 raeburn 3962: $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57 albertel 3963:
1.203 www 3964: if ($parmlev eq 'full') {
1.506 www 3965: #
3966: # This produces the cascading table output of parameters
3967: #
1.578 raeburn 3968: my $coursespan=$csec?8:5;
3969: my $userspan=3;
1.560 damieng 3970: if ($cgroup ne '') {
1.578 raeburn 3971: $coursespan += 3;
1.560 damieng 3972: }
1.473 amueller 3973:
1.560 damieng 3974: $r->print(&Apache::loncommon::start_data_table());
3975: #
3976: # This produces the headers
3977: #
3978: $r->print('<tr><td colspan="5"></td>');
3979: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
3980: if ($uname) {
1.473 amueller 3981: if (@usersgroups > 1) {
1.560 damieng 3982: $userspan ++;
3983: }
3984: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
3985: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
3986: }
3987: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 3988: 'pie' => "Parameter in Effect",
3989: 'csv' => "Current Session Value",
1.472 amueller 3990: 'rl' => "Resource Level",
1.473 amueller 3991: 'ic' => 'in Course',
3992: 'aut' => "Assessment URL and Title",
3993: 'type' => 'Type',
3994: 'emof' => "Enclosing Map or Folder",
3995: 'part' => 'Part',
1.472 amueller 3996: 'pn' => 'Parameter Name',
1.473 amueller 3997: 'def' => 'default',
3998: 'femof' => 'from Enclosing Map or Folder',
3999: 'gen' => 'general',
4000: 'foremf' => 'for Enclosing Map or Folder',
4001: 'fr' => 'for Resource'
4002: );
1.560 damieng 4003: $r->print(<<ENDTABLETWO);
1.419 bisitz 4004: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 4005: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 4006: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 4007: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 4008:
1.10 www 4009: ENDTABLETWO
1.560 damieng 4010: if ($csec) {
1.578 raeburn 4011: $r->print('<th colspan="3">'.
1.560 damieng 4012: &mt("in Section")." $csec</th>");
4013: }
4014: if ($cgroup) {
1.578 raeburn 4015: $r->print('<th colspan="3">'.
1.472 amueller 4016: &mt("in Group")." $cgroup</th>");
1.560 damieng 4017: }
4018: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 4019: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
4020: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 4021: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 4022: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 4023: ENDTABLEHEADFOUR
1.57 albertel 4024:
1.560 damieng 4025: if ($csec) {
1.578 raeburn 4026: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 4027: }
1.473 amueller 4028:
1.560 damieng 4029: if ($cgroup) {
1.578 raeburn 4030: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 4031: }
4032:
4033: if ($uname) {
4034: if (@usersgroups > 1) {
4035: $r->print('<th>'.&mt('Control by other group?').'</th>');
4036: }
1.578 raeburn 4037: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 4038: }
4039:
4040: $r->print('</tr>');
1.506 www 4041: #
4042: # Done with the headers
4043: #
1.560 damieng 4044: my $defbgone='';
4045: my $defbgtwo='';
4046: my $defbgthree = '';
1.57 albertel 4047:
1.560 damieng 4048: foreach my $rid (@ids) {
1.57 albertel 4049:
4050: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 4051: if ((!$pssymb &&
1.560 damieng 4052: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
4053: ||
4054: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 4055: # ------------------------------------------------------ Entry for one resource
1.473 amueller 4056: if ($defbgone eq '#E0E099') {
4057: $defbgone='#E0E0DD';
1.57 albertel 4058: } else {
1.419 bisitz 4059: $defbgone='#E0E099';
1.57 albertel 4060: }
1.419 bisitz 4061: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 4062: $defbgtwo='#FFFFDD';
1.57 albertel 4063: } else {
1.473 amueller 4064: $defbgtwo='#FFFF99';
1.57 albertel 4065: }
1.419 bisitz 4066: if ($defbgthree eq '#FFBB99') {
4067: $defbgthree='#FFBBDD';
1.269 raeburn 4068: } else {
1.419 bisitz 4069: $defbgthree='#FFBB99';
1.269 raeburn 4070: }
4071:
1.57 albertel 4072: my $thistitle='';
4073: my %name= ();
4074: undef %name;
4075: my %part= ();
4076: my %display=();
4077: my %type= ();
4078: my %default=();
1.196 www 4079: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4080: my $toolsymb;
4081: if ($uri =~ /ext\.tool$/) {
4082: $toolsymb = $symbp{$rid};
4083: }
1.57 albertel 4084:
1.506 www 4085: my $filter=$env{'form.filter'};
1.548 raeburn 4086: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 4087: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 4088: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 4089: # We may only want certain parameters listed
4090: if ($filter) {
4091: unless ($filter=~/\Q$parmname\E/) { next; }
4092: }
4093: $name{$tempkeyp}=$parmname;
1.584 raeburn 4094: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 4095:
1.584 raeburn 4096: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 4097: if ($allparms{$name{$tempkeyp}} ne '') {
4098: my $identifier;
4099: if ($parmdis =~ /(\s*\[Part.*)$/) {
4100: $identifier = $1;
4101: }
4102: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4103: } else {
4104: $display{$tempkeyp} = $parmdis;
4105: }
4106: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4107: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 4108: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
4109: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
4110: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 4111: }
4112: }
1.548 raeburn 4113: my $totalparms=scalar(keys(%name));
1.57 albertel 4114: if ($totalparms>0) {
1.560 damieng 4115: my $firstrow=1;
1.473 amueller 4116: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 4117: my $navmap = Apache::lonnavmaps::navmap->new();
4118: my @recurseup;
4119: if (ref($navmap) && $mapp{$rid}) {
4120: @recurseup = $navmap->recurseup_maps($mapp{$rid});
4121: }
1.419 bisitz 4122: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 4123: ' rowspan='.$totalparms.
1.419 bisitz 4124: '><tt><font size="-1">'.
1.57 albertel 4125: join(' / ',split(/\//,$uri)).
4126: '</font></tt><p><b>'.
1.154 albertel 4127: "<a href=\"javascript:openWindow('".
1.473 amueller 4128: &Apache::lonnet::clutter($uri).'?symb='.
4129: &escape($symbp{$rid}).
1.336 albertel 4130: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
4131: " target=\"_self\">$title");
1.57 albertel 4132:
4133: if ($thistitle) {
1.473 amueller 4134: $r->print(' ('.$thistitle.')');
1.57 albertel 4135: }
4136: $r->print('</a></b></td>');
1.419 bisitz 4137: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 4138: ' rowspan='.$totalparms.'>'.$typep{$rid}.
4139: '</td>');
4140:
1.419 bisitz 4141: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 4142: ' rowspan='.$totalparms.
1.238 www 4143: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 4144: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 4145: unless ($firstrow) {
4146: $r->print('<tr>');
4147: } else {
4148: undef $firstrow;
4149: }
1.548 raeburn 4150: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 4151: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 4152: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 4153: $cgroup,\@usersgroups,$noeditgrp,$readonly,
4154: \@recurseup,\%maptitles,\%allmaps_inverted,
4155: \$numreclinks);
1.57 albertel 4156: }
4157: }
4158: }
4159: } # end foreach ids
1.43 albertel 4160: # -------------------------------------------------- End entry for one resource
1.517 www 4161: $r->print(&Apache::loncommon::end_data_table);
1.203 www 4162: } # end of full
1.57 albertel 4163: #--------------------------------------------------- Entry for parm level map
4164: if ($parmlev eq 'map') {
1.419 bisitz 4165: my $defbgone = '#E0E099';
4166: my $defbgtwo = '#FFFF99';
4167: my $defbgthree = '#FFBB99';
1.57 albertel 4168:
4169: my %maplist;
4170:
4171: if ($pschp eq 'all') {
1.446 bisitz 4172: %maplist = %allmaps;
1.57 albertel 4173: } else {
4174: %maplist = ($pschp => $mapp{$pschp});
4175: }
4176:
4177: #-------------------------------------------- for each map, gather information
4178: my $mapid;
1.607 raeburn 4179: foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60 albertel 4180: my $maptitle = $maplist{$mapid};
1.57 albertel 4181:
4182: #----------------------- loop through ids and get all parameter types for map
4183: #----------------------------------------- and associated information
4184: my %name = ();
4185: my %part = ();
4186: my %display = ();
4187: my %type = ();
4188: my %default = ();
4189: my $map = 0;
4190:
1.473 amueller 4191: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 4192:
1.548 raeburn 4193: foreach my $id (@ids) {
4194: ($map)=($id =~ /([\d]*?)\./);
4195: my $rid = $id;
1.446 bisitz 4196:
1.57 albertel 4197: # $r->print("$mapid:$map: $rid <br /> \n");
4198:
1.560 damieng 4199: if ($map eq $mapid) {
1.473 amueller 4200: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4201: my $toolsymb;
4202: if ($uri =~ /ext\.tool$/) {
4203: $toolsymb = $symbp{$rid};
4204: }
1.582 raeburn 4205:
1.57 albertel 4206: # $r->print("Keys: $keyp{$rid} <br />\n");
4207:
4208: #--------------------------------------------------------------------
4209: # @catmarker contains list of all possible parameters including part #s
4210: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4211: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4212: # When storing information, store as part 0
4213: # When requesting information, request from full part
4214: #-------------------------------------------------------------------
1.548 raeburn 4215: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4216: my $tempkeyp = $fullkeyp;
4217: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 4218:
1.548 raeburn 4219: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4220: $part{$tempkeyp}="0";
1.584 raeburn 4221: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4222: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4223: if ($allparms{$name{$tempkeyp}} ne '') {
4224: my $identifier;
4225: if ($parmdis =~ /(\s*\[Part.*)$/) {
4226: $identifier = $1;
4227: }
4228: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4229: } else {
4230: $display{$tempkeyp} = $parmdis;
4231: }
4232: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4233: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4234: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4235: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4236: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 4237: }
4238: } # end loop through keys
1.560 damieng 4239: }
1.57 albertel 4240: } # end loop through ids
1.446 bisitz 4241:
1.57 albertel 4242: #---------------------------------------------------- print header information
1.133 www 4243: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 4244: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 4245: my $tmp="";
1.57 albertel 4246: if ($uname) {
1.473 amueller 4247: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 4248: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
4249: &mt('in')." \n";
1.57 albertel 4250: } else {
1.401 bisitz 4251: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 4252: }
1.269 raeburn 4253: if ($cgroup) {
1.401 bisitz 4254: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
4255: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4256: $csec = '';
4257: } elsif ($csec) {
1.401 bisitz 4258: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
4259: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4260: }
1.401 bisitz 4261: $r->print('<div align="center"><h4>'
4262: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 4263: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 4264: ,$tmp
4265: ,'<font color="red"><i>'.$coursename.'</i></font>'
4266: )
4267: ."<br /></h4>\n"
1.422 bisitz 4268: );
1.57 albertel 4269: #---------------------------------------------------------------- print table
1.419 bisitz 4270: $r->print('<p>'.&Apache::loncommon::start_data_table()
4271: .&Apache::loncommon::start_data_table_header_row()
4272: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 4273: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4274: .'<th>'.&mt('Parameter in Effect').'</th>'
4275: .&Apache::loncommon::end_data_table_header_row()
4276: );
1.57 albertel 4277:
1.582 raeburn 4278: my $navmap = Apache::lonnavmaps::navmap->new();
4279: my @recurseup;
4280: if (ref($navmap)) {
4281: my $mapres = $navmap->getByMapPc($mapid);
4282: if (ref($mapres)) {
4283: @recurseup = $navmap->recurseup_maps($mapres->src());
4284: }
4285: }
4286:
4287:
1.548 raeburn 4288: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4289: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4290: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4291: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4292: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4293: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4294: \$numreclinks);
1.57 albertel 4295: }
1.422 bisitz 4296: $r->print(&Apache::loncommon::end_data_table().'</p>'
4297: .'</div>'
4298: );
1.57 albertel 4299: } # end each map
4300: } # end of $parmlev eq map
4301: #--------------------------------- Entry for parm level general (Course level)
4302: if ($parmlev eq 'general') {
1.473 amueller 4303: my $defbgone = '#E0E099';
1.419 bisitz 4304: my $defbgtwo = '#FFFF99';
4305: my $defbgthree = '#FFBB99';
1.57 albertel 4306:
4307: #-------------------------------------------- for each map, gather information
4308: my $mapid="0.0";
4309: #----------------------- loop through ids and get all parameter types for map
4310: #----------------------------------------- and associated information
4311: my %name = ();
4312: my %part = ();
4313: my %display = ();
4314: my %type = ();
4315: my %default = ();
1.446 bisitz 4316:
1.548 raeburn 4317: foreach $id (@ids) {
4318: my $rid = $id;
1.446 bisitz 4319:
1.196 www 4320: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4321: my $toolsymb;
4322: if ($uri =~ /ext\.tool$/) {
4323: $toolsymb = $symbp{$rid};
4324: }
1.57 albertel 4325:
4326: #--------------------------------------------------------------------
4327: # @catmarker contains list of all possible parameters including part #s
4328: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4329: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4330: # When storing information, store as part 0
4331: # When requesting information, request from full part
4332: #-------------------------------------------------------------------
1.548 raeburn 4333: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4334: my $tempkeyp = $fullkeyp;
4335: $tempkeyp =~ s/_\w+_/_0_/;
4336: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4337: $part{$tempkeyp}="0";
1.584 raeburn 4338: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4339: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4340: if ($allparms{$name{$tempkeyp}} ne '') {
4341: my $identifier;
4342: if ($parmdis =~ /(\s*\[Part.*)$/) {
4343: $identifier = $1;
4344: }
4345: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4346: } else {
4347: $display{$tempkeyp} = $parmdis;
4348: }
4349: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4350: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4351: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4352: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4353: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4354: }
1.57 albertel 4355: } # end loop through keys
4356: } # end loop through ids
1.446 bisitz 4357:
1.57 albertel 4358: #---------------------------------------------------- print header information
1.473 amueller 4359: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4360: $r->print(<<ENDMAPONE);
1.419 bisitz 4361: <center>
4362: <h4>$setdef
1.135 albertel 4363: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4364: ENDMAPONE
4365: if ($uname) {
1.473 amueller 4366: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4367: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4368: } else {
1.135 albertel 4369: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4370: }
1.446 bisitz 4371:
1.135 albertel 4372: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4373: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4374: $r->print("</h4>\n");
1.57 albertel 4375: #---------------------------------------------------------------- print table
1.419 bisitz 4376: $r->print('<p>'.&Apache::loncommon::start_data_table()
4377: .&Apache::loncommon::start_data_table_header_row()
4378: .'<th>'.&mt('Parameter Name').'</th>'
4379: .'<th>'.&mt('Default Value').'</th>'
4380: .'<th>'.&mt('Parameter in Effect').'</th>'
4381: .&Apache::loncommon::end_data_table_header_row()
4382: );
1.57 albertel 4383:
1.548 raeburn 4384: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4385: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4386: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4387: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4388: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4389: $readonly);
1.57 albertel 4390: }
1.419 bisitz 4391: $r->print(&Apache::loncommon::end_data_table()
4392: .'</p>'
4393: .'</center>'
4394: );
1.57 albertel 4395: } # end of $parmlev eq general
1.606 raeburn 4396: $r->print('</div>');
1.43 albertel 4397: }
1.507 www 4398: $r->print('</form>');
1.582 raeburn 4399: if ($numreclinks) {
4400: $r->print(<<"END");
4401: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4402: <input type="hidden" name="pschp" />
4403: <input type="hidden" name="pscat" />
4404: <input type="hidden" name="psprt" />
4405: <input type="hidden" name="hideparmsel" value="hidden" />
4406: </form>
4407: <script type="text/javascript">
4408: function pjumprec(rid,name,part) {
4409: document.forms.recurseform.pschp.value = rid;
4410: document.forms.recurseform.pscat.value = name;
4411: document.forms.recurseform.psprt.value = part;
4412: document.forms.recurseform.submit();
4413: return false;
4414: }
4415: </script>
4416: END
4417: }
1.507 www 4418: &endSettingsScreen($r);
4419: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4420: } # end sub assessparms
1.30 www 4421:
1.560 damieng 4422:
4423:
1.120 www 4424: ##################################################
1.560 damieng 4425: # OVERVIEW MODE
1.207 www 4426: ##################################################
1.124 www 4427:
1.563 damieng 4428: my $tableopen; # boolean, true if HTML table is already opened
4429:
4430: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4431: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4432: # @returns {string}
1.124 www 4433: sub tablestart {
1.576 raeburn 4434: my ($readonly,$is_map) = @_;
1.124 www 4435: if ($tableopen) {
1.552 raeburn 4436: return '';
1.124 www 4437: } else {
1.552 raeburn 4438: $tableopen=1;
4439: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4440: if ($readonly) {
4441: $output .= '<th>'.&mt('Current value').'</th>';
4442: } else {
1.576 raeburn 4443: $output .= '<th>'.&mt('Delete').'</th>'.
4444: '<th>'.&mt('Set to ...').'</th>';
4445: if ($is_map) {
4446: $output .= '<th>'.&mt('Recursive?').'</th>';
4447: }
1.552 raeburn 4448: }
4449: $output .= '</tr>';
4450: return $output;
1.124 www 4451: }
4452: }
4453:
1.563 damieng 4454: # Returns HTML with the HTML table end tag, unless the table is not opened.
4455: # @returns {string}
1.124 www 4456: sub tableend {
4457: if ($tableopen) {
1.560 damieng 4458: $tableopen=0;
4459: return &Apache::loncommon::end_data_table();
1.124 www 4460: } else {
1.560 damieng 4461: return'';
1.124 www 4462: }
4463: }
4464:
1.563 damieng 4465: # Reads course and user information.
4466: # 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).
4467: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4468: # If the context is looking for a list, returns a list with the scalar data and the class list.
4469: # @param {string} $crs - course number
4470: # @param {string} $dom - course domain
4471: # @returns {hash reference|Array}
1.207 www 4472: sub readdata {
4473: my ($crs,$dom)=@_;
4474: # Read coursedata
4475: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4476: # Read userdata
4477:
4478: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4479: foreach my $user (keys(%$classlist)) {
4480: if ($user=~/^($match_username)\:($match_domain)$/) {
4481: my ($tuname,$tudom)=($1,$2);
4482: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4483: foreach my $userkey (keys(%{$useropt})) {
4484: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4485: my $newkey=$userkey;
1.548 raeburn 4486: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4487: $$resourcedata{$newkey}=$$useropt{$userkey};
4488: }
4489: }
1.473 amueller 4490: }
4491: }
1.552 raeburn 4492: if (wantarray) {
4493: return ($resourcedata,$classlist);
4494: } else {
4495: return $resourcedata;
4496: }
1.207 www 4497: }
4498:
4499:
1.563 damieng 4500: # Stores parameter data, using form parameters directly.
4501: #
4502: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.622 ! raeburn 4503: # set_* (except settext, setipallow, setipdeny, setdeeplink, setgrace) - set a parameter value
1.563 damieng 4504: # del_* - remove a parameter
4505: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4506: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4507: # key_* - date values
4508: # days_* - for date intervals
4509: # hours_* - for date intervals
4510: # minutes_* - for date intervals
4511: # seconds_* - for date intervals
4512: # done_* - for date intervals
4513: # typeof_* - parameter type
4514: #
4515: # @param {Apache2::RequestRec} $r - the Apache request
4516: # @param {string} $crs - course number
4517: # @param {string} $dom - course domain
1.208 www 4518: sub storedata {
4519: my ($r,$crs,$dom)=@_;
1.207 www 4520: # Set userlevel immediately
4521: # Do an intermediate store of course level
4522: my $olddata=&readdata($crs,$dom);
1.124 www 4523: my %newdata=();
4524: undef %newdata;
4525: my @deldata=();
1.576 raeburn 4526: my @delrec=();
4527: my @delnonrec=();
1.124 www 4528: undef @deldata;
1.504 raeburn 4529: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4530: my $now = time;
1.560 damieng 4531: foreach my $key (keys(%env)) {
4532: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4533: my $cmd=$1;
4534: my $thiskey=$2;
1.576 raeburn 4535: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.622 ! raeburn 4536: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink' || $cmd eq 'setgrace');
1.576 raeburn 4537: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4538: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4539: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4540: $altkey = $thiskey;
4541: $altkey =~ s/\Q___(all)\E/___(rec)/;
4542: if ($env{'form.rec_'.$thiskey}) {
4543: $recursive = 1;
4544: }
4545: }
4546: }
1.560 damieng 4547: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4548: if ($tuname) {
1.576 raeburn 4549: $tkey=$thiskey;
1.560 damieng 4550: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4551: if ($altkey) {
4552: $tkeynonrec = $tkey;
4553: $tkeyrec = $altkey;
4554: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4555: }
1.560 damieng 4556: }
4557: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4558: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4559: if ($cmd eq 'set') {
4560: $data=$env{$key};
4561: $valmatch = '';
4562: $valchk = $data;
4563: $typeof=$env{'form.typeof_'.$thiskey};
4564: $text = &mt('Saved modified parameter for');
4565: if ($typeof eq 'string_questiontype') {
4566: $name = 'type';
1.588 raeburn 4567: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4568: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4569: my $stringmatch = &standard_string_matches($typeof);
4570: if (ref($stringmatch) eq 'ARRAY') {
4571: foreach my $item (@{$stringmatch}) {
4572: if (ref($item) eq 'ARRAY') {
4573: my ($regexpname,$pattern) = @{$item};
4574: if ($pattern ne '') {
4575: if ($data =~ /$pattern/) {
4576: $valmatch = $regexpname;
4577: $valchk = '';
4578: last;
4579: }
1.560 damieng 4580: }
1.549 raeburn 4581: }
4582: }
4583: }
1.563 damieng 4584: } elsif ($typeof eq 'string_discussvote') {
4585: $name = 'discussvote';
4586: } elsif ($typeof eq 'string_examcode') {
4587: $name = 'examcode';
4588: if (&Apache::lonnet::validCODE($data)) {
4589: $valchk = 'valid';
4590: }
4591: } elsif ($typeof eq 'string_yesno') {
4592: if ($thiskey =~ /\.retrypartial$/) {
4593: $name = 'retrypartial';
4594: }
1.621 raeburn 4595: } elsif ($typeof eq 'string_tex') {
4596: $name = 'texdisplay';
1.549 raeburn 4597: }
1.563 damieng 4598: } elsif ($cmd eq 'datepointer') {
4599: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4600: $typeof=$env{'form.typeof_'.$thiskey};
4601: $text = &mt('Saved modified date for');
4602: if ($typeof eq 'date_start') {
4603: if ($thiskey =~ /\.printstartdate$/) {
4604: $name = 'printstartdate';
4605: if (($data) && ($data > $now)) {
4606: $valchk = 'future';
4607: }
1.560 damieng 4608: }
1.563 damieng 4609: } elsif ($typeof eq 'date_end') {
4610: if ($thiskey =~ /\.printenddate$/) {
4611: $name = 'printenddate';
4612: if (($data) && ($data < $now)) {
4613: $valchk = 'past';
4614: }
1.560 damieng 4615: }
1.504 raeburn 4616: }
1.563 damieng 4617: } elsif ($cmd eq 'dateinterval') {
4618: $data=&get_date_interval_from_form($thiskey);
4619: if ($thiskey =~ /\.interval$/) {
4620: $name = 'interval';
4621: my $intervaltype = &get_intervaltype($name);
4622: my $intervalmatch = &standard_interval_matches($intervaltype);
4623: if (ref($intervalmatch) eq 'ARRAY') {
4624: foreach my $item (@{$intervalmatch}) {
4625: if (ref($item) eq 'ARRAY') {
4626: my ($regexpname,$pattern) = @{$item};
4627: if ($pattern ne '') {
4628: if ($data =~ /$pattern/) {
4629: $valmatch = $regexpname;
4630: $valchk = '';
4631: last;
4632: }
1.560 damieng 4633: }
1.554 raeburn 4634: }
4635: }
4636: }
4637: }
1.563 damieng 4638: $typeof=$env{'form.typeof_'.$thiskey};
4639: $text = &mt('Saved modified date for');
1.554 raeburn 4640: }
1.576 raeburn 4641: if ($recursive) {
1.563 damieng 4642: $namematch = 'maplevelrecurse';
1.560 damieng 4643: }
1.563 damieng 4644: if (($name ne '') || ($namematch ne '')) {
4645: my ($needsrelease,$needsnewer);
4646: if ($name ne '') {
4647: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4648: if ($needsrelease) {
4649: unless ($got_chostname) {
1.563 damieng 4650: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4651: $got_chostname = 1;
4652: }
1.563 damieng 4653: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4654: $needsrelease,
4655: $cmajor,$cminor);
4656: }
4657: }
4658: if ($namematch ne '') {
4659: if ($needsnewer) {
4660: undef($namematch);
1.560 damieng 4661: } else {
1.563 damieng 4662: my $currneeded;
4663: if ($needsrelease) {
4664: $currneeded = $needsrelease;
4665: }
4666: $needsrelease =
4667: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4668: if (($needsrelease) &&
4669: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4670: unless ($got_chostname) {
4671: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4672: $got_chostname = 1;
4673: }
4674: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4675: $namematch, $needsrelease,$cmajor,$cminor);
4676: } else {
4677: undef($namematch);
4678: }
1.560 damieng 4679: }
1.557 raeburn 4680: }
1.563 damieng 4681: if ($needsnewer) {
4682: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4683: $chostname,$cmajor,
4684: $cminor,$needsrelease));
4685: next;
4686: }
1.504 raeburn 4687: }
1.576 raeburn 4688: my ($reconlychg,$haschange,$storekey);
4689: if ($tuname) {
4690: my $ustorekey;
4691: if ($altkey) {
4692: if ($recursive) {
4693: if (exists($$olddata{$thiskey})) {
4694: if ($$olddata{$thiskey} eq $data) {
4695: $reconlychg = 1;
4696: }
4697: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4698: }
4699: if (exists($$olddata{$altkey})) {
4700: if (defined($data) && $$olddata{$altkey} ne $data) {
4701: $haschange = 1;
4702: }
4703: } elsif ((!$reconlychg) && ($data ne '')) {
4704: $haschange = 1;
4705: }
4706: $ustorekey = $tkeyrec;
4707: } else {
4708: if (exists($$olddata{$altkey})) {
4709: if ($$olddata{$altkey} eq $data) {
4710: $reconlychg = 1;
4711: }
4712: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4713: }
4714: if (exists($$olddata{$thiskey})) {
4715: if (defined($data) && $$olddata{$thiskey} ne $data) {
4716: $haschange = 1;
4717: }
4718: } elsif ((!$reconlychg) && ($data ne '')) {
4719: $haschange = 1;
4720: }
4721: $ustorekey = $tkeynonrec;
4722: }
4723: } else {
4724: if (exists($$olddata{$tkey})) {
4725: if (defined($data) && $$olddata{$tkey} ne $data) {
4726: $haschange = 1;
4727: }
4728: $ustorekey = $tkey;
4729: }
4730: }
4731: if ($haschange || $reconlychg) {
4732: unless ($env{'form.del_'.$thiskey}) {
4733: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4734: $ustorekey.'.type' => $typeof},
4735: $tudom,$tuname) eq 'ok') {
4736: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4737: $r->print('<br />'.$text.' '.
4738: &Apache::loncommon::plainname($tuname,$tudom));
4739: } else {
4740: $r->print('<div class="LC_error">'.
4741: &mt('Error saving parameters').'</div>');
4742: }
4743: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4744: }
4745: }
4746: } else {
4747: if ($altkey) {
4748: if ($recursive) {
4749: if (exists($$olddata{$thiskey})) {
4750: if ($$olddata{$thiskey} eq $data) {
4751: $reconlychg = 1;
4752: }
4753: push(@delnonrec,($thiskey,$thiskey.'.type'));
4754: }
4755: if (exists($$olddata{$altkey})) {
4756: if (defined($data) && $$olddata{$altkey} ne $data) {
4757: $haschange = 1;
4758: }
4759: } elsif (($data ne '') && (!$reconlychg)) {
4760: $haschange = 1;
4761: }
4762: $storekey = $altkey;
1.563 damieng 4763: } else {
1.576 raeburn 4764: if (exists($$olddata{$altkey})) {
4765: if ($$olddata{$altkey} eq $data) {
4766: $reconlychg = 1;
4767: }
4768: push(@delrec,($altkey,$altkey.'.type'));
4769: }
4770: if (exists($$olddata{$thiskey})) {
4771: if (defined($data) && $$olddata{$thiskey} ne $data) {
4772: $haschange = 1;
4773: }
4774: } elsif (($data ne '') && (!$reconlychg)) {
4775: $haschange = 1;
4776: }
4777: $storekey = $thiskey;
1.563 damieng 4778: }
1.560 damieng 4779: } else {
1.576 raeburn 4780: if (defined($data) && $$olddata{$thiskey} ne $data) {
4781: $haschange = 1;
4782: $storekey = $thiskey;
4783: }
4784: }
4785: }
4786: if ($reconlychg || $haschange) {
4787: unless ($env{'form.del_'.$thiskey}) {
4788: $newdata{$storekey}=$data;
4789: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4790: }
4791: }
4792: } elsif ($cmd eq 'del') {
4793: if ($tuname) {
1.576 raeburn 4794: my $error;
4795: if ($altkey) {
4796: if (exists($$olddata{$altkey})) {
4797: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4798: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4799: if ($recursive) {
4800: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4801: }
4802: } elsif ($recursive) {
4803: $error = 1;
4804: }
4805: }
4806: if (exists($$olddata{$thiskey})) {
4807: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4808: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4809: unless ($recursive) {
4810: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4811: }
4812: } elsif (!$recursive) {
4813: $error = 1;
4814: }
4815: }
1.560 damieng 4816: } else {
1.576 raeburn 4817: if (exists($$olddata{$thiskey})) {
4818: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4819: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4820: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4821: } else {
4822: $error = 1;
4823: }
4824: }
4825: }
4826: if ($error) {
1.560 damieng 4827: $r->print('<div class="LC_error">'.
4828: &mt('Error deleting parameters').'</div>');
4829: }
4830: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4831: } else {
1.576 raeburn 4832: if ($altkey) {
4833: if (exists($$olddata{$altkey})) {
4834: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4835: push(@deldata,($altkey,$altkey.'.type'));
4836: }
4837: }
4838: if (exists($$olddata{$thiskey})) {
4839: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4840: push(@deldata,($thiskey,$thiskey.'.type'));
4841: }
4842: }
4843: } elsif (exists($$olddata{$thiskey})) {
4844: push(@deldata,($thiskey,$thiskey.'.type'));
4845: }
1.560 damieng 4846: }
1.473 amueller 4847: }
4848: }
4849: }
1.207 www 4850: # Store all course level
1.144 www 4851: my $delentries=$#deldata+1;
1.576 raeburn 4852: my @alldels;
4853: if (@delrec) {
4854: push(@alldels,@delrec);
4855: }
4856: if (@delnonrec) {
4857: push(@alldels,@delnonrec);
4858: }
4859: if (@deldata) {
4860: push(@alldels,@deldata);
4861: }
1.548 raeburn 4862: my @newdatakeys=keys(%newdata);
1.144 www 4863: my $putentries=$#newdatakeys+1;
1.576 raeburn 4864: my ($delresult,$devalidate);
4865: if (@alldels) {
4866: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4867: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4868: &log_parmset(\%loghash,1);
1.576 raeburn 4869: if ($delentries) {
4870: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4871: }
4872: } elsif ($delentries) {
1.560 damieng 4873: $r->print('<div class="LC_error">'.
4874: &mt('Error deleting parameters').'</div>');
4875: }
1.576 raeburn 4876: $devalidate = 1;
1.144 www 4877: }
4878: if ($putentries) {
1.560 damieng 4879: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4880: &log_parmset(\%newdata,0);
4881: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4882: } else {
4883: $r->print('<div class="LC_error">'.
4884: &mt('Error saving parameters').'</div>');
4885: }
1.576 raeburn 4886: $devalidate = 1;
4887: }
4888: if ($devalidate) {
1.560 damieng 4889: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4890: }
1.208 www 4891: }
1.207 www 4892:
1.563 damieng 4893: # Returns the username and domain from a key created in readdata from a resourcedata key.
4894: #
4895: # @param {string} $key - the key
4896: # @returns {Array}
1.208 www 4897: sub extractuser {
4898: my $key=shift;
1.350 albertel 4899: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4900: }
1.206 www 4901:
1.563 damieng 4902: # Parses a parameter key and returns the components.
4903: #
4904: # @param {string} $key -
4905: # @param {hash reference} $listdata -
4906: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4907: sub parse_listdata_key {
4908: my ($key,$listdata) = @_;
4909: # split into student/section affected, and
4910: # the realm (folder/resource part and parameter
1.446 bisitz 4911: my ($student,$realm) =
1.473 amueller 4912: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4913: # if course wide student would be undefined
4914: if (!defined($student)) {
1.560 damieng 4915: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4916: }
4917: # strip off the .type if it's not the Question type parameter
4918: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4919: $realm=~s/\.type//;
1.381 albertel 4920: }
4921: # split into resource+part and parameter name
1.388 albertel 4922: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4923: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4924: return ($student,$res,$part,$parm);
4925: }
4926:
1.563 damieng 4927: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
4928: #
4929: # @param {Apache2::RequestRec} $r - the Apache request
4930: # @param {hash reference} $resourcedata - parameter data returned by readdata
4931: # @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
4932: # @param {string} $sortorder - realmstudent|studentrealm
4933: # @param {string} $caller - name of the calling sub (overview|newoverview)
4934: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 4935: # @param {boolean} $readonly - true if editing not allowed
1.608 raeburn 4936: # @param {string} $parmlev - full|map
4937: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order
4938: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 4939: # @returns{integer} - number of $listdata parameters processed
1.208 www 4940: sub listdata {
1.608 raeburn 4941: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552 raeburn 4942:
1.207 www 4943: # Start list output
1.206 www 4944:
1.122 www 4945: my $oldsection='';
4946: my $oldrealm='';
4947: my $oldpart='';
1.123 www 4948: my $pointer=0;
1.124 www 4949: $tableopen=0;
1.145 www 4950: my $foundkeys=0;
1.248 albertel 4951: my %keyorder=&standardkeyorder();
1.594 raeburn 4952: my $readonlyall = $readonly;
1.381 albertel 4953:
1.552 raeburn 4954: my ($secidx,%grouphash);
4955: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4956: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 4957: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4958: %grouphash = &Apache::longroup::coursegroups();
4959: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 4960: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 4961: }
1.552 raeburn 4962: }
4963:
1.576 raeburn 4964: foreach my $key (sort {
1.560 damieng 4965: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
4966: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608 raeburn 4967: my ($aid,$bid);
4968: if ($caller eq 'newoverview') {
4969: if (ref($hash_for_realm) eq 'HASH') {
4970: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4971: my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4972: my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4973: $aid = $hash_for_realm->{$aurl};
4974: $bid = $hash_for_realm->{$burl};
4975: } elsif ($parmlev eq 'full') {
4976: $aid = $hash_for_realm->{$ares};
4977: $bid = $hash_for_realm->{$bres};
4978: }
4979: }
4980: }
1.381 albertel 4981:
1.560 damieng 4982: # get the numerical order for the param
4983: $aparm=$keyorder{'parameter_0_'.$aparm};
4984: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 4985:
1.560 damieng 4986: my $result=0;
1.381 albertel 4987:
1.560 damieng 4988: if ($sortorder eq 'realmstudent') {
1.381 albertel 4989: if ($ares ne $bres ) {
1.608 raeburn 4990: if ($caller eq 'newoverview') {
4991: if (ref($hash_for_realm) eq 'HASH') {
4992: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4993: $result = ($aid <=> $bid);
4994: } elsif ($parmlev eq 'full') {
4995: $result = ($aid <=> $bid);
4996: } else {
4997: $result = ($ares cmp $bres);
4998: }
4999: } else {
5000: $result = ($ares cmp $bres);
5001: }
5002: } else {
5003: $result = ($ares cmp $bres);
5004: }
1.446 bisitz 5005: } elsif ($astudent ne $bstudent) {
1.560 damieng 5006: $result = ($astudent cmp $bstudent);
5007: } elsif ($apart ne $bpart ) {
5008: $result = ($apart cmp $bpart);
5009: }
5010: } else {
5011: if ($astudent ne $bstudent) {
5012: $result = ($astudent cmp $bstudent);
5013: } elsif ($ares ne $bres ) {
1.608 raeburn 5014: if ($caller eq 'newoverview') {
5015: if (ref($hash_for_realm) eq 'HASH') {
5016: if (($parmlev eq 'map') && ($pschp eq 'all')) {
5017: $result = ($aid <=> $bid);
5018: } elsif ($parmlev eq 'full') {
5019: $result = ($aid <=> $bid);
5020: } else {
5021: $result = ($ares cmp $bres);
5022: }
5023: } else {
5024: $result = ($ares cmp $bres);
5025: }
5026: } else {
5027: $result = ($ares cmp $bres);
5028: }
1.560 damieng 5029: } elsif ($apart ne $bpart ) {
5030: $result = ($apart cmp $bpart);
5031: }
1.473 amueller 5032: }
1.446 bisitz 5033:
1.560 damieng 5034: if (!$result) {
1.381 albertel 5035: if (defined($aparm) && defined($bparm)) {
1.560 damieng 5036: $result = ($aparm <=> $bparm);
1.381 albertel 5037: } elsif (defined($aparm)) {
1.560 damieng 5038: $result = -1;
1.381 albertel 5039: } elsif (defined($bparm)) {
1.560 damieng 5040: $result = 1;
5041: }
1.473 amueller 5042: }
1.381 albertel 5043:
1.560 damieng 5044: $result;
5045:
1.576 raeburn 5046: } keys(%{$listdata})) { # foreach my $key
5047: my $thiskey = $key;
1.560 damieng 5048: if ($$listdata{$thiskey.'.type'}) {
5049: my $thistype=$$listdata{$thiskey.'.type'};
5050: if ($$resourcedata{$thiskey.'.type'}) {
5051: $thistype=$$resourcedata{$thiskey.'.type'};
5052: }
5053: my ($middle,$part,$name)=
1.572 damieng 5054: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 5055: my $section=&mt('All Students');
1.594 raeburn 5056: $readonly = $readonlyall;
1.599 raeburn 5057: my $userscope;
1.576 raeburn 5058: my $showval = $$resourcedata{$thiskey};
1.560 damieng 5059: if ($middle=~/^\[(.*)\]/) {
5060: my $issection=$1;
5061: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
5062: my ($stuname,$studom) = ($1,$2);
5063: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
5064: if (ref($classlist) eq 'HASH') {
5065: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
5066: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
5067: }
5068: }
5069: }
5070: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 5071: $userscope = 1;
1.560 damieng 5072: } else {
5073: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
5074: if (exists($grouphash{$issection})) {
5075: $section=&mt('Group').': '.$issection;
5076: } elsif ($issection eq $env{'request.course.sec'}) {
5077: $section = &mt('Section').': '.$issection;
5078: } else {
5079: next;
1.552 raeburn 5080: }
1.560 damieng 5081: } else {
5082: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 5083: }
5084: }
1.560 damieng 5085: $middle=~s/^\[(.*)\]//;
5086: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
5087: $readonly = 1;
5088: }
5089: $middle=~s/\.+$//;
5090: $middle=~s/^\.+//;
5091: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 5092: my ($is_map,$is_recursive,$mapurl,$maplevel);
5093: if ($caller eq 'overview') {
5094: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
5095: $mapurl = $1;
5096: $maplevel = $2;
5097: $is_map = 1;
5098: }
5099: } elsif ($caller eq 'newoverview') {
5100: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
5101: $mapurl = $1;
5102: $maplevel = $2;
5103: $is_map = 1;
5104: }
5105: }
5106: if ($is_map) {
1.560 damieng 5107: my $leveltitle = &mt('Folder/Map');
1.615 raeburn 5108: my $title = &Apache::lonnet::gettitle($mapurl);
1.608 raeburn 5109: if (ref($hash_for_realm) eq 'HASH') {
5110: if ($hash_for_realm->{$mapurl} eq '1') {
5111: $title = &mt('Main Content');
5112: }
5113: }
1.576 raeburn 5114: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
5115: if ($caller eq 'newoverview') {
5116: my $altkey = $thiskey;
5117: $altkey =~ s/\Q___(all)\E/___(rec)/;
5118: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
5119: $is_recursive = 1;
5120: if ($$resourcedata{$altkey.'.type'}) {
5121: $thistype=$$resourcedata{$altkey.'.type'};
5122: }
5123: $showval = $$resourcedata{$altkey};
5124: }
5125: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
5126: $thiskey =~ s/\Q___(rec)\E/___(all)/;
5127: $is_recursive = 1;
5128: }
1.560 damieng 5129: }
1.608 raeburn 5130: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560 damieng 5131: } elsif ($middle) {
5132: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609 raeburn 5133: next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560 damieng 5134: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
5135: ': '.&Apache::lonnet::gettitle($middle).
5136: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
5137: $id.')</span></span>';
5138: }
5139: if ($sortorder eq 'realmstudent') {
5140: if ($realm ne $oldrealm) {
5141: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
5142: $oldrealm=$realm;
5143: $oldsection='';
5144: }
5145: if ($section ne $oldsection) {
5146: $r->print(&tableend()."\n<h2>$section</h2>");
5147: $oldsection=$section;
5148: $oldpart='';
5149: }
1.552 raeburn 5150: } else {
1.560 damieng 5151: if ($section ne $oldsection) {
5152: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
5153: $oldsection=$section;
5154: $oldrealm='';
5155: }
5156: if ($realm ne $oldrealm) {
5157: $r->print(&tableend()."\n<h2>$realm</h2>");
5158: $oldrealm=$realm;
5159: $oldpart='';
1.552 raeburn 5160: }
5161: }
1.560 damieng 5162: if ($part ne $oldpart) {
5163: $r->print(&tableend().
5164: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
5165: $oldpart=$part;
1.556 raeburn 5166: }
1.560 damieng 5167: #
5168: # Ready to print
5169: #
1.470 raeburn 5170: my $parmitem = &standard_parameter_names($name);
1.619 raeburn 5171: my $advice;
5172: if (($name eq 'mapalias') && ($middle) && (!$is_map)) {
5173: if ($middle =~ m{^uploaded/}) {
5174: $advice = &mt('Use Course Editor to set this.');
5175: } else {
5176: $advice = &mt('Use Resource Assembly Tool to set this.');
5177: }
5178: $advice = '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
5179: }
1.576 raeburn 5180: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 5181: &Apache::loncommon::start_data_table_row().
5182: '<td><b>'.&mt($parmitem).
1.619 raeburn 5183: '</b>'.$advice.'</td>');
1.560 damieng 5184: unless ($readonly) {
1.599 raeburn 5185: my $disabled;
5186: if (($name eq 'availablestudent') &&
5187: (($showval eq '') || ($userscope))) {
5188: $disabled = ' disabled="disabled"';
1.619 raeburn 5189: } elsif (($name eq 'mapalias') && ($showval eq '')) {
5190: $disabled = ' disabled="disabled"';
1.599 raeburn 5191: }
1.560 damieng 5192: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 5193: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 5194: }
5195: $r->print('<td>');
5196: $foundkeys++;
5197: if (&isdateparm($thistype)) {
5198: my $jskey='key_'.$pointer;
5199: my $state;
5200: $pointer++;
5201: if ($readonly) {
5202: $state = 'disabled';
5203: }
5204: $r->print(
5205: &Apache::lonhtmlcommon::date_setter('parmform',
5206: $jskey,
1.576 raeburn 5207: $showval,
1.560 damieng 5208: '',1,$state));
5209: unless ($readonly) {
5210: $r->print(
5211: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 5212: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 5213: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 5214: &date_sanity_info($showval)
1.560 damieng 5215: );
5216: }
5217: } elsif ($thistype eq 'date_interval') {
5218: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 5219: $showval,$readonly));
1.560 damieng 5220: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 5221: if ($name eq 'availablestudent') {
5222: $readonly = 1;
1.619 raeburn 5223: } elsif (($name eq 'mapalias') && ($showval eq '')) {
5224: $readonly = 1;
1.599 raeburn 5225: }
1.560 damieng 5226: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 5227: $showval,$name,$readonly));
1.560 damieng 5228: } else {
1.576 raeburn 5229: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 5230: }
1.560 damieng 5231: unless ($readonly) {
5232: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
5233: $thistype.'" />');
1.552 raeburn 5234: }
1.576 raeburn 5235: $r->print('</td>');
5236: if ($is_map) {
5237: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
5238: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
5239: } else {
5240: my ($disabled,$recon,$recoff);
5241: if ($readonly) {
5242: $disabled = ' disabled="disabled"';
5243: }
5244: if ($is_recursive) {
5245: $recon = ' checked="checked"';
5246: } else {
5247: $recoff = ' checked="checked"';
5248: }
5249: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
5250: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
5251: }
5252: }
5253: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 5254: }
1.121 www 5255: }
1.208 www 5256: return $foundkeys;
5257: }
5258:
1.563 damieng 5259: # Returns a string representing the interval, directly using form data matching the given key.
5260: # The returned string may also include information related to proctored exams.
5261: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
5262: #
5263: # @param {string} $key - suffix for form fields related to the interval
5264: # @returns {string}
1.385 albertel 5265: sub get_date_interval_from_form {
5266: my ($key) = @_;
5267: my $seconds = 0;
1.611 raeburn 5268: my $numnotnull = 0;
1.385 albertel 5269: foreach my $which (['days', 86400],
1.473 amueller 5270: ['hours', 3600],
5271: ['minutes', 60],
5272: ['seconds', 1]) {
1.560 damieng 5273: my ($name, $factor) = @{ $which };
5274: if (defined($env{'form.'.$name.'_'.$key})) {
1.611 raeburn 5275: unless ($env{'form.'.$name.'_'.$key} eq '') {
5276: $numnotnull ++;
5277: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
5278: }
1.560 damieng 5279: }
1.473 amueller 5280: }
1.560 damieng 5281: if (($key =~ /\.interval$/) &&
5282: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 5283: if ($env{'form.done_'.$key.'_buttontext'}) {
5284: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
5285: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
5286: if ($env{'form.done_'.$key} eq '_done_proctor') {
5287: $seconds .= '_proctor';
5288: }
5289: } else {
5290: $seconds .= $env{'form.done_'.$key};
5291: }
5292: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 5293: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 5294: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
5295: }
1.554 raeburn 5296: }
1.611 raeburn 5297: return if (!$numnotnull);
1.385 albertel 5298: return $seconds;
5299: }
5300:
5301:
1.563 damieng 5302: # Returns HTML to enter a text value for a parameter.
5303: #
5304: # @param {string} $thiskey - parameter key
5305: # @param {string} $showval - the current value
5306: # @param {boolean} $readonly - true if the field should not be made editable
5307: # @returns {string}
1.383 albertel 5308: sub default_selector {
1.552 raeburn 5309: my ($thiskey, $showval, $readonly) = @_;
5310: my $disabled;
5311: if ($readonly) {
5312: $disabled = ' disabled="disabled"';
5313: }
5314: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 5315: }
5316:
1.563 damieng 5317: # Returns HTML to enter allow/deny rules related to IP addresses.
5318: #
5319: # @param {string} $thiskey - parameter key
5320: # @param {string} $showval - the current value
5321: # @param {boolean} $readonly - true if the fields should not be made editable
5322: # @returns {string}
1.549 raeburn 5323: sub string_ip_selector {
1.552 raeburn 5324: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 5325: my %access = (
5326: allow => [],
5327: deny => [],
5328: );
5329: if ($showval ne '') {
5330: my @current;
5331: if ($showval =~ /,/) {
5332: @current = split(/,/,$showval);
5333: } else {
5334: @current = ($showval);
5335: }
5336: foreach my $item (@current) {
5337: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
5338: push(@{$access{'deny'}},$1);
5339: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
5340: push(@{$access{'allow'}},$item);
5341: }
5342: }
5343: }
5344: if (!@{$access{'allow'}}) {
5345: @{$access{'allow'}} = ('');
5346: }
5347: if (!@{$access{'deny'}}) {
5348: @{$access{'deny'}} = ('');
5349: }
1.552 raeburn 5350: my ($disabled,$addmore);
1.567 raeburn 5351: if ($readonly) {
1.552 raeburn 5352: $disabled=' disabled="disabled"';
5353: } else {
5354: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5355: }
1.549 raeburn 5356: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5357: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5358: foreach my $acctype ('allow','deny') {
5359: $output .= '
5360: <td valign="top">
5361: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5362: <div class="LC_string_ipacc_inner">'."\n";
5363: my $num = 0;
5364: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5365: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5366: if ($num > 0) {
5367: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5368: }
5369: $output .= '</div>'."\n";
5370: $num ++;
5371: }
5372: $output .= '
1.552 raeburn 5373: </div>'.$addmore.'
1.549 raeburn 5374: </div>
5375: </td>';
5376: }
5377: $output .= '
5378: </tr>
5379: </table>'."\n";
5380: return $output;
5381: }
5382:
1.588 raeburn 5383: sub string_deeplink_selector {
5384: my ($thiskey, $showval, $readonly) = @_;
1.616 raeburn 5385: my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
5386: %selectnull,%domlti,%crslti,@possmenus,%components);
5387: @tables = ('upper','lower');
5388: %components = (
5389: upper => ['state','others','listing','scope'],
5390: lower => ['protect','menus','target','exit'],
5391: );
1.588 raeburn 5392: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5393: state => 'Access status',
5394: others => 'Hide other resources',
1.588 raeburn 5395: listing => 'In Contents and/or Gradebook',
5396: scope => 'Access scope for link',
1.601 raeburn 5397: protect => 'Link protection',
1.597 raeburn 5398: menus => 'Menu Items Displayed',
1.613 raeburn 5399: target => 'Embedded?',
1.616 raeburn 5400: exit => 'Exit Tool Button?',
1.588 raeburn 5401: );
5402: %options = (
1.601 raeburn 5403: state => ['only','off','both'],
5404: others => ['hide','unhide'],
1.588 raeburn 5405: listing => ['full','absent','grades','details','datestatus'],
5406: scope => ['res','map','rec'],
1.601 raeburn 5407: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5408: menus => ['std','colls'],
1.613 raeburn 5409: target => ['_self','_top'],
1.616 raeburn 5410: exit => ['no','yes','url'],
1.588 raeburn 5411: );
5412: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5413: only => 'deep only',
5414: off => 'deeplink off',
5415: both => 'regular + deep',
5416: hide => 'Hidden',
5417: unhide => 'Unhidden',
1.588 raeburn 5418: full => 'Listed (linked) in both',
5419: absent => 'Not listed',
5420: grades => 'Listed in grades only',
5421: details => 'Listed (unlinked) in both',
5422: datestatus => 'Listed (unlinked) inc. status in both',
5423: res => 'resource only',
5424: map => 'enclosing map/folder',
5425: rec => 'recursive map/folder',
1.601 raeburn 5426: none => 'not in use',
5427: key => 'key access',
5428: ltic => 'LTI access (course)',
5429: ltid => 'LTI access (domain)' ,
1.597 raeburn 5430: std => 'Standard (all menus)',
5431: colls => 'Numbered collection',
1.614 raeburn 5432: _self => 'Embedded',
1.613 raeburn 5433: _top => 'Not embedded',
1.616 raeburn 5434: no => 'Not in use',
5435: yes => 'In use, no URL redirect',
5436: url => 'In use, redirect to URL',
1.597 raeburn 5437: );
5438: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5439: ltic => 'Select Launcher',
5440: ltid => 'Select Launcher',
1.597 raeburn 5441: colls => 'Select',
1.588 raeburn 5442: );
5443: if ($showval =~ /,/) {
1.597 raeburn 5444: %values=();
1.588 raeburn 5445: @current = split(/,/,$showval);
1.601 raeburn 5446: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5447: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5448: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5449: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5450: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5451: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613 raeburn 5452: ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616 raeburn 5453: ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588 raeburn 5454: } else {
1.601 raeburn 5455: $defaults{'state'} = 'off',
5456: $defaults{'others'} = 'unhide',
1.588 raeburn 5457: $defaults{'listing'} = 'full';
5458: $defaults{'scope'} = 'res';
1.601 raeburn 5459: $defaults{'protect'} = 'none';
1.597 raeburn 5460: $defaults{'menus'} = '0';
1.613 raeburn 5461: $defaults{'target'} = '_top';
1.616 raeburn 5462: $defaults{'exit'} = 'yes';
1.588 raeburn 5463: }
5464: my $disabled;
5465: if ($readonly) {
5466: $disabled=' disabled="disabled"';
5467: }
1.601 raeburn 5468: my %courselti =
5469: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
1.620 raeburn 5470: $env{'course.'.$env{'request.course.id'}.'.domain'},
5471: 'provider');
1.601 raeburn 5472: foreach my $item (keys(%courselti)) {
5473: if (ref($courselti{$item}) eq 'HASH') {
5474: $crslti{$item} = $courselti{$item}{'name'};
5475: }
5476: }
5477: my %lti =
1.588 raeburn 5478: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 5479: 'linkprot');
1.588 raeburn 5480: foreach my $item (keys(%lti)) {
1.604 raeburn 5481: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
5482: $domlti{$item} = $lti{$item}{'name'};
1.588 raeburn 5483: }
5484: }
1.597 raeburn 5485: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5486: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5487: my ($num,$value) = split(/\%/,$item);
5488: if ($num =~ /^\d+$/) {
5489: push(@possmenus,$num);
5490: }
5491: }
5492: }
5493:
1.616 raeburn 5494: my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
5495: foreach my $table ('upper','lower') {
5496: next unless (ref($components{$table}) eq 'ARRAY');
5497: $output .= '<table width="100%"><tr>';
5498: foreach my $item (@{$components{$table}}) {
5499: $output .= '<th>'.$titles{$item}.'</th>';
5500: }
5501: $output .= '</tr><tr>';
5502: foreach my $item (@{$components{$table}}) {
5503: $output .= '<td>';
5504: if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
5505: my $selected = $values{$item};
5506: foreach my $option (@{$options{$item}}) {
5507: if ($item eq 'protect') {
5508: if ($option eq 'ltid') {
5509: next unless (keys(%domlti));
5510: } elsif ($option eq 'ltic') {
5511: next unless (keys(%crslti));
5512: }
5513: } elsif (($item eq 'menus') && ($option eq 'colls')) {
5514: next unless (@possmenus);
5515: }
5516: my $checked;
5517: if ($item eq 'menus') {
5518: if (($selected =~ /^\d+$/) && (@possmenus) &&
5519: (grep(/^\Q$selected\E$/,@possmenus))) {
5520: if ($option eq 'colls') {
5521: $checked = ' checked="checked"';
5522: }
5523: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597 raeburn 5524: $checked = ' checked="checked"';
5525: }
1.616 raeburn 5526: } elsif ($selected =~ /^\Q$option\E/) {
1.597 raeburn 5527: $checked = ' checked="checked"';
5528: }
1.616 raeburn 5529: my $onclick;
5530: unless ($readonly) {
5531: my $esc_key = &js_escape($thiskey);
5532: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
5533: }
5534: $output .= '<span class="LC_nobreak"><label>'.
5535: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
5536: $optiontext{$option}.'</label>';
5537: if (($item eq 'protect') && ($option eq 'key')) {
5538: my $visibility="hidden";
5539: my $currkey;
5540: if ($checked) {
5541: $visibility = "text";
5542: $currkey = (split(/\:/,$values{$item}))[1];
5543: }
5544: $output .= ' '.
5545: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
5546: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
5547: my $display="none";
5548: my ($current,$blankcheck,@possibles);
5549: if ($checked) {
5550: $display = 'inline-block';
5551: if (($option eq 'ltic') || ($option eq 'ltid')) {
5552: $current = (split(/\:/,$selected))[1];
5553: } else {
5554: $current = $selected;
5555: }
1.597 raeburn 5556: } else {
1.616 raeburn 5557: $blankcheck = ' selected="selected"';
1.597 raeburn 5558: }
1.601 raeburn 5559: if ($option eq 'ltid') {
1.616 raeburn 5560: @possibles = keys(%domlti);
1.601 raeburn 5561: } elsif ($option eq 'ltic') {
1.616 raeburn 5562: @possibles = keys(%crslti);
5563: } else {
5564: @possibles = @possmenus;
5565: }
5566: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
5567: ' style="display: '.$display.'"> <select name="'.
5568: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
5569: if (@possibles > 1) {
5570: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
5571: '</option>'."\n";
5572: }
5573: foreach my $poss (sort { $a <=> $b } @possibles) {
5574: my $selected;
5575: if (($poss == $current) || (scalar(@possibles) ==1)) {
5576: $selected = ' selected="selected"';
5577: }
5578: my $shown = $poss;
5579: if ($option eq 'ltid') {
5580: $shown = $domlti{$poss};
5581: } elsif ($option eq 'ltic') {
5582: $shown = $crslti{$poss};
5583: }
5584: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
5585: }
5586: $output .= '</select></div>';
5587: }
5588: $output .= '</span> ';
5589: }
5590: if ($item eq 'exit') {
5591: my $exitsty = 'none';
5592: my $displayval;
5593: if ($values{$item} =~ /^(yes|url)/) {
5594: $exitsty = 'inline-block';
5595: my $currval = (split(/\:/,$values{$item}))[1];
5596: if ($currval eq '') {
5597: $displayval = 'Exit Tool';
5598: } else {
5599: $displayval = $currval;
1.597 raeburn 5600: }
1.588 raeburn 5601: }
1.616 raeburn 5602: $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
5603: ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
5604: '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
5605: ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
5606: ' size="10"'.$disabled.' /></div>';
1.588 raeburn 5607: }
1.616 raeburn 5608: } else {
5609: my $selected = $values{$item};
5610: my $defsel;
5611: if ($selected eq '') {
5612: $defsel = ' selected="selected"';
5613: }
5614: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
5615: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
5616: foreach my $option (@{$options{$item}}) {
5617: $output .= '<option value="'.$option.'"';
5618: if ($option eq $selected) {
5619: $output .= ' selected="selected"';
5620: }
5621: $output .= '>'.$optiontext{$option}.'</option>';
1.588 raeburn 5622: }
1.616 raeburn 5623: $output .= '</select>';
1.588 raeburn 5624: }
1.616 raeburn 5625: $output .= '</td>';
5626: }
5627: $output .= '</tr></table>'."\n";
5628: if ($table eq 'upper') {
5629: $output .= '<br />';
1.588 raeburn 5630: }
5631: }
5632: return $output;
5633: }
5634:
1.622 ! raeburn 5635: sub string_grace_selector {
! 5636: my ($thiskey, $showval, $readonly) = @_;
! 5637: my $addmore;
! 5638: unless ($readonly) {
! 5639: $addmore = "\n".'<button class="LC_add_grace_button">'.&mt('Add more').'</button>';
! 5640: }
! 5641: my $output = '<input type="hidden" name="set_'.$thiskey.'" value="" />'.
! 5642: '<div class="LC_string_grace_wrap" id="LC_string_grace_'.$thiskey.'">'."\n".
! 5643: '<div class="LC_string_grace_inner">'."\n";
! 5644: if ($showval ne '') {
! 5645: my @current;
! 5646: if ($showval =~ /,/) {
! 5647: @current = split(/,/,$showval);
! 5648: } else {
! 5649: @current = ($showval);
! 5650: }
! 5651: my $num = scalar(@current);
! 5652: foreach my $item (@current) {
! 5653: my ($delta,$fraction,$gradational) = split(/:/,$item);
! 5654: if (($delta =~ /^\d+$/) && ($fraction =~ /^(0|1)\.?\d*$/) &&
! 5655: (($gradational eq 1) || ($gradational eq '0'))) {
! 5656: my $gradchk = '';
! 5657: if ($gradational) {
! 5658: $gradchk = ' checked="checked"';
! 5659: }
! 5660: $output .= &grace_form($thiskey,$delta,$fraction,$gradchk,
! 5661: $readonly);
! 5662: }
! 5663: }
! 5664: } elsif (!$readonly) {
! 5665: $output .= &grace_form($thiskey,'','','',$readonly);
! 5666: }
! 5667: $output .= '</div>'.$addmore.'</div>';
! 5668: return $output;
! 5669: }
! 5670:
! 5671: sub grace_form {
! 5672: my ($thiskey,$delta,$fraction,$gradchkon,$readonly) = @_;
! 5673: my $disabled;
! 5674: if ($readonly) {
! 5675: $disabled = ' disabled="disabled"';
! 5676: }
! 5677: my %lt = &grace_titles();
! 5678: my $output = '<div><input type="hidden" name="setgrace_'.$thiskey.'" value="" />'.
! 5679: '<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
! 5680: foreach my $which (['days', 86400, 31],
! 5681: ['hours', 3600, 23],
! 5682: ['minutes', 60, 59],
! 5683: ['seconds', 1, 59]) {
! 5684: my ($name, $factor, $max) = @{ $which };
! 5685: my $amount;
! 5686: if ($delta ne '') {
! 5687: $amount = int($delta/$factor);
! 5688: $delta %= $factor;
! 5689: }
! 5690: my %select = ((map {$_ => $_} (0..$max)),
! 5691: 'select_form_order' => [0..$max]);
! 5692: $output .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
! 5693: \%select,'',$readonly);
! 5694: $output .= ' '.$lt{$name}.' ';
! 5695: }
! 5696: $output .= '</fieldset>'.
! 5697: '<fieldset class="LC_grace"><legend>'.$lt{'pcr'}.'</legend>'.
! 5698: '<input type="text" size="3" name="frac_'.$thiskey.'" value="'.$fraction.'"'.$disabled.' />'.
! 5699: ' <label><input type="checkbox" value="1" name="grad_'.$thiskey.'"'.$gradchkon.$disabled.' />'.
! 5700: $lt{'grad'}.'</label></fieldset>';
! 5701: unless ($readonly) {
! 5702: $output .= '<a href="#" class="LC_remove_grace">'.$lt{'remo'}.'</a>';
! 5703: }
! 5704: $output .= '</div>'."\n";
! 5705: return $output;
! 5706: }
! 5707:
! 5708: sub grace_titles {
! 5709: return &Apache::lonlocal::texthash (
! 5710: sinc => 'Time past due',
! 5711: remo => 'Remove',
! 5712: pcr => 'Partial credit',
! 5713: grad => 'gradual',
! 5714: days => 'days',
! 5715: hours => 'hours',
! 5716: minutes => 'minutes',
! 5717: seconds => 'seconds',
! 5718: );
! 5719: }
1.560 damieng 5720:
5721: { # block using some constants related to parameter types (overview mode)
5722:
1.446 bisitz 5723: my %strings =
1.383 albertel 5724: (
5725: 'string_yesno'
5726: => [[ 'yes', 'Yes' ],
1.560 damieng 5727: [ 'no', 'No' ]],
1.383 albertel 5728: 'string_problemstatus'
5729: => [[ 'yes', 'Yes' ],
1.473 amueller 5730: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5731: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5732: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5733: 'string_questiontype'
5734: => [[ 'problem', 'Standard Problem'],
5735: [ 'survey', 'Survey'],
5736: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5737: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5738: [ 'anonsurvey', 'Anonymous Survey'],
5739: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5740: [ 'practice', 'Practice'],
5741: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5742: 'string_lenient'
5743: => [['yes', 'Yes' ],
5744: [ 'no', 'No' ],
1.549 raeburn 5745: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5746: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5747: 'string_discussvote'
5748: => [['yes','Yes'],
5749: ['notended','Yes, unless discussion ended'],
5750: ['no','No']],
1.549 raeburn 5751: 'string_ip'
5752: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5753: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5754: 'string_deeplink'
1.616 raeburn 5755: => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.621 raeburn 5756: 'string_tex'
5757: => [['tth', 'tth (TeX to HTML)'],
5758: ['mathjax', 'MathJax']],
1.622 ! raeburn 5759: 'string_grace'
! 5760: => [['on','Set grading scale and grace period for submissions after due date']],
1.587 raeburn 5761: );
5762:
1.383 albertel 5763:
1.549 raeburn 5764: my %stringmatches = (
5765: 'string_lenient'
5766: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5767: 'string_ip'
5768: => [['_allowfrom_','[^\!]+'],
5769: ['_denyfrom_','\!']],
1.588 raeburn 5770: 'string_deeplink'
1.616 raeburn 5771: => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],
1.622 ! raeburn 5772: 'string_grace'
! 5773: => [['on','^\d+,(0|1)\.?\d*,(0|1)']],
1.549 raeburn 5774: );
5775:
5776: my %stringtypes = (
5777: type => 'string_questiontype',
5778: lenient => 'string_lenient',
5779: retrypartial => 'string_yesno',
5780: discussvote => 'string_discussvote',
5781: examcode => 'string_examcode',
5782: acc => 'string_ip',
1.587 raeburn 5783: deeplink => 'string_deeplink',
1.622 ! raeburn 5784: grace => 'string_grace',
1.621 raeburn 5785: texdisplay => 'string_tex',
1.549 raeburn 5786: );
5787:
1.563 damieng 5788: # Returns the possible values and titles for a given string type, or undef if there are none.
5789: # Used by courseprefs.
5790: #
5791: # @param {string} $string_type - a parameter type for strings
5792: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5793: sub standard_string_options {
5794: my ($string_type) = @_;
5795: if (ref($strings{$string_type}) eq 'ARRAY') {
5796: return $strings{$string_type};
5797: }
5798: return;
5799: }
1.383 albertel 5800:
1.563 damieng 5801: # Returns regular expressions to match kinds of string types, or undef if there are none.
5802: #
5803: # @param {string} $string_type - a parameter type for strings
5804: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5805: sub standard_string_matches {
5806: my ($string_type) = @_;
5807: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5808: return $stringmatches{$string_type};
5809: }
5810: return;
5811: }
5812:
1.563 damieng 5813: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5814: #
5815: # @param {string} $name - parameter name
5816: # @returns {string}
1.549 raeburn 5817: sub get_stringtype {
5818: my ($name) = @_;
5819: if (exists($stringtypes{$name})) {
5820: return $stringtypes{$name};
5821: }
5822: return;
5823: }
5824:
1.563 damieng 5825: # Returns HTML to edit a string parameter.
5826: #
5827: # @param {string} $thistype - parameter type
5828: # @param {string} $thiskey - parameter key
5829: # @param {string} $showval - parameter current value
5830: # @param {string} $name - parameter name
5831: # @param {boolean} $readonly - true if the values should not be made editable
5832: # @returns {string}
1.383 albertel 5833: sub string_selector {
1.552 raeburn 5834: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5835:
1.383 albertel 5836: if (!exists($strings{$thistype})) {
1.552 raeburn 5837: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5838: }
5839:
1.504 raeburn 5840: my %skiptype;
1.514 raeburn 5841: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5842: ($thistype eq 'string_lenient') ||
5843: ($thistype eq 'string_discussvote') ||
5844: ($thistype eq 'string_ip') ||
1.588 raeburn 5845: ($thistype eq 'string_deeplink') ||
1.621 raeburn 5846: ($thistype eq 'string_tex') ||
1.622 ! raeburn 5847: ($thistype eq 'string_grace') ||
1.560 damieng 5848: ($name eq 'retrypartial')) {
1.504 raeburn 5849: my ($got_chostname,$chostname,$cmajor,$cminor);
5850: foreach my $possibilities (@{ $strings{$thistype} }) {
5851: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5852: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5853: my $parmmatch;
5854: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5855: foreach my $item (@{$stringmatches{$thistype}}) {
5856: if (ref($item) eq 'ARRAY') {
5857: if ($parmval eq $item->[0]) {
5858: $parmmatch = $parmval;
5859: $parmval = '';
5860: last;
5861: }
5862: }
5863: }
5864: }
5865: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5866: if ($needsrelease) {
5867: unless ($got_chostname) {
1.514 raeburn 5868: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5869: $got_chostname = 1;
5870: }
1.557 raeburn 5871: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5872: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5873: if ($needsnewer) {
1.549 raeburn 5874: if ($parmmatch ne '') {
5875: $skiptype{$parmmatch} = 1;
5876: } elsif ($parmval ne '') {
5877: $skiptype{$parmval} = 1;
5878: }
1.504 raeburn 5879: }
5880: }
5881: }
5882: }
1.549 raeburn 5883:
5884: if ($thistype eq 'string_ip') {
1.622 ! raeburn 5885: return &string_ip_selector($thiskey,$showval,$readonly);
! 5886: } elsif ($thistype eq 'string_grace') {
! 5887: return &string_grace_selector($thiskey,$showval,$readonly);
1.588 raeburn 5888: } elsif ($thistype eq 'string_deeplink') {
5889: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5890: }
1.504 raeburn 5891:
1.552 raeburn 5892: my ($result,$disabled);
5893:
5894: if ($readonly) {
5895: $disabled = ' disabled="disabled"';
5896: }
1.504 raeburn 5897: my $numinrow = 3;
5898: if ($thistype eq 'string_problemstatus') {
5899: $numinrow = 2;
5900: } elsif ($thistype eq 'string_questiontype') {
5901: if (keys(%skiptype) > 0) {
5902: $numinrow = 4;
5903: }
5904: }
5905: my $rem;
5906: if (ref($strings{$thistype}) eq 'ARRAY') {
5907: my $i=0;
5908: foreach my $possibilities (@{ $strings{$thistype} }) {
5909: next unless (ref($possibilities) eq 'ARRAY');
5910: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5911: next if ($skiptype{$name});
1.504 raeburn 5912: $rem = $i%($numinrow);
5913: if ($rem == 0) {
5914: if ($i > 0) {
5915: $result .= '</tr>';
5916: }
5917: $result .= '<tr>';
5918: }
1.549 raeburn 5919: my $colspan;
5920: if ($i == @{ $strings{$thistype} }-1) {
5921: $rem = @{ $strings{$thistype} }%($numinrow);
5922: if ($rem) {
5923: my $colsleft = $numinrow - $rem;
5924: if ($colsleft) {
5925: $colspan = $colsleft+1;
5926: $colspan = ' colspan="'.$colspan.'"';
5927: }
5928: }
5929: }
5930: my ($add,$onchange,$css_class);
5931: if ($thistype eq 'string_lenient') {
5932: if ($name eq 'weighted') {
5933: my $display;
5934: my %relatives = &Apache::lonlocal::texthash(
5935: corrchkd => 'Correct (checked)',
5936: corrunchkd => 'Correct (unchecked)',
5937: incorrchkd => 'Incorrect (checked)',
5938: incorrunchkd => 'Incorrect (unchecked)',
5939: );
5940: my %textval = (
5941: corrchkd => '1.0',
5942: corrunchkd => '1.0',
5943: incorrchkd => '0.0',
5944: incorrunchkd => '0.0',
5945: );
5946: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
5947: $textval{'corrchkd'} = $1;
5948: $textval{'corrunchkd'} = $2;
5949: $textval{'incorrchkd'} = $3;
5950: $textval{'incorrunchkd'} = $4;
5951: $display = 'inline';
5952: $showval = $name;
5953: } else {
5954: $display = 'none';
5955: }
5956: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
5957: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
5958: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
5959: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
5960: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 5961: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 5962: '</td></tr>';
5963: }
5964: $add .= '</table></div>'."\n";
5965: }
5966: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
5967: $css_class = ' class="LC_lenient_radio"';
5968: }
5969: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 5970: '<span class="LC_nobreak"><label>'.
5971: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 5972: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 5973: if ($showval eq $name) {
5974: $result .= ' checked="checked"';
5975: }
1.549 raeburn 5976: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 5977: $i++;
5978: }
5979: $result .= '</tr>';
1.473 amueller 5980: }
1.504 raeburn 5981: if ($result) {
5982: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 5983: }
5984: return $result;
5985: }
5986:
1.554 raeburn 5987: my %intervals =
5988: (
5989: 'date_interval'
5990: => [[ 'done', 'Yes' ],
1.558 raeburn 5991: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 5992: [ '', 'No' ]],
5993: );
5994:
5995: my %intervalmatches = (
5996: 'date_interval'
1.559 raeburn 5997: => [['done','\d+_done(|\:[^\:]+\:)$'],
5998: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 5999: );
6000:
6001: my %intervaltypes = (
6002: interval => 'date_interval',
6003: );
6004:
1.563 damieng 6005: # Returns regular expressions to match kinds of interval type, or undef if there are none.
6006: #
6007: # @param {string} $interval_type - a parameter type for intervals
6008: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 6009: sub standard_interval_matches {
6010: my ($interval_type) = @_;
6011: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
6012: return $intervalmatches{$interval_type};
6013: }
6014: return;
6015: }
6016:
1.563 damieng 6017: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
6018: #
6019: # @param {string} $name - parameter name
6020: # @returns {string}
1.554 raeburn 6021: sub get_intervaltype {
6022: my ($name) = @_;
6023: if (exists($intervaltypes{$name})) {
6024: return $intervaltypes{$name};
6025: }
6026: return;
6027: }
6028:
1.563 damieng 6029: # Returns the possible values and titles for a given interval type, or undef if there are none.
6030: # Used by courseprefs.
6031: #
6032: # @param {string} $interval_type - a parameter type for intervals
6033: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 6034: sub standard_interval_options {
6035: my ($interval_type) = @_;
6036: if (ref($intervals{$interval_type}) eq 'ARRAY') {
6037: return $intervals{$interval_type};
6038: }
6039: return;
6040: }
6041:
1.563 damieng 6042: # Returns HTML to edit a date interval parameter.
6043: #
6044: # @param {string} $thiskey - parameter key
6045: # @param {string} $name - parameter name
6046: # @param {string} $showval - parameter current value
6047: # @param {boolean} $readonly - true if the values should not be made editable
6048: # @returns {string}
1.554 raeburn 6049: sub date_interval_selector {
6050: my ($thiskey, $name, $showval, $readonly) = @_;
6051: my ($result,%skipval);
6052: if ($name eq 'interval') {
6053: my $intervaltype = &get_intervaltype($name);
6054: my ($got_chostname,$chostname,$cmajor,$cminor);
6055: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
6056: next unless (ref($possibilities) eq 'ARRAY');
6057: my ($parmval, $description) = @{ $possibilities };
6058: my $parmmatch;
6059: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
6060: foreach my $item (@{$intervalmatches{$intervaltype}}) {
6061: if (ref($item) eq 'ARRAY') {
6062: if ($parmval eq $item->[0]) {
6063: $parmmatch = $parmval;
6064: $parmval = '';
6065: last;
6066: }
6067: }
6068: }
6069: }
6070: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
6071: if ($needsrelease) {
6072: unless ($got_chostname) {
6073: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
6074: $got_chostname = 1;
6075: }
1.557 raeburn 6076: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 6077: $needsrelease,$cmajor,$cminor);
6078: if ($needsnewer) {
6079: if ($parmmatch ne '') {
6080: $skipval{$parmmatch} = 1;
6081: } elsif ($parmval ne '') {
6082: $skipval{$parmval} = 1;
6083: }
6084: }
6085: }
6086: }
6087: }
6088:
6089: my $currval = $showval;
6090: foreach my $which (['days', 86400, 31],
6091: ['hours', 3600, 23],
6092: ['minutes', 60, 59],
6093: ['seconds', 1, 59]) {
1.560 damieng 6094: my ($name, $factor, $max) = @{ $which };
6095: my $amount = int($showval/$factor);
6096: $showval %= $factor;
6097: my %select = ((map {$_ => $_} (0..$max)),
6098: 'select_form_order' => [0..$max]);
1.611 raeburn 6099: if ($currval eq '') {
6100: unshift(@{$select{'select_form_order'}},'');
6101: $select{''} = '';
6102: $amount = '';
6103: }
1.560 damieng 6104: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
6105: \%select,'',$readonly);
6106: $result .= ' '.&mt($name);
1.554 raeburn 6107: }
6108: if ($name eq 'interval') {
6109: unless ($skipval{'done'}) {
6110: my $checkedon = '';
1.611 raeburn 6111: my $checkedoff = '';
1.558 raeburn 6112: my $checkedproc = '';
6113: my $currproctorkey = '';
6114: my $currprocdisplay = 'hidden';
1.559 raeburn 6115: my $currdonetext = &mt('Done');
6116: if ($currval =~ /^(?:\d+)_done$/) {
6117: $checkedon = ' checked="checked"';
6118: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
6119: $currdonetext = $1;
1.554 raeburn 6120: $checkedon = ' checked="checked"';
1.558 raeburn 6121: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
6122: $currproctorkey = $1;
6123: $checkedproc = ' checked="checked"';
6124: $currprocdisplay = 'text';
1.559 raeburn 6125: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
6126: $currdonetext = $1;
6127: $currproctorkey = $2;
6128: $checkedproc = ' checked="checked"';
6129: $currprocdisplay = 'text';
1.611 raeburn 6130: } elsif ($currval ne '') {
6131: $checkedoff = ' checked="checked"';
6132: } else {
6133: $currdonetext = '';
1.554 raeburn 6134: }
1.558 raeburn 6135: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 6136: my $disabled;
6137: if ($readonly) {
6138: $disabled = ' disabled="disabled"';
6139: }
1.558 raeburn 6140: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 6141: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 6142: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 6143: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 6144: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 6145: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 6146: &mt('Yes, with proctor key').'</label>'.
6147: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 6148: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 6149: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611 raeburn 6150: '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
6151: &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 6152: }
6153: }
6154: unless ($readonly) {
6155: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
6156: }
6157: return $result;
6158: }
6159:
1.563 damieng 6160: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
6161: #
6162: # @param {string} $name - parameter name
6163: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
6164: # @param {string} $value - parameter value
6165: # @param {string} $chostname - course server name
6166: # @param {integer} $cmajor - major version number
6167: # @param {integer} $cminor - minor version number
6168: # @param {string} $needsrelease - release version needed (major.minor)
6169: # @returns {string}
1.549 raeburn 6170: sub oldversion_warning {
1.557 raeburn 6171: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
6172: my $standard_name = &standard_parameter_names($name);
6173: if ($namematch) {
6174: my $level = &standard_parameter_levels($namematch);
6175: my $msg = '';
6176: if ($level) {
6177: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
6178: $standard_name,'<b>','</b>','"'.$level.'"');
6179: } else {
6180: $msg = &mt('[_1] was [_2]not[_3] set.',
6181: $standard_name,'<b>','</b>');
6182: }
6183: return '<p class="LC_warning">'.$msg.'<br />'.
6184: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
6185: $cmajor.'.'.$cminor,$chostname,
6186: $needsrelease).
6187: '</p>';
6188: }
1.549 raeburn 6189: my $desc;
6190: my $stringtype = &get_stringtype($name);
6191: if ($stringtype ne '') {
6192: if ($name eq 'examcode') {
6193: $desc = $value;
6194: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
6195: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
6196: next unless (ref($possibilities) eq 'ARRAY');
6197: my ($parmval, $description) = @{ $possibilities };
6198: my $parmmatch;
6199: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
6200: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
6201: if (ref($item) eq 'ARRAY') {
6202: my ($regexpname,$pattern) = @{$item};
6203: if ($parmval eq $regexpname) {
6204: if ($value =~ /$pattern/) {
6205: $desc = $description;
6206: $parmmatch = 1;
6207: last;
6208: }
6209: }
6210: }
6211: }
6212: last if ($parmmatch);
6213: } elsif ($parmval eq $value) {
6214: $desc = $description;
6215: last;
6216: }
6217: }
6218: }
6219: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
6220: my $now = time;
6221: if ($value =~ /^\d+$/) {
6222: if ($name eq 'printstartdate') {
6223: if ($value > $now) {
6224: $desc = &Apache::lonlocal::locallocaltime($value);
6225: }
6226: } elsif ($name eq 'printenddate') {
6227: if ($value < $now) {
6228: $desc = &Apache::lonlocal::locallocaltime($value);
6229: }
6230: }
6231: }
6232: }
6233: return '<p class="LC_warning">'.
1.557 raeburn 6234: &mt('[_1] was [_2]not[_3] set to [_4].',
6235: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
6236: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
6237: $cmajor.'.'.$cminor,$chostname,
6238: $needsrelease).
6239: '</p>';
1.549 raeburn 6240: }
6241:
1.560 damieng 6242: } # end of block using some constants related to parameter types
6243:
1.549 raeburn 6244:
1.563 damieng 6245:
6246: # Shifts all start and end dates in the current course by $shift.
1.389 www 6247: #
1.563 damieng 6248: # @param {integer} $shift - time to shift, in seconds
6249: # @returns {string} - error name or 'ok'
1.389 www 6250: sub dateshift {
1.594 raeburn 6251: my ($shift,$numchanges)=@_;
1.389 www 6252: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6253: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6254: my $sec = $env{'request.course.sec'};
1.595 raeburn 6255: my $secgrpregex;
6256: if ($sec ne '') {
6257: my @groups;
6258: if ($env{'request.course.groups'} ne '') {
6259: @groups = split(/:/,$env{'request.course.groups'});
6260: }
6261: if (@groups) {
6262: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
6263: } else {
6264: $secgrpregex = $sec;
6265: }
6266: }
1.389 www 6267: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
6268: # ugly retro fix for broken version of types
1.548 raeburn 6269: foreach my $key (keys(%data)) {
1.389 www 6270: if ($key=~/\wtype$/) {
6271: my $newkey=$key;
6272: $newkey=~s/type$/\.type/;
6273: $data{$newkey}=$data{$key};
6274: delete $data{$key};
6275: }
6276: }
1.391 www 6277: my %storecontent=();
1.389 www 6278: # go through all parameters and look for dates
1.548 raeburn 6279: foreach my $key (keys(%data)) {
1.389 www 6280: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 6281: if ($sec ne '') {
1.595 raeburn 6282: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 6283: }
1.389 www 6284: my $newdate=$data{$key}+$shift;
1.594 raeburn 6285: $$numchanges ++;
1.391 www 6286: $storecontent{$key}=$newdate;
1.389 www 6287: }
6288: }
1.391 www 6289: my $reply=&Apache::lonnet::cput
6290: ('resourcedata',\%storecontent,$dom,$crs);
6291: if ($reply eq 'ok') {
6292: &log_parmset(\%storecontent);
6293: }
6294: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
6295: return $reply;
1.389 www 6296: }
6297:
1.563 damieng 6298: # Overview mode UI to edit course parameters.
6299: #
6300: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6301: sub newoverview {
1.568 raeburn 6302: my ($r,$parm_permission) = @_;
1.280 albertel 6303:
1.208 www 6304: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6305: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6306: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6307: my $readonly = 1;
6308: if ($parm_permission->{'edit'}) {
6309: undef($readonly);
6310: }
1.414 droeschl 6311: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6312: text=>"Overview Mode"});
1.523 raeburn 6313:
6314: my %loaditems = (
1.549 raeburn 6315: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 6316: );
6317: my $js = '
6318: <script type="text/javascript">
6319: // <![CDATA[
6320: '.
6321: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
6322: &showhide_js()."\n".
1.549 raeburn 6323: &toggleparmtextbox_js()."\n".
6324: &validateparms_js()."\n".
6325: &ipacc_boxes_js()."\n".
1.622 ! raeburn 6326: &grace_js()."\n".
1.558 raeburn 6327: &done_proctor_js()."\n".
1.588 raeburn 6328: &deeplink_js()."\n".
1.523 raeburn 6329: '// ]]>
6330: </script>
6331: ';
1.549 raeburn 6332:
1.523 raeburn 6333: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
6334: {'add_entries' => \%loaditems,});
1.298 albertel 6335: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6336: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6337: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 6338: $r->print(<<ENDOVER);
1.549 raeburn 6339: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208 www 6340: ENDOVER
1.211 www 6341: my @ids=();
6342: my %typep=();
6343: my %keyp=();
6344: my %allparms=();
6345: my %allparts=();
6346: my %allmaps=();
6347: my %mapp=();
6348: my %symbp=();
6349: my %maptitles=();
6350: my %uris=();
6351: my %keyorder=&standardkeyorder();
6352: my %defkeytype=();
6353:
6354: my %alllevs=();
6355: $alllevs{'Resource Level'}='full';
1.215 www 6356: $alllevs{'Map/Folder Level'}='map';
1.211 www 6357: $alllevs{'Course Level'}='general';
6358:
6359: my $csec=$env{'form.csec'};
1.269 raeburn 6360: my $cgroup=$env{'form.cgroup'};
1.211 www 6361:
6362: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
6363: my $pschp=$env{'form.pschp'};
1.506 www 6364:
1.211 www 6365: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 6366: if (!@psprt) { $psprt[0]='all'; }
1.211 www 6367:
1.446 bisitz 6368: my @selected_sections =
1.473 amueller 6369: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 6370: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 6371: foreach my $sec (@selected_sections) {
6372: if ($sec eq 'all') {
1.211 www 6373: @selected_sections = ('all');
6374: }
6375: }
1.552 raeburn 6376: if ($env{'request.course.sec'} ne '') {
6377: @selected_sections = ($env{'request.course.sec'});
6378: }
1.269 raeburn 6379: my @selected_groups =
6380: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 6381:
6382: my $pssymb='';
6383: my $parmlev='';
1.446 bisitz 6384:
1.211 www 6385: unless ($env{'form.parmlev'}) {
6386: $parmlev = 'map';
6387: } else {
6388: $parmlev = $env{'form.parmlev'};
6389: }
6390:
1.446 bisitz 6391: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 6392: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 6393: \%keyorder,\%defkeytype,$pssymb);
1.211 www 6394:
1.374 albertel 6395: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 6396: @psprt = keys(%allparts);
1.374 albertel 6397: }
1.211 www 6398: # Menu to select levels, etc
6399:
1.456 bisitz 6400: $r->print('<div class="LC_Box">');
1.445 neumanie 6401: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 6402: $r->print('<div>');
1.523 raeburn 6403: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 6404: &levelmenu($r,\%alllevs,$parmlev);
1.610 raeburn 6405: $r->print(&Apache::lonhtmlcommon::row_closure());
6406: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447 bisitz 6407: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6408: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6409: $r->print('</div></div>');
1.446 bisitz 6410:
1.456 bisitz 6411: $r->print('<div class="LC_Box">');
1.452 bisitz 6412: $r->print('<div>');
1.581 raeburn 6413: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 6414: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 6415: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 6416: my $sectionselector = §ionmenu(\@selected_sections);
6417: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 6418: $r->print('<table>'.
1.553 raeburn 6419: '<tr><th>'.&mt('Parts').'</th>');
6420: if ($sectionselector) {
6421: $r->print('<th>'.&mt('Section(s)').'</th>');
6422: }
6423: if ($groupselector) {
6424: $r->print('<th>'.&mt('Group(s)').'</th>');
6425: }
6426: $r->print('</tr><tr><td>');
1.211 www 6427: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 6428: $r->print('</td>');
6429: if ($sectionselector) {
6430: $r->print('<td>'.$sectionselector.'</td>');
6431: }
6432: if ($groupselector) {
6433: $r->print('<td>'.$groupselector.'</td>');
6434: }
6435: $r->print('</tr></table>');
1.447 bisitz 6436: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6437: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6438: $r->print('</div></div>');
6439:
1.456 bisitz 6440: $r->print('<div class="LC_Box">');
1.452 bisitz 6441: $r->print('<div>');
1.214 www 6442: my $sortorder=$env{'form.sortorder'};
6443: unless ($sortorder) { $sortorder='realmstudent'; }
1.612 raeburn 6444: &sortmenu($r,$sortorder,'newoverview');
1.445 neumanie 6445: $r->print('</div></div>');
1.446 bisitz 6446:
1.214 www 6447: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446 bisitz 6448:
1.211 www 6449: # Build the list data hash from the specified parms
6450:
6451: my $listdata;
6452: %{$listdata}=();
6453:
6454: foreach my $cat (@pscat) {
1.269 raeburn 6455: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
6456: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 6457: }
6458:
1.212 www 6459: if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211 www 6460:
1.481 amueller 6461: if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211 www 6462:
6463: # Read modified data
6464:
1.481 amueller 6465: my $resourcedata=&readdata($crs,$dom);
1.211 www 6466:
6467: # List data
6468:
1.608 raeburn 6469: my $hash_for_realm;
6470: if (($parmlev eq 'map') && (keys(%allmaps))) {
6471: %{$hash_for_realm} = reverse(%allmaps);
6472: } elsif (($parmlev eq 'full') && (keys(%symbp))) {
6473: for (my $i=0; $i<@ids; $i++) {
6474: $hash_for_realm->{$symbp{$ids[$i]}} = $i;
6475: }
6476: }
6477: &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568 raeburn 6478: }
6479: $r->print(&tableend());
6480: unless ($readonly) {
6481: $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211 www 6482: }
1.568 raeburn 6483: $r->print('</form>');
1.507 www 6484: &endSettingsScreen($r);
6485: $r->print(&Apache::loncommon::end_page());
1.208 www 6486: }
6487:
1.563 damieng 6488: # Fills $listdata with parameter information.
6489: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
6490: # The non-type value is always 1.
6491: #
6492: # @param {string} $cat - parameter name
1.566 damieng 6493: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 6494: # @param {string} $parmlev - selected level value (full|map|general), or ''
6495: # @param {hash reference} $listdata - the parameter data that will be modified
6496: # @param {array reference} $psprt - selected parts
6497: # @param {array reference} $selections - selected sections
6498: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6499: # @param {hash reference} $allmaps - hash map pc -> map src
6500: # @param {array reference} $ids - resource and map ids
6501: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6502: sub secgroup_lister {
6503: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6504: foreach my $item (@{$selections}) {
6505: foreach my $part (@{$psprt}) {
6506: my $rootparmkey=$env{'request.course.id'};
6507: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6508: $rootparmkey.='.['.$item.']';
6509: }
6510: if ($parmlev eq 'general') {
6511: # course-level parameter
6512: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6513: $$listdata{$newparmkey}=1;
6514: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6515: } elsif ($parmlev eq 'map') {
6516: # map-level parameter
1.548 raeburn 6517: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6518: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6519: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6520: $$listdata{$newparmkey}=1;
6521: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6522: }
6523: } else {
6524: # resource-level parameter
6525: foreach my $rid (@{$ids}) {
6526: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6527: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6528: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6529: $$listdata{$newparmkey}=1;
6530: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6531: }
6532: }
6533: }
6534: }
6535: }
6536:
1.563 damieng 6537: # UI to edit parameter settings starting with a list of all existing parameters.
6538: # (called by setoverview action)
6539: #
6540: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6541: sub overview {
1.568 raeburn 6542: my ($r,$parm_permission) = @_;
1.208 www 6543: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6544: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6545: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6546: my $readonly = 1;
6547: if ($parm_permission->{'edit'}) {
6548: undef($readonly);
6549: }
1.549 raeburn 6550: my $js = '<script type="text/javascript">'."\n".
6551: '// <![CDATA['."\n".
6552: &toggleparmtextbox_js()."\n".
6553: &validateparms_js()."\n".
6554: &ipacc_boxes_js()."\n".
1.622 ! raeburn 6555: &grace_js()."\n".
1.558 raeburn 6556: &done_proctor_js()."\n".
1.588 raeburn 6557: &deeplink_js()."\n".
1.549 raeburn 6558: '// ]]>'."\n".
6559: '</script>'."\n";
1.414 droeschl 6560: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6561: text=>"Overview Mode"});
1.549 raeburn 6562: my %loaditems = (
6563: 'onload' => "showHideLenient();",
6564: );
6565:
6566: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6567: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6568: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6569: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6570: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6571:
1.208 www 6572: # Store modified
6573:
1.568 raeburn 6574: unless ($readonly) {
6575: &storedata($r,$crs,$dom);
6576: }
1.208 www 6577:
6578: # Read modified data
6579:
1.552 raeburn 6580: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6581:
1.214 www 6582:
6583: my $sortorder=$env{'form.sortorder'};
6584: unless ($sortorder) { $sortorder='realmstudent'; }
1.608 raeburn 6585: &sortmenu($r,$sortorder,'overview');
1.214 www 6586:
1.568 raeburn 6587: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6588:
6589: if ($readonly) {
6590: $r->print('<p>'.$submitbutton.'</p>');
6591: }
6592:
1.208 www 6593: # List data
6594:
1.568 raeburn 6595: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6596: $r->print(&tableend().'<p>');
6597: if ($foundkeys) {
6598: unless ($readonly) {
6599: $r->print('<p>'.$submitbutton.'</p>');
6600: }
6601: } else {
6602: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6603: }
6604: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6605: }
1.121 www 6606:
1.560 damieng 6607: # Unused sub.
1.563 damieng 6608: #
6609: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6610: sub clean_parameters {
6611: my ($r) = @_;
6612: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6613: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6614:
1.414 droeschl 6615: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6616: text=>"Clean Parameters"});
1.333 albertel 6617: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6618: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6619: $r->print(<<ENDOVER);
6620: $start_page
6621: $breadcrumbs
6622: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6623: ENDOVER
6624: # Store modified
6625:
6626: &storedata($r,$crs,$dom);
6627:
6628: # Read modified data
6629:
6630: my $resourcedata=&readdata($crs,$dom);
6631:
6632: # List data
6633:
6634: $r->print('<h3>'.
1.473 amueller 6635: &mt('These parameters refer to resources that do not exist.').
6636: '</h3>'.
6637: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6638: '<br />');
1.333 albertel 6639: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6640: '<tr>'.
6641: '<th>'.&mt('Delete').'</th>'.
6642: '<th>'.&mt('Parameter').'</th>'.
6643: '</tr>');
1.333 albertel 6644: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6645: next if (!exists($resourcedata->{$thiskey.'.type'})
6646: && $thiskey=~/\.type$/);
6647: my %data = &parse_key($thiskey);
6648: if (1) { #exists($data{'realm_exists'})
6649: #&& !$data{'realm_exists'}) {
6650: $r->print(&Apache::loncommon::start_data_table_row().
6651: '<tr>'.
6652: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6653:
6654: $r->print('<td>');
6655: my $display_value = $resourcedata->{$thiskey};
6656: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6657: $display_value =
6658: &Apache::lonlocal::locallocaltime($display_value);
6659: }
1.470 raeburn 6660: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6661: $parmitem = &mt($parmitem);
1.560 damieng 6662: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6663: $parmitem,$resourcedata->{$thiskey}));
6664: $r->print('<br />');
6665: if ($data{'scope_type'} eq 'all') {
6666: $r->print(&mt('All users'));
6667: } elsif ($data{'scope_type'} eq 'user') {
6668: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6669: } elsif ($data{'scope_type'} eq 'secgroup') {
6670: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6671: }
6672: $r->print('<br />');
6673: if ($data{'realm_type'} eq 'all') {
6674: $r->print(&mt('All Resources'));
6675: } elsif ($data{'realm_type'} eq 'folder') {
6676: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6677: } elsif ($data{'realm_type'} eq 'symb') {
6678: my ($map,$resid,$url) =
6679: &Apache::lonnet::decode_symb($data{'realm'});
6680: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6681: $url.' <br /> ',
6682: $resid.' <br /> ',$map));
6683: }
6684: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6685: $r->print('</td></tr>');
6686:
1.473 amueller 6687: }
1.333 albertel 6688: }
6689: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6690: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6691: '</p></form>');
6692: &endSettingsScreen($r);
6693: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6694: }
6695:
1.563 damieng 6696: # UI to shift all dates (called by dateshift1 action).
6697: # Used by overview mode.
6698: #
6699: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6700: sub date_shift_one {
6701: my ($r) = @_;
6702: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6703: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6704: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6705: my $sec = $env{'request.course.sec'};
1.414 droeschl 6706: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6707: text=>"Shifting Dates"});
1.594 raeburn 6708: my $submit_text = &mt('Shift all dates accordingly');
6709: if ($sec ne '') {
1.595 raeburn 6710: my @groups;
6711: if ($env{'request.course.groups'} ne '') {
6712: @groups = split(/:/,$env{'request.course.groups'});
6713: }
6714: if (@groups) {
6715: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6716: } else {
6717: $submit_text = &mt("Shift dates set just for your section, accordingly");
6718: }
1.594 raeburn 6719: }
1.390 www 6720: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6721: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6722: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6723: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6724: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6725: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6726: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6727: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6728: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6729: 'timeshifted',
6730: $env{'form.timebase'},,
6731: '').
6732: '</td></tr></table>'.
6733: '<input type="hidden" name="action" value="dateshift2" />'.
6734: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6735: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6736: &endSettingsScreen($r);
1.390 www 6737: $r->print(&Apache::loncommon::end_page());
6738: }
6739:
1.563 damieng 6740: # UI to shift all dates (second form).
6741: #
6742: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6743: sub date_shift_two {
6744: my ($r) = @_;
6745: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6746: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6747: my $sec = $env{'request.course.sec'};
1.531 raeburn 6748: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6749: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6750: text=>"Shifting Dates"});
1.390 www 6751: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6752: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6753: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6754: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6755: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6756: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6757: if ($sec ne '') {
1.595 raeburn 6758: my @groups;
6759: if ($env{'request.course.groups'} ne '') {
6760: @groups = split(/:/,$env{'request.course.groups'});
6761: }
6762: if (@groups) {
6763: $r->print('<p>'.
6764: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6765: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6766: &Apache::lonlocal::locallocaltime($timeshifted)).
6767: '</p>');
6768: } else {
6769: $r->print('<p>'.
6770: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6771: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6772: &Apache::lonlocal::locallocaltime($timeshifted)).
6773: '</p>');
6774: }
1.594 raeburn 6775: } else {
6776: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6777: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6778: &Apache::lonlocal::locallocaltime($timeshifted)).
6779: '</p>');
6780: }
1.390 www 6781: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6782: my $numchanges = 0;
6783: my $result = &dateshift($delta,\$numchanges);
6784: if ($result eq 'ok') {
6785: $r->print(
6786: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6787: $numchanges)));
6788: } elsif ($result eq 'con_delayed') {
6789: $r->print(
6790: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6791: $numchanges)));
6792: } else {
6793: $r->print(
6794: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6795: }
1.543 bisitz 6796: $r->print(
6797: '<br /><br />'.
6798: &Apache::lonhtmlcommon::actionbox(
6799: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6800: &endSettingsScreen($r);
1.390 www 6801: $r->print(&Apache::loncommon::end_page());
6802: }
6803:
1.563 damieng 6804: # Returns the different components of a resourcedata key.
6805: # Keys: scope_type, scope, realm_type, realm, realm_title,
6806: # realm_exists, parameter_part, parameter_name.
6807: # Was used by clean_parameters (which is unused).
6808: #
6809: # @param {string} $key - the parameter key
6810: # @returns {hash}
1.333 albertel 6811: sub parse_key {
6812: my ($key) = @_;
6813: my %data;
6814: my ($middle,$part,$name)=
1.572 damieng 6815: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6816: $data{'scope_type'} = 'all';
6817: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6818: $data{'scope'} = $1;
6819: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6820: $data{'scope_type'} = 'user';
6821: $data{'scope'} = [$1,$2];
6822: } else {
1.581 raeburn 6823: $data{'scope_type'} = 'secgroup';
1.560 damieng 6824: }
6825: $middle=~s/^\[(.*)\]//;
1.333 albertel 6826: }
6827: $middle=~s/\.+$//;
6828: $middle=~s/^\.+//;
6829: $data{'realm_type'}='all';
6830: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6831: $data{'realm'} = $1;
6832: $data{'realm_type'} = 'folder';
6833: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6834: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6835: } elsif ($middle) {
1.560 damieng 6836: $data{'realm'} = $middle;
6837: $data{'realm_type'} = 'symb';
6838: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6839: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6840: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6841: }
1.446 bisitz 6842:
1.333 albertel 6843: $data{'parameter_part'} = $part;
6844: $data{'parameter_name'} = $name;
6845:
6846: return %data;
6847: }
6848:
1.239 raeburn 6849:
1.563 damieng 6850: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6851: sub header {
1.507 www 6852: return &Apache::loncommon::start_page('Settings');
1.416 jms 6853: }
1.193 albertel 6854:
6855:
6856:
1.560 damieng 6857: ##################################################
6858: # MAIN MENU
6859: ##################################################
6860:
1.563 damieng 6861: # Content and problem settings main menu.
6862: #
6863: # @param {Apache2::RequestRec} $r - the Apache request
6864: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 6865: sub print_main_menu {
6866: my ($r,$parm_permission)=@_;
6867: #
1.414 droeschl 6868: $r->print(&header());
1.507 www 6869: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 6870: my $crstype = &Apache::loncommon::course_type();
6871: my $lc_crstype = lc($crstype);
6872:
6873: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 6874: $r->print(<<ENDMAINFORMHEAD);
6875: <form method="post" enctype="multipart/form-data"
6876: action="/adm/parmset" name="studentform">
6877: ENDMAINFORMHEAD
6878: #
1.195 albertel 6879: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6880: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 6881: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 6882: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 6883: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 6884: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
6885: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 6886: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
6887: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
6888: '/'.$env{'request.course.sec'});
6889: }
1.568 raeburn 6890: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
6891: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
6892: '/'.$env{'request.course.sec'});
6893: }
6894: my (%linktext,%linktitle,%url);
6895: if ($parm_permission->{'edit'}) {
6896: %linktext = (
6897: newoverview => 'Edit Resource Parameters - Overview Mode',
6898: settable => 'Edit Resource Parameters - Table Mode',
6899: setoverview => 'Modify Resource Parameters - Overview Mode',
6900: );
6901: %linktitle = (
6902: newoverview => 'Set/Modify resource parameters in overview mode.',
6903: settable => 'Set/Modify resource parameters in table mode.',
6904: setoverview => 'Set/Modify existing resource parameters in overview mode.',
6905: );
6906: } else {
6907: %linktext = (
6908: newoverview => 'View Resource Parameters - Overview Mode',
6909: settable => 'View Resource Parameters - Table Mode',
6910: setoverview => 'View Resource Parameters - Overview Mode',
6911: );
6912: %linktitle = (
6913: newoverview => 'Display resource parameters in overview mode.',
6914: settable => 'Display resource parameters in table mode.',
6915: setoverview => 'Display existing resource parameters in overview mode.',
6916: );
6917: }
6918: if ($mgr) {
6919: $linktext{'resettimes'} = 'Reset Student Access Times';
6920: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
6921: $url{'resettimes'} = '/adm/helper/resettimes.helper';
6922: } elsif ($vgr) {
6923: $linktext{'resettimes'} = 'Display Student Access Times',
6924: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
6925: $url{'resettimes'} = '/adm/accesstimes';
6926: }
1.193 albertel 6927: my @menu =
1.507 www 6928: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 6929: items => [
6930: { linktext => 'Portfolio Metadata',
6931: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 6932: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 6933: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 6934: icon =>'contact-new.png' ,
6935: },
1.568 raeburn 6936: { linktext => $linktext{'resettimes'},
6937: url => $url{'resettimes'},
6938: permission => ($vgr || $mgr),
6939: linktitle => $linktitle{'resettimes'},
6940: icon => 'start-here.png',
1.473 amueller 6941: },
1.520 raeburn 6942: { linktext => 'Blocking Communication/Resource Access',
6943: url => '/adm/setblock',
1.568 raeburn 6944: permission => ($vcb || $dcm),
1.520 raeburn 6945: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
6946: icon => 'comblock.png',
6947: },
1.473 amueller 6948: { linktext => 'Set Parameter Setting Default Actions',
6949: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 6950: permission => $parm_permission->{'setdefaults'},
1.473 amueller 6951: linktitle =>'Set default actions for parameters.' ,
6952: icon => 'folder-new.png' ,
6953: }]},
6954: { categorytitle => 'New and Existing Parameter Settings for Resources',
6955: items => [
6956: { linktext => 'Edit Resource Parameters - Helper Mode',
6957: url => '/adm/helper/parameter.helper',
1.568 raeburn 6958: permission => $parm_permission->{'helper'},
1.473 amueller 6959: linktitle =>'Set/Modify resource parameters in helper mode.' ,
6960: icon => 'dialog-information.png' ,
6961: #help => 'Parameter_Helper',
6962: },
1.568 raeburn 6963: { linktext => $linktext{'newoverview'},
1.473 amueller 6964: url => '/adm/parmset?action=newoverview',
1.568 raeburn 6965: permission => $parm_permission->{'newoverview'},
6966: linktitle => $linktitle{'newoverview'},
6967: icon => 'edit-find.png',
1.473 amueller 6968: #help => 'Parameter_Overview',
6969: },
1.568 raeburn 6970: { linktext => $linktext{'settable'},
1.473 amueller 6971: url => '/adm/parmset?action=settable',
1.568 raeburn 6972: permission => $parm_permission->{'settable'},
6973: linktitle => $linktitle{'settable'},
6974: icon => 'edit-copy.png',
1.473 amueller 6975: #help => 'Table_Mode',
6976: }]},
1.417 droeschl 6977: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 6978: items => [
1.570 raeburn 6979: { linktext => $linktext{'setoverview'},
1.473 amueller 6980: url => '/adm/parmset?action=setoverview',
1.568 raeburn 6981: permission => $parm_permission->{'setoverview'},
6982: linktitle => $linktitle{'setoverview'},
6983: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 6984: #help => 'Parameter_Overview',
6985: },
6986: { linktext => 'Change Log',
6987: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 6988: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 6989: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 6990: icon => 'document-properties.png',
1.473 amueller 6991: }]}
1.193 albertel 6992: );
1.414 droeschl 6993: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 6994: $r->print('</form>');
1.507 www 6995: &endSettingsScreen($r);
1.539 raeburn 6996: $r->print(&Apache::loncommon::end_page());
1.193 albertel 6997: return;
6998: }
1.414 droeschl 6999:
1.416 jms 7000:
7001:
1.560 damieng 7002: ##################################################
7003: # PORTFOLIO METADATA
7004: ##################################################
7005:
1.563 damieng 7006: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
7007: # It looks like field titles are not localized.
7008: #
7009: # @param {Apache2::RequestRec} $r - the Apache request
7010: # @param {string} $field_name - metadata field name
7011: # @param {string} $field_text - metadata field title, in English unless manually added
7012: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 7013: sub output_row {
1.347 banghart 7014: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 7015: my $output;
1.263 banghart 7016: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
7017: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 7018: if (!defined($options)) {
1.254 banghart 7019: $options = 'active,stuadd';
1.261 banghart 7020: $values = '';
1.252 banghart 7021: }
1.337 banghart 7022: if (!($options =~ /deleted/)) {
7023: my @options= ( ['active', 'Show to student'],
1.418 schafran 7024: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 7025: ['choices','Provide choices for students to select from']);
1.473 amueller 7026: # ['onlyone','Student may select only one choice']);
1.337 banghart 7027: if ($added_flag) {
7028: push @options,['deleted', 'Delete Metadata Field'];
7029: }
1.351 banghart 7030: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 7031: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 7032: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 7033: foreach my $opt (@options) {
1.560 damieng 7034: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
7035: $output .= &Apache::loncommon::continue_data_table_row();
7036: $output .= '<td>'.(' ' x 5).'<label>
7037: <input type="checkbox" name="'.
7038: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
7039: &mt($opt->[1]).'</label></td>';
7040: $output .= &Apache::loncommon::end_data_table_row();
7041: }
1.351 banghart 7042: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 7043: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 7044: $output .= &Apache::loncommon::end_data_table_row();
7045: my $multiple_checked;
7046: my $single_checked;
7047: if ($options =~ m/onlyone/) {
1.422 bisitz 7048: $multiple_checked = '';
1.423 bisitz 7049: $single_checked = ' checked="checked"';
1.351 banghart 7050: } else {
1.423 bisitz 7051: $multiple_checked = ' checked="checked"';
1.422 bisitz 7052: $single_checked = '';
1.351 banghart 7053: }
1.560 damieng 7054: $output .= &Apache::loncommon::continue_data_table_row();
7055: $output .= '<td>'.(' ' x 10).'
7056: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
7057: '.&mt('Student may select multiple choices from list').'</td>';
7058: $output .= &Apache::loncommon::end_data_table_row();
7059: $output .= &Apache::loncommon::continue_data_table_row();
7060: $output .= '<td>'.(' ' x 10).'
7061: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
7062: '.&mt('Student may select only one choice from list').'</td>';
7063: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 7064: }
7065: return ($output);
7066: }
1.416 jms 7067:
7068:
1.560 damieng 7069: # UI to order portfolio metadata fields.
1.563 damieng 7070: # Currently useless because addmetafield does not work.
7071: #
7072: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 7073: sub order_meta_fields {
7074: my ($r)=@_;
7075: my $idx = 1;
7076: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7077: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7078: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 7079: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 7080: &Apache::lonhtmlcommon::add_breadcrumb(
7081: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 7082: text=>"Add Metadata Field"});
1.560 damieng 7083: &Apache::lonhtmlcommon::add_breadcrumb(
7084: {href=>"/adm/parmset?action=setrestrictmeta",
7085: text=>"Restrict Metadata"},
7086: {text=>"Order Metadata"});
1.345 banghart 7087: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 7088: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 7089: if ($env{'form.storeorder'}) {
7090: my $newpos = $env{'form.newpos'} - 1;
7091: my $currentpos = $env{'form.currentpos'} - 1;
7092: my @neworder = ();
1.548 raeburn 7093: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 7094: my $i;
1.341 banghart 7095: if ($newpos > $currentpos) {
1.340 banghart 7096: # moving stuff up
7097: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 7098: $neworder[$i]=$oldorder[$i];
1.340 banghart 7099: }
7100: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 7101: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 7102: }
7103: $neworder[$newpos]=$oldorder[$currentpos];
7104: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 7105: $neworder[$i]=$oldorder[$i];
1.340 banghart 7106: }
7107: } else {
7108: # moving stuff down
1.473 amueller 7109: for ($i=0;$i<$newpos;$i++) {
7110: $neworder[$i]=$oldorder[$i];
7111: }
7112: $neworder[$newpos]=$oldorder[$currentpos];
7113: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
7114: $neworder[$i]=$oldorder[$i-1];
7115: }
7116: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
7117: $neworder[$i]=$oldorder[$i];
7118: }
1.340 banghart 7119: }
1.560 damieng 7120: my $ordered_fields = join ",", @neworder;
1.343 banghart 7121: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 7122: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
7123: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 7124: }
1.357 raeburn 7125: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 7126: my $ordered_fields;
1.548 raeburn 7127: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 7128: if (!@fields_in_order) {
7129: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 7130: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 7131: push @fields_in_order, $key;
1.341 banghart 7132: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 7133: }
1.341 banghart 7134: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 7135: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
7136: }
1.340 banghart 7137: $r->print('<table>');
7138: my $num_fields = scalar(@fields_in_order);
7139: foreach my $key (@fields_in_order) {
7140: $r->print('<tr><td>');
7141: $r->print('<form method="post" action="">');
1.537 bisitz 7142: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 7143: for (my $i = 1;$i le $num_fields;$i ++) {
7144: if ($i eq $idx) {
7145: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
7146: } else {
7147: $r->print('<option value="'.$i.'">'.$i.'</option>');
7148: }
7149: }
7150: $r->print('</select></td><td>');
7151: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
7152: $r->print('<input type="hidden" name="storeorder" value="true" />');
7153: $r->print('</form>');
7154: $r->print($$fields{$key}.'</td></tr>');
7155: $idx ++;
7156: }
7157: $r->print('</table>');
1.507 www 7158: &endSettingsScreen($r);
1.340 banghart 7159: return 'ok';
7160: }
1.416 jms 7161:
7162:
1.563 damieng 7163: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
7164: # @returns {string}
1.359 banghart 7165: sub continue {
7166: my $output;
7167: $output .= '<form action="" method="post">';
7168: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 7169: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 7170: return ($output);
7171: }
1.416 jms 7172:
7173:
1.563 damieng 7174: # UI to add a metadata field.
7175: # Currenly does not work because of an HTML error (the field is not visible).
7176: #
7177: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 7178: sub addmetafield {
7179: my ($r)=@_;
1.414 droeschl 7180: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 7181: text=>"Add Metadata Field"});
1.334 banghart 7182: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
7183: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 7184: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7185: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7186: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
7187: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 7188: if (exists($env{'form.undelete'})) {
1.358 banghart 7189: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 7190: foreach my $meta_field(@meta_fields) {
7191: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
7192: $options =~ s/deleted//;
7193: $options =~ s/,,/,/;
7194: my $put_result = &Apache::lonnet::put('environment',
7195: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 7196:
1.586 raeburn 7197: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
7198: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
7199: '</strong>',$put_result).
7200: '<br />');
1.339 banghart 7201: }
1.359 banghart 7202: $r->print(&continue());
1.339 banghart 7203: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 7204: my $meta_field = $env{'form.fieldname'};
7205: my $display_field = $env{'form.fieldname'};
7206: $meta_field =~ s/\W/_/g;
1.338 banghart 7207: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 7208: my $put_result = &Apache::lonnet::put('environment',
7209: {'metadata.'.$meta_field.'.values'=>"",
7210: 'metadata.'.$meta_field.'.added'=>"$display_field",
7211: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 7212: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
7213: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
7214: '<br />');
1.359 banghart 7215: $r->print(&continue());
1.335 banghart 7216: } else {
1.357 raeburn 7217: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 7218: if ($fields) {
1.586 raeburn 7219: $r->print(&mt('You may undelete previously deleted fields.').
7220: '<br />'.
7221: &mt('Check those you wish to undelete and click Undelete.').
7222: '<br />');
1.339 banghart 7223: $r->print('<form method="post" action="">');
7224: foreach my $key(keys(%$fields)) {
1.581 raeburn 7225: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 7226: }
1.586 raeburn 7227: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 7228: $r->print('</form>');
7229: }
1.586 raeburn 7230: $r->print('<hr />'.
7231: &mt('[_1]Or[_2] you may enter a new metadata field name.',
7232: '<strong>','</strong>').
1.581 raeburn 7233: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 7234: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 7235: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 7236: $r->print('</form>');
1.334 banghart 7237: }
1.507 www 7238: &endSettingsScreen($r);
1.334 banghart 7239: }
1.416 jms 7240:
7241:
7242:
1.560 damieng 7243: # Display or save portfolio metadata.
1.563 damieng 7244: #
7245: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 7246: sub setrestrictmeta {
1.240 banghart 7247: my ($r)=@_;
1.242 banghart 7248: my $next_meta;
1.244 banghart 7249: my $output;
1.245 banghart 7250: my $item_num;
1.246 banghart 7251: my $put_result;
1.414 droeschl 7252: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 7253: text=>"Restrict Metadata"});
1.280 albertel 7254: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 7255: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 7256: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7257: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7258: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
7259: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 7260: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 7261: my $save_field = '';
1.586 raeburn 7262: my %lt = &Apache::lonlocal::texthash(
7263: addm => 'Add Metadata Field',
7264: ordm => 'Order Metadata Fields',
7265: save => 'Save',
7266: );
1.259 banghart 7267: if ($env{'form.restrictmeta'}) {
1.254 banghart 7268: foreach my $field (sort(keys(%env))) {
1.252 banghart 7269: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 7270: my $options;
1.252 banghart 7271: my $meta_field = $1;
7272: my $meta_key = $2;
1.253 banghart 7273: if ($save_field ne $meta_field) {
1.252 banghart 7274: $save_field = $meta_field;
1.473 amueller 7275: if ($env{'form.'.$meta_field.'_stuadd'}) {
7276: $options.='stuadd,';
7277: }
7278: if ($env{'form.'.$meta_field.'_choices'}) {
7279: $options.='choices,';
7280: }
7281: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
7282: $options.='onlyone,';
7283: }
7284: if ($env{'form.'.$meta_field.'_active'}) {
7285: $options.='active,';
7286: }
7287: if ($env{'form.'.$meta_field.'_deleted'}) {
7288: $options.='deleted,';
7289: }
1.259 banghart 7290: my $name = $save_field;
1.560 damieng 7291: $put_result = &Apache::lonnet::put('environment',
7292: {'metadata.'.$meta_field.'.options'=>$options,
7293: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
7294: },$dom,$crs);
1.252 banghart 7295: }
7296: }
7297: }
7298: }
1.296 albertel 7299: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 7300: {'freshen_cache' => 1});
1.335 banghart 7301: # Get the default metadata fields
1.258 albertel 7302: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 7303: # Now get possible added metadata fields
1.357 raeburn 7304: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 7305: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 7306: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 7307: if ($field ne 'courserestricted') {
1.586 raeburn 7308: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 7309: }
1.255 banghart 7310: }
1.351 banghart 7311: my $buttons = (<<ENDButtons);
1.586 raeburn 7312: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 7313: </form><br />
7314: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 7315: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 7316: </form>
7317: <br />
7318: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 7319: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 7320: ENDButtons
1.337 banghart 7321: my $added_flag = 1;
1.335 banghart 7322: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 7323: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 7324: }
1.347 banghart 7325: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 7326: $r->print(<<ENDenv);
1.259 banghart 7327: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 7328: $output
1.351 banghart 7329: $buttons
1.340 banghart 7330: </form>
1.244 banghart 7331: ENDenv
1.507 www 7332: &endSettingsScreen($r);
1.280 albertel 7333: $r->print(&Apache::loncommon::end_page());
1.240 banghart 7334: return 'ok';
7335: }
1.416 jms 7336:
7337:
1.563 damieng 7338: # Returns metadata fields that have been manually added.
7339: #
7340: # @param {string} $cid - course id
7341: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 7342: sub get_added_meta_fieldnames {
1.357 raeburn 7343: my ($cid) = @_;
1.335 banghart 7344: my %fields;
7345: foreach my $key(%env) {
1.357 raeburn 7346: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 7347: my $field_name = $1;
7348: my ($display_field_name) = $env{$key};
7349: $fields{$field_name} = $display_field_name;
7350: }
7351: }
7352: return \%fields;
7353: }
1.416 jms 7354:
7355:
1.563 damieng 7356: # Returns metadata fields that have been manually added and deleted.
7357: #
7358: # @param {string} $cid - course id
7359: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 7360: sub get_deleted_meta_fieldnames {
1.357 raeburn 7361: my ($cid) = @_;
1.339 banghart 7362: my %fields;
7363: foreach my $key(%env) {
1.357 raeburn 7364: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 7365: my $field_name = $1;
7366: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
7367: my ($display_field_name) = $env{$key};
7368: $fields{$field_name} = $display_field_name;
7369: }
7370: }
7371: }
7372: return \%fields;
7373: }
1.560 damieng 7374:
7375:
7376: ##################################################
7377: # PARAMETER SETTINGS DEFAULT ACTIONS
7378: ##################################################
7379:
7380: # UI to change parameter setting default actions
1.563 damieng 7381: #
7382: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 7383: sub defaultsetter {
1.280 albertel 7384: my ($r) = @_;
7385:
1.414 droeschl 7386: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 7387: text=>"Set Defaults"});
1.531 raeburn 7388: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7389: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
7390: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 7391: my $start_page =
1.531 raeburn 7392: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 7393: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 7394: $r->print($start_page.$breadcrumbs);
1.531 raeburn 7395: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 7396: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 7397:
1.221 www 7398: my @ids=();
7399: my %typep=();
7400: my %keyp=();
7401: my %allparms=();
7402: my %allparts=();
7403: my %allmaps=();
7404: my %mapp=();
7405: my %symbp=();
7406: my %maptitles=();
7407: my %uris=();
7408: my %keyorder=&standardkeyorder();
7409: my %defkeytype=();
7410:
1.446 bisitz 7411: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 7412: \%mapp, \%symbp,\%maptitles,\%uris,
7413: \%keyorder,\%defkeytype);
1.224 www 7414: if ($env{'form.storerules'}) {
1.560 damieng 7415: my %newrules=();
7416: my @delrules=();
7417: my %triggers=();
7418: foreach my $key (keys(%env)) {
1.225 albertel 7419: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 7420: my $tempkey=$1;
7421: my $action=$env{$key};
1.226 www 7422: if ($action) {
1.560 damieng 7423: $newrules{$tempkey.'_action'}=$action;
7424: if ($action ne 'default') {
7425: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
7426: $triggers{$whichparm}.=$tempkey.':';
7427: }
7428: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
7429: if (&isdateparm($defkeytype{$tempkey})) {
7430: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
7431: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
7432: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
7433: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
7434: } else {
7435: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
7436: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
7437: }
7438: } else {
7439: push(@delrules,$tempkey.'_action');
7440: push(@delrules,$tempkey.'_type');
7441: push(@delrules,$tempkey.'_hours');
7442: push(@delrules,$tempkey.'_min');
7443: push(@delrules,$tempkey.'_sec');
7444: push(@delrules,$tempkey.'_value');
7445: }
1.473 amueller 7446: }
7447: }
1.560 damieng 7448: foreach my $key (keys(%allparms)) {
7449: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 7450: }
1.560 damieng 7451: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
7452: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
7453: &resetrulescache();
1.224 www 7454: }
1.227 www 7455: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 7456: 'hours' => 'Hours',
7457: 'min' => 'Minutes',
7458: 'sec' => 'Seconds',
7459: 'yes' => 'Yes',
7460: 'no' => 'No');
1.222 www 7461: my @standardoptions=('','default');
7462: my @standarddisplay=('',&mt('Default value when manually setting'));
7463: my @dateoptions=('','default');
7464: my @datedisplay=('',&mt('Default value when manually setting'));
7465: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7466: unless ($tempkey) { next; }
7467: push @standardoptions,'when_setting_'.$tempkey;
7468: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
7469: if (&isdateparm($defkeytype{$tempkey})) {
7470: push @dateoptions,'later_than_'.$tempkey;
7471: push @datedisplay,&mt('Automatically set later than ').$tempkey;
7472: push @dateoptions,'earlier_than_'.$tempkey;
7473: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
7474: }
1.222 www 7475: }
1.563 damieng 7476: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
7477: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 7478: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 7479: &Apache::loncommon::start_data_table_header_row().
7480: "<th>".&mt('Rule for parameter').'</th><th>'.
7481: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
7482: &Apache::loncommon::end_data_table_header_row());
1.221 www 7483: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7484: unless ($tempkey) { next; }
7485: $r->print("\n".&Apache::loncommon::start_data_table_row().
7486: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
7487: my $action=&rulescache($tempkey.'_action');
7488: $r->print('<select name="'.$tempkey.'_action">');
7489: if (&isdateparm($defkeytype{$tempkey})) {
7490: for (my $i=0;$i<=$#dateoptions;$i++) {
7491: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
7492: $r->print("\n<option value='$dateoptions[$i]'".
7493: ($dateoptions[$i] eq $action?' selected="selected"':'').
7494: ">$datedisplay[$i]</option>");
7495: }
7496: } else {
7497: for (my $i=0;$i<=$#standardoptions;$i++) {
7498: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
7499: $r->print("\n<option value='$standardoptions[$i]'".
7500: ($standardoptions[$i] eq $action?' selected="selected"':'').
7501: ">$standarddisplay[$i]</option>");
7502: }
1.473 amueller 7503: }
1.560 damieng 7504: $r->print('</select>');
7505: unless (&isdateparm($defkeytype{$tempkey})) {
7506: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7507: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7508: }
1.560 damieng 7509: $r->print("\n</td><td>\n");
1.222 www 7510:
1.221 www 7511: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7512: my $days=&rulescache($tempkey.'_days');
7513: my $hours=&rulescache($tempkey.'_hours');
7514: my $min=&rulescache($tempkey.'_min');
7515: my $sec=&rulescache($tempkey.'_sec');
7516: $r->print(<<ENDINPUTDATE);
7517: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7518: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7519: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7520: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7521: ENDINPUTDATE
1.560 damieng 7522: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7523: my $yeschecked='';
7524: my $nochecked='';
7525: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7526: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7527:
7528: $r->print(<<ENDYESNO);
7529: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7530: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7531: ENDYESNO
1.221 www 7532: } else {
1.560 damieng 7533: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7534: }
1.318 albertel 7535: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7536: }
1.318 albertel 7537: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7538: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7539: &mt('Save').'" /></form>'."\n");
7540: &endSettingsScreen($r);
7541: $r->print(&Apache::loncommon::end_page());
1.220 www 7542: return;
7543: }
1.193 albertel 7544:
1.560 damieng 7545: ##################################################
7546: # PARAMETER CHANGES LOG
7547: ##################################################
7548:
1.563 damieng 7549: # Returns some info for a parameter log entry.
7550: # Returned entries:
7551: # $realm - HTML title for the parameter level and resource
7552: # $section - parameter section
7553: # $name - parameter name
7554: # $part - parameter part
7555: # $what - $part.'.'.$name
7556: # $middle - resource symb ?
7557: # $uname - user name (same as given)
7558: # $udom - user domain (same as given)
7559: # $issection - section or group name
7560: # $realmdescription - title for the parameter level and resource (without using HTML)
7561: #
7562: # @param {string} $key - parameter log key
7563: # @param {string} $uname - user name
7564: # @param {string} $udom - user domain
7565: # @param {boolean} $typeflag - .type log entry
7566: # @returns {Array}
1.290 www 7567: sub components {
1.581 raeburn 7568: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7569:
7570: if ($typeflag) {
1.560 damieng 7571: $key=~s/\.type$//;
1.290 www 7572: }
1.330 albertel 7573:
7574: my ($middle,$part,$name)=
1.572 damieng 7575: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7576: my $issection;
1.330 albertel 7577:
1.290 www 7578: my $section=&mt('All Students');
7579: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7580: $issection=$1;
7581: $section=&mt('Group/Section').': '.$issection;
7582: $middle=~s/^\[(.*)\]//;
1.290 www 7583: }
7584: $middle=~s/\.+$//;
7585: $middle=~s/^\.+//;
1.291 www 7586: if ($uname) {
1.560 damieng 7587: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7588: $issection='';
1.291 www 7589: }
1.316 albertel 7590: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7591: my $realmdescription=&mt('all resources');
1.556 raeburn 7592: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7593: my $mapurl = $1;
7594: my $maplevel = $2;
7595: my $leveltitle = &mt('Folder/Map');
7596: if ($maplevel eq 'rec') {
7597: $leveltitle = &mt('Recursive');
7598: }
1.560 damieng 7599: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7600: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7601: $mapurl.')</span></span>';
7602: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7603: } elsif ($middle) {
7604: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7605: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7606: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7607: ' in '.$map.' id: '.$id.')</span></span>';
7608: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7609: }
1.291 www 7610: my $what=$part.'.'.$name;
1.330 albertel 7611: return ($realm,$section,$name,$part,
1.473 amueller 7612: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7613: }
1.293 www 7614:
1.563 damieng 7615: my %standard_parms; # hash parameter name -> parameter title (not localized)
7616: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7617:
1.563 damieng 7618: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7619: sub load_parameter_names {
1.583 raeburn 7620: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7621: while (my $configline=<$config>) {
1.560 damieng 7622: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7623: chomp($configline);
7624: my ($short,$plain)=split(/:/,$configline);
7625: my (undef,$name,$type)=split(/\&/,$short,3);
7626: if ($type eq 'display') {
7627: $standard_parms{$name} = $plain;
1.469 raeburn 7628: } elsif ($type eq 'type') {
1.560 damieng 7629: $standard_parms_types{$name} = $plain;
1.469 raeburn 7630: }
1.328 albertel 7631: }
7632: close($config);
7633: $standard_parms{'int_pos'} = 'Positive Integer';
7634: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7635: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7636: }
7637:
1.563 damieng 7638: # Returns a parameter title for standard parameters, the name for others.
7639: #
7640: # @param {string} $name - parameter name
7641: # @returns {string}
1.292 www 7642: sub standard_parameter_names {
7643: my ($name)=@_;
1.328 albertel 7644: if (!%standard_parms) {
1.560 damieng 7645: &load_parameter_names();
1.328 albertel 7646: }
1.292 www 7647: if ($standard_parms{$name}) {
1.560 damieng 7648: return $standard_parms{$name};
1.446 bisitz 7649: } else {
1.560 damieng 7650: return $name;
1.292 www 7651: }
7652: }
1.290 www 7653:
1.563 damieng 7654: # Returns a parameter type for standard parameters, undef for others.
7655: #
7656: # @param {string} $name - parameter name
7657: # @returns {string}
1.469 raeburn 7658: sub standard_parameter_types {
7659: my ($name)=@_;
7660: if (!%standard_parms_types) {
7661: &load_parameter_names();
7662: }
7663: if ($standard_parms_types{$name}) {
7664: return $standard_parms_types{$name};
7665: }
7666: return;
7667: }
1.309 www 7668:
1.563 damieng 7669: # Returns a parameter level title (not localized) from the parameter level name.
7670: #
7671: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7672: # @returns {string}
1.557 raeburn 7673: sub standard_parameter_levels {
7674: my ($name)=@_;
7675: my %levels = (
7676: 'resourcelevel' => 'a single resource',
7677: 'maplevel' => 'the enclosing map/folder',
7678: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7679: 'courselevel' => 'the general (course) level',
7680: );
7681: if ($levels{$name}) {
7682: return $levels{$name};
7683: }
7684: return;
7685: }
7686:
1.560 damieng 7687: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7688: #
7689: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7690: sub parm_change_log {
1.568 raeburn 7691: my ($r,$parm_permission)=@_;
1.531 raeburn 7692: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7693: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7694: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7695: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7696: text=>"Parameter Change Log"});
1.522 raeburn 7697: my $js = '<script type="text/javascript">'."\n".
7698: '// <![CDATA['."\n".
7699: &Apache::loncommon::display_filter_js('parmslog')."\n".
7700: '// ]]>'."\n".
7701: '</script>'."\n";
7702: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7703: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7704: &startSettingsScreen($r,'parmset',$crstype);
7705: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7706:
1.301 www 7707: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7708:
1.522 raeburn 7709: $r->print('<div class="LC_left_float">'.
7710: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7711: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7712: method="post" name="parameterlog">');
1.446 bisitz 7713:
1.311 albertel 7714: my %saveable_parameters = ('show' => 'scalar',);
7715: &Apache::loncommon::store_course_settings('parameter_log',
7716: \%saveable_parameters);
7717: &Apache::loncommon::restore_course_settings('parameter_log',
7718: \%saveable_parameters);
1.522 raeburn 7719: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7720: '<input type="submit" value="'.&mt('Display').'" />'.
7721: '</form></fieldset></div><br clear="all" />');
1.301 www 7722:
1.568 raeburn 7723: my $readonly = 1;
7724: if ($parm_permission->{'edit'}) {
7725: undef($readonly);
7726: }
1.531 raeburn 7727: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7728: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7729: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7730: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7731: unless ($readonly) {
7732: $r->print('<th>'.&mt('Announce').'</th>');
7733: }
7734: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7735: my $shown=0;
1.349 www 7736: my $folder='';
7737: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7738: my $last='';
7739: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7740: &GDBM_READER(),0640)) {
7741: $last=$hash{'last_known'};
7742: untie(%hash);
7743: }
7744: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7745: }
1.595 raeburn 7746: my $numgroups = 0;
7747: my @groups;
7748: if ($env{'request.course.groups'} ne '') {
7749: @groups = split(/:/,$env{'request.course.groups'});
7750: $numgroups = scalar(@groups);
7751: }
1.560 damieng 7752: foreach my $id (sort {
7753: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7754: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7755: }
7756: my $aid = (split('00000',$a))[-1];
7757: my $bid = (split('00000',$b))[-1];
7758: return $bid<=>$aid;
1.473 amueller 7759: } (keys(%parmlog))) {
1.294 www 7760: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7761: my $count = 0;
7762: my $time =
7763: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7764: my $plainname =
7765: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7766: $parmlog{$id}{'exe_udom'});
7767: my $about_me_link =
7768: &Apache::loncommon::aboutmewrapper($plainname,
7769: $parmlog{$id}{'exe_uname'},
7770: $parmlog{$id}{'exe_udom'});
7771: my $send_msg_link='';
1.568 raeburn 7772: if ((!$readonly) &&
7773: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7774: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7775: $send_msg_link ='<br />'.
7776: &Apache::loncommon::messagewrapper(&mt('Send message'),
7777: $parmlog{$id}{'exe_uname'},
7778: $parmlog{$id}{'exe_udom'});
7779: }
7780: my $row_start=&Apache::loncommon::start_data_table_row();
7781: my $makenewrow=0;
7782: my %istype=();
7783: my $output;
7784: foreach my $changed (reverse(sort(@changes))) {
7785: my $value=$parmlog{$id}{'logentry'}{$changed};
7786: my $typeflag = ($changed =~/\.type$/ &&
7787: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7788: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7789: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7790: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7791: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7792: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7793: if ($uname ne '') {
7794: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7795: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7796: }
7797: }
7798: if ($env{'form.displayfilter'} eq 'currentfolder') {
7799: if ($folder) {
7800: if ($middle!~/^\Q$folder\E/) { next; }
7801: }
7802: }
7803: if ($typeflag) {
7804: $istype{$parmname}=$value;
7805: if (!$env{'form.includetypes'}) { next; }
7806: }
7807: $count++;
7808: if ($makenewrow) {
7809: $output .= $row_start;
7810: } else {
7811: $makenewrow=1;
7812: }
1.470 raeburn 7813: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7814: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7815: &mt($parmitem).'</td><td>'.
7816: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7817: my $stillactive=0;
7818: if ($parmlog{$id}{'delflag'}) {
7819: $output .= &mt('Deleted');
7820: } else {
7821: if ($typeflag) {
1.470 raeburn 7822: my $parmitem = &standard_parameter_names($value);
7823: $parmitem = &mt($parmitem);
1.560 damieng 7824: $output .= &mt('Type: [_1]',$parmitem);
7825: } else {
1.584 raeburn 7826: my $toolsymb;
7827: if ($middle =~ /ext\.tool$/) {
7828: $toolsymb = $middle;
7829: }
1.560 damieng 7830: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7831: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7832: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7833: my $showvalue = $value;
7834: if ($istype{$parmname} eq '') {
7835: my $type = &standard_parameter_types($parmname);
7836: if ($type ne '') {
7837: if (&isdateparm($type)) {
7838: $showvalue =
7839: &Apache::lonlocal::locallocaltime($value);
7840: }
7841: }
7842: } else {
1.560 damieng 7843: if (&isdateparm($istype{$parmname})) {
7844: $showvalue = &Apache::lonlocal::locallocaltime($value);
1.622 ! raeburn 7845: } elsif (($istype{$parmname} eq 'string_grace') ||
! 7846: ($istype{$parmname} eq 'string_ip')) {
! 7847: $showvalue =~ s/,/, /g;
1.560 damieng 7848: }
1.469 raeburn 7849: }
7850: $output .= $showvalue;
1.560 damieng 7851: if ($value ne $all[$level]) {
7852: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7853: } else {
7854: $stillactive=1;
7855: }
7856: }
1.473 amueller 7857: }
1.568 raeburn 7858: $output .= '</td>';
7859:
7860: unless ($readonly) {
7861: $output .= '<td>';
7862: if ($stillactive) {
7863: my $parmitem = &standard_parameter_names($parmname);
7864: $parmitem = &mt($parmitem);
7865: my $title=&mt('Changed [_1]',$parmitem);
7866: my $description=&mt('Changed [_1] for [_2] to [_3]',
7867: $parmitem,$realmdescription,
7868: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
7869: if (($uname) && ($udom)) {
7870: $output .=
7871: &Apache::loncommon::messagewrapper('Notify User',
7872: $uname,$udom,$title,
7873: $description);
7874: } else {
7875: $output .=
7876: &Apache::lonrss::course_blog_link($id,$title,
7877: $description);
7878: }
1.560 damieng 7879: }
1.568 raeburn 7880: $output .= '</td>';
1.560 damieng 7881: }
1.568 raeburn 7882: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 7883: }
1.560 damieng 7884: if ($env{'form.displayfilter'} eq 'containing') {
7885: my $wholeentry=$about_me_link.':'.
7886: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
7887: $output;
7888: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 7889: }
1.349 www 7890: if ($count) {
1.560 damieng 7891: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
7892: <td rowspan="'.$count.'">'.$about_me_link.
7893: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
7894: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
7895: $send_msg_link.'</td>'.$output);
7896: $shown++;
7897: }
7898: if (!($env{'form.show'} eq &mt('all')
7899: || $shown<=$env{'form.show'})) { last; }
1.286 www 7900: }
1.301 www 7901: $r->print(&Apache::loncommon::end_data_table());
1.507 www 7902: &endSettingsScreen($r);
1.284 www 7903: $r->print(&Apache::loncommon::end_page());
7904: }
7905:
1.560 damieng 7906: ##################################################
7907: # MISC !
7908: ##################################################
7909:
1.563 damieng 7910: # Stores slot information.
1.560 damieng 7911: # Used by table UI
1.563 damieng 7912: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7913: #
7914: # @param {string} $slot_name - slot name
7915: # @param {string} $cdom - course domain
7916: # @param {string} $cnum - course number
7917: # @param {string} $symb - resource symb
7918: # @param {string} $uname - user name
7919: # @param {string} $udom - user domain
7920: # @returns {string} - 'ok' or error name
1.437 raeburn 7921: sub update_slots {
7922: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
7923: my %slot=&Apache::lonnet::get_slot($slot_name);
7924: if (!keys(%slot)) {
7925: return 'error: slot does not exist';
7926: }
7927: my $max=$slot{'maxspace'};
7928: if (!defined($max)) { $max=99999; }
7929:
7930: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
7931: "^$slot_name\0");
7932: my ($tmp)=%consumed;
7933: if ($tmp=~/^error: 2 / ) {
7934: return 'error: unable to determine current slot status';
7935: }
7936: my $last=0;
7937: foreach my $key (keys(%consumed)) {
7938: my $num=(split('\0',$key))[1];
7939: if ($num > $last) { $last=$num; }
7940: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7941: return 'ok';
7942: }
7943: }
7944:
7945: if (scalar(keys(%consumed)) >= $max) {
7946: return 'error: no space left in slot';
7947: }
7948: my $wanted=$last+1;
7949:
7950: my %reservation=('name' => $uname.':'.$udom,
7951: 'timestamp' => time,
7952: 'symb' => $symb);
7953:
7954: my $success=&Apache::lonnet::newput('slot_reservations',
7955: {"$slot_name\0$wanted" =>
7956: \%reservation},
7957: $cdom, $cnum);
1.438 raeburn 7958: if ($success eq 'ok') {
7959: my %storehash = (
7960: symb => $symb,
7961: slot => $slot_name,
7962: action => 'reserve',
7963: context => 'parameter',
7964: );
1.526 raeburn 7965: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7966: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 7967:
1.526 raeburn 7968: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7969: '',$uname,$udom,$uname,$udom);
1.438 raeburn 7970: }
1.437 raeburn 7971: return $success;
7972: }
7973:
1.563 damieng 7974: # Deletes a slot reservation.
1.560 damieng 7975: # Used by table UI
1.563 damieng 7976: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7977: #
7978: # @param {string} $slot_name - slot name
7979: # @param {string} $cdom - course domain
7980: # @param {string} $cnum - course number
7981: # @param {string} $uname - user name
7982: # @param {string} $udom - user domain
7983: # @param {string} $symb - resource symb
7984: # @returns {string} - 'ok' or error name
1.437 raeburn 7985: sub delete_slots {
7986: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
7987: my $delresult;
7988: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
7989: $cnum, "^$slot_name\0");
7990: if (&Apache::lonnet::error(%consumed)) {
7991: return 'error: unable to determine current slot status';
7992: }
7993: my ($tmp)=%consumed;
7994: if ($tmp=~/^error: 2 /) {
7995: return 'error: unable to determine current slot status';
7996: }
7997: foreach my $key (keys(%consumed)) {
7998: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7999: my $num=(split('\0',$key))[1];
8000: my $entry = $slot_name.'\0'.$num;
8001: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
8002: $cdom,$cnum);
8003: if ($delresult eq 'ok') {
8004: my %storehash = (
8005: symb => $symb,
8006: slot => $slot_name,
8007: action => 'release',
8008: context => 'parameter',
8009: );
1.526 raeburn 8010: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 8011: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 8012: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 8013: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 8014: }
8015: }
8016: }
8017: return $delresult;
8018: }
8019:
1.563 damieng 8020: # Returns true if there is a current course.
1.560 damieng 8021: # Used by handler
1.563 damieng 8022: #
8023: # @returns {boolean}
1.355 albertel 8024: sub check_for_course_info {
8025: my $navmap = Apache::lonnavmaps::navmap->new();
8026: return 1 if ($navmap);
8027: return 0;
8028: }
8029:
1.563 damieng 8030: # Returns the current course host and host LON-CAPA version.
8031: #
8032: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 8033: sub parameter_release_vars {
1.504 raeburn 8034: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
8035: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
8036: my $chostname = &Apache::lonnet::hostname($chome);
8037: my ($cmajor,$cminor) =
8038: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
8039: return ($chostname,$cmajor,$cminor);
8040: }
8041:
1.563 damieng 8042: # Checks if the course host version can handle a parameter required version,
8043: # and if it does, stores the release needed for the course.
8044: #
8045: # @param {string} $name - parameter name
8046: # @param {string} $value - parameter value
8047: # @param {string} $valmatch - name of the test used for checking the value
8048: # @param {string} $namematch - name of the test used for checking the name
8049: # @param {string} $needsrelease - version needed by the parameter, major.minor
8050: # @param {integer} $cmajor - course major version number
8051: # @param {integer} $cminor - course minor version number
8052: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 8053: sub parameter_releasecheck {
1.557 raeburn 8054: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 8055: my $needsnewer;
8056: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
8057: if (($cmajor < $needsmajor) ||
8058: ($cmajor == $needsmajor && $cminor < $needsminor)) {
8059: $needsnewer = 1;
1.557 raeburn 8060: } elsif ($name) {
8061: if ($valmatch) {
8062: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
8063: } elsif ($value) {
8064: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
8065: }
8066: } elsif ($namematch) {
8067: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 8068: }
8069: return $needsnewer;
8070: }
8071:
1.568 raeburn 8072: sub get_permission {
8073: my %permission;
8074: my $allowed = 0;
8075: return (\%permission,$allowed) unless ($env{'request.course.id'});
8076: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
8077: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
8078: $env{'request.course.sec'}))) {
8079: %permission= (
8080: 'edit' => 1,
8081: 'set' => 1,
8082: 'setoverview' => 1,
8083: 'addmetadata' => 1,
8084: 'ordermetadata' => 1,
8085: 'setrestrictmeta' => 1,
8086: 'newoverview' => 1,
8087: 'setdefaults' => 1,
8088: 'settable' => 1,
8089: 'parameterchangelog' => 1,
8090: 'cleanparameters' => 1,
8091: 'dateshift1' => 1,
8092: 'dateshift2' => 1,
8093: 'helper' => 1,
8094: );
8095: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
8096: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
8097: $env{'request.course.sec'}))) {
8098: %permission = (
8099: 'set' => 1,
8100: 'settable' => 1,
8101: 'newoverview' => 1,
8102: 'setoverview' => 1,
8103: 'parameterchangelog' => 1,
8104: );
8105: }
8106: foreach my $perm (values(%permission)) {
8107: if ($perm) { $allowed=1; last; }
8108: }
8109: return (\%permission,$allowed);
8110: }
8111:
1.560 damieng 8112: ##################################################
8113: # HANDLER
8114: ##################################################
8115:
8116: # Main handler for lonparmset.
8117: # Sub called based on request parameters action and command:
8118: # no command or action: print_main_menu
8119: # command 'set': assessparms (direct access to table mode for a resource)
8120: # (this can also be accessed simply with the symb parameter)
8121: # action 'setoverview': overview (display all existing parameter settings)
8122: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
8123: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
8124: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
8125: # action 'newoverview': newoverview (overview mode)
8126: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
8127: # action 'settable': assessparms (table mode)
8128: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
8129: # blog postings, user notification changes)
8130: # action 'cleanparameters': clean_parameters (unused)
8131: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
8132: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 8133: sub handler {
1.43 albertel 8134: my $r=shift;
1.30 www 8135:
1.376 albertel 8136: &reset_caches();
8137:
1.414 droeschl 8138: &Apache::loncommon::content_type($r,'text/html');
8139: $r->send_http_header;
8140: return OK if $r->header_only;
8141:
1.193 albertel 8142: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 8143: ['action','state',
1.205 www 8144: 'pres_marker',
8145: 'pres_value',
1.206 www 8146: 'pres_type',
1.506 www 8147: 'filter','part',
1.390 www 8148: 'udom','uname','symb','serial','timebase']);
1.131 www 8149:
1.83 bowersj2 8150:
1.193 albertel 8151: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 8152: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 8153: text=>"Content and Problem Settings",
1.473 amueller 8154: faq=>10,
8155: bug=>'Instructor Interface',
1.442 droeschl 8156: help =>
8157: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 8158:
1.30 www 8159: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 8160: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 8161: my $exists = &check_for_course_info();
8162:
1.568 raeburn 8163: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 8164: #
8165: # Main switch on form.action and form.state, as appropriate
8166: #
8167: # Check first if coming from someone else headed directly for
8168: # the table mode
1.568 raeburn 8169: if (($parm_permission->{'set'}) &&
8170: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
8171: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
8172: &assessparms($r,$parm_permission);
1.193 albertel 8173: } elsif (! exists($env{'form.action'})) {
8174: &print_main_menu($r,$parm_permission);
1.568 raeburn 8175: } elsif (!$parm_permission->{$env{'form.action'}}) {
8176: &print_main_menu($r,$parm_permission);
1.414 droeschl 8177: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 8178: &overview($r,$parm_permission);
1.560 damieng 8179: } elsif ($env{'form.action'} eq 'addmetadata') {
8180: &addmetafield($r);
8181: } elsif ($env{'form.action'} eq 'ordermetadata') {
8182: &order_meta_fields($r);
1.414 droeschl 8183: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 8184: &setrestrictmeta($r);
1.414 droeschl 8185: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 8186: &newoverview($r,$parm_permission);
1.414 droeschl 8187: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 8188: &defaultsetter($r);
8189: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 8190: &assessparms($r,$parm_permission);
1.414 droeschl 8191: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 8192: &parm_change_log($r,$parm_permission);
1.414 droeschl 8193: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 8194: &clean_parameters($r);
1.414 droeschl 8195: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 8196: &date_shift_one($r);
1.414 droeschl 8197: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 8198: &date_shift_two($r);
1.446 bisitz 8199: }
1.43 albertel 8200: } else {
1.1 www 8201: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 8202: if ($exists) {
8203: $env{'user.error.msg'}=
8204: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
8205: } else {
8206: $env{'user.error.msg'}=
8207: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
8208: }
8209: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 8210: }
1.376 albertel 8211: &reset_caches();
8212:
1.43 albertel 8213: return OK;
1.1 www 8214: }
8215:
8216: 1;
8217: __END__
8218:
8219:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>