Annotation of loncom/interface/lonparmset.pm, revision 1.607
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.607 ! raeburn 4: # $Id: lonparmset.pm,v 1.606 2022/03/24 15:57:36 raeburn Exp $
1.40 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.59 matthew 28: ###################################################################
29: ###################################################################
30:
31: =pod
32:
33: =head1 NAME
34:
35: lonparmset - Handler to set parameters for assessments and course
36:
37: =head1 SYNOPSIS
38:
1.579 raeburn 39: lonparmset provides an interface to setting content parameters in a
40: course.
1.560 damieng 41:
42: It contains all the code for the "Content and Problem Settings" UI, except
43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
44: and lonblockingmenu.pm.
1.59 matthew 45:
46: =head1 DESCRIPTION
47:
48: This module sets coursewide and assessment parameters.
49:
50: =head1 INTERNAL SUBROUTINES
51:
1.416 jms 52: =over
1.59 matthew 53:
1.416 jms 54: =item parmval()
1.59 matthew 55:
56: Figure out a cascading parameter.
57:
1.71 albertel 58: Inputs: $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162 albertel 59: $id - a bighash Id number
1.71 albertel 60: $def - the resource's default value 'stupid emacs
61:
1.556 raeburn 62: Returns: A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71 albertel 63:
1.556 raeburn 64: 18 - General Course
65: 17 - Map or Folder level in course (recursive)
66: 16 - Map or Folder level in course (non-recursive)
67: 15 - resource default
68: 14 - map default
69: 13 - resource level in course
70: 12 - General for section
71: 11 - Map or Folder level for section (recursive)
72: 10 - Map or Folder level for section (non-recursive)
73: 9 - resource level in section
74: 8 - General for group
75: 7 - Map or Folder level for group (recursive)
76: 6 - Map or Folder level for group (non-recursive)
77: 5 - resource level in group
78: 4 - General for specific student
79: 3 - Map or Folder level for specific student (recursive)
80: 2 - Map or Folder level for specific student (non-recursive)
1.71 albertel 81: 1 - resource level for specific student
1.2 www 82:
1.416 jms 83: =item parmval_by_symb()
84:
85: =item reset_caches()
86:
87: =item cacheparmhash()
88:
89: =item parmhash()
90:
91: =item symbcache()
92:
93: =item preset_defaults()
94:
95: =item date_sanity_info()
96:
97: =item storeparm()
98:
99: Store a parameter by symb
100:
101: Takes
102: - symb
103: - name of parameter
104: - level
105: - new value
106: - new type
107: - username
108: - userdomain
109:
110: =item log_parmset()
111:
112: =item storeparm_by_symb_inner()
113:
114: =item valout()
115:
116: Format a value for output.
117:
118: Inputs: $value, $type, $editable
119:
120: Returns: $value, formatted for output. If $type indicates it is a date,
121: localtime($value) is returned.
122: $editable will return an icon to click on
123:
124: =item plink()
125:
126: Produces a link anchor.
127:
128: Inputs: $type,$dis,$value,$marker,$return,$call
129:
130: Returns: scalar with html code for a link which will envoke the
131: javascript function 'pjump'.
132:
133: =item page_js()
134:
135: =item startpage()
136:
137: =item print_row()
138:
139: =item print_td()
140:
1.580 raeburn 141: =item check_other_groups()
1.416 jms 142:
143: =item parm_control_group()
144:
145: =item extractResourceInformation() :
146:
1.512 foxr 147: extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416 jms 148:
1.542 raeburn 149: Input: See list below
150:
151: =over 4
1.416 jms 152:
1.512 foxr 153: =item * B<env{'user.name'}> : Current username
1.416 jms 154:
1.512 foxr 155: =item * B<env{'user.domain'}> : Domain of current user.
1.416 jms 156:
1.542 raeburn 157: =item * B<env{"request.course.fn"}> : Course
158:
159: =back
1.416 jms 160:
1.512 foxr 161: Outputs: See list below:
1.416 jms 162:
1.542 raeburn 163: =over 4
164:
1.512 foxr 165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416 jms 166:
1.512 foxr 167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416 jms 168:
1.512 foxr 169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416 jms 170:
1.512 foxr 171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416 jms 172:
1.512 foxr 173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
174:
175: =item * B<allmaps> (out) : hash, ???
1.416 jms 176:
177: =item * B<mapp> : ??
178:
179: =item * B<symbp> : hash, id->full sym?
180:
1.512 foxr 181: =item * B<maptitles>
182:
183: =item * B<uris>
1.416 jms 184:
1.512 foxr 185: =item * B<keyorder>
186:
187: =item * B<defkeytype>
1.416 jms 188:
1.542 raeburn 189: =back
190:
1.416 jms 191: =item isdateparm()
192:
193: =item parmmenu()
194:
195: =item partmenu()
196:
197: =item usermenu()
198:
199: =item displaymenu()
200:
201: =item mapmenu()
202:
203: =item levelmenu()
204:
205: =item sectionmenu()
206:
207: =item keysplit()
208:
209: =item keysinorder()
210:
211: =item keysinorder_bytype()
212:
213: =item keysindisplayorder()
214:
215: =item standardkeyorder()
216:
217: =item assessparms() :
218:
219: Show assessment data and parameters. This is a large routine that should
220: be simplified and shortened... someday.
221:
1.513 foxr 222: Inputs: $r - the Apache request object.
223:
1.416 jms 224: Returns: nothing
225:
226: Variables used (guessed by Jeremy):
227:
1.542 raeburn 228: =over
229:
1.416 jms 230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
231:
232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
233:
234: =item * B<@catmarker> contains list of all possible parameters including part #s
235:
236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
237:
238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
239: When storing information, store as part 0
240: When requesting information, request from full part
241:
1.542 raeburn 242: =back
243:
1.416 jms 244: =item tablestart()
245:
246: =item tableend()
247:
248: =item extractuser()
249:
250: =item parse_listdata_key()
251:
252: =item listdata()
253:
254: =item date_interval_selector()
255:
256: =item get_date_interval_from_form()
257:
258: =item default_selector()
259:
260: =item string_selector()
261:
262: =item dateshift()
263:
264: =item newoverview()
265:
266: =item secgroup_lister()
267:
268: =item overview()
269:
270: =item clean_parameters()
271:
272: =item date_shift_one()
273:
274: =item date_shift_two()
275:
276: =item parse_key()
277:
278: =item header()
279:
280: Output html header for page
281:
282: =item print_main_menu()
283:
284: =item output_row()
285:
286: Set portfolio metadata
287:
288: =item order_meta_fields()
289:
290: =item addmetafield()
291:
292: =item setrestrictmeta()
293:
294: =item get_added_meta_fieldnames()
295:
296: =item get_deleted_meta_fieldnames()
297:
298: =item defaultsetter()
299:
300: =item components()
301:
302: =item load_parameter_names()
303:
304: =item parm_change_log()
305:
306: =item handler() :
307:
1.450 raeburn 308: Main handler. Calls &assessparms subroutine.
1.416 jms 309:
310: =back
311:
1.59 matthew 312: =cut
313:
1.416 jms 314: ###################################################################
315: ###################################################################
316:
317: package Apache::lonparmset;
318:
319: use strict;
320: use Apache::lonnet;
321: use Apache::Constants qw(:common :http REDIRECT);
322: use Apache::lonhtmlcommon();
323: use Apache::loncommon;
324: use GDBM_File;
325: use Apache::lonhomework;
326: use Apache::lonxml;
327: use Apache::lonlocal;
328: use Apache::lonnavmaps;
329: use Apache::longroup;
330: use Apache::lonrss;
1.506 www 331: use HTML::Entities;
1.416 jms 332: use LONCAPA qw(:DEFAULT :match);
333:
334:
1.560 damieng 335: ##################################################
336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
337: ##################################################
338:
339: # Page header
1.561 damieng 340: #
341: # @param {Apache2::RequestRec} $r - Apache request object
342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
343: # @param {string} $crstype - course type ('Community' for community settings)
1.507 www 344: sub startSettingsScreen {
1.531 raeburn 345: my ($r,$mode,$crstype)=@_;
1.507 www 346:
1.531 raeburn 347: my $tabtext = &mt('Course Settings');
348: if ($crstype eq 'Community') {
349: $tabtext = &mt('Community Settings');
350: }
1.507 www 351: $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
352: $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b> '.
1.531 raeburn 353: $tabtext.
1.507 www 354: ' </b></a></li>');
355:
1.523 raeburn 356: $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507 www 357: &mt('Content and Problem Settings').'</b></a></li>');
358: $r->print("\n".'</ul>'."\n");
1.523 raeburn 359: $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507 www 360: }
361:
1.560 damieng 362: # Page footer
1.507 www 363: sub endSettingsScreen {
364: my ($r)=@_;
365: $r->print('</div></div></div>');
366: }
367:
368:
369:
1.560 damieng 370: ##################################################
1.563 damieng 371: # (mostly) TABLE MODE
1.560 damieng 372: # (parmval is also used for the log of parameter changes)
373: ##################################################
374:
1.566 damieng 375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561 damieng 376: #
377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 378: # @param {string} $id - resource id or map pc
1.561 damieng 379: # @param {string} $def - the resource's default value for this parameter
380: # @param {string} $uname - user name
381: # @param {string} $udom - user domain
382: # @param {string} $csec - section name
383: # @param {string} $cgroup - group name
384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
385: # @returns {Array}
1.2 www 386: sub parmval {
1.275 raeburn 387: my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
388: return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
389: $cgroup,$courseopt);
1.201 www 390: }
391:
1.561 damieng 392: # Returns an array containing
393: # - the most specific level that is defined for that parameter (integer)
394: # - an array with the level as index and the parameter value as value (when defined)
395: # (level 1 is the most specific and will have precedence)
396: #
397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 398: # @param {string} $symb - resource symb or map src
1.561 damieng 399: # @param {string} $def - the resource's default value for this parameter
400: # @param {string} $uname - user name
401: # @param {string} $udom - user domain
402: # @param {string} $csec - section name
403: # @param {string} $cgroup - group name
404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
405: # @returns {Array}
1.201 www 406: sub parmval_by_symb {
1.275 raeburn 407: my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200 www 408:
1.352 albertel 409: my $useropt;
410: if ($uname ne '' && $udom ne '') {
1.561 damieng 411: $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352 albertel 412: }
1.200 www 413:
1.8 www 414: my $result='';
1.44 albertel 415: my @outpar=();
1.2 www 416: # ----------------------------------------------------- Cascading lookup scheme
1.446 bisitz 417: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 418: $map = &Apache::lonnet::deversion($map);
1.561 damieng 419:
420: # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
421: # any change should be reflected there.
422:
1.201 www 423: my $symbparm=$symb.'.'.$what;
1.556 raeburn 424: my $recurseparm=$map.'___(rec).'.$what;
1.201 www 425: my $mapparm=$map.'___(all).'.$what;
1.10 www 426:
1.269 raeburn 427: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
428: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 429: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 430: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
431:
1.190 albertel 432: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
433: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 434: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 435: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
436:
437: my $courselevel=$env{'request.course.id'}.'.'.$what;
438: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 439: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 440: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2 www 441:
1.11 www 442:
1.182 albertel 443: # --------------------------------------------------------- first, check course
1.11 www 444:
1.561 damieng 445: # 18 - General Course
1.200 www 446: if (defined($$courseopt{$courselevel})) {
1.556 raeburn 447: $outpar[18]=$$courseopt{$courselevel};
448: $result=18;
449: }
450:
1.561 damieng 451: # 17 - Map or Folder level in course (recursive)
1.556 raeburn 452: if (defined($$courseopt{$courseleveli})) {
453: $outpar[17]=$$courseopt{$courseleveli};
454: $result=17;
1.43 albertel 455: }
1.11 www 456:
1.561 damieng 457: # 16 - Map or Folder level in course (non-recursive)
1.200 www 458: if (defined($$courseopt{$courselevelm})) {
1.556 raeburn 459: $outpar[16]=$$courseopt{$courselevelm};
460: $result=16;
1.43 albertel 461: }
1.11 www 462:
1.182 albertel 463: # ------------------------------------------------------- second, check default
464:
1.561 damieng 465: # 15 - resource default
1.556 raeburn 466: if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182 albertel 467:
468: # ------------------------------------------------------ third, check map parms
469:
1.556 raeburn 470:
1.561 damieng 471: # 14 - map default
1.376 albertel 472: my $thisparm=&parmhash($symbparm);
1.556 raeburn 473: if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182 albertel 474:
1.561 damieng 475: # 13 - resource level in course
1.200 www 476: if (defined($$courseopt{$courselevelr})) {
1.556 raeburn 477: $outpar[13]=$$courseopt{$courselevelr};
478: $result=13;
1.43 albertel 479: }
1.11 www 480:
1.182 albertel 481: # ------------------------------------------------------ fourth, back to course
1.352 albertel 482: if ($csec ne '') {
1.561 damieng 483: # 12 - General for section
1.200 www 484: if (defined($$courseopt{$seclevel})) {
1.556 raeburn 485: $outpar[12]=$$courseopt{$seclevel};
486: $result=12;
487: }
1.561 damieng 488: # 11 - Map or Folder level for section (recursive)
1.556 raeburn 489: if (defined($$courseopt{$secleveli})) {
490: $outpar[11]=$$courseopt{$secleveli};
491: $result=11;
492: }
1.561 damieng 493: # 10 - Map or Folder level for section (non-recursive)
1.200 www 494: if (defined($$courseopt{$seclevelm})) {
1.556 raeburn 495: $outpar[10]=$$courseopt{$seclevelm};
496: $result=10;
497: }
1.561 damieng 498: # 9 - resource level in section
1.200 www 499: if (defined($$courseopt{$seclevelr})) {
1.556 raeburn 500: $outpar[9]=$$courseopt{$seclevelr};
501: $result=9;
502: }
1.43 albertel 503: }
1.275 raeburn 504: # ------------------------------------------------------ fifth, check course group
1.352 albertel 505: if ($cgroup ne '') {
1.561 damieng 506: # 8 - General for group
1.269 raeburn 507: if (defined($$courseopt{$grplevel})) {
1.556 raeburn 508: $outpar[8]=$$courseopt{$grplevel};
509: $result=8;
510: }
1.561 damieng 511: # 7 - Map or Folder level for group (recursive)
1.556 raeburn 512: if (defined($$courseopt{$grpleveli})) {
513: $outpar[7]=$$courseopt{$grpleveli};
514: $result=7;
1.269 raeburn 515: }
1.561 damieng 516: # 6 - Map or Folder level for group (non-recursive)
1.269 raeburn 517: if (defined($$courseopt{$grplevelm})) {
1.556 raeburn 518: $outpar[6]=$$courseopt{$grplevelm};
519: $result=6;
1.269 raeburn 520: }
1.561 damieng 521: # 5 - resource level in group
1.269 raeburn 522: if (defined($$courseopt{$grplevelr})) {
1.556 raeburn 523: $outpar[5]=$$courseopt{$grplevelr};
524: $result=5;
1.269 raeburn 525: }
526: }
1.11 www 527:
1.556 raeburn 528: # ---------------------------------------------------------- sixth, check user
1.11 www 529:
1.352 albertel 530: if ($uname ne '') {
1.561 damieng 531: # 4 - General for specific student
532: if (defined($$useropt{$courselevel})) {
533: $outpar[4]=$$useropt{$courselevel};
534: $result=4;
535: }
1.556 raeburn 536:
1.561 damieng 537: # 3 - Map or Folder level for specific student (recursive)
538: if (defined($$useropt{$courseleveli})) {
539: $outpar[3]=$$useropt{$courseleveli};
540: $result=3;
541: }
1.473 amueller 542:
1.561 damieng 543: # 2 - Map or Folder level for specific student (non-recursive)
544: if (defined($$useropt{$courselevelm})) {
545: $outpar[2]=$$useropt{$courselevelm};
546: $result=2;
547: }
1.473 amueller 548:
1.561 damieng 549: # 1 - resource level for specific student
550: if (defined($$useropt{$courselevelr})) {
551: $outpar[1]=$$useropt{$courselevelr};
552: $result=1;
553: }
1.43 albertel 554: }
1.44 albertel 555: return ($result,@outpar);
1.2 www 556: }
557:
1.198 www 558:
559:
1.376 albertel 560: # --- Caches local to lonparmset
561:
1.446 bisitz 562:
1.561 damieng 563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376 albertel 564: sub reset_caches {
565: &resetparmhash();
566: &resetsymbcache();
567: &resetrulescache();
1.203 www 568: }
569:
1.561 damieng 570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376 albertel 572: {
1.561 damieng 573: my $parmhashid; # course identifier, to initialize the cache only once for a course
574: my %parmhash; # the parameter cache
575: # reset map parameter hash
1.376 albertel 576: sub resetparmhash {
1.560 damieng 577: undef($parmhashid);
578: undef(%parmhash);
1.376 albertel 579: }
1.446 bisitz 580:
1.561 damieng 581: # dump the _parms.db database into %parmhash
1.376 albertel 582: sub cacheparmhash {
1.560 damieng 583: if ($parmhashid eq $env{'request.course.fn'}) { return; }
584: my %parmhashfile;
585: if (tie(%parmhashfile,'GDBM_File',
586: $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
587: %parmhash=%parmhashfile;
588: untie(%parmhashfile);
589: $parmhashid=$env{'request.course.fn'};
590: }
1.201 www 591: }
1.446 bisitz 592:
1.561 damieng 593: # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376 albertel 594: sub parmhash {
1.560 damieng 595: my ($id) = @_;
596: &cacheparmhash();
597: return $parmhash{$id};
1.376 albertel 598: }
1.560 damieng 599: }
1.376 albertel 600:
1.566 damieng 601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446 bisitz 602: {
1.561 damieng 603: my $symbsid; # course identifier, to initialize the cache only once for a course
604: my %symbs; # hash id->symb
605: # reset the id->symb cache
1.376 albertel 606: sub resetsymbcache {
1.560 damieng 607: undef($symbsid);
608: undef(%symbs);
1.376 albertel 609: }
1.446 bisitz 610:
1.566 damieng 611: # returns the resource symb or map src corresponding to a resource id or map pc
612: # (using lonnavmaps and a cache)
1.376 albertel 613: sub symbcache {
1.560 damieng 614: my $id=shift;
615: if ($symbsid ne $env{'request.course.id'}) {
616: undef(%symbs);
617: }
618: if (!$symbs{$id}) {
619: my $navmap = Apache::lonnavmaps::navmap->new();
620: if ($id=~/\./) {
621: my $resource=$navmap->getById($id);
622: $symbs{$id}=$resource->symb();
623: } else {
624: my $resource=$navmap->getByMapPc($id);
625: $symbs{$id}=&Apache::lonnet::declutter($resource->src());
626: }
627: $symbsid=$env{'request.course.id'};
1.473 amueller 628: }
1.560 damieng 629: return $symbs{$id};
1.473 amueller 630: }
1.560 damieng 631: }
1.201 www 632:
1.561 damieng 633: # cache for parameter default actions (stored in parmdefactions.db)
1.446 bisitz 634: {
1.561 damieng 635: my $rulesid; # course identifier, to initialize the cache only once for a course
636: my %rules; # parameter default actions hash
1.376 albertel 637: sub resetrulescache {
1.560 damieng 638: undef($rulesid);
639: undef(%rules);
1.376 albertel 640: }
1.446 bisitz 641:
1.561 damieng 642: # returns the value for a given key in the parameter default action hash
1.376 albertel 643: sub rulescache {
1.560 damieng 644: my $id=shift;
645: if ($rulesid ne $env{'request.course.id'}
646: && !defined($rules{$id})) {
647: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
648: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
649: %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
650: $rulesid=$env{'request.course.id'};
651: }
652: return $rules{$id};
1.221 www 653: }
654: }
655:
1.416 jms 656:
1.561 damieng 657: # Returns the values of the parameter type default action
658: # "default value when manually setting".
659: # If none is defined, ('','','','','') is returned.
660: #
661: # @param {string} $type - parameter type
662: # @returns {Array<string>} - (hours, min, sec, value)
1.229 www 663: sub preset_defaults {
664: my $type=shift;
665: if (&rulescache($type.'_action') eq 'default') {
1.560 damieng 666: # yes, there is something
667: return (&rulescache($type.'_hours'),
668: &rulescache($type.'_min'),
669: &rulescache($type.'_sec'),
670: &rulescache($type.'_value'));
1.229 www 671: } else {
1.560 damieng 672: # nothing there or something else
673: return ('','','','','');
1.229 www 674: }
675: }
676:
1.416 jms 677:
1.561 damieng 678: # Checks that a date is after enrollment start date and before
679: # enrollment end date.
680: # Returns HTML with a warning if it is not, or the empty string otherwise.
681: # This is used by both overview and table modes.
682: #
683: # @param {integer} $checkdate - the date to check.
684: # @returns {string} - HTML possibly containing a localized warning message.
1.277 www 685: sub date_sanity_info {
686: my $checkdate=shift;
687: unless ($checkdate) { return ''; }
688: my $result='';
689: my $crsprefix='course.'.$env{'request.course.id'}.'.';
690: if ($env{$crsprefix.'default_enrollment_end_date'}) {
691: if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413 bisitz 692: $result.='<div class="LC_warning">'
693: .&mt('After course enrollment end!')
694: .'</div>';
1.277 www 695: }
696: }
697: if ($env{$crsprefix.'default_enrollment_start_date'}) {
698: if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413 bisitz 699: $result.='<div class="LC_warning">'
700: .&mt('Before course enrollment start!')
701: .'</div>';
1.277 www 702: }
703: }
1.413 bisitz 704: # Preparation for additional warnings about dates in the past/future.
705: # An improved, more context sensitive version is recommended,
706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
707: # if ($checkdate<time) {
708: # $result.='<div class="LC_info">'
709: # .'('.&mt('in the past').')'
710: # .'</div>';
711: # }
712: # if ($checkdate>time) {
713: # $result.='<div class="LC_info">'
714: # .'('.&mt('in the future').')'
715: # .'</div>';
716: # }
1.277 www 717: return $result;
718: }
1.561 damieng 719:
720:
721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186 www 722: #
1.566 damieng 723: # @param {string} $sresid - resource id or map pc
1.565 damieng 724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 725: # @param {integer} $snum - level
726: # @param {string} $nval - new value
727: # @param {string} $ntype - new type
728: # @param {string} $uname - username
729: # @param {string} $udom - userdomain
730: # @param {string} $csec - section name
731: # @param {string} $cgroup - group name
1.186 www 732: sub storeparm {
1.269 raeburn 733: my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275 raeburn 734: &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197 www 735: }
736:
1.561 damieng 737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
738:
739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
741: #
1.566 damieng 742: # @param {string} $symb - resource symb or map src
1.565 damieng 743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 744: # @param {integer} $snum - level
745: # @param {string} $nval - new value
746: # @param {string} $ntype - new type
747: # @param {string} $uname - username
748: # @param {string} $udom - userdomain
749: # @param {string} $csec - section name
750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
751: # @param {string} $cgroup - group name
1.197 www 752: sub storeparm_by_symb {
1.275 raeburn 753: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226 www 754: unless ($recflag) {
1.560 damieng 755: # first time call
756: %recstack=();
757: $recflag=1;
1.226 www 758: }
1.560 damieng 759: # store parameter
1.226 www 760: &storeparm_by_symb_inner
1.473 amueller 761: ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560 damieng 762: # don't do anything if parameter was reset
1.266 www 763: unless ($nval) { return; }
1.226 www 764: my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560 damieng 765: # remember that this was set
1.226 www 766: $recstack{$parm}=1;
1.560 damieng 767: # what does this trigger?
1.226 www 768: foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560 damieng 769: # don't backfire
770: unless ((!$triggered) || ($recstack{$triggered})) {
771: my $action=&rulescache($triggered.'_action');
772: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
773: # set triggered parameter on same level
774: my $newspnam=$prefix.$triggered;
775: my $newvalue='';
776: my $active=1;
777: if ($action=~/^when\_setting/) {
778: # are there restrictions?
779: if (&rulescache($triggered.'_triggervalue')=~/\w/) {
780: $active=0;
1.565 damieng 781: foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560 damieng 782: if (lc($possiblevalue) eq lc($nval)) { $active=1; }
783: }
784: }
785: $newvalue=&rulescache($triggered.'_value');
786: } else {
787: my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
788: if ($action=~/^later\_than/) {
789: $newvalue=$nval+$totalsecs;
790: } else {
791: $newvalue=$nval-$totalsecs;
792: }
793: }
794: if ($active) {
795: &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
796: $uname,$udom,$csec,$recflag,$cgroup);
797: }
798: }
1.226 www 799: }
800: return '';
801: }
802:
1.561 damieng 803: # Adds all given arguments to the course parameter log.
804: # @returns {string} - the answer to the lonnet query.
1.293 www 805: sub log_parmset {
1.525 raeburn 806: return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284 www 807: }
808:
1.561 damieng 809: # Store a parameter value and type by symb, without using the parameter default actions.
810: # Expire related sheets.
811: #
1.566 damieng 812: # @param {string} $symb - resource symb or map src
1.561 damieng 813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
814: # @param {integer} $snum - level
815: # @param {string} $nval - new value
816: # @param {string} $ntype - new type
817: # @param {string} $uname - username
818: # @param {string} $udom - userdomain
819: # @param {string} $csec - section name
820: # @param {string} $cgroup - group name
821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226 www 822: sub storeparm_by_symb_inner {
1.197 www 823: # ---------------------------------------------------------- Get symb, map, etc
1.269 raeburn 824: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197 www 825: # ---------------------------------------------------------- Construct prefixes
1.186 www 826: $spnam=~s/\_([^\_]+)$/\.$1/;
1.446 bisitz 827: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 828: $map = &Apache::lonnet::deversion($map);
829:
1.197 www 830: my $symbparm=$symb.'.'.$spnam;
1.556 raeburn 831: my $recurseparm=$map.'___(rec).'.$spnam;
1.197 www 832: my $mapparm=$map.'___(all).'.$spnam;
833:
1.269 raeburn 834: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
835: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 836: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 837: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
838:
1.190 albertel 839: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
840: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 841: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 842: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446 bisitz 843:
1.190 albertel 844: my $courselevel=$env{'request.course.id'}.'.'.$spnam;
845: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 846: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 847: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446 bisitz 848:
1.186 www 849: my $storeunder='';
1.578 raeburn 850: my $possreplace='';
1.556 raeburn 851: if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578 raeburn 852: if (($snum==17) || ($snum==3)) {
853: $storeunder=$courseleveli;
854: $possreplace=$courselevelm;
855: }
856: if (($snum==16) || ($snum==2)) {
857: $storeunder=$courselevelm;
858: $possreplace=$courseleveli;
859: }
1.556 raeburn 860: if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
861: if ($snum==12) { $storeunder=$seclevel; }
1.578 raeburn 862: if ($snum==11) {
863: $storeunder=$secleveli;
864: $possreplace=$seclevelm;
865: }
866: if ($snum==10) {
867: $storeunder=$seclevelm;
868: $possreplace=$secleveli;
869: }
1.556 raeburn 870: if ($snum==9) { $storeunder=$seclevelr; }
871: if ($snum==8) { $storeunder=$grplevel; }
1.578 raeburn 872: if ($snum==7) {
873: $storeunder=$grpleveli;
874: $possreplace=$grplevelm;
875: }
876: if ($snum==6) {
877: $storeunder=$grplevelm;
878: $possreplace=$grpleveli;
879: }
1.556 raeburn 880: if ($snum==5) { $storeunder=$grplevelr; }
1.269 raeburn 881:
1.446 bisitz 882:
1.186 www 883: my $delete;
884: if ($nval eq '') { $delete=1;}
885: my %storecontent = ($storeunder => $nval,
1.473 amueller 886: $storeunder.'.type' => $ntype);
1.186 www 887: my $reply='';
1.560 damieng 888:
1.556 raeburn 889: if ($snum>4) {
1.186 www 890: # ---------------------------------------------------------------- Store Course
891: #
1.560 damieng 892: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
893: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
894: # Expire sheets
895: &Apache::lonnet::expirespread('','','studentcalc');
896: if (($snum==13) || ($snum==9) || ($snum==5)) {
897: &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578 raeburn 898: } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560 damieng 899: &Apache::lonnet::expirespread('','','assesscalc',$map);
900: } else {
901: &Apache::lonnet::expirespread('','','assesscalc');
902: }
903: # Store parameter
904: if ($delete) {
905: $reply=&Apache::lonnet::del
906: ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
907: &log_parmset(\%storecontent,1);
908: } else {
909: $reply=&Apache::lonnet::cput
910: ('resourcedata',\%storecontent,$cdom,$cnum);
911: &log_parmset(\%storecontent);
1.578 raeburn 912: if ($possreplace) {
913: my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
914: if (ref($resdata) eq 'HASH') {
915: if (exists($resdata->{$possreplace})) {
916: if (&Apache::lonnet::del
917: ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
918: &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);
919: }
920: }
921: }
922: }
1.560 damieng 923: }
924: &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186 www 925: } else {
926: # ------------------------------------------------------------------ Store User
927: #
1.560 damieng 928: # Expire sheets
929: &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
930: if ($snum==1) {
931: &Apache::lonnet::expirespread
932: ($uname,$udom,'assesscalc',$symb);
1.578 raeburn 933: } elsif (($snum==2) || ($snum==3)) {
1.560 damieng 934: &Apache::lonnet::expirespread
935: ($uname,$udom,'assesscalc',$map);
936: } else {
937: &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
938: }
939: # Store parameter
940: if ($delete) {
941: $reply=&Apache::lonnet::del
942: ('resourcedata',[keys(%storecontent)],$udom,$uname);
943: &log_parmset(\%storecontent,1,$uname,$udom);
944: } else {
945: $reply=&Apache::lonnet::cput
946: ('resourcedata',\%storecontent,$udom,$uname);
947: &log_parmset(\%storecontent,0,$uname,$udom);
1.578 raeburn 948: if ($possreplace) {
949: my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
950: if (ref($resdata) eq 'HASH') {
951: if (exists($resdata->{$possreplace})) {
952: if (&Apache::lonnet::del
953: ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
954: &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
955: $uname,$udom);
956: }
957: }
958: }
959: }
1.560 damieng 960: }
961: &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186 www 962: }
1.446 bisitz 963:
1.186 www 964: if ($reply=~/^error\:(.*)/) {
1.560 damieng 965: return "<span class=\"LC_error\">Write Error: $1</span>";
1.186 www 966: }
967: return '';
968: }
969:
1.9 www 970:
1.561 damieng 971: # Returns HTML with the value of the given parameter,
972: # using a readable format for dates, and
973: # a warning if there is a problem with a date.
974: # Used by table mode.
975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
976: #
977: # @param {string} $value - the parameter value
978: # @param {string} $type - the parameter type
979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9 www 980: sub valout {
1.600 raeburn 981: my ($value,$type,$editable)=@_;
1.59 matthew 982: my $result = '';
983: # Values of zero are valid.
984: if (! $value && $value ne '0') {
1.528 bisitz 985: if ($editable) {
986: $result =
987: '<img src="/res/adm/pages/editmap.png"'
988: .' alt="'.&mt('Change').'"'
1.539 raeburn 989: .' title="'.&mt('Change').'" style="border:0;" />';
1.528 bisitz 990: } else {
991: $result=' ';
992: }
1.59 matthew 993: } else {
1.66 www 994: if ($type eq 'date_interval') {
1.559 raeburn 995: my ($totalsecs,$donesuffix) = split(/_/,$value,2);
996: my ($usesdone,$donebuttontext,$proctor,$secretkey);
997: if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
998: $donebuttontext = $1;
999: (undef,$proctor,$secretkey) = split(/_/,$2);
1000: $usesdone = 'done';
1001: } elsif ($donesuffix =~ /^done(|_.+)$/) {
1002: $donebuttontext = &mt('Done');
1003: ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
1004: }
1.554 raeburn 1005: my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413 bisitz 1006: my @timer;
1.66 www 1007: $year=$year-70;
1008: $mday--;
1009: if ($year) {
1.413 bisitz 1010: # $result.=&mt('[quant,_1,yr]',$year).' ';
1011: push(@timer,&mt('[quant,_1,yr]',$year));
1.66 www 1012: }
1013: if ($mon) {
1.413 bisitz 1014: # $result.=&mt('[quant,_1,mth]',$mon).' ';
1015: push(@timer,&mt('[quant,_1,mth]',$mon));
1.66 www 1016: }
1017: if ($mday) {
1.413 bisitz 1018: # $result.=&mt('[quant,_1,day]',$mday).' ';
1019: push(@timer,&mt('[quant,_1,day]',$mday));
1.66 www 1020: }
1021: if ($hour) {
1.413 bisitz 1022: # $result.=&mt('[quant,_1,hr]',$hour).' ';
1023: push(@timer,&mt('[quant,_1,hr]',$hour));
1.66 www 1024: }
1025: if ($min) {
1.413 bisitz 1026: # $result.=&mt('[quant,_1,min]',$min).' ';
1027: push(@timer,&mt('[quant,_1,min]',$min));
1.66 www 1028: }
1029: if ($sec) {
1.413 bisitz 1030: # $result.=&mt('[quant,_1,sec]',$sec).' ';
1031: push(@timer,&mt('[quant,_1,sec]',$sec));
1.66 www 1032: }
1.413 bisitz 1033: # $result=~s/\s+$//;
1034: if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
1035: push(@timer,&mt('[quant,_1,sec]',0));
1036: }
1037: $result.=join(", ",@timer);
1.559 raeburn 1038: if ($usesdone eq 'done') {
1.558 raeburn 1039: if ($secretkey) {
1.559 raeburn 1040: $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
1.558 raeburn 1041: } else {
1.559 raeburn 1042: $result .= ' + "'.$donebuttontext.'"';
1043: }
1.554 raeburn 1044: }
1.213 www 1045: } elsif (&isdateparm($type)) {
1.361 albertel 1046: $result = &Apache::lonlocal::locallocaltime($value).
1.560 damieng 1047: &date_sanity_info($value);
1.59 matthew 1048: } else {
1049: $result = $value;
1.517 www 1050: $result=~s/\,/\, /gs;
1.560 damieng 1051: $result = &HTML::Entities::encode($result,'"<>&');
1.59 matthew 1052: }
1053: }
1054: return $result;
1.9 www 1055: }
1056:
1.59 matthew 1057:
1.561 damieng 1058: # Returns HTML containing a link on a parameter value, for table mode.
1059: # The link uses the javascript function 'pjump'.
1060: #
1061: # @param {string} $type - parameter type
1062: # @param {string} $dis - dialog title for editing the parameter value and type
1063: # @param {string} $value - parameter value
1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588 raeburn 1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5 www 1069: sub plink {
1.588 raeburn 1070: my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23 www 1071: my $winvalue=$value;
1072: unless ($winvalue) {
1.592 raeburn 1073: if (&isdateparm($type) || (&is_specialstring($type))) {
1.190 albertel 1074: $winvalue=$env{'form.recent_'.$type};
1.591 raeburn 1075: } elsif ($type eq 'string_yesno') {
1076: if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
1077: $winvalue=$env{'form.recent_string'};
1078: }
1.23 www 1079: } else {
1.190 albertel 1080: $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23 www 1081: }
1082: }
1.229 www 1083: my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
1084: my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
1085: unless (defined($winvalue)) { $winvalue=$val; }
1.593 raeburn 1086: my $valout = &valout($value,$type,1);
1.429 raeburn 1087: my $unencmarker = $marker;
1.378 albertel 1088: foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588 raeburn 1089: \$hour, \$min, \$sec, \$extra) {
1.560 damieng 1090: $$item = &HTML::Entities::encode($$item,'"<>&');
1091: $$item =~ s/\'/\\\'/g;
1.378 albertel 1092: }
1.429 raeburn 1093: return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473 amueller 1094: '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588 raeburn 1095: .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578 raeburn 1096: $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
1097: &mt('recursive').'</td></tr>' : '').'</table>';
1098:
1.5 www 1099: }
1100:
1.561 damieng 1101: # Javascript for table mode.
1.280 albertel 1102: sub page_js {
1103:
1.81 www 1104: my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88 matthew 1105: my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280 albertel 1106:
1107: return(<<ENDJS);
1108: <script type="text/javascript">
1.454 bisitz 1109: // <![CDATA[
1.44 albertel 1110:
1.88 matthew 1111: $pjump_def
1.44 albertel 1112:
1113: function psub() {
1.591 raeburn 1114: var specstring = /^string_!(yesno|any)/i;
1.44 albertel 1115: if (document.parmform.pres_marker.value!='') {
1116: document.parmform.action+='#'+document.parmform.pres_marker.value;
1117: var typedef=new Array();
1118: typedef=document.parmform.pres_type.value.split('_');
1.562 damieng 1119: if (document.parmform.pres_type.value!='') {
1.589 raeburn 1120: if ((typedef[0]=='date') ||
1.591 raeburn 1121: (specstring.test(document.parmform.pres_type.value))) {
1.562 damieng 1122: eval('document.parmform.recent_'+
1123: document.parmform.pres_type.value+
1124: '.value=document.parmform.pres_value.value;');
1125: } else {
1126: eval('document.parmform.recent_'+typedef[0]+
1127: '.value=document.parmform.pres_value.value;');
1128: }
1.44 albertel 1129: }
1130: document.parmform.submit();
1131: } else {
1132: document.parmform.pres_value.value='';
1133: document.parmform.pres_marker.value='';
1134: }
1135: }
1136:
1.57 albertel 1137: function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
1138: var options = "width=" + w + ",height=" + h + ",";
1139: options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
1140: options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
1141: var newWin = window.open(url, wdwName, options);
1142: newWin.focus();
1143: }
1.523 raeburn 1144:
1.454 bisitz 1145: // ]]>
1.523 raeburn 1146:
1.44 albertel 1147: </script>
1.81 www 1148: $selscript
1.280 albertel 1149: ENDJS
1150:
1151: }
1.507 www 1152:
1.561 damieng 1153: # Javascript to show or hide the map selection (function showHide_courseContent),
1154: # for table and overview modes.
1.523 raeburn 1155: sub showhide_js {
1156: return <<"COURSECONTENTSCRIPT";
1157:
1158: function showHide_courseContent() {
1159: var parmlevValue=document.getElementById("parmlev").value;
1160: if (parmlevValue == 'general') {
1161: document.getElementById('mapmenu').style.display="none";
1162: } else {
1163: if ((parmlevValue == "full") || (parmlevValue == "map")) {
1164: document.getElementById('mapmenu').style.display ="";
1165: } else {
1166: document.getElementById('mapmenu').style.display="none";
1167: }
1168: }
1169: return;
1170: }
1171:
1172: COURSECONTENTSCRIPT
1173: }
1174:
1.561 damieng 1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549 raeburn 1176: sub toggleparmtextbox_js {
1177: return <<"ENDSCRIPT";
1178:
1179: if (!document.getElementsByClassName) {
1180: function getElementsByClassName(node, classname) {
1181: var a = [];
1182: var re = new RegExp('(^| )'+classname+'( |$)');
1183: var els = node.getElementsByTagName("*");
1184: for(var i=0,j=els.length; i<j; i++)
1185: if(re.test(els[i].className))a.push(els[i]);
1186: return a;
1187: }
1188: }
1189:
1190: function showHideLenient() {
1191: var lenients;
1192: var setRegExp = /^set_/;
1193: if (document.getElementsByClassName) {
1194: lenients = document.getElementsByClassName('LC_lenient_radio');
1195: } else {
1196: lenients = getElementsByClassName(document.body,'LC_lenient_radio');
1197: }
1198: if (lenients != 'undefined') {
1199: for (var i=0; i<lenients.length; i++) {
1200: if (lenients[i].checked) {
1201: if (lenients[i].value == 'weighted') {
1202: if (setRegExp.test(lenients[i].name)) {
1203: var identifier = lenients[i].name.replace(setRegExp,'');
1204: toggleParmTextbox(document.parmform,identifier);
1205: }
1206: }
1207: }
1208: }
1209: }
1210: return;
1211: }
1212:
1213: function toggleParmTextbox(form,key) {
1214: var divfortext = document.getElementById('LC_parmtext_'+key);
1215: if (divfortext) {
1216: var caller = form.elements['set_'+key];
1217: if (caller.length) {
1218: for (i=0; i<caller.length; i++) {
1219: if (caller[i].checked) {
1220: if (caller[i].value == 'weighted') {
1221: divfortext.style.display = 'inline';
1222: } else {
1223: divfortext.style.display = 'none';
1224: }
1225: }
1226: }
1227: }
1228: }
1229: return;
1230: }
1231:
1232: ENDSCRIPT
1233: }
1234:
1.561 damieng 1235: # Javascript function validateParms, for overview mode
1.549 raeburn 1236: sub validateparms_js {
1237: return <<'ENDSCRIPT';
1238:
1239: function validateParms() {
1240: var textRegExp = /^settext_/;
1241: var tailLenient = /\.lenient$/;
1242: var patternRelWeight = /^\-?[\d.]+$/;
1243: var patternLenientStd = /^(yes|no|default)$/;
1.597 raeburn 1244: var ipRegExp = /^setip/;
1.549 raeburn 1245: var ipallowRegExp = /^setipallow_/;
1246: var ipdenyRegExp = /^setipdeny_/;
1.597 raeburn 1247: var deeplinkRegExp = /^deeplink_/;
1.601 raeburn 1248: var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;
1249: var dlLinkProtectRegExp = /^deeplink_protect_/;
1250: var dlLtidRegExp = /^deeplink_ltid_/;
1251: var dlLticRegExp = /^deeplink_ltic_/;
1.597 raeburn 1252: var dlKeyRegExp = /^deeplink_key_/;
1253: var dlMenusRegExp = /^deeplink_menus_/;
1254: var dlCollsRegExp = /^deeplink_colls_/;
1.549 raeburn 1255: var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1256: if ((document.parmform.elements.length != 'undefined') && (document.parmform.elements.length) != 'null') {
1257: if (document.parmform.elements.length) {
1258: for (i=0; i<document.parmform.elements.length; i++) {
1259: var name=document.parmform.elements[i].name;
1.588 raeburn 1260: if (textRegExp.test(name)) {
1.549 raeburn 1261: var identifier = name.replace(textRegExp,'');
1262: if (tailLenient.test(identifier)) {
1263: if (document.parmform.elements['set_'+identifier].length) {
1264: for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
1265: if (document.parmform.elements['set_'+identifier][j].checked) {
1266: if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
1267: var relweight = document.parmform.elements[i].value;
1268: relweight = relweight.replace(/^\s+|\s+$/g,'');
1269: if (!patternRelWeight.test(relweight)) {
1270: relweight = '0.0';
1271: }
1272: if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
1273: document.parmform.elements['set_'+identifier][j].value = relweight;
1274: } else {
1275: document.parmform.elements['set_'+identifier][j].value += ','+relweight;
1276: }
1277: }
1278: break;
1279: }
1280: }
1281: }
1282: }
1.597 raeburn 1283: } else if (ipRegExp.test(name)) {
1284: if (ipallowRegExp.test(name)) {
1285: var identifier = name.replace(ipallowRegExp,'');
1286: var possallow = document.parmform.elements[i].value;
1287: possallow = possallow.replace(/^\s+|\s+$/g,'');
1288: if (patternIP.test(possallow)) {
1289: if (document.parmform.elements['set_'+identifier].value) {
1290: possallow = ','+possallow;
1291: }
1292: document.parmform.elements['set_'+identifier].value += possallow;
1293: }
1294: } else if (ipdenyRegExp.test(name)) {
1295: var identifier = name.replace(ipdenyRegExp,'');
1296: var possdeny = document.parmform.elements[i].value;
1297: possdeny = possdeny.replace(/^\s+|\s+$/g,'');
1298: if (patternIP.test(possdeny)) {
1299: possdeny = '!'+possdeny;
1300: if (document.parmform.elements['set_'+identifier].value) {
1301: possdeny = ','+possdeny;
1302: }
1303: document.parmform.elements['set_'+identifier].value += possdeny;
1.588 raeburn 1304: }
1305: }
1306: } else if (deeplinkRegExp.test(name)) {
1.597 raeburn 1307: if (dlListScopeRegExp.test(name)) {
1308: var identifier = name.replace(dlListScopeRegExp,'');
1309: var idx = document.parmform.elements[i].selectedIndex;
1310: if (idx > 0) {
1311: var possdeeplink = document.parmform.elements[i].options[idx].value
1312: possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
1313: if (document.parmform.elements['set_'+identifier].value) {
1314: possdeeplink = ','+possdeeplink;
1315: }
1316: document.parmform.elements['set_'+identifier].value += possdeeplink;
1317: }
1.601 raeburn 1318: } else if (dlLinkProtectRegExp.test(name)) {
1.597 raeburn 1319: if (document.parmform.elements[i].checked) {
1.601 raeburn 1320: var identifier = name.replace(dlLinkProtectRegExp,'');
1.597 raeburn 1321: var posslinkurl = document.parmform.elements[i].value;
1322: posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
1323: if (document.parmform.elements['set_'+identifier].value) {
1324: posslinkurl = ','+posslinkurl;
1325: }
1326: document.parmform.elements['set_'+identifier].value += posslinkurl;
1327: }
1.601 raeburn 1328: } else if (dlLtidRegExp.test(name)) {
1329: var identifier = name.replace(dlLtidRegExp,'');
1330: if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
1331: var possltid = document.parmform.elements[i].value;
1332: possltid = possltid.replace(/\D+/g,'');
1333: if (possltid.length) {
1.597 raeburn 1334: if (document.parmform.elements['set_'+identifier].value) {
1.601 raeburn 1335: possltid = ':'+possltid;
1.597 raeburn 1336: }
1.601 raeburn 1337: document.parmform.elements['set_'+identifier].value += possltid;
1.597 raeburn 1338: } else {
1339: document.parmform.elements['set_'+identifier].value = '';
1.601 raeburn 1340: alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597 raeburn 1341: return false;
1342: }
1343: }
1.601 raeburn 1344: } else if (dlLticRegExp.test(name)) {
1345: var identifier = name.replace(dlLticRegExp,'');
1346: if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
1347: var possltic = document.parmform.elements[i].value;
1348: possltic = possltic.replace(/\D+/g,'');
1349: if (possltic.length) {
1350: if (document.parmform.elements['set_'+identifier].value) {
1351: possltic = ':'+possltic;
1352: }
1353: document.parmform.elements['set_'+identifier].value += possltic;
1354: } else {
1355: document.parmform.elements['set_'+identifier].value = '';
1356: alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1357: return false;
1358: }
1359: }
1.597 raeburn 1360: } else if (dlKeyRegExp.test(name)) {
1361: var identifier = name.replace(dlKeyRegExp,'');
1.601 raeburn 1362: if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597 raeburn 1363: var posskey = document.parmform.elements[i].value;
1364: posskey = posskey.replace(/^\s+|\s+$/g,'');
1365: var origlength = posskey.length;
1366: posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
1367: var newlength = posskey.length;
1368: if (newlength > 0) {
1369: var change = origlength - newlength;
1370: if (change) {
1371: alert(change+' disallowed character(s) removed from deeplink key');
1372: }
1373: if (document.parmform.elements['set_'+identifier].value) {
1374: posskey = ':'+posskey;
1375: }
1376: document.parmform.elements['set_'+identifier].value += posskey;
1377: } else {
1378: document.parmform.elements['set_'+identifier].value = '';
1379: if (newlength < origlength) {
1380: alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
1381: } else {
1382: alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
1383: }
1384: return false;
1385: }
1386: }
1387: } else if (dlMenusRegExp.test(name)) {
1388: if (document.parmform.elements[i].checked) {
1389: var identifier = name.replace(dlMenusRegExp,'');
1390: var posslinkmenu = document.parmform.elements[i].value;
1391: posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
1392: if (posslinkmenu == 'std') {
1393: posslinkmenu = '0';
1394: if (document.parmform.elements['set_'+identifier].value) {
1395: posslinkmenu = ','+posslinkmenu;
1396: }
1397: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1398: }
1399: }
1400: } else if (dlCollsRegExp.test(name)) {
1401: var identifier = name.replace(dlCollsRegExp,'');
1402: if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
1403: var posslinkmenu = document.parmform.elements[i].value;
1404: if (document.parmform.elements['set_'+identifier].value) {
1405: posslinkmenu = ','+posslinkmenu;
1406: }
1407: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1408: }
1.549 raeburn 1409: }
1410: }
1411: }
1412: }
1413: }
1414: return true;
1415: }
1416:
1.597 raeburn 1417: function isRadioSet(name,expected) {
1418: var menuitems = document.getElementsByName(name);
1419: var radioLength = menuitems.length;
1420: result = false;
1421: if (radioLength > 1) {
1422: for (var j=0; j<radioLength; j++) {
1423: if (menuitems[j].checked) {
1424: if (menuitems[j].value == expected) {
1425: result = true;
1426: break;
1427: }
1428: }
1429: }
1430: }
1431: return result;
1432: }
1433:
1.549 raeburn 1434: ENDSCRIPT
1435: }
1436:
1.561 damieng 1437: # Javascript initialization, for overview mode
1.549 raeburn 1438: sub ipacc_boxes_js {
1439: my $remove = &mt('Remove');
1440: return <<"END";
1441: \$(document).ready(function() {
1442: var wrapper = \$(".LC_string_ipacc_wrap");
1443: var add_button = \$(".LC_add_ipacc_button");
1444: var ipaccRegExp = /^LC_string_ipacc_/;
1445:
1446: \$(add_button).click(function(e){
1447: e.preventDefault();
1448: var identifier = \$(this).closest("div").attr("id");
1449: identifier = identifier.replace(ipaccRegExp,'');
1.551 raeburn 1450: \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');
1.549 raeburn 1451: });
1452:
1453: \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
1454: e.preventDefault(); \$(this).closest("div").remove();
1455: })
1456: });
1457:
1458:
1459: END
1460: }
1461:
1.561 damieng 1462: # Javascript function toggleSecret, for overview mode.
1.558 raeburn 1463: sub done_proctor_js {
1464: return <<"END";
1465: function toggleSecret(form,radio,key) {
1466: var radios = form[radio+key];
1467: if (radios.length) {
1468: for (var i=0; i<radios.length; i++) {
1469: if (radios[i].checked) {
1470: if (radios[i].value == '_done_proctor') {
1471: if (document.getElementById('done_'+key+'_proctorkey')) {
1472: document.getElementById('done_'+key+'_proctorkey').type='text';
1473: }
1474: } else {
1475: if (document.getElementById('done_'+key+'_proctorkey')) {
1476: document.getElementById('done_'+key+'_proctorkey').type='hidden';
1477: document.getElementById('done_'+key+'_proctorkey').value='';
1478: }
1479: }
1480: }
1481: }
1482: }
1483: }
1484: END
1485:
1486: }
1487:
1.588 raeburn 1488: # Javascript function toggle
1489: sub deeplink_js {
1490: return <<"END";
1491: function toggleDeepLink(form,item,key) {
1492: var radios = form['deeplink_'+item+'_'+key];
1493: if (radios.length) {
1494: var keybox;
1495: if (document.getElementById('deeplink_key_'+item+'_'+key)) {
1496: keybox = document.getElementById('deeplink_key_'+item+'_'+key);
1497: }
1.601 raeburn 1498: var divoptions = new Array();
1499: if (item == 'protect') {
1500: divoptions = ['ltic','ltid'];
1.597 raeburn 1501: } else {
1502: if (item == 'menus') {
1.601 raeburn 1503: divoptions = ['colls'];
1.597 raeburn 1504: }
1505: }
1.601 raeburn 1506: var seldivs = new Array();
1507: if ((item == 'protect') || (item == 'menus')) {
1508: for (var i=0; i<divoptions.length; i++) {
1509: if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
1510: seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
1511: } else {
1512: seldivs[i] = '';
1513: }
1514: }
1.588 raeburn 1515: }
1516: for (var i=0; i<radios.length; i++) {
1517: if (radios[i].checked) {
1.601 raeburn 1518: if ((item == 'protect') || (item == 'menus')) {
1519: for (var j=0; j<seldivs.length; j++) {
1520: if (radios[i].value == divoptions[j]) {
1521: if (seldivs[j] != '') {
1522: seldivs[j].style.display = 'inline-block';
1523: }
1524: if (item == 'protect') {
1525: keybox.type = 'hidden';
1526: keybox.value = '';
1527: }
1528: } else {
1529: if (seldivs[j] != '') {
1530: seldivs[j].style.display = 'none';
1531: form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
1532: }
1533: }
1.597 raeburn 1534: }
1.601 raeburn 1535: if (item == 'protect') {
1.597 raeburn 1536: if (radios[i].value == 'key') {
1537: keybox.type = 'text';
1538: } else {
1539: keybox.type = 'hidden';
1540: }
1.588 raeburn 1541: }
1542: }
1543: }
1544: }
1545: }
1546: }
1547: END
1548:
1549: }
1550:
1.561 damieng 1551: # Prints HTML page start for table mode.
1552: # @param {Apache2::RequestRec} $r - the Apache request
1553: # @param {string} $psymb - resource symb
1554: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280 albertel 1555: sub startpage {
1.531 raeburn 1556: my ($r,$psymb,$crstype) = @_;
1.281 albertel 1557:
1.515 raeburn 1558: my %loaditems = (
1559: 'onload' => "group_or_section('cgroup')",
1560: );
1561: if (!$psymb) {
1.523 raeburn 1562: $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515 raeburn 1563: }
1.280 albertel 1564:
1.560 damieng 1565: if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
1566: (!$env{'form.dis'})) || ($env{'form.symb'})) {
1567: &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
1568: text=>"Problem Parameters"});
1.414 droeschl 1569: } else {
1.560 damieng 1570: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1571: text=>"Table Mode",
1572: help => 'Course_Setting_Parameters'});
1.414 droeschl 1573: }
1.523 raeburn 1574: my $js = &page_js().'
1575: <script type="text/javascript">
1576: // <![CDATA[
1577: '.
1578: &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
1579: // ]]>
1580: </script>
1581: ';
1.446 bisitz 1582: my $start_page =
1.523 raeburn 1583: &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
1584: {'add_entries' => \%loaditems,});
1.446 bisitz 1585: my $breadcrumbs =
1.473 amueller 1586: &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506 www 1587: my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
1588: my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507 www 1589: $r->print($start_page.$breadcrumbs);
1.531 raeburn 1590: &startSettingsScreen($r,'parmset',$crstype);
1.280 albertel 1591: $r->print(<<ENDHEAD);
1.193 albertel 1592: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419 bisitz 1593: <input type="hidden" value="" name="pres_value" />
1594: <input type="hidden" value="" name="pres_type" />
1595: <input type="hidden" value="" name="pres_marker" />
1596: <input type="hidden" value="1" name="prevvisit" />
1.506 www 1597: <input type="hidden" value="$escfilter" name="filter" />
1598: <input type="hidden" value="$escpart" name="part" />
1.44 albertel 1599: ENDHEAD
1600: }
1601:
1.209 www 1602:
1.561 damieng 1603: # Prints a row for table mode (except for the tr start).
1604: # Every time a hash reference is passed, a single entry is used, so print_row
1605: # could just use these values, but why make it simple when it can be complicated ?
1606: #
1607: # @param {Apache2::RequestRec} $r - the Apache request
1608: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
1609: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
1610: # @param {hash reference} $name - parameter key -> parameter name
1.566 damieng 1611: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561 damieng 1612: # @param {string} $rid - resource id
1613: # @param {hash reference} $default - parameter key -> resource parameter default value
1614: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
1615: # @param {hash reference} $display - parameter key -> full title for the parameter
1616: # @param {string} $defbgone - user level and other levels background color
1617: # @param {string} $defbgtwo - section level background color, also used for part number
1618: # @param {string} $defbgthree - group level background color
1619: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1620: # @param {string} $uname - user name
1621: # @param {string} $udom - user domain
1622: # @param {string} $csec - section name
1623: # @param {string} $cgroup - group name
1624: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1625: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582 raeburn 1626: # @param {boolean} $readonly - true if no editing allowed.
1627: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
1628: # @param {hash reference} - $maptitles - - hash map id or src -> map title
1629: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
1630: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set
1.44 albertel 1631: sub print_row {
1.201 www 1632: my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568 raeburn 1633: $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582 raeburn 1634: $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275 raeburn 1635: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1636: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1637: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582 raeburn 1638: my $numlinks = 0;
1.553 raeburn 1639:
1.560 damieng 1640: # get the values for the parameter in cascading order
1641: # empty levels will remain empty
1.44 albertel 1642: my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473 amueller 1643: $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1644: # get the type for the parameters
1645: # problem: these may not be set for all levels
1.66 www 1646: my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275 raeburn 1647: $$name{$which}.'.type',$rid,
1.473 amueller 1648: $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1649: # cascade down manually
1.182 albertel 1650: my $cascadetype=$$defaulttype{$which};
1.556 raeburn 1651: for (my $i=18;$i>0;$i--) {
1.560 damieng 1652: if ($typeoutpar[$i]) {
1.66 www 1653: $cascadetype=$typeoutpar[$i];
1.560 damieng 1654: } else {
1.66 www 1655: $typeoutpar[$i]=$cascadetype;
1656: }
1657: }
1.57 albertel 1658: my $parm=$$display{$which};
1659:
1.203 www 1660: if ($parmlev eq 'full') {
1.419 bisitz 1661: $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506 www 1662: .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433 raeburn 1663: } else {
1.57 albertel 1664: $parm=~s|\[.*\]\s||g;
1665: }
1.231 www 1666: my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
1667: if ($automatic) {
1.560 damieng 1668: $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231 www 1669: }
1.427 bisitz 1670: $r->print('<td>'.$parm.'</td>');
1.446 bisitz 1671:
1.44 albertel 1672: my $thismarker=$which;
1673: $thismarker=~s/^parameter\_//;
1674: my $mprefix=$rid.'&'.$thismarker.'&';
1.582 raeburn 1675: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1676: my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588 raeburn 1677: $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582 raeburn 1678: if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
1679: if ($result eq '') {
1680: $recurse_check = 1;
1681: } elsif (($uname ne '') && ($result > 3)) {
1682: $recurse_check = 1;
1683: } elsif (($cgroup ne '') && ($result > 7)) {
1684: $recurse_check = 1;
1685: } elsif (($csec ne '') && ($result > 11)) {
1686: $recurse_check = 1;
1687: } elsif ($result > 17) {
1688: $recurse_check = 1;
1689: }
1690: if ($recurse_check) {
1691: my $what = $$part{$which}.'.'.$$name{$which};
1692: my $prefix;
1693: if (($uname ne '') && ($udom ne '')) {
1694: my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1695: $prefix = $env{'request.course.id'};
1696: $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
1697: if (ref($recursinfo) eq 'ARRAY') {
1698: $effparm_rec = 1;
1699: $effparm_level = &mt('user: [_1]',$uname);
1700: }
1701: }
1702: if (($cgroup ne '') && (!$effparm_rec)) {
1703: $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
1704: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1705: if (ref($recursinfo) eq 'ARRAY') {
1706: $effparm_rec = 1;
1707: $effparm_level = &mt('group: [_1]',$cgroup);
1708: }
1709: }
1710: if (($csec ne '') && (!$effparm_rec)) {
1711: $prefix = $env{'request.course.id'}.'.['.$csec.']';
1712: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1713: if (ref($recursinfo) eq 'ARRAY') {
1714: $effparm_rec = 1;
1715: $effparm_level = &mt('section: [_1]',$csec);
1716: }
1717: }
1718: if (!$effparm_rec) {
1719: $prefix = $env{'request.course.id'};
1720: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1721: if (ref($recursinfo) eq 'ARRAY') {
1722: $effparm_rec = 1;
1723: }
1724: }
1725: }
1726: }
1727: if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
1728: $effparm_rec = 1;
1729: }
1730: if ((!$effparm_rec) &&
1731: (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) &&
1732: ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578 raeburn 1733: $effparm_rec = 1;
1734: }
1.588 raeburn 1735: if ($parmname eq 'deeplink') {
1.601 raeburn 1736: my ($domltistr,$crsltistr);
1.588 raeburn 1737: my %lti =
1738: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 1739: 'linkprot');
1.601 raeburn 1740: if (keys(%lti)) {
1741: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1.604 raeburn 1742: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
1743: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588 raeburn 1744: }
1745: }
1.601 raeburn 1746: $domltistr =~ s/,$//;
1747: if ($domltistr) {
1748: $extra = 'ltid_'.$domltistr;
1749: }
1.588 raeburn 1750: }
1.601 raeburn 1751: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
1752: if (keys(%courselti)) {
1753: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
1754: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
1755: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
1756: }
1757: }
1758: $crsltistr =~ s/,$//;
1759: if ($crsltistr) {
1760: if ($extra) {
1761: $extra .= '&';
1762: }
1763: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 1764: }
1765: }
1.597 raeburn 1766: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
1767: my @colls;
1768: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
1769: my ($num,$value) = split(/\%/,$item);
1770: if ($num =~ /^\d+$/) {
1771: push(@colls,$num);
1772: }
1773: }
1774: if (@colls) {
1775: if ($extra) {
1776: $extra .= '&';
1777: }
1778: $extra .= 'menus_'.join(',',@colls);
1779: }
1780: }
1.588 raeburn 1781: }
1.57 albertel 1782: if ($parmlev eq 'general') {
1783: if ($uname) {
1.588 raeburn 1784: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 1785: } elsif ($cgroup) {
1.588 raeburn 1786: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 1787: } elsif ($csec) {
1.588 raeburn 1788: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1789: } else {
1.588 raeburn 1790: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1791: }
1792: } elsif ($parmlev eq 'map') {
1793: if ($uname) {
1.588 raeburn 1794: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 1795: } elsif ($cgroup) {
1.588 raeburn 1796: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 1797: } elsif ($csec) {
1.588 raeburn 1798: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1799: } else {
1.588 raeburn 1800: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1801: }
1802: } else {
1.275 raeburn 1803: if ($uname) {
1804: if (@{$usersgroups} > 1) {
1.582 raeburn 1805: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 1806: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 1807: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 1808: if (($coursereply) && ($result > 4)) {
1.275 raeburn 1809: if (defined($controlgrp)) {
1810: if ($cgroup ne $controlgrp) {
1.582 raeburn 1811: $eff_groupparm = $grp_parm;
1812: undef($result);
1813: undef($effparm_rec);
1814: if ($grp_is_rec) {
1815: $effparm_rec = 1;
1816: }
1.275 raeburn 1817: }
1818: }
1819: }
1820: }
1821: }
1.57 albertel 1822:
1.588 raeburn 1823: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1824: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1825: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1826: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1827: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1828:
1829: if ($csec) {
1.588 raeburn 1830: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1831: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1832: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1833: }
1.269 raeburn 1834:
1835: if ($cgroup) {
1.588 raeburn 1836: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1837: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1838: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 1839: }
1.446 bisitz 1840:
1.548 raeburn 1841: if ($uname) {
1.275 raeburn 1842: if ($othergrp) {
1843: $r->print($othergrp);
1844: }
1.588 raeburn 1845: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1846: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1847: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1848: }
1.57 albertel 1849: } # end of $parmlev if/else
1.582 raeburn 1850: if (ref($recursinfo) eq 'ARRAY') {
1851: my $rectitle = &mt('recursive');
1852: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
1853: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
1854: $rectitle = &mt('set in: [_1]','"'.
1855: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
1856: "'$parmname','$$part{$which}'".');">'.
1857: $maptitles->{$recursinfo->[2]}.'</a>"');
1858:
1859: $numlinks ++;
1860: }
1861: }
1862: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 1863: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 1864: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1865: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
1866: $effparm_level.'</span></td>');
1867: } else {
1868: if ($result) {
1.593 raeburn 1869: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 1870: }
1871: if ($eff_groupparm) {
1872: $effective_parm = $eff_groupparm;
1873: }
1874: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1875: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
1876: '</span>':'').'</td>');
1877: }
1.203 www 1878: if ($parmlev eq 'full') {
1.136 albertel 1879: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 1880: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 1881: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 1882: if (!defined($sessionvaltype)) {
1883: $sessionvaltype=$$defaulttype{$which};
1884: }
1.419 bisitz 1885: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 1886: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 1887: '</font></td>');
1.136 albertel 1888: }
1.44 albertel 1889: $r->print('</tr>');
1.57 albertel 1890: $r->print("\n");
1.582 raeburn 1891: if (($numlinks) && (ref($reclinks))) {
1892: $$reclinks = $numlinks;
1893: }
1.44 albertel 1894: }
1.59 matthew 1895:
1.561 damieng 1896: # Prints a cell for table mode.
1897: #
1898: # FIXME: some of these parameter names are uninspired ($which and $value)
1899: # Also, it would make more sense to pass the display for this cell rather
1900: # than the full display hash and the key to use.
1901: #
1902: # @param {Apache2::RequestRec} $r - the Apache request
1903: # @param {integer} $which - level
1904: # @param {string} $defbg - cell background color
1905: # @param {integer} $result - the most specific level that is defined for that parameter
1906: # @param {array reference} $outpar - array level -> parameter value (when defined)
1907: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
1908: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
1909: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
1910: # @param {hash reference} $display - parameter key -> full title for the parameter
1911: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 1912: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 1913: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 1914: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 1915: sub print_td {
1.578 raeburn 1916: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 1917: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 1918: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
1919: $ineffect = 0;
1920: $currval = $$outpar[$which];
1921: $currtype = $$typeoutpar[$which];
1922: $currlevel = $which;
1923: if (($result) && ($result == $which)) {
1924: $ineffect = 1;
1925: }
1926: if ($ismaplevel) {
1927: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
1928: if (($result) && ($result == $which)) {
1929: $recursive = 1;
1930: }
1931: } elsif ($$outpar[$which+1] ne '') {
1932: $recursive = 1;
1933: $currlevel = $which+1;
1934: $currval = $$outpar[$currlevel];
1935: $currtype = $$typeoutpar[$currlevel];
1936: if (($result) && ($result == $currlevel)) {
1937: $ineffect = 1;
1938: }
1939: }
1940: }
1941: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 1942: ';" align="center">');
1.437 raeburn 1943: my $nolink = 0;
1.568 raeburn 1944: if ($readonly) {
1.552 raeburn 1945: $nolink = 1;
1.568 raeburn 1946: } else {
1.578 raeburn 1947: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 1948: $nolink = 1;
1.568 raeburn 1949: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 1950: $nolink = 1;
1.568 raeburn 1951: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
1952: if ($noeditgrp) {
1953: $nolink = 1;
1954: }
1955: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 1956: $nolink = 1;
1.568 raeburn 1957: } elsif ($mprefix =~ /examcode\&$/) {
1958: unless ($which == 2) {
1959: $nolink = 1;
1960: }
1.533 raeburn 1961: }
1.437 raeburn 1962: }
1963: if ($nolink) {
1.577 raeburn 1964: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 1965: $r->print(&valout($currval,$currtype));
1.114 www 1966: } else {
1.578 raeburn 1967: $r->print(&plink($currtype,
1968: $$display{$value},$currval,
1.588 raeburn 1969: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
1970: $extra));
1.114 www 1971: }
1972: $r->print('</td>'."\n");
1.57 albertel 1973: }
1974:
1.561 damieng 1975: # Returns HTML and other info for the cell added when a user is selected
1976: # and that user is in several groups. This is the cell with the title "Control by other group".
1977: #
1978: # @param {string} $what - parameter part.'.'.parameter name
1979: # @param {string} $rid - resource id
1980: # @param {string} $cgroup - group name
1981: # @param {string} $defbg - cell background color
1982: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1983: # @param {integer} $result - level
1984: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 1985: # @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 1986: sub check_other_groups {
1987: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 1988: my $courseid = $env{'request.course.id'};
1989: my $output;
1990: my $symb = &symbcache($rid);
1991: my $symbparm=$symb.'.'.$what;
1992: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 1993: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 1994: my $mapparm=$map.'___(all).'.$what;
1995: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 1996: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
1997: $recurseparm,$what,$courseopt);
1.275 raeburn 1998: my $bgcolor = $defbg;
1.582 raeburn 1999: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2000: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2001: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2002: if ($result > 3) {
1.419 bisitz 2003: $bgcolor = '#AAFFAA';
1.275 raeburn 2004: }
1.593 raeburn 2005: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2006: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2007: if ($resultgroup && $resultlevel) {
1.582 raeburn 2008: if ($resultlevel eq 'recursive') {
2009: $resultlevel = 'map/folder';
2010: $grp_is_rec = 1;
2011: }
2012: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2013: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2014:
1.275 raeburn 2015: } else {
2016: $output .= ' ';
2017: }
2018: $output .= '</td>';
2019: } else {
1.419 bisitz 2020: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2021: }
1.582 raeburn 2022: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2023: }
2024:
1.561 damieng 2025: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2026: # Used by check_other_groups.
1.561 damieng 2027: #
2028: # @param {string} $courseid - the course id
2029: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2030: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2031: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2032: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2033: # @param {string} $what - parameter part.'.'.parameter name
2034: # @param {hash reference} $courseopt - course parameters hash
2035: # @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 2036: sub parm_control_group {
1.556 raeburn 2037: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2038: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2039: my $grpfound = 0;
1.556 raeburn 2040: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2041: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2042: foreach my $group (@{$usersgroups}) {
2043: if ($grpfound) { last; }
2044: for (my $i=0; $i<@levels; $i++) {
2045: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2046: if (defined($$courseopt{$item})) {
2047: $coursereply = $$courseopt{$item};
2048: $resultitem = $item;
2049: $resultgroup = $group;
2050: $resultlevel = $levelnames[$i];
2051: $resulttype = $$courseopt{$item.'.type'};
2052: $grpfound = 1;
2053: last;
2054: }
2055: }
2056: }
2057: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2058: }
1.201 www 2059:
1.63 bowersj2 2060:
2061:
1.562 damieng 2062: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2063: # All the parameters are references and are filled by the sub.
2064: #
1.566 damieng 2065: # @param {array reference} $ids - resource and map ids
2066: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2067: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2068: # @param {hash reference} $allparms - hash parameter name -> parameter title
2069: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2070: # @param {hash reference} $allmaps - hash map pc -> map src
2071: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2072: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2073: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2074: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2075: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2076: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.63 bowersj2 2077: sub extractResourceInformation {
2078: my $ids = shift;
2079: my $typep = shift;
2080: my $keyp = shift;
2081: my $allparms = shift;
2082: my $allparts = shift;
2083: my $allmaps = shift;
2084: my $mapp = shift;
2085: my $symbp = shift;
1.82 www 2086: my $maptitles=shift;
1.196 www 2087: my $uris=shift;
1.210 www 2088: my $keyorder=shift;
1.211 www 2089: my $defkeytype=shift;
1.603 raeburn 2090: my $pssymb=shift;
1.196 www 2091:
1.210 www 2092: my $keyordercnt=100;
1.63 bowersj2 2093:
1.196 www 2094: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 raeburn 2095: return unless(ref($navmap));
2096: my @allres;
2097: if ($pssymb ne '') {
2098: my $res = $navmap->getBySymb($pssymb);
2099: if (ref($res)) {
2100: @allres = ($res);
2101: }
2102: }
2103: if (!@allres) {
2104: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
2105: }
1.196 www 2106: foreach my $resource (@allres) {
1.480 amueller 2107: my $id=$resource->id();
1.196 www 2108: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2109: if ($mapid eq '0') { next; }
2110: $$ids[$#$ids+1]=$id;
2111: my $srcf=$resource->src();
2112: $srcf=~/\.(\w+)$/;
2113: $$typep{$id}=$1;
1.584 raeburn 2114: my $toolsymb;
2115: if ($srcf =~ /ext\.tool$/) {
2116: $toolsymb = $resource->symb();
2117: }
1.480 amueller 2118: $$keyp{$id}='';
1.196 www 2119: $$uris{$id}=$srcf;
1.512 foxr 2120:
1.584 raeburn 2121: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2122: next if ($key!~/^parameter_/);
1.363 albertel 2123:
1.209 www 2124: # Hidden parameters
1.584 raeburn 2125: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2126: #
2127: # allparms is a hash of parameter names
2128: #
1.584 raeburn 2129: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2130: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2131: my ($display,$parmdis);
2132: $display = &standard_parameter_names($name);
2133: if ($display eq '') {
1.584 raeburn 2134: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2135: $parmdis = $display;
2136: $parmdis =~ s/\s*\[Part.*$//g;
2137: } else {
2138: $parmdis = &mt($display);
2139: }
2140: $$allparms{$name}=$parmdis;
2141: if (ref($defkeytype)) {
2142: $$defkeytype{$name}=
1.584 raeburn 2143: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2144: }
2145: }
1.363 albertel 2146:
1.209 www 2147: #
2148: # allparts is a hash of all parts
2149: #
1.584 raeburn 2150: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2151: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2152: #
2153: # Remember all keys going with this resource
2154: #
1.480 amueller 2155: if ($$keyp{$id}) {
2156: $$keyp{$id}.=','.$key;
2157: } else {
2158: $$keyp{$id}=$key;
2159: }
1.210 www 2160: #
2161: # Put in order
1.446 bisitz 2162: #
1.480 amueller 2163: unless ($$keyorder{$key}) {
2164: $$keyorder{$key}=$keyordercnt;
2165: $keyordercnt++;
2166: }
1.473 amueller 2167: }
2168:
2169:
1.480 amueller 2170: if (!exists($$mapp{$mapid})) {
2171: $$mapp{$id}=
2172: &Apache::lonnet::declutter($resource->enclosing_map_src());
2173: $$mapp{$mapid}=$$mapp{$id};
2174: $$allmaps{$mapid}=$$mapp{$id};
2175: if ($mapid eq '1') {
1.532 raeburn 2176: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2177: } else {
2178: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2179: }
2180: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2181: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2182: # Lines 1038 and 1114 which use $symbp{$mapid}
2183: # are commented out in rev. 1.57
1.473 amueller 2184: } else {
1.480 amueller 2185: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2186: }
1.480 amueller 2187: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2188: }
2189: }
2190:
1.582 raeburn 2191: sub get_recursive {
2192: my ($recurseup,$resdata,$what,$prefix) = @_;
2193: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2194: foreach my $item (@{$recurseup}) {
2195: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2196: if (defined($resdata->{$norecursechk})) {
2197: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2198: my $type = $resdata->{$norecursechk.'.type'};
2199: return [$resdata->{$norecursechk},$type,$item];
2200: } else {
2201: last;
2202: }
2203: }
2204: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2205: if (defined($resdata->{$recursechk})) {
2206: my $type = $resdata->{$recursechk.'.type'};
2207: return [$resdata->{$recursechk},$type,$item];
2208: }
2209: }
2210: }
2211: return;
2212: }
2213:
1.208 www 2214:
1.562 damieng 2215: # Tells if a parameter type is a date.
2216: #
2217: # @param {string} type - parameter type
2218: # @returns{boolean} - true if it is a date
1.213 www 2219: sub isdateparm {
2220: my $type=shift;
2221: return (($type=~/^date/) && (!($type eq 'date_interval')));
2222: }
2223:
1.589 raeburn 2224: # Determine if parameter type is specialized string type (i.e.,
2225: # not just string or string_yesno.
2226:
2227: sub is_specialstring {
2228: my $type=shift;
1.603 raeburn 2229: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2230: }
2231:
1.562 damieng 2232: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2233: #
1.581 raeburn 2234: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2235: sub parmmenu {
1.581 raeburn 2236: my ($r)=@_;
1.208 www 2237: $r->print(<<ENDSCRIPT);
2238: <script type="text/javascript">
1.454 bisitz 2239: // <![CDATA[
1.208 www 2240: function checkall(value, checkName) {
1.453 schualex 2241:
2242: var li = "_li";
2243: var displayOverview = "";
2244:
2245: if (value == false) {
2246: displayOverview = "none"
2247: }
2248:
1.562 damieng 2249: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2250: ele = document.forms.parmform.elements[i];
2251: if (ele.name == checkName) {
2252: document.forms.parmform.elements[i].checked=value;
2253: }
2254: }
2255: }
1.210 www 2256:
2257: function checkthis(thisvalue, checkName) {
1.562 damieng 2258: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2259: ele = document.forms.parmform.elements[i];
2260: if (ele.name == checkName) {
1.562 damieng 2261: if (ele.value == thisvalue) {
2262: document.forms.parmform.elements[i].checked=true;
2263: }
1.210 www 2264: }
2265: }
2266: }
2267:
2268: function checkdates() {
1.562 damieng 2269: checkthis('duedate','pscat');
2270: checkthis('opendate','pscat');
2271: checkthis('answerdate','pscat');
1.218 www 2272: }
2273:
2274: function checkdisset() {
1.562 damieng 2275: checkthis('discussend','pscat');
2276: checkthis('discusshide','pscat');
2277: checkthis('discussvote','pscat');
1.218 www 2278: }
2279:
2280: function checkcontdates() {
1.562 damieng 2281: checkthis('contentopen','pscat');
2282: checkthis('contentclose','pscat');
1.218 www 2283: }
1.446 bisitz 2284:
1.210 www 2285: function checkvisi() {
1.562 damieng 2286: checkthis('hiddenresource','pscat');
2287: checkthis('encrypturl','pscat');
2288: checkthis('problemstatus','pscat');
2289: checkthis('contentopen','pscat');
2290: checkthis('opendate','pscat');
1.210 www 2291: }
2292:
2293: function checkparts() {
1.562 damieng 2294: checkthis('hiddenparts','pscat');
2295: checkthis('display','pscat');
2296: checkthis('ordered','pscat');
1.210 www 2297: }
2298:
2299: function checkstandard() {
2300: checkall(false,'pscat');
1.562 damieng 2301: checkdates();
2302: checkthis('weight','pscat');
2303: checkthis('maxtries','pscat');
2304: checkthis('type','pscat');
2305: checkthis('problemstatus','pscat');
1.210 www 2306: }
2307:
1.454 bisitz 2308: // ]]>
1.208 www 2309: </script>
2310: ENDSCRIPT
1.453 schualex 2311:
1.491 bisitz 2312: $r->print('<hr />');
1.581 raeburn 2313: &shortCuts($r);
1.491 bisitz 2314: $r->print('<hr />');
1.453 schualex 2315: }
1.562 damieng 2316:
2317: # Returns parameter categories.
2318: #
2319: # @returns {hash} - category name -> title in English
1.465 amueller 2320: sub categories {
2321: return ('time_settings' => 'Time Settings',
2322: 'grading' => 'Grading',
2323: 'tries' => 'Tries',
2324: 'problem_appearance' => 'Problem Appearance',
2325: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2326: 'hiding' => 'Hiding',
2327: 'high_level_randomization' => 'High Level Randomization',
2328: 'slots' => 'Slots',
2329: 'file_submission' => 'File Submission',
2330: 'misc' => 'Miscellaneous' );
2331: }
2332:
1.562 damieng 2333: # Returns the category for each parameter.
2334: #
2335: # @returns {hash} - parameter name -> category name
1.465 amueller 2336: sub lookUpTableParameter {
2337:
2338: return (
2339: 'opendate' => 'time_settings',
2340: 'duedate' => 'time_settings',
2341: 'answerdate' => 'time_settings',
2342: 'interval' => 'time_settings',
2343: 'contentopen' => 'time_settings',
2344: 'contentclose' => 'time_settings',
2345: 'discussend' => 'time_settings',
1.560 damieng 2346: 'printstartdate' => 'time_settings',
2347: 'printenddate' => 'time_settings',
1.465 amueller 2348: 'weight' => 'grading',
2349: 'handgrade' => 'grading',
2350: 'maxtries' => 'tries',
2351: 'hinttries' => 'tries',
1.503 raeburn 2352: 'randomizeontries' => 'tries',
1.465 amueller 2353: 'type' => 'problem_appearance',
2354: 'problemstatus' => 'problem_appearance',
2355: 'display' => 'problem_appearance',
2356: 'ordered' => 'problem_appearance',
2357: 'numbubbles' => 'problem_appearance',
2358: 'tol' => 'behaviour_of_input_fields',
2359: 'sig' => 'behaviour_of_input_fields',
2360: 'turnoffunit' => 'behaviour_of_input_fields',
2361: 'hiddenresource' => 'hiding',
2362: 'hiddenparts' => 'hiding',
2363: 'discusshide' => 'hiding',
2364: 'buttonshide' => 'hiding',
2365: 'turnoffeditor' => 'hiding',
2366: 'encrypturl' => 'hiding',
1.587 raeburn 2367: 'deeplink' => 'hiding',
1.465 amueller 2368: 'randomorder' => 'high_level_randomization',
2369: 'randompick' => 'high_level_randomization',
2370: 'available' => 'slots',
2371: 'useslots' => 'slots',
2372: 'availablestudent' => 'slots',
2373: 'uploadedfiletypes' => 'file_submission',
2374: 'maxfilesize' => 'file_submission',
2375: 'cssfile' => 'misc',
2376: 'mapalias' => 'misc',
2377: 'acc' => 'misc',
2378: 'maxcollaborators' => 'misc',
2379: 'scoreformat' => 'misc',
1.514 raeburn 2380: 'lenient' => 'grading',
1.519 raeburn 2381: 'retrypartial' => 'tries',
1.521 raeburn 2382: 'discussvote' => 'misc',
1.584 raeburn 2383: 'examcode' => 'high_level_randomization',
1.575 raeburn 2384: );
1.465 amueller 2385: }
2386:
1.562 damieng 2387: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2388: #
2389: # @param {string} $name - parameter name
2390: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2391: sub whatIsMyCategory {
2392: my $name = shift;
2393: my $catList = shift;
2394: my @list;
2395: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2396: my $cat = $lookUpList{$name};
2397: if (defined($cat)) {
2398: if (!defined($$catList{$cat})){
2399: push @list, ($name);
2400: $$catList{$cat} = \@list;
2401: } else {
2402: push @{${$catList}{$cat}}, ($name);
2403: }
2404: } else {
2405: if (!defined($$catList{'misc'})){
2406: push @list, ($name);
2407: $$catList{'misc'} = \@list;
2408: } else {
2409: push @{${$catList}{'misc'}}, ($name);
2410: }
2411: }
2412: }
2413:
1.562 damieng 2414: # Sorts parameter names based on appearance order.
2415: #
2416: # @param {array reference} name - array reference of parameter names
2417: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2418: # @returns {Array} - array of parameter names
1.465 amueller 2419: sub keysindisplayorderCategory {
2420: my ($name,$keyorder)=@_;
2421: return sort {
1.473 amueller 2422: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2423: } ( @{$name});
2424: }
2425:
1.562 damieng 2426: # Returns a hash category name -> order, starting at 1 (integer)
2427: #
2428: # @returns {hash}
1.467 amueller 2429: sub category_order {
2430: return (
2431: 'time_settings' => 1,
2432: 'grading' => 2,
2433: 'tries' => 3,
2434: 'problem_appearance' => 4,
2435: 'hiding' => 5,
2436: 'behaviour_of_input_fields' => 6,
2437: 'high_level_randomization' => 7,
2438: 'slots' => 8,
2439: 'file_submission' => 9,
2440: 'misc' => 10
2441: );
2442:
2443: }
1.453 schualex 2444:
1.562 damieng 2445: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2446: #
2447: # @param {Apache2::RequestRec} $r - the Apache request
2448: # @param {hash reference} $allparms - hash parameter name -> parameter title
2449: # @param {array reference} $pscat - list of selected parameter names
2450: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2451: sub parmboxes {
2452: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2453: my %categories = &categories();
1.467 amueller 2454: my %category_order = &category_order();
1.465 amueller 2455: my %categoryList = (
2456: 'time_settings' => [],
2457: 'grading' => [],
2458: 'tries' => [],
2459: 'problem_appearance' => [],
2460: 'behaviour_of_input_fields' => [],
2461: 'hiding' => [],
2462: 'high_level_randomization' => [],
2463: 'slots' => [],
2464: 'file_submission' => [],
2465: 'misc' => [],
1.489 bisitz 2466: );
1.510 www 2467:
1.548 raeburn 2468: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2469: &whatIsMyCategory($tempparameter, \%categoryList);
2470: }
1.453 schualex 2471: #part to print the parm-list
1.536 raeburn 2472: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2473: next if (@{$categoryList{$key}} == 0);
2474: next if ($key eq '');
2475: $r->print('<div class="LC_Box LC_400Box">'
2476: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2477: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2478: next if ($tempkey eq '');
1.536 raeburn 2479: $r->print('<span class="LC_nobreak">'
2480: .'<label><input type="checkbox" name="pscat" '
2481: .'value="'.$tempkey.'" ');
2482: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2483: $r->print( ' checked="checked"');
2484: }
2485: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465 amueller 2486: : $tempkey)
1.536 raeburn 2487: .'</label></span><br />'."\n");
1.465 amueller 2488: }
1.536 raeburn 2489: $r->print('</div>');
1.465 amueller 2490: }
1.536 raeburn 2491: $r->print("\n");
1.453 schualex 2492: }
1.562 damieng 2493:
2494: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2495: #
1.562 damieng 2496: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2497: sub shortCuts {
1.581 raeburn 2498: my ($r)=@_;
1.453 schualex 2499:
1.491 bisitz 2500: # Parameter Selection
2501: $r->print(
2502: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2503: .&Apache::lonhtmlcommon::add_item_funclist(
2504: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2505: .&Apache::lonhtmlcommon::add_item_funclist(
2506: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2507: .&Apache::lonhtmlcommon::add_item_funclist(
2508: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2509: .&Apache::lonhtmlcommon::end_funclist()
2510: );
2511:
2512: # Add Selection for...
2513: $r->print(
2514: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2515: .&Apache::lonhtmlcommon::add_item_funclist(
2516: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2517: .&Apache::lonhtmlcommon::add_item_funclist(
2518: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2519: .&Apache::lonhtmlcommon::add_item_funclist(
2520: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2521: .&Apache::lonhtmlcommon::add_item_funclist(
2522: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2523: .&Apache::lonhtmlcommon::add_item_funclist(
2524: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2525: .&Apache::lonhtmlcommon::end_funclist()
2526: );
1.208 www 2527: }
2528:
1.562 damieng 2529: # Prints HTML to select parts to view (except for the title).
2530: # Used by table and overview modes.
2531: #
2532: # @param {Apache2::RequestRec} $r - the Apache request
2533: # @param {hash reference} $allparts - hash parameter part -> part title
2534: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2535: sub partmenu {
1.446 bisitz 2536: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2537: my $selsize = 1+scalar(keys(%{$allparts}));
2538: if ($selsize > 8) {
2539: $selsize = 8;
2540: }
1.446 bisitz 2541:
1.523 raeburn 2542: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2543: $r->print('<option value="all"');
1.562 damieng 2544: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2545: $r->print('>'.&mt('All Parts').'</option>');
2546: my %temphash=();
2547: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2548: foreach my $tempkey (sort {
1.560 damieng 2549: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2550: } keys(%{$allparts})) {
2551: unless ($tempkey =~ /\./) {
2552: $r->print('<option value="'.$tempkey.'"');
2553: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2554: $r->print(' selected="selected"');
2555: }
2556: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2557: }
1.208 www 2558: }
1.446 bisitz 2559: $r->print('</select>');
1.209 www 2560: }
2561:
1.562 damieng 2562: # Prints HTML to select a user and/or a group.
2563: # Used by table mode.
2564: #
2565: # @param {Apache2::RequestRec} $r - the Apache request
2566: # @param {string} $uname - selected user name
2567: # @param {string} $id - selected Student/Employee ID
2568: # @param {string} $udom - selected user domain
2569: # @param {string} $csec - selected section name
2570: # @param {string} $cgroup - selected group name
2571: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2572: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2573: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2574: sub usermenu {
1.553 raeburn 2575: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2576: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2577: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2578: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2579: function setCourseadv(form,caller) {
2580: if (caller.value == 'st') {
2581: form.courseadv.value = 'none';
2582: } else {
2583: form.courseadv.value = '';
2584: }
2585: return;
2586: }
2587: ENDJS
1.412 bisitz 2588:
1.596 raeburn 2589: my (%chkroles,$stuonly,$courseadv);
2590: if ($env{'form.userroles'} eq 'any') {
2591: $chkroles{'any'} = ' checked="checked"';
2592: } else {
2593: $chkroles{'st'} = ' checked="checked"';
2594: $courseadv = 'none';
2595: }
2596: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2597: if ($crstype eq 'Community') {
2598: $stuonly = &mt('member only');
2599: } else {
2600: $stuonly = &mt('student only');
2601: }
2602: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2603: &mt("User's role").': '.
2604: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2605: $stuonly.'</label> '.
2606: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2607: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2608: my $sections='';
1.300 albertel 2609: my %sectionhash = &Apache::loncommon::get_sections();
2610:
1.269 raeburn 2611: my $groups;
1.553 raeburn 2612: my %grouphash;
2613: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2614: %grouphash = &Apache::longroup::coursegroups();
2615: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2616: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2617: }
1.299 albertel 2618:
1.412 bisitz 2619: my $g_s_header='';
2620: my $g_s_footer='';
1.446 bisitz 2621:
1.552 raeburn 2622: my $currsec = $env{'request.course.sec'};
2623: if ($currsec) {
2624: $sections=&mt('Section:').' '.$currsec;
2625: if (%grouphash) {
2626: $sections .= ';'.(' ' x2);
2627: }
2628: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2629: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2630: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2631: $sections .= qq| onchange="group_or_section('csec')" |;
2632: }
2633: $sections .= '>';
1.548 raeburn 2634: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2635: $sections.='<option value="'.$section.'" '.
2636: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2637: '</option>';
1.209 www 2638: }
2639: $sections.='</select>';
1.269 raeburn 2640: }
1.412 bisitz 2641:
1.552 raeburn 2642: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2643: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2644: $sections .= qq|
2645: <script type="text/javascript">
1.454 bisitz 2646: // <![CDATA[
1.269 raeburn 2647: function group_or_section(caller) {
2648: if (caller == "cgroup") {
2649: if (document.parmform.cgroup.selectedIndex != 0) {
2650: document.parmform.csec.selectedIndex = 0;
2651: }
2652: } else {
2653: if (document.parmform.csec.selectedIndex != 0) {
2654: document.parmform.cgroup.selectedIndex = 0;
2655: }
2656: }
2657: }
1.454 bisitz 2658: // ]]>
1.269 raeburn 2659: </script>
2660: |;
1.554 raeburn 2661: } else {
1.269 raeburn 2662: $sections .= qq|
2663: <script type="text/javascript">
1.454 bisitz 2664: // <![CDATA[
1.269 raeburn 2665: function group_or_section(caller) {
2666: return;
2667: }
1.454 bisitz 2668: // ]]>
1.269 raeburn 2669: </script>
2670: |;
1.446 bisitz 2671: }
1.299 albertel 2672:
2673: if (%grouphash) {
1.597 raeburn 2674: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2675: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2676: $groups .= qq| onchange="group_or_section('cgroup')" |;
2677: }
2678: $groups .= '>';
1.548 raeburn 2679: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2680: $groups.='<option value="'.$grp.'" ';
2681: if ($grp eq $cgroup) {
2682: unless ((defined($uname)) && ($grp eq '')) {
2683: $groups .= 'selected="selected" ';
2684: }
2685: } elsif (!defined($cgroup)) {
2686: if (@{$usersgroups} == 1) {
2687: if ($grp eq $$usersgroups[0]) {
2688: $groups .= 'selected="selected" ';
2689: }
2690: }
2691: }
2692: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2693: }
2694: $groups.='</select>';
2695: }
1.412 bisitz 2696:
1.445 neumanie 2697: if (%sectionhash || %grouphash) {
1.446 bisitz 2698: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2699: $r->print($sections.$groups);
1.448 bisitz 2700: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 2701: } else {
2702: $r->print($sections);
1.445 neumanie 2703: }
1.446 bisitz 2704:
2705: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 2706: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 2707: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
2708: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 2709: ,$chooseopt));
1.209 www 2710: }
2711:
1.562 damieng 2712: # Prints HTML to select parameters from a list of all parameters.
2713: # Uses parmmenu and parmboxes.
2714: # Used by table and overview modes.
1.468 amueller 2715: #
1.562 damieng 2716: # @param {Apache2::RequestRec} $r - the Apache request
2717: # @param {hash reference} $allparms - hash parameter name -> parameter title
2718: # @param {array reference} $pscat - list of selected parameter names
2719: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2720: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 2721: sub displaymenu {
1.581 raeburn 2722: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 2723:
1.445 neumanie 2724: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 2725: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
2726:
1.581 raeburn 2727: &parmmenu($r);
1.536 raeburn 2728: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 2729: &parmboxes($r,$allparms,$pscat,$keyorder);
2730: $r->print(&Apache::loncommon::end_scrollbox());
2731:
2732: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 2733: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 2734:
1.209 www 2735: }
2736:
1.562 damieng 2737: # Prints HTML to select a map.
2738: # Used by table mode and overview mode.
2739: #
2740: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 2741: # @param {hash reference} $allmaps - hash map pc -> map src
2742: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 2743: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 2744: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445 neumanie 2745: sub mapmenu {
1.499 raeburn 2746: my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468 amueller 2747: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 2748: my $navmap = Apache::lonnavmaps::navmap->new();
2749: my $tree=[];
2750: my $treeinfo={};
2751: if (defined($navmap)) {
1.499 raeburn 2752: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 2753: my $curRes;
2754: my $depth = 0;
1.468 amueller 2755: my %parent = ();
2756: my $startcount = 5;
2757: my $lastcontainer = $startcount;
2758: # preparing what is to show ...
1.461 neumanie 2759: while ($curRes = $it->next()) {
2760: if ($curRes == $it->BEGIN_MAP()) {
2761: $depth++;
1.468 amueller 2762: $parent{$depth}= $lastcontainer;
1.461 neumanie 2763: }
2764: if ($curRes == $it->END_MAP()) {
2765: $depth--;
1.468 amueller 2766: $lastcontainer = $parent{$depth};
1.461 neumanie 2767: }
2768: if (ref($curRes)) {
1.468 amueller 2769: my $symb = $curRes->symb();
2770: my $ressymb = $symb;
1.461 neumanie 2771: if (($curRes->is_sequence()) || ($curRes->is_page())) {
2772: my $type = 'sequence';
2773: if ($curRes->is_page()) {
2774: $type = 'page';
2775: }
2776: my $id= $curRes->id();
1.468 amueller 2777: my $srcf = $curRes->src();
2778: my $resource_name = &Apache::lonnet::gettitle($srcf);
2779: if(!exists($treeinfo->{$id})) {
2780: push(@$tree,$id);
1.473 amueller 2781: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 2782: $treeinfo->{$id} = {
1.461 neumanie 2783: depth => $depth,
2784: type => $type,
1.468 amueller 2785: name => $resource_name,
2786: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 2787: };
1.462 neumanie 2788: }
1.461 neumanie 2789: }
2790: }
2791: }
1.462 neumanie 2792: }
1.473 amueller 2793: # Show it ...
1.484 amueller 2794: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461 neumanie 2795: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
2796: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 2797: my $whitespace =
2798: '<img src="'
2799: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
2800: .'" alt="" />';
2801:
1.498 bisitz 2802: # Info about selectable folders/maps
2803: $r->print(
2804: '<div class="LC_info">'
1.508 www 2805: .&mt('You can only select maps and folders which have modifiable settings.')
2806: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 2807: .'</div>'
2808: );
2809:
1.536 raeburn 2810: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 2811: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 2812:
1.498 bisitz 2813: # Display row: "All Maps or Folders"
2814: $r->print(
1.523 raeburn 2815: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 2816: .'<td>'
2817: .'<label>'
2818: .'<input type="radio" name="pschp"'
1.497 bisitz 2819: );
2820: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 2821: $r->print(
2822: ' value="all" /> '.$icon.' '
2823: .&mt('All Maps or Folders')
2824: .'</label>'
2825: .'<hr /></td>'
2826: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2827: );
1.497 bisitz 2828:
1.532 raeburn 2829: # Display row: "Main Content"
1.468 amueller 2830: if (exists($$allmaps{1})) {
1.498 bisitz 2831: $r->print(
2832: &Apache::loncommon::start_data_table_row()
2833: .'<td>'
2834: .'<label>'
2835: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 2836: );
1.497 bisitz 2837: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 2838: $r->print(
2839: '/> '.$icon.' '
2840: .$$maptitles{1}
2841: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
2842: .'</label>'
2843: .'</td>'
2844: .&Apache::loncommon::end_data_table_row()
1.468 amueller 2845: );
2846: }
1.497 bisitz 2847:
2848: # Display rows for all course maps and folders
1.468 amueller 2849: foreach my $id (@{$tree}) {
2850: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 2851: # Indentation
1.468 amueller 2852: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 2853: my $indent;
2854: for (my $i = 0; $i < $depth; $i++) {
2855: $indent.= $whitespace;
2856: }
1.461 neumanie 2857: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 2858: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 2859: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
2860: }
1.468 amueller 2861: my $symb_name = $$symbp{$id};
2862: my ($front, $tail) = split (/___${resid}___/, $symb_name);
2863: $symb_name = $tail;
1.498 bisitz 2864: $r->print(
2865: &Apache::loncommon::start_data_table_row()
2866: .'<td>'
2867: .'<label>'
1.463 bisitz 2868: );
1.498 bisitz 2869: # Only offer radio button for folders/maps which can be parameterized
2870: if ($allmaps_inverted{$symb_name}) {
2871: $r->print(
2872: '<input type ="radio" name="pschp"'
2873: .' value="'.$allmaps_inverted{$symb_name}.'"'
2874: );
2875: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
2876: $r->print('/>');
2877: } else {
2878: $r->print($whitespace);
1.461 neumanie 2879: }
1.498 bisitz 2880: $r->print(
2881: $indent.$icon.' '
2882: .$treeinfo->{$id}->{name}
2883: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
2884: .'</label>'
2885: .'</td>'
2886: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2887: );
1.461 neumanie 2888: }
1.497 bisitz 2889:
1.523 raeburn 2890: $r->print(&Apache::loncommon::end_data_table().
2891: '<br style="line-height:2px;" />'.
2892: &Apache::loncommon::end_scrollbox());
1.209 www 2893: }
2894: }
2895:
1.563 damieng 2896: # Prints HTML to select the parameter level (resource, map/folder or course).
2897: # Used by table and overview modes.
2898: #
2899: # @param {Apache2::RequestRec} $r - the Apache request
2900: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
2901: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 2902: sub levelmenu {
1.446 bisitz 2903: my ($r,$alllevs,$parmlev)=@_;
2904:
1.548 raeburn 2905: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
2906: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 2907: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 2908: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
2909: $r->print('<option value="'.$$alllevs{$lev}.'"');
2910: if ($parmlev eq $$alllevs{$lev}) {
2911: $r->print(' selected="selected"');
2912: }
2913: $r->print('>'.&mt($lev).'</option>');
1.208 www 2914: }
1.446 bisitz 2915: $r->print("</select>");
1.208 www 2916: }
2917:
1.211 www 2918:
1.563 damieng 2919: # Returns HTML to select a section (with a select HTML element).
2920: # Used by overview mode.
2921: #
2922: # @param {array reference} $selectedsections - list of selected section ids
2923: # @returns {string}
1.211 www 2924: sub sectionmenu {
1.553 raeburn 2925: my ($selectedsections)=@_;
1.300 albertel 2926: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 2927: return '' if (!%sectionhash);
1.300 albertel 2928:
1.552 raeburn 2929: my (@possibles,$disabled);
2930: if ($env{'request.course.sec'} ne '') {
2931: @possibles = ($env{'request.course.sec'});
2932: $selectedsections = [$env{'request.course.sec'}];
2933: $disabled = ' disabled="disabled"';
2934: } else {
2935: @possibles = ('all',sort(keys(%sectionhash)));
2936: }
1.553 raeburn 2937: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 2938: foreach my $s (@possibles) {
1.553 raeburn 2939: $output .= ' <option value="'.$s.'"';
2940: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
2941: $output .= ' selected="selected"';
1.473 amueller 2942: }
1.553 raeburn 2943: $output .= '>'."$s</option>\n";
1.300 albertel 2944: }
1.553 raeburn 2945: $output .= "</select>\n";
2946: return $output;
1.269 raeburn 2947: }
2948:
1.563 damieng 2949: # Returns HTML to select a group (with a select HTML element).
2950: # Used by overview mode.
2951: #
2952: # @param {array reference} $selectedgroups - list of selected group names
2953: # @returns {string}
1.269 raeburn 2954: sub groupmenu {
1.553 raeburn 2955: my ($selectedgroups)=@_;
2956: my %grouphash;
2957: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2958: %grouphash = &Apache::longroup::coursegroups();
2959: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2960: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2961: }
2962: return '' if (!%grouphash);
1.299 albertel 2963:
1.553 raeburn 2964: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 2965: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 2966: $output .= ' <option value="'.$group.'"';
2967: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
2968: $output .= ' selected="selected"';
1.473 amueller 2969: }
1.553 raeburn 2970: $output .= '>'."$group</option>\n";
1.211 www 2971: }
1.553 raeburn 2972: $output .= "</select>\n";
2973: return $output;
1.211 www 2974: }
2975:
1.563 damieng 2976: # Returns an array with the given parameter split by comma.
2977: # Used by assessparms (table mode).
2978: #
2979: # @param {string} $keyp - the string to split
2980: # @returns {Array<string>}
1.210 www 2981: sub keysplit {
2982: my $keyp=shift;
2983: return (split(/\,/,$keyp));
2984: }
2985:
1.563 damieng 2986: # Returns the keys in $name, sorted using $keyorder.
2987: # Parameters are sorted by key, which means they are sorted by part first, then by name.
2988: # Used by assessparms (table mode) for resource level.
2989: #
2990: # @param {hash reference} $name - parameter key -> parameter name
2991: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2992: # @returns {Array<string>}
1.210 www 2993: sub keysinorder {
2994: my ($name,$keyorder)=@_;
2995: return sort {
1.560 damieng 2996: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 2997: } (keys(%{$name}));
1.210 www 2998: }
2999:
1.563 damieng 3000: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3001: # Used by assessparms (table mode) for map and general levels.
3002: #
3003: # @param {hash reference} $name - parameter key -> parameter name
3004: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3005: # @returns {Array<string>}
1.236 albertel 3006: sub keysinorder_bytype {
3007: my ($name,$keyorder)=@_;
3008: return sort {
1.563 damieng 3009: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3010: my $tb=(split('_',$b))[-1];
3011: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3012: return ($a cmp $b);
3013: }
3014: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3015: } (keys(%{$name}));
1.236 albertel 3016: }
3017:
1.563 damieng 3018: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3019: # Used by defaultsetter (parameter settings default actions).
3020: #
3021: # @param {hash reference} $name - hash parameter name -> parameter title
3022: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3023: # @returns {Array<string>}
1.211 www 3024: sub keysindisplayorder {
3025: my ($name,$keyorder)=@_;
3026: return sort {
1.560 damieng 3027: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3028: } (keys(%{$name}));
1.211 www 3029: }
3030:
1.563 damieng 3031: # Prints HTML with a choice to sort results by realm or student first.
3032: # Used by overview mode.
3033: #
3034: # @param {Apache2::RequestRec} $r - the Apache request
3035: # @param {string} $sortorder - realmstudent|studentrealm
1.214 www 3036: sub sortmenu {
3037: my ($r,$sortorder)=@_;
1.236 albertel 3038: $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214 www 3039: if ($sortorder eq 'realmstudent') {
1.422 bisitz 3040: $r->print(' checked="checked"');
1.214 www 3041: }
3042: $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236 albertel 3043: $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214 www 3044: if ($sortorder eq 'studentrealm') {
1.422 bisitz 3045: $r->print(' checked="checked"');
1.214 www 3046: }
1.236 albertel 3047: $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473 amueller 3048: '</label>');
1.214 www 3049: }
3050:
1.563 damieng 3051: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3052: #
3053: # @returns {hash}
1.211 www 3054: sub standardkeyorder {
3055: return ('parameter_0_opendate' => 1,
1.473 amueller 3056: 'parameter_0_duedate' => 2,
3057: 'parameter_0_answerdate' => 3,
3058: 'parameter_0_interval' => 4,
3059: 'parameter_0_weight' => 5,
3060: 'parameter_0_maxtries' => 6,
3061: 'parameter_0_hinttries' => 7,
3062: 'parameter_0_contentopen' => 8,
3063: 'parameter_0_contentclose' => 9,
3064: 'parameter_0_type' => 10,
3065: 'parameter_0_problemstatus' => 11,
3066: 'parameter_0_hiddenresource' => 12,
3067: 'parameter_0_hiddenparts' => 13,
3068: 'parameter_0_display' => 14,
3069: 'parameter_0_ordered' => 15,
3070: 'parameter_0_tol' => 16,
3071: 'parameter_0_sig' => 17,
3072: 'parameter_0_turnoffunit' => 18,
1.521 raeburn 3073: 'parameter_0_discussend' => 19,
3074: 'parameter_0_discusshide' => 20,
3075: 'parameter_0_discussvote' => 21,
1.560 damieng 3076: 'parameter_0_printstartdate' => 22,
3077: 'parameter_0_printenddate' => 23);
1.211 www 3078: }
3079:
1.59 matthew 3080:
1.560 damieng 3081: # Table mode UI.
1.563 damieng 3082: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3083: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3084: #
3085: # Parameters used from the request:
3086: # action - handler action (see handler), usermenu is checking for value 'settable'
3087: # cgroup - selected group
3088: # command - 'set': direct access to table mode for a resource
3089: # csec - selected section
3090: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3091: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3092: # id - student/employee ID
3093: # parmlev - selected level (full|map|general)
3094: # part - selected part (unused ?)
3095: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3096: # pres_type - &&&-separated parameter types
3097: # pres_value - &&&-separated parameter values
3098: # prevvisit - '1' if the user has submitted the form before
3099: # pscat (multiple values) - selected parameter names
1.566 damieng 3100: # pschp - selected map pc, or 'all'
1.563 damieng 3101: # psprt (multiple values) - list of selected parameter parts
3102: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3103: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3104: # symb - resource symb (when a single resource is selected)
3105: # udom - selected user domain
3106: # uname - selected user name
3107: # url - used only with command 'set', the resource url
3108: #
3109: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3110: # @param $parm_permission - ref to hash of permissions
3111: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3112: sub assessparms {
1.1 www 3113:
1.568 raeburn 3114: my ($r,$parm_permission) = @_;
1.201 www 3115:
1.512 foxr 3116:
3117: # -------------------------------------------------------- Variable declaration
1.566 damieng 3118: my @ids=(); # resource and map ids
3119: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3120: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3121: my %typep=(); # hash resource/map id -> resource type (file extension)
3122: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3123: my %uris=(); # hash resource/map id -> resource src
3124: my %maptitles=(); # hash map pc or src -> map title
3125: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3126: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3127: my %alllevs=(); # hash English level title -> value
3128:
3129: my $uname; # selected user name
3130: my $udom; # selected user domain
3131: my $uhome; # server with the user's files, or 'no_host'
3132: my $csec; # selected section name
3133: my $cgroup; # selected group name
3134: my @usersgroups = (); # list of the user groups
1.582 raeburn 3135: my $numreclinks = 0;
1.446 bisitz 3136:
1.190 albertel 3137: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3138:
1.57 albertel 3139: $alllevs{'Resource Level'}='full';
1.215 www 3140: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3141: $alllevs{'Course Level'}='general';
3142:
1.563 damieng 3143: my %allparms; # hash parameter name -> parameter title
3144: my %allparts; # hash parameter part -> part title
1.512 foxr 3145: # ------------------------------------------------------------------------------
3146:
1.210 www 3147: #
3148: # Order in which these parameters will be displayed
3149: #
1.211 www 3150: my %keyorder=&standardkeyorder();
3151:
1.512 foxr 3152: # @ids=();
3153: # %symbp=(); # These seem defined above already.
3154: # %typep=();
1.43 albertel 3155:
3156: my $message='';
3157:
1.190 albertel 3158: $csec=$env{'form.csec'};
1.552 raeburn 3159: if ($env{'request.course.sec'} ne '') {
3160: $csec = $env{'request.course.sec'};
3161: }
3162:
1.553 raeburn 3163: # Check group privs.
1.269 raeburn 3164: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3165: my $noeditgrp;
3166: if ($cgroup ne '') {
3167: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3168: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3169: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3170: $noeditgrp = 1;
3171: }
3172: }
3173: }
1.188 www 3174:
1.190 albertel 3175: if ($udom=$env{'form.udom'}) {
3176: } elsif ($udom=$env{'request.role.domain'}) {
3177: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3178: } else {
1.473 amueller 3179: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3180: }
1.468 amueller 3181:
1.43 albertel 3182:
1.134 albertel 3183: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3184: my $pschp=$env{'form.pschp'};
1.506 www 3185:
3186:
1.134 albertel 3187: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3188: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3189: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3190:
1.43 albertel 3191: my $pssymb='';
1.57 albertel 3192: my $parmlev='';
1.446 bisitz 3193:
1.190 albertel 3194: unless ($env{'form.parmlev'}) {
1.57 albertel 3195: $parmlev = 'map';
3196: } else {
1.190 albertel 3197: $parmlev = $env{'form.parmlev'};
1.57 albertel 3198: }
1.26 www 3199:
1.29 www 3200: # ----------------------------------------------- Was this started from grades?
3201:
1.560 damieng 3202: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3203: (!$env{'form.dis'})) {
1.473 amueller 3204: my $url=$env{'form.url'};
3205: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3206: $pssymb=&Apache::lonnet::symbread($url);
3207: if (!@pscat) { @pscat=('all'); }
3208: $pschp='';
1.57 albertel 3209: $parmlev = 'full';
1.190 albertel 3210: } elsif ($env{'form.symb'}) {
1.473 amueller 3211: $pssymb=$env{'form.symb'};
3212: if (!@pscat) { @pscat=('all'); }
3213: $pschp='';
1.57 albertel 3214: $parmlev = 'full';
1.43 albertel 3215: } else {
1.473 amueller 3216: $env{'form.url'}='';
1.43 albertel 3217: }
3218:
1.190 albertel 3219: my $id=$env{'form.id'};
1.43 albertel 3220: if (($id) && ($udom)) {
1.555 raeburn 3221: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3222: if ($uname) {
3223: $id='';
3224: } else {
3225: $message=
1.540 bisitz 3226: '<p class="LC_warning">'.
3227: &mt('Unknown ID [_1] at domain [_2]',
3228: "'".$id."'","'".$udom."'").
3229: '</p>';
1.473 amueller 3230: }
1.43 albertel 3231: } else {
1.473 amueller 3232: $uname=$env{'form.uname'};
1.43 albertel 3233: }
3234: unless ($udom) { $uname=''; }
3235: $uhome='';
3236: if ($uname) {
1.473 amueller 3237: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3238: if ($uhome eq 'no_host') {
1.473 amueller 3239: $message=
1.540 bisitz 3240: '<p class="LC_warning">'.
3241: &mt('Unknown user [_1] at domain [_2]',
3242: "'".$uname."'","'".$udom."'").
3243: '</p>';
1.473 amueller 3244: $uname='';
1.12 www 3245: } else {
1.473 amueller 3246: $csec=&Apache::lonnet::getsection($udom,$uname,
3247: $env{'request.course.id'});
3248: if ($csec eq '-1') {
1.596 raeburn 3249: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3250: if ($env{'form.userroles'} eq 'any') {
3251: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3252: $csec = $env{'request.course.sec'};
3253: $message = '<span class="LC_info">';
3254: if ($crstype eq 'Community') {
3255: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3256: $uname,$udom);
3257: } else {
3258: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3259: $uname,$udom);
3260: }
3261: $message .= '</span>';
3262: } else {
3263: my @possroles = ('in','ep','ta','cr');
3264: if ($crstype eq 'Community') {
3265: unshift(@possroles,'co');
3266: } else {
3267: unshift(@possroles,'cc');
3268: }
3269: my %not_student_roles =
3270: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3271: \@possroles,[$udom],1,1);
3272: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3273: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3274: my %sections_by_role;
3275: foreach my $role (keys(%not_student_roles)) {
3276: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3277: my ($rolename,$sec) = ($1,$2);
3278: if ($rolename =~ m{^cr/}) {
3279: $rolename = 'cr';
3280: }
3281: push(@{$sections_by_role{$rolename}},$sec);
3282: }
3283: }
3284: my $numroles = scalar(keys(%sections_by_role));
3285: if ($numroles) {
3286: foreach my $role (@possroles) {
3287: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3288: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3289: $csec = $secs[0];
3290: last;
3291: }
3292: }
3293: }
3294: if ($csec eq '-1') {
3295: $message = '<span class="LC_warning">';
3296: if ($crstype eq 'Community') {
3297: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3298: $uname,$udom);
3299: } else {
3300: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3301: $uname,$udom);
3302: }
3303: $message .= '</span>';
3304: $uname='';
3305: if ($env{'request.course.sec'} ne '') {
3306: $csec=$env{'request.course.sec'};
3307: } else {
3308: $csec=$env{'form.csec'};
3309: }
3310: $cgroup=$env{'form.cgroup'};
3311: } else {
3312: $message = '<span class="LC_info">';
3313: if ($crstype eq 'Community') {
3314: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3315: $uname,$udom);
3316: } else {
3317: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3318: $uname,$udom);
3319: }
3320: $message .= '</span>';
3321: }
3322: }
1.594 raeburn 3323: } else {
1.596 raeburn 3324: $message = '<span class="LC_warning">';
3325: if ($crstype eq 'Community') {
3326: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3327: $uname,$udom);
3328: } else {
3329: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3330: $uname,$udom);
3331: }
3332: $message .= '</span>';
3333: $uname='';
3334: if ($env{'request.course.sec'} ne '') {
3335: $csec=$env{'request.course.sec'};
3336: } else {
3337: $csec=$env{'form.csec'};
3338: }
3339: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3340: }
3341: } elsif ($env{'request.course.sec'} ne '') {
3342: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3343: $message='<span class="LC_warning">'.
1.594 raeburn 3344: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3345: $uname,$udom,$env{'request.course.sec'}).
3346: '</span>';
3347: $uname='';
3348: $csec=$env{'request.course.sec'};
3349: }
1.269 raeburn 3350: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3351: }
3352: if ($uname ne '') {
1.473 amueller 3353: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3354: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3355: $message .= "\n<p>\n".&mt('Full Name').': '
3356: .$name{'firstname'}.' '.$name{'middlename'}.' '
3357: .$name{'lastname'}.' '.$name{'generation'}
3358: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3359: @usersgroups = &Apache::lonnet::get_users_groups(
3360: $udom,$uname,$env{'request.course.id'});
3361: if (@usersgroups > 0) {
3362: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3363: $cgroup = $usersgroups[0];
3364: }
3365: } else {
3366: $cgroup = '';
1.297 raeburn 3367: }
1.269 raeburn 3368: }
1.12 www 3369: }
1.43 albertel 3370: }
1.2 www 3371:
1.43 albertel 3372: unless ($csec) { $csec=''; }
1.269 raeburn 3373: unless ($cgroup) { $cgroup=''; }
1.12 www 3374:
1.14 www 3375: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3376: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3377: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 3378: \%keyorder,undef,$pssymb);
1.63 bowersj2 3379:
1.582 raeburn 3380: %allmaps_inverted = reverse(%allmaps);
3381:
1.57 albertel 3382: $mapp{'0.0'} = '';
3383: $symbp{'0.0'} = '';
1.99 albertel 3384:
1.14 www 3385: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3386: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3387: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3388: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3389: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3390: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3391: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3392: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3393: my ($got_chostname,$chostname,$cmajor,$cminor);
3394: my $totalstored = 0;
1.605 raeburn 3395: my $totalskippeduser = 0;
1.546 raeburn 3396: my $now = time;
1.473 amueller 3397: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3398: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3399: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3400: next if ($csec ne $env{'request.course.sec'});
3401: }
1.556 raeburn 3402: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3403: next if ($noeditgrp);
1.605 raeburn 3404: } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
3405: if ($uname eq '') {
3406: $totalskippeduser ++;
3407: next;
3408: }
1.557 raeburn 3409: }
3410: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3411: $namematch = 'maplevelrecurse';
3412: }
1.556 raeburn 3413: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3414: my (@ok_slots,@fail_slots,@del_slots);
3415: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3416: my ($level,@all) =
3417: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3418: $csec,$cgroup,$courseopt);
3419: foreach my $slot_name (split(/:/,$values[$i])) {
3420: next if ($slot_name eq '');
3421: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3422: push(@ok_slots,$slot_name);
3423:
3424: } else {
3425: push(@fail_slots,$slot_name);
3426: }
3427: }
3428: if (@ok_slots) {
3429: $values[$i] = join(':',@ok_slots);
3430: } else {
3431: $values[$i] = '';
3432: }
3433: if ($all[$level] ne '') {
3434: my @existing = split(/:/,$all[$level]);
3435: foreach my $slot_name (@existing) {
3436: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3437: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3438: push(@del_slots,$slot_name);
3439: }
3440: }
3441: }
3442: }
1.554 raeburn 3443: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3444: $name = $1;
1.533 raeburn 3445: my $val = $values[$i];
1.549 raeburn 3446: my $valmatch = '';
1.533 raeburn 3447: if ($name eq 'examcode') {
1.544 raeburn 3448: if (&Apache::lonnet::validCODE($values[$i])) {
3449: $val = 'valid';
3450: }
1.546 raeburn 3451: } elsif ($name eq 'printstartdate') {
3452: if ($val =~ /^\d+$/) {
3453: if ($val > $now) {
3454: $val = 'future';
3455: }
3456: }
3457: } elsif ($name eq 'printenddate') {
3458: if ($val =~ /^\d+$/) {
3459: if ($val < $now) {
3460: $val = 'past';
3461: }
3462: }
1.549 raeburn 3463: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3464: my $stringtype = &get_stringtype($name);
3465: my $stringmatch = &standard_string_matches($stringtype);
3466: if (ref($stringmatch) eq 'ARRAY') {
3467: foreach my $item (@{$stringmatch}) {
3468: if (ref($item) eq 'ARRAY') {
3469: my ($regexpname,$pattern) = @{$item};
3470: if ($pattern ne '') {
3471: if ($val =~ /$pattern/) {
3472: $valmatch = $regexpname;
3473: $val = '';
3474: last;
3475: }
3476: }
3477: }
3478: }
3479: }
1.554 raeburn 3480: } elsif ($name eq 'interval') {
3481: my $intervaltype = &get_intervaltype($name);
3482: my $intervalmatch = &standard_interval_matches($intervaltype);
3483: if (ref($intervalmatch) eq 'ARRAY') {
3484: foreach my $item (@{$intervalmatch}) {
3485: if (ref($item) eq 'ARRAY') {
3486: my ($regexpname,$pattern) = @{$item};
3487: if ($pattern ne '') {
3488: if ($val =~ /$pattern/) {
3489: $valmatch = $regexpname;
3490: $val = '';
3491: last;
3492: }
3493: }
3494: }
3495: }
3496: }
1.533 raeburn 3497: }
1.504 raeburn 3498: $needsrelease =
1.557 raeburn 3499: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3500: if ($needsrelease) {
1.505 raeburn 3501: unless ($got_chostname) {
1.514 raeburn 3502: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3503: $got_chostname = 1;
1.546 raeburn 3504: }
1.557 raeburn 3505: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3506: $needsrelease,
3507: $cmajor,$cminor);
1.500 raeburn 3508: }
1.437 raeburn 3509: }
1.504 raeburn 3510: if ($needsnewer) {
1.557 raeburn 3511: undef($namematch);
3512: } else {
3513: my $currneeded;
3514: if ($needsrelease) {
3515: $currneeded = $needsrelease;
3516: }
3517: if ($namematch) {
3518: $needsrelease =
3519: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3520: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3521: unless ($got_chostname) {
3522: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3523: $got_chostname = 1;
3524: }
3525: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3526: $needsrelease,
3527: $cmajor,$cminor);
3528: } else {
3529: undef($namematch);
3530: }
3531: }
3532: }
3533: if ($needsnewer) {
3534: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3535: $cminor,$needsrelease);
3536: } else {
3537: $message.=&storeparm(split(/\&/,$markers[$i]),
3538: $values[$i],
3539: $types[$i],
3540: $uname,$udom,$csec,$cgroup);
3541: $totalstored ++;
3542: }
1.473 amueller 3543: }
1.68 www 3544: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3545: if ($totalstored) {
3546: $message.='<p class="LC_warning">'
1.605 raeburn 3547: .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
3548: .'<br />'
1.504 raeburn 3549: .&mt('Changes can take up to 10 minutes before being active for all students.')
3550: .&Apache::loncommon::help_open_topic('Caching')
3551: .'</p>';
1.605 raeburn 3552: } else {
3553: $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
3554: }
3555: if ($totalskippeduser) {
3556: $message .= '<p class="LC_warning">';
3557: if ($uhome eq 'no_host') {
3558: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
3559: $totalskippeduser);
3560: } elsif ($env{'form.userroles'} eq 'any') {
3561: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
3562: $totalskippeduser);
3563: } else {
3564: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
3565: $totalskippeduser);
3566: }
3567: $message .= '</p>';
1.504 raeburn 3568: }
1.68 www 3569: }
1.584 raeburn 3570:
1.57 albertel 3571: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3572: if ($pscat[0] eq "all") {
3573: @pscat = (keys(%allparms));
3574: }
3575: if (!@pscat) {
3576: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3577: };
3578: if ($psprt[0] eq "all" || !@psprt) {
3579: @psprt = (keys(%allparts));
3580: }
1.2 www 3581: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3582:
1.531 raeburn 3583: my $crstype = &Apache::loncommon::course_type();
3584: &startpage($r,$pssymb,$crstype);
1.57 albertel 3585:
1.548 raeburn 3586: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3587: 'date_interval','int','float','string','string_lenient',
3588: 'string_examcode','string_deeplink','string_discussvote',
3589: 'string_useslots','string_problemstatus','string_ip',
3590: 'string_questiontype') {
1.473 amueller 3591: $r->print('<input type="hidden" value="'.
1.563 damieng 3592: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3593: '" name="recent_'.$item.'" />');
1.44 albertel 3594: }
1.446 bisitz 3595:
1.459 bisitz 3596: # ----- Start Parameter Selection
3597:
1.606 raeburn 3598: # Hide parm selection and possibly table?
3599: my ($tablejs,$tabledivsty);
3600: if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
3601: ($env{'form.dis'}) && ($pssymb eq '')) {
3602: $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
3603: $tabledivsty = ' style="display:none"';
3604: }
1.459 bisitz 3605: $r->print(<<ENDPARMSELSCRIPT);
3606: <script type="text/javascript">
3607: // <![CDATA[
3608: function parmsel_show() {
1.562 damieng 3609: document.getElementById('parmsel').style.display = "";
3610: document.getElementById('parmsellink').style.display = "none";
1.606 raeburn 3611: $tablejs
1.459 bisitz 3612: }
3613: // ]]>
3614: </script>
3615: ENDPARMSELSCRIPT
1.474 amueller 3616:
1.445 neumanie 3617: if (!$pssymb) {
1.563 damieng 3618: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3619: my $parmselhiddenstyle=' style="display:none"';
3620: if($env{'form.hideparmsel'} eq 'hidden') {
3621: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3622: } else {
3623: $r->print('<div id="parmsel">');
3624: }
3625:
1.491 bisitz 3626: # Step 1
1.523 raeburn 3627: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3628: $r->print('
1.474 amueller 3629: <script type="text/javascript">
1.523 raeburn 3630: // <![CDATA['.
3631: &showhide_js().'
1.474 amueller 3632: // ]]>
3633: </script>
1.523 raeburn 3634: ');
3635: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3636: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3637: $r->print(&Apache::lonhtmlcommon::row_closure());
1.474 amueller 3638: &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491 bisitz 3639: $r->print(&Apache::lonhtmlcommon::row_closure());
3640: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3641: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3642: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3643: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3644:
3645: # Step 2
1.523 raeburn 3646: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3647: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3648:
3649: # Step 3
1.523 raeburn 3650: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3651: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3652: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3653: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3654: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3655:
3656: # Update Display Button
1.486 www 3657: $r->print('<p>'
3658: .'<input type="submit" name="dis"'
1.511 www 3659: .' value="'.&mt('Update Display').'" />'
1.486 www 3660: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3661: .'</p>');
3662: $r->print('</div>');
1.491 bisitz 3663:
1.486 www 3664: # Offer link to display parameter selection again
3665: $r->print('<p id="parmsellink"');
3666: if ($env{'form.hideparmsel'} ne 'hidden') {
3667: $r->print($parmselhiddenstyle);
3668: }
3669: $r->print('>'
3670: .'<a href="javascript:parmsel_show()">'
3671: .&mt('Change Parameter Selection')
3672: .'</a>'
3673: .'</p>');
1.44 albertel 3674: } else {
1.478 amueller 3675: # parameter screen for a single resource.
1.486 www 3676: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3677: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3678: $r->print(&mt('Specific Resource: [_1] ([_2])',
3679: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3680: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 3681: '<br />');
3682: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
3683: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3684: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3685: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3686: $r->print(&Apache::lonhtmlcommon::end_pick_box());
3687: $r->print('<p>'
1.459 bisitz 3688: .'<input type="submit" name="dis"'
1.511 www 3689: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 3690: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 3691: .'</p>');
1.459 bisitz 3692: }
1.478 amueller 3693:
1.486 www 3694: # ----- End Parameter Selection
1.57 albertel 3695:
1.459 bisitz 3696: # Display Messages
3697: $r->print('<div>'.$message.'</div>');
1.210 www 3698:
1.57 albertel 3699:
3700: my @temp_pscat;
3701: map {
3702: my $cat = $_;
3703: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
3704: } @pscat;
3705:
3706: @pscat = @temp_pscat;
3707:
1.548 raeburn 3708:
1.209 www 3709: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 3710: # ----------------------------------------------------------------- Start Table
1.57 albertel 3711: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 3712: my $csuname=$env{'user.name'};
3713: my $csudom=$env{'user.domain'};
1.568 raeburn 3714: my $readonly = 1;
3715: if ($parm_permission->{'edit'}) {
3716: undef($readonly);
3717: }
1.606 raeburn 3718: $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57 albertel 3719:
1.203 www 3720: if ($parmlev eq 'full') {
1.506 www 3721: #
3722: # This produces the cascading table output of parameters
3723: #
1.578 raeburn 3724: my $coursespan=$csec?8:5;
3725: my $userspan=3;
1.560 damieng 3726: if ($cgroup ne '') {
1.578 raeburn 3727: $coursespan += 3;
1.560 damieng 3728: }
1.473 amueller 3729:
1.560 damieng 3730: $r->print(&Apache::loncommon::start_data_table());
3731: #
3732: # This produces the headers
3733: #
3734: $r->print('<tr><td colspan="5"></td>');
3735: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
3736: if ($uname) {
1.473 amueller 3737: if (@usersgroups > 1) {
1.560 damieng 3738: $userspan ++;
3739: }
3740: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
3741: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
3742: }
3743: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 3744: 'pie' => "Parameter in Effect",
3745: 'csv' => "Current Session Value",
1.472 amueller 3746: 'rl' => "Resource Level",
1.473 amueller 3747: 'ic' => 'in Course',
3748: 'aut' => "Assessment URL and Title",
3749: 'type' => 'Type',
3750: 'emof' => "Enclosing Map or Folder",
3751: 'part' => 'Part',
1.472 amueller 3752: 'pn' => 'Parameter Name',
1.473 amueller 3753: 'def' => 'default',
3754: 'femof' => 'from Enclosing Map or Folder',
3755: 'gen' => 'general',
3756: 'foremf' => 'for Enclosing Map or Folder',
3757: 'fr' => 'for Resource'
3758: );
1.560 damieng 3759: $r->print(<<ENDTABLETWO);
1.419 bisitz 3760: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 3761: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 3762: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 3763: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 3764:
1.10 www 3765: ENDTABLETWO
1.560 damieng 3766: if ($csec) {
1.578 raeburn 3767: $r->print('<th colspan="3">'.
1.560 damieng 3768: &mt("in Section")." $csec</th>");
3769: }
3770: if ($cgroup) {
1.578 raeburn 3771: $r->print('<th colspan="3">'.
1.472 amueller 3772: &mt("in Group")." $cgroup</th>");
1.560 damieng 3773: }
3774: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 3775: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
3776: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 3777: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 3778: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 3779: ENDTABLEHEADFOUR
1.57 albertel 3780:
1.560 damieng 3781: if ($csec) {
1.578 raeburn 3782: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3783: }
1.473 amueller 3784:
1.560 damieng 3785: if ($cgroup) {
1.578 raeburn 3786: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3787: }
3788:
3789: if ($uname) {
3790: if (@usersgroups > 1) {
3791: $r->print('<th>'.&mt('Control by other group?').'</th>');
3792: }
1.578 raeburn 3793: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3794: }
3795:
3796: $r->print('</tr>');
1.506 www 3797: #
3798: # Done with the headers
3799: #
1.560 damieng 3800: my $defbgone='';
3801: my $defbgtwo='';
3802: my $defbgthree = '';
1.57 albertel 3803:
1.560 damieng 3804: foreach my $rid (@ids) {
1.57 albertel 3805:
3806: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 3807: if ((!$pssymb &&
1.560 damieng 3808: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
3809: ||
3810: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 3811: # ------------------------------------------------------ Entry for one resource
1.473 amueller 3812: if ($defbgone eq '#E0E099') {
3813: $defbgone='#E0E0DD';
1.57 albertel 3814: } else {
1.419 bisitz 3815: $defbgone='#E0E099';
1.57 albertel 3816: }
1.419 bisitz 3817: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 3818: $defbgtwo='#FFFFDD';
1.57 albertel 3819: } else {
1.473 amueller 3820: $defbgtwo='#FFFF99';
1.57 albertel 3821: }
1.419 bisitz 3822: if ($defbgthree eq '#FFBB99') {
3823: $defbgthree='#FFBBDD';
1.269 raeburn 3824: } else {
1.419 bisitz 3825: $defbgthree='#FFBB99';
1.269 raeburn 3826: }
3827:
1.57 albertel 3828: my $thistitle='';
3829: my %name= ();
3830: undef %name;
3831: my %part= ();
3832: my %display=();
3833: my %type= ();
3834: my %default=();
1.196 www 3835: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3836: my $toolsymb;
3837: if ($uri =~ /ext\.tool$/) {
3838: $toolsymb = $symbp{$rid};
3839: }
1.57 albertel 3840:
1.506 www 3841: my $filter=$env{'form.filter'};
1.548 raeburn 3842: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 3843: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 3844: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 3845: # We may only want certain parameters listed
3846: if ($filter) {
3847: unless ($filter=~/\Q$parmname\E/) { next; }
3848: }
3849: $name{$tempkeyp}=$parmname;
1.584 raeburn 3850: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 3851:
1.584 raeburn 3852: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 3853: if ($allparms{$name{$tempkeyp}} ne '') {
3854: my $identifier;
3855: if ($parmdis =~ /(\s*\[Part.*)$/) {
3856: $identifier = $1;
3857: }
3858: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3859: } else {
3860: $display{$tempkeyp} = $parmdis;
3861: }
3862: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3863: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 3864: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
3865: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
3866: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 3867: }
3868: }
1.548 raeburn 3869: my $totalparms=scalar(keys(%name));
1.57 albertel 3870: if ($totalparms>0) {
1.560 damieng 3871: my $firstrow=1;
1.473 amueller 3872: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 3873: my $navmap = Apache::lonnavmaps::navmap->new();
3874: my @recurseup;
3875: if (ref($navmap) && $mapp{$rid}) {
3876: @recurseup = $navmap->recurseup_maps($mapp{$rid});
3877: }
1.419 bisitz 3878: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 3879: ' rowspan='.$totalparms.
1.419 bisitz 3880: '><tt><font size="-1">'.
1.57 albertel 3881: join(' / ',split(/\//,$uri)).
3882: '</font></tt><p><b>'.
1.154 albertel 3883: "<a href=\"javascript:openWindow('".
1.473 amueller 3884: &Apache::lonnet::clutter($uri).'?symb='.
3885: &escape($symbp{$rid}).
1.336 albertel 3886: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
3887: " target=\"_self\">$title");
1.57 albertel 3888:
3889: if ($thistitle) {
1.473 amueller 3890: $r->print(' ('.$thistitle.')');
1.57 albertel 3891: }
3892: $r->print('</a></b></td>');
1.419 bisitz 3893: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 3894: ' rowspan='.$totalparms.'>'.$typep{$rid}.
3895: '</td>');
3896:
1.419 bisitz 3897: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 3898: ' rowspan='.$totalparms.
1.238 www 3899: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 3900: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 3901: unless ($firstrow) {
3902: $r->print('<tr>');
3903: } else {
3904: undef $firstrow;
3905: }
1.548 raeburn 3906: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 3907: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 3908: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 3909: $cgroup,\@usersgroups,$noeditgrp,$readonly,
3910: \@recurseup,\%maptitles,\%allmaps_inverted,
3911: \$numreclinks);
1.57 albertel 3912: }
3913: }
3914: }
3915: } # end foreach ids
1.43 albertel 3916: # -------------------------------------------------- End entry for one resource
1.517 www 3917: $r->print(&Apache::loncommon::end_data_table);
1.203 www 3918: } # end of full
1.57 albertel 3919: #--------------------------------------------------- Entry for parm level map
3920: if ($parmlev eq 'map') {
1.419 bisitz 3921: my $defbgone = '#E0E099';
3922: my $defbgtwo = '#FFFF99';
3923: my $defbgthree = '#FFBB99';
1.57 albertel 3924:
3925: my %maplist;
3926:
3927: if ($pschp eq 'all') {
1.446 bisitz 3928: %maplist = %allmaps;
1.57 albertel 3929: } else {
3930: %maplist = ($pschp => $mapp{$pschp});
3931: }
3932:
3933: #-------------------------------------------- for each map, gather information
3934: my $mapid;
1.607 ! raeburn 3935: foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60 albertel 3936: my $maptitle = $maplist{$mapid};
1.57 albertel 3937:
3938: #----------------------- loop through ids and get all parameter types for map
3939: #----------------------------------------- and associated information
3940: my %name = ();
3941: my %part = ();
3942: my %display = ();
3943: my %type = ();
3944: my %default = ();
3945: my $map = 0;
3946:
1.473 amueller 3947: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 3948:
1.548 raeburn 3949: foreach my $id (@ids) {
3950: ($map)=($id =~ /([\d]*?)\./);
3951: my $rid = $id;
1.446 bisitz 3952:
1.57 albertel 3953: # $r->print("$mapid:$map: $rid <br /> \n");
3954:
1.560 damieng 3955: if ($map eq $mapid) {
1.473 amueller 3956: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3957: my $toolsymb;
3958: if ($uri =~ /ext\.tool$/) {
3959: $toolsymb = $symbp{$rid};
3960: }
1.582 raeburn 3961:
1.57 albertel 3962: # $r->print("Keys: $keyp{$rid} <br />\n");
3963:
3964: #--------------------------------------------------------------------
3965: # @catmarker contains list of all possible parameters including part #s
3966: # $fullkeyp contains the full part/id # for the extraction of proper parameters
3967: # $tempkeyp contains part 0 only (no ids - ie, subparts)
3968: # When storing information, store as part 0
3969: # When requesting information, request from full part
3970: #-------------------------------------------------------------------
1.548 raeburn 3971: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
3972: my $tempkeyp = $fullkeyp;
3973: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 3974:
1.548 raeburn 3975: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 3976: $part{$tempkeyp}="0";
1.584 raeburn 3977: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
3978: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 3979: if ($allparms{$name{$tempkeyp}} ne '') {
3980: my $identifier;
3981: if ($parmdis =~ /(\s*\[Part.*)$/) {
3982: $identifier = $1;
3983: }
3984: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3985: } else {
3986: $display{$tempkeyp} = $parmdis;
3987: }
3988: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3989: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
3990: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 3991: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
3992: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 3993: }
3994: } # end loop through keys
1.560 damieng 3995: }
1.57 albertel 3996: } # end loop through ids
1.446 bisitz 3997:
1.57 albertel 3998: #---------------------------------------------------- print header information
1.133 www 3999: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 4000: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 4001: my $tmp="";
1.57 albertel 4002: if ($uname) {
1.473 amueller 4003: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 4004: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
4005: &mt('in')." \n";
1.57 albertel 4006: } else {
1.401 bisitz 4007: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 4008: }
1.269 raeburn 4009: if ($cgroup) {
1.401 bisitz 4010: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
4011: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4012: $csec = '';
4013: } elsif ($csec) {
1.401 bisitz 4014: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
4015: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4016: }
1.401 bisitz 4017: $r->print('<div align="center"><h4>'
4018: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 4019: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 4020: ,$tmp
4021: ,'<font color="red"><i>'.$coursename.'</i></font>'
4022: )
4023: ."<br /></h4>\n"
1.422 bisitz 4024: );
1.57 albertel 4025: #---------------------------------------------------------------- print table
1.419 bisitz 4026: $r->print('<p>'.&Apache::loncommon::start_data_table()
4027: .&Apache::loncommon::start_data_table_header_row()
4028: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 4029: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4030: .'<th>'.&mt('Parameter in Effect').'</th>'
4031: .&Apache::loncommon::end_data_table_header_row()
4032: );
1.57 albertel 4033:
1.582 raeburn 4034: my $navmap = Apache::lonnavmaps::navmap->new();
4035: my @recurseup;
4036: if (ref($navmap)) {
4037: my $mapres = $navmap->getByMapPc($mapid);
4038: if (ref($mapres)) {
4039: @recurseup = $navmap->recurseup_maps($mapres->src());
4040: }
4041: }
4042:
4043:
1.548 raeburn 4044: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4045: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4046: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4047: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4048: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4049: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4050: \$numreclinks);
1.57 albertel 4051: }
1.422 bisitz 4052: $r->print(&Apache::loncommon::end_data_table().'</p>'
4053: .'</div>'
4054: );
1.57 albertel 4055: } # end each map
4056: } # end of $parmlev eq map
4057: #--------------------------------- Entry for parm level general (Course level)
4058: if ($parmlev eq 'general') {
1.473 amueller 4059: my $defbgone = '#E0E099';
1.419 bisitz 4060: my $defbgtwo = '#FFFF99';
4061: my $defbgthree = '#FFBB99';
1.57 albertel 4062:
4063: #-------------------------------------------- for each map, gather information
4064: my $mapid="0.0";
4065: #----------------------- loop through ids and get all parameter types for map
4066: #----------------------------------------- and associated information
4067: my %name = ();
4068: my %part = ();
4069: my %display = ();
4070: my %type = ();
4071: my %default = ();
1.446 bisitz 4072:
1.548 raeburn 4073: foreach $id (@ids) {
4074: my $rid = $id;
1.446 bisitz 4075:
1.196 www 4076: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4077: my $toolsymb;
4078: if ($uri =~ /ext\.tool$/) {
4079: $toolsymb = $symbp{$rid};
4080: }
1.57 albertel 4081:
4082: #--------------------------------------------------------------------
4083: # @catmarker contains list of all possible parameters including part #s
4084: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4085: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4086: # When storing information, store as part 0
4087: # When requesting information, request from full part
4088: #-------------------------------------------------------------------
1.548 raeburn 4089: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4090: my $tempkeyp = $fullkeyp;
4091: $tempkeyp =~ s/_\w+_/_0_/;
4092: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4093: $part{$tempkeyp}="0";
1.584 raeburn 4094: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4095: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4096: if ($allparms{$name{$tempkeyp}} ne '') {
4097: my $identifier;
4098: if ($parmdis =~ /(\s*\[Part.*)$/) {
4099: $identifier = $1;
4100: }
4101: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4102: } else {
4103: $display{$tempkeyp} = $parmdis;
4104: }
4105: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4106: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4107: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4108: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4109: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4110: }
1.57 albertel 4111: } # end loop through keys
4112: } # end loop through ids
1.446 bisitz 4113:
1.57 albertel 4114: #---------------------------------------------------- print header information
1.473 amueller 4115: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4116: $r->print(<<ENDMAPONE);
1.419 bisitz 4117: <center>
4118: <h4>$setdef
1.135 albertel 4119: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4120: ENDMAPONE
4121: if ($uname) {
1.473 amueller 4122: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4123: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4124: } else {
1.135 albertel 4125: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4126: }
1.446 bisitz 4127:
1.135 albertel 4128: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4129: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4130: $r->print("</h4>\n");
1.57 albertel 4131: #---------------------------------------------------------------- print table
1.419 bisitz 4132: $r->print('<p>'.&Apache::loncommon::start_data_table()
4133: .&Apache::loncommon::start_data_table_header_row()
4134: .'<th>'.&mt('Parameter Name').'</th>'
4135: .'<th>'.&mt('Default Value').'</th>'
4136: .'<th>'.&mt('Parameter in Effect').'</th>'
4137: .&Apache::loncommon::end_data_table_header_row()
4138: );
1.57 albertel 4139:
1.548 raeburn 4140: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4141: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4142: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4143: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4144: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4145: $readonly);
1.57 albertel 4146: }
1.419 bisitz 4147: $r->print(&Apache::loncommon::end_data_table()
4148: .'</p>'
4149: .'</center>'
4150: );
1.57 albertel 4151: } # end of $parmlev eq general
1.606 raeburn 4152: $r->print('</div>');
1.43 albertel 4153: }
1.507 www 4154: $r->print('</form>');
1.582 raeburn 4155: if ($numreclinks) {
4156: $r->print(<<"END");
4157: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4158: <input type="hidden" name="pschp" />
4159: <input type="hidden" name="pscat" />
4160: <input type="hidden" name="psprt" />
4161: <input type="hidden" name="hideparmsel" value="hidden" />
4162: </form>
4163: <script type="text/javascript">
4164: function pjumprec(rid,name,part) {
4165: document.forms.recurseform.pschp.value = rid;
4166: document.forms.recurseform.pscat.value = name;
4167: document.forms.recurseform.psprt.value = part;
4168: document.forms.recurseform.submit();
4169: return false;
4170: }
4171: </script>
4172: END
4173: }
1.507 www 4174: &endSettingsScreen($r);
4175: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4176: } # end sub assessparms
1.30 www 4177:
1.560 damieng 4178:
4179:
1.120 www 4180: ##################################################
1.560 damieng 4181: # OVERVIEW MODE
1.207 www 4182: ##################################################
1.124 www 4183:
1.563 damieng 4184: my $tableopen; # boolean, true if HTML table is already opened
4185:
4186: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4187: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4188: # @returns {string}
1.124 www 4189: sub tablestart {
1.576 raeburn 4190: my ($readonly,$is_map) = @_;
1.124 www 4191: if ($tableopen) {
1.552 raeburn 4192: return '';
1.124 www 4193: } else {
1.552 raeburn 4194: $tableopen=1;
4195: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4196: if ($readonly) {
4197: $output .= '<th>'.&mt('Current value').'</th>';
4198: } else {
1.576 raeburn 4199: $output .= '<th>'.&mt('Delete').'</th>'.
4200: '<th>'.&mt('Set to ...').'</th>';
4201: if ($is_map) {
4202: $output .= '<th>'.&mt('Recursive?').'</th>';
4203: }
1.552 raeburn 4204: }
4205: $output .= '</tr>';
4206: return $output;
1.124 www 4207: }
4208: }
4209:
1.563 damieng 4210: # Returns HTML with the HTML table end tag, unless the table is not opened.
4211: # @returns {string}
1.124 www 4212: sub tableend {
4213: if ($tableopen) {
1.560 damieng 4214: $tableopen=0;
4215: return &Apache::loncommon::end_data_table();
1.124 www 4216: } else {
1.560 damieng 4217: return'';
1.124 www 4218: }
4219: }
4220:
1.563 damieng 4221: # Reads course and user information.
4222: # 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).
4223: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4224: # If the context is looking for a list, returns a list with the scalar data and the class list.
4225: # @param {string} $crs - course number
4226: # @param {string} $dom - course domain
4227: # @returns {hash reference|Array}
1.207 www 4228: sub readdata {
4229: my ($crs,$dom)=@_;
4230: # Read coursedata
4231: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4232: # Read userdata
4233:
4234: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4235: foreach my $user (keys(%$classlist)) {
4236: if ($user=~/^($match_username)\:($match_domain)$/) {
4237: my ($tuname,$tudom)=($1,$2);
4238: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4239: foreach my $userkey (keys(%{$useropt})) {
4240: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4241: my $newkey=$userkey;
1.548 raeburn 4242: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4243: $$resourcedata{$newkey}=$$useropt{$userkey};
4244: }
4245: }
1.473 amueller 4246: }
4247: }
1.552 raeburn 4248: if (wantarray) {
4249: return ($resourcedata,$classlist);
4250: } else {
4251: return $resourcedata;
4252: }
1.207 www 4253: }
4254:
4255:
1.563 damieng 4256: # Stores parameter data, using form parameters directly.
4257: #
4258: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.588 raeburn 4259: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563 damieng 4260: # del_* - remove a parameter
4261: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4262: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4263: # key_* - date values
4264: # days_* - for date intervals
4265: # hours_* - for date intervals
4266: # minutes_* - for date intervals
4267: # seconds_* - for date intervals
4268: # done_* - for date intervals
4269: # typeof_* - parameter type
4270: #
4271: # @param {Apache2::RequestRec} $r - the Apache request
4272: # @param {string} $crs - course number
4273: # @param {string} $dom - course domain
1.208 www 4274: sub storedata {
4275: my ($r,$crs,$dom)=@_;
1.207 www 4276: # Set userlevel immediately
4277: # Do an intermediate store of course level
4278: my $olddata=&readdata($crs,$dom);
1.124 www 4279: my %newdata=();
4280: undef %newdata;
4281: my @deldata=();
1.576 raeburn 4282: my @delrec=();
4283: my @delnonrec=();
1.124 www 4284: undef @deldata;
1.504 raeburn 4285: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4286: my $now = time;
1.560 damieng 4287: foreach my $key (keys(%env)) {
4288: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4289: my $cmd=$1;
4290: my $thiskey=$2;
1.576 raeburn 4291: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588 raeburn 4292: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576 raeburn 4293: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4294: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4295: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4296: $altkey = $thiskey;
4297: $altkey =~ s/\Q___(all)\E/___(rec)/;
4298: if ($env{'form.rec_'.$thiskey}) {
4299: $recursive = 1;
4300: }
4301: }
4302: }
1.560 damieng 4303: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4304: if ($tuname) {
1.576 raeburn 4305: $tkey=$thiskey;
1.560 damieng 4306: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4307: if ($altkey) {
4308: $tkeynonrec = $tkey;
4309: $tkeyrec = $altkey;
4310: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4311: }
1.560 damieng 4312: }
4313: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4314: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4315: if ($cmd eq 'set') {
4316: $data=$env{$key};
4317: $valmatch = '';
4318: $valchk = $data;
4319: $typeof=$env{'form.typeof_'.$thiskey};
4320: $text = &mt('Saved modified parameter for');
4321: if ($typeof eq 'string_questiontype') {
4322: $name = 'type';
1.588 raeburn 4323: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4324: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4325: my $stringmatch = &standard_string_matches($typeof);
4326: if (ref($stringmatch) eq 'ARRAY') {
4327: foreach my $item (@{$stringmatch}) {
4328: if (ref($item) eq 'ARRAY') {
4329: my ($regexpname,$pattern) = @{$item};
4330: if ($pattern ne '') {
4331: if ($data =~ /$pattern/) {
4332: $valmatch = $regexpname;
4333: $valchk = '';
4334: last;
4335: }
1.560 damieng 4336: }
1.549 raeburn 4337: }
4338: }
4339: }
1.563 damieng 4340: } elsif ($typeof eq 'string_discussvote') {
4341: $name = 'discussvote';
4342: } elsif ($typeof eq 'string_examcode') {
4343: $name = 'examcode';
4344: if (&Apache::lonnet::validCODE($data)) {
4345: $valchk = 'valid';
4346: }
4347: } elsif ($typeof eq 'string_yesno') {
4348: if ($thiskey =~ /\.retrypartial$/) {
4349: $name = 'retrypartial';
4350: }
1.549 raeburn 4351: }
1.563 damieng 4352: } elsif ($cmd eq 'datepointer') {
4353: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4354: $typeof=$env{'form.typeof_'.$thiskey};
4355: $text = &mt('Saved modified date for');
4356: if ($typeof eq 'date_start') {
4357: if ($thiskey =~ /\.printstartdate$/) {
4358: $name = 'printstartdate';
4359: if (($data) && ($data > $now)) {
4360: $valchk = 'future';
4361: }
1.560 damieng 4362: }
1.563 damieng 4363: } elsif ($typeof eq 'date_end') {
4364: if ($thiskey =~ /\.printenddate$/) {
4365: $name = 'printenddate';
4366: if (($data) && ($data < $now)) {
4367: $valchk = 'past';
4368: }
1.560 damieng 4369: }
1.504 raeburn 4370: }
1.563 damieng 4371: } elsif ($cmd eq 'dateinterval') {
4372: $data=&get_date_interval_from_form($thiskey);
4373: if ($thiskey =~ /\.interval$/) {
4374: $name = 'interval';
4375: my $intervaltype = &get_intervaltype($name);
4376: my $intervalmatch = &standard_interval_matches($intervaltype);
4377: if (ref($intervalmatch) eq 'ARRAY') {
4378: foreach my $item (@{$intervalmatch}) {
4379: if (ref($item) eq 'ARRAY') {
4380: my ($regexpname,$pattern) = @{$item};
4381: if ($pattern ne '') {
4382: if ($data =~ /$pattern/) {
4383: $valmatch = $regexpname;
4384: $valchk = '';
4385: last;
4386: }
1.560 damieng 4387: }
1.554 raeburn 4388: }
4389: }
4390: }
4391: }
1.563 damieng 4392: $typeof=$env{'form.typeof_'.$thiskey};
4393: $text = &mt('Saved modified date for');
1.554 raeburn 4394: }
1.576 raeburn 4395: if ($recursive) {
1.563 damieng 4396: $namematch = 'maplevelrecurse';
1.560 damieng 4397: }
1.563 damieng 4398: if (($name ne '') || ($namematch ne '')) {
4399: my ($needsrelease,$needsnewer);
4400: if ($name ne '') {
4401: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4402: if ($needsrelease) {
4403: unless ($got_chostname) {
1.563 damieng 4404: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4405: $got_chostname = 1;
4406: }
1.563 damieng 4407: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4408: $needsrelease,
4409: $cmajor,$cminor);
4410: }
4411: }
4412: if ($namematch ne '') {
4413: if ($needsnewer) {
4414: undef($namematch);
1.560 damieng 4415: } else {
1.563 damieng 4416: my $currneeded;
4417: if ($needsrelease) {
4418: $currneeded = $needsrelease;
4419: }
4420: $needsrelease =
4421: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4422: if (($needsrelease) &&
4423: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4424: unless ($got_chostname) {
4425: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4426: $got_chostname = 1;
4427: }
4428: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4429: $namematch, $needsrelease,$cmajor,$cminor);
4430: } else {
4431: undef($namematch);
4432: }
1.560 damieng 4433: }
1.557 raeburn 4434: }
1.563 damieng 4435: if ($needsnewer) {
4436: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4437: $chostname,$cmajor,
4438: $cminor,$needsrelease));
4439: next;
4440: }
1.504 raeburn 4441: }
1.576 raeburn 4442: my ($reconlychg,$haschange,$storekey);
4443: if ($tuname) {
4444: my $ustorekey;
4445: if ($altkey) {
4446: if ($recursive) {
4447: if (exists($$olddata{$thiskey})) {
4448: if ($$olddata{$thiskey} eq $data) {
4449: $reconlychg = 1;
4450: }
4451: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4452: }
4453: if (exists($$olddata{$altkey})) {
4454: if (defined($data) && $$olddata{$altkey} ne $data) {
4455: $haschange = 1;
4456: }
4457: } elsif ((!$reconlychg) && ($data ne '')) {
4458: $haschange = 1;
4459: }
4460: $ustorekey = $tkeyrec;
4461: } else {
4462: if (exists($$olddata{$altkey})) {
4463: if ($$olddata{$altkey} eq $data) {
4464: $reconlychg = 1;
4465: }
4466: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4467: }
4468: if (exists($$olddata{$thiskey})) {
4469: if (defined($data) && $$olddata{$thiskey} ne $data) {
4470: $haschange = 1;
4471: }
4472: } elsif ((!$reconlychg) && ($data ne '')) {
4473: $haschange = 1;
4474: }
4475: $ustorekey = $tkeynonrec;
4476: }
4477: } else {
4478: if (exists($$olddata{$tkey})) {
4479: if (defined($data) && $$olddata{$tkey} ne $data) {
4480: $haschange = 1;
4481: }
4482: $ustorekey = $tkey;
4483: }
4484: }
4485: if ($haschange || $reconlychg) {
4486: unless ($env{'form.del_'.$thiskey}) {
4487: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4488: $ustorekey.'.type' => $typeof},
4489: $tudom,$tuname) eq 'ok') {
4490: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4491: $r->print('<br />'.$text.' '.
4492: &Apache::loncommon::plainname($tuname,$tudom));
4493: } else {
4494: $r->print('<div class="LC_error">'.
4495: &mt('Error saving parameters').'</div>');
4496: }
4497: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4498: }
4499: }
4500: } else {
4501: if ($altkey) {
4502: if ($recursive) {
4503: if (exists($$olddata{$thiskey})) {
4504: if ($$olddata{$thiskey} eq $data) {
4505: $reconlychg = 1;
4506: }
4507: push(@delnonrec,($thiskey,$thiskey.'.type'));
4508: }
4509: if (exists($$olddata{$altkey})) {
4510: if (defined($data) && $$olddata{$altkey} ne $data) {
4511: $haschange = 1;
4512: }
4513: } elsif (($data ne '') && (!$reconlychg)) {
4514: $haschange = 1;
4515: }
4516: $storekey = $altkey;
1.563 damieng 4517: } else {
1.576 raeburn 4518: if (exists($$olddata{$altkey})) {
4519: if ($$olddata{$altkey} eq $data) {
4520: $reconlychg = 1;
4521: }
4522: push(@delrec,($altkey,$altkey.'.type'));
4523: }
4524: if (exists($$olddata{$thiskey})) {
4525: if (defined($data) && $$olddata{$thiskey} ne $data) {
4526: $haschange = 1;
4527: }
4528: } elsif (($data ne '') && (!$reconlychg)) {
4529: $haschange = 1;
4530: }
4531: $storekey = $thiskey;
1.563 damieng 4532: }
1.560 damieng 4533: } else {
1.576 raeburn 4534: if (defined($data) && $$olddata{$thiskey} ne $data) {
4535: $haschange = 1;
4536: $storekey = $thiskey;
4537: }
4538: }
4539: }
4540: if ($reconlychg || $haschange) {
4541: unless ($env{'form.del_'.$thiskey}) {
4542: $newdata{$storekey}=$data;
4543: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4544: }
4545: }
4546: } elsif ($cmd eq 'del') {
4547: if ($tuname) {
1.576 raeburn 4548: my $error;
4549: if ($altkey) {
4550: if (exists($$olddata{$altkey})) {
4551: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4552: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4553: if ($recursive) {
4554: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4555: }
4556: } elsif ($recursive) {
4557: $error = 1;
4558: }
4559: }
4560: if (exists($$olddata{$thiskey})) {
4561: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4562: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4563: unless ($recursive) {
4564: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4565: }
4566: } elsif (!$recursive) {
4567: $error = 1;
4568: }
4569: }
1.560 damieng 4570: } else {
1.576 raeburn 4571: if (exists($$olddata{$thiskey})) {
4572: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4573: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4574: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4575: } else {
4576: $error = 1;
4577: }
4578: }
4579: }
4580: if ($error) {
1.560 damieng 4581: $r->print('<div class="LC_error">'.
4582: &mt('Error deleting parameters').'</div>');
4583: }
4584: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4585: } else {
1.576 raeburn 4586: if ($altkey) {
4587: if (exists($$olddata{$altkey})) {
4588: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4589: push(@deldata,($altkey,$altkey.'.type'));
4590: }
4591: }
4592: if (exists($$olddata{$thiskey})) {
4593: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4594: push(@deldata,($thiskey,$thiskey.'.type'));
4595: }
4596: }
4597: } elsif (exists($$olddata{$thiskey})) {
4598: push(@deldata,($thiskey,$thiskey.'.type'));
4599: }
1.560 damieng 4600: }
1.473 amueller 4601: }
4602: }
4603: }
1.207 www 4604: # Store all course level
1.144 www 4605: my $delentries=$#deldata+1;
1.576 raeburn 4606: my @alldels;
4607: if (@delrec) {
4608: push(@alldels,@delrec);
4609: }
4610: if (@delnonrec) {
4611: push(@alldels,@delnonrec);
4612: }
4613: if (@deldata) {
4614: push(@alldels,@deldata);
4615: }
1.548 raeburn 4616: my @newdatakeys=keys(%newdata);
1.144 www 4617: my $putentries=$#newdatakeys+1;
1.576 raeburn 4618: my ($delresult,$devalidate);
4619: if (@alldels) {
4620: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4621: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4622: &log_parmset(\%loghash,1);
1.576 raeburn 4623: if ($delentries) {
4624: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4625: }
4626: } elsif ($delentries) {
1.560 damieng 4627: $r->print('<div class="LC_error">'.
4628: &mt('Error deleting parameters').'</div>');
4629: }
1.576 raeburn 4630: $devalidate = 1;
1.144 www 4631: }
4632: if ($putentries) {
1.560 damieng 4633: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4634: &log_parmset(\%newdata,0);
4635: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4636: } else {
4637: $r->print('<div class="LC_error">'.
4638: &mt('Error saving parameters').'</div>');
4639: }
1.576 raeburn 4640: $devalidate = 1;
4641: }
4642: if ($devalidate) {
1.560 damieng 4643: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4644: }
1.208 www 4645: }
1.207 www 4646:
1.563 damieng 4647: # Returns the username and domain from a key created in readdata from a resourcedata key.
4648: #
4649: # @param {string} $key - the key
4650: # @returns {Array}
1.208 www 4651: sub extractuser {
4652: my $key=shift;
1.350 albertel 4653: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4654: }
1.206 www 4655:
1.563 damieng 4656: # Parses a parameter key and returns the components.
4657: #
4658: # @param {string} $key -
4659: # @param {hash reference} $listdata -
4660: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4661: sub parse_listdata_key {
4662: my ($key,$listdata) = @_;
4663: # split into student/section affected, and
4664: # the realm (folder/resource part and parameter
1.446 bisitz 4665: my ($student,$realm) =
1.473 amueller 4666: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4667: # if course wide student would be undefined
4668: if (!defined($student)) {
1.560 damieng 4669: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4670: }
4671: # strip off the .type if it's not the Question type parameter
4672: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4673: $realm=~s/\.type//;
1.381 albertel 4674: }
4675: # split into resource+part and parameter name
1.388 albertel 4676: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4677: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4678: return ($student,$res,$part,$parm);
4679: }
4680:
1.563 damieng 4681: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
4682: #
4683: # @param {Apache2::RequestRec} $r - the Apache request
4684: # @param {hash reference} $resourcedata - parameter data returned by readdata
4685: # @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
4686: # @param {string} $sortorder - realmstudent|studentrealm
4687: # @param {string} $caller - name of the calling sub (overview|newoverview)
4688: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 4689: # @param {boolean} $readonly - true if editing not allowed
1.563 damieng 4690: # @returns{integer} - number of $listdata parameters processed
1.208 www 4691: sub listdata {
1.568 raeburn 4692: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552 raeburn 4693:
1.207 www 4694: # Start list output
1.206 www 4695:
1.122 www 4696: my $oldsection='';
4697: my $oldrealm='';
4698: my $oldpart='';
1.123 www 4699: my $pointer=0;
1.124 www 4700: $tableopen=0;
1.145 www 4701: my $foundkeys=0;
1.248 albertel 4702: my %keyorder=&standardkeyorder();
1.594 raeburn 4703: my $readonlyall = $readonly;
1.381 albertel 4704:
1.552 raeburn 4705: my ($secidx,%grouphash);
4706: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4707: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 4708: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4709: %grouphash = &Apache::longroup::coursegroups();
4710: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 4711: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 4712: }
1.552 raeburn 4713: }
4714:
1.576 raeburn 4715: foreach my $key (sort {
1.560 damieng 4716: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
4717: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381 albertel 4718:
1.560 damieng 4719: # get the numerical order for the param
4720: $aparm=$keyorder{'parameter_0_'.$aparm};
4721: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 4722:
1.560 damieng 4723: my $result=0;
1.381 albertel 4724:
1.560 damieng 4725: if ($sortorder eq 'realmstudent') {
1.381 albertel 4726: if ($ares ne $bres ) {
1.560 damieng 4727: $result = ($ares cmp $bres);
1.446 bisitz 4728: } elsif ($astudent ne $bstudent) {
1.560 damieng 4729: $result = ($astudent cmp $bstudent);
4730: } elsif ($apart ne $bpart ) {
4731: $result = ($apart cmp $bpart);
4732: }
4733: } else {
4734: if ($astudent ne $bstudent) {
4735: $result = ($astudent cmp $bstudent);
4736: } elsif ($ares ne $bres ) {
4737: $result = ($ares cmp $bres);
4738: } elsif ($apart ne $bpart ) {
4739: $result = ($apart cmp $bpart);
4740: }
1.473 amueller 4741: }
1.446 bisitz 4742:
1.560 damieng 4743: if (!$result) {
1.381 albertel 4744: if (defined($aparm) && defined($bparm)) {
1.560 damieng 4745: $result = ($aparm <=> $bparm);
1.381 albertel 4746: } elsif (defined($aparm)) {
1.560 damieng 4747: $result = -1;
1.381 albertel 4748: } elsif (defined($bparm)) {
1.560 damieng 4749: $result = 1;
4750: }
1.473 amueller 4751: }
1.381 albertel 4752:
1.560 damieng 4753: $result;
4754:
1.576 raeburn 4755: } keys(%{$listdata})) { # foreach my $key
4756: my $thiskey = $key;
1.560 damieng 4757: if ($$listdata{$thiskey.'.type'}) {
4758: my $thistype=$$listdata{$thiskey.'.type'};
4759: if ($$resourcedata{$thiskey.'.type'}) {
4760: $thistype=$$resourcedata{$thiskey.'.type'};
4761: }
4762: my ($middle,$part,$name)=
1.572 damieng 4763: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 4764: my $section=&mt('All Students');
1.594 raeburn 4765: $readonly = $readonlyall;
1.599 raeburn 4766: my $userscope;
1.576 raeburn 4767: my $showval = $$resourcedata{$thiskey};
1.560 damieng 4768: if ($middle=~/^\[(.*)\]/) {
4769: my $issection=$1;
4770: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
4771: my ($stuname,$studom) = ($1,$2);
4772: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4773: if (ref($classlist) eq 'HASH') {
4774: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
4775: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
4776: }
4777: }
4778: }
4779: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 4780: $userscope = 1;
1.560 damieng 4781: } else {
4782: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4783: if (exists($grouphash{$issection})) {
4784: $section=&mt('Group').': '.$issection;
4785: } elsif ($issection eq $env{'request.course.sec'}) {
4786: $section = &mt('Section').': '.$issection;
4787: } else {
4788: next;
1.552 raeburn 4789: }
1.560 damieng 4790: } else {
4791: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 4792: }
4793: }
1.560 damieng 4794: $middle=~s/^\[(.*)\]//;
4795: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4796: $readonly = 1;
4797: }
4798: $middle=~s/\.+$//;
4799: $middle=~s/^\.+//;
4800: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 4801: my ($is_map,$is_recursive,$mapurl,$maplevel);
4802: if ($caller eq 'overview') {
4803: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
4804: $mapurl = $1;
4805: $maplevel = $2;
4806: $is_map = 1;
4807: }
4808: } elsif ($caller eq 'newoverview') {
4809: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
4810: $mapurl = $1;
4811: $maplevel = $2;
4812: $is_map = 1;
4813: }
4814: }
4815: if ($is_map) {
1.560 damieng 4816: my $leveltitle = &mt('Folder/Map');
1.576 raeburn 4817: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
4818: if ($caller eq 'newoverview') {
4819: my $altkey = $thiskey;
4820: $altkey =~ s/\Q___(all)\E/___(rec)/;
4821: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
4822: $is_recursive = 1;
4823: if ($$resourcedata{$altkey.'.type'}) {
4824: $thistype=$$resourcedata{$altkey.'.type'};
4825: }
4826: $showval = $$resourcedata{$altkey};
4827: }
4828: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
4829: $thiskey =~ s/\Q___(rec)\E/___(all)/;
4830: $is_recursive = 1;
4831: }
1.560 damieng 4832: }
4833: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
4834: } elsif ($middle) {
4835: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
4836: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
4837: ': '.&Apache::lonnet::gettitle($middle).
4838: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
4839: $id.')</span></span>';
4840: }
4841: if ($sortorder eq 'realmstudent') {
4842: if ($realm ne $oldrealm) {
4843: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
4844: $oldrealm=$realm;
4845: $oldsection='';
4846: }
4847: if ($section ne $oldsection) {
4848: $r->print(&tableend()."\n<h2>$section</h2>");
4849: $oldsection=$section;
4850: $oldpart='';
4851: }
1.552 raeburn 4852: } else {
1.560 damieng 4853: if ($section ne $oldsection) {
4854: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
4855: $oldsection=$section;
4856: $oldrealm='';
4857: }
4858: if ($realm ne $oldrealm) {
4859: $r->print(&tableend()."\n<h2>$realm</h2>");
4860: $oldrealm=$realm;
4861: $oldpart='';
1.552 raeburn 4862: }
4863: }
1.560 damieng 4864: if ($part ne $oldpart) {
4865: $r->print(&tableend().
4866: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
4867: $oldpart=$part;
1.556 raeburn 4868: }
1.560 damieng 4869: #
4870: # Ready to print
4871: #
1.470 raeburn 4872: my $parmitem = &standard_parameter_names($name);
1.576 raeburn 4873: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 4874: &Apache::loncommon::start_data_table_row().
4875: '<td><b>'.&mt($parmitem).
4876: '</b></td>');
4877: unless ($readonly) {
1.599 raeburn 4878: my $disabled;
4879: if (($name eq 'availablestudent') &&
4880: (($showval eq '') || ($userscope))) {
4881: $disabled = ' disabled="disabled"';
4882: }
1.560 damieng 4883: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 4884: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 4885: }
4886: $r->print('<td>');
4887: $foundkeys++;
4888: if (&isdateparm($thistype)) {
4889: my $jskey='key_'.$pointer;
4890: my $state;
4891: $pointer++;
4892: if ($readonly) {
4893: $state = 'disabled';
4894: }
4895: $r->print(
4896: &Apache::lonhtmlcommon::date_setter('parmform',
4897: $jskey,
1.576 raeburn 4898: $showval,
1.560 damieng 4899: '',1,$state));
4900: unless ($readonly) {
4901: $r->print(
4902: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 4903: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 4904: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 4905: &date_sanity_info($showval)
1.560 damieng 4906: );
4907: }
4908: } elsif ($thistype eq 'date_interval') {
4909: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 4910: $showval,$readonly));
1.560 damieng 4911: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 4912: if ($name eq 'availablestudent') {
4913: $readonly = 1;
4914: }
1.560 damieng 4915: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 4916: $showval,$name,$readonly));
1.560 damieng 4917: } else {
1.576 raeburn 4918: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 4919: }
1.560 damieng 4920: unless ($readonly) {
4921: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
4922: $thistype.'" />');
1.552 raeburn 4923: }
1.576 raeburn 4924: $r->print('</td>');
4925: if ($is_map) {
4926: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
4927: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
4928: } else {
4929: my ($disabled,$recon,$recoff);
4930: if ($readonly) {
4931: $disabled = ' disabled="disabled"';
4932: }
4933: if ($is_recursive) {
4934: $recon = ' checked="checked"';
4935: } else {
4936: $recoff = ' checked="checked"';
4937: }
4938: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
4939: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
4940: }
4941: }
4942: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 4943: }
1.121 www 4944: }
1.208 www 4945: return $foundkeys;
4946: }
4947:
1.563 damieng 4948: # Returns a string representing the interval, directly using form data matching the given key.
4949: # The returned string may also include information related to proctored exams.
4950: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
4951: #
4952: # @param {string} $key - suffix for form fields related to the interval
4953: # @returns {string}
1.385 albertel 4954: sub get_date_interval_from_form {
4955: my ($key) = @_;
4956: my $seconds = 0;
4957: foreach my $which (['days', 86400],
1.473 amueller 4958: ['hours', 3600],
4959: ['minutes', 60],
4960: ['seconds', 1]) {
1.560 damieng 4961: my ($name, $factor) = @{ $which };
4962: if (defined($env{'form.'.$name.'_'.$key})) {
4963: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
4964: }
1.473 amueller 4965: }
1.560 damieng 4966: if (($key =~ /\.interval$/) &&
4967: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 4968: if ($env{'form.done_'.$key.'_buttontext'}) {
4969: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
4970: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
4971: if ($env{'form.done_'.$key} eq '_done_proctor') {
4972: $seconds .= '_proctor';
4973: }
4974: } else {
4975: $seconds .= $env{'form.done_'.$key};
4976: }
4977: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 4978: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 4979: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
4980: }
1.554 raeburn 4981: }
1.385 albertel 4982: return $seconds;
4983: }
4984:
4985:
1.563 damieng 4986: # Returns HTML to enter a text value for a parameter.
4987: #
4988: # @param {string} $thiskey - parameter key
4989: # @param {string} $showval - the current value
4990: # @param {boolean} $readonly - true if the field should not be made editable
4991: # @returns {string}
1.383 albertel 4992: sub default_selector {
1.552 raeburn 4993: my ($thiskey, $showval, $readonly) = @_;
4994: my $disabled;
4995: if ($readonly) {
4996: $disabled = ' disabled="disabled"';
4997: }
4998: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 4999: }
5000:
1.563 damieng 5001: # Returns HTML to enter allow/deny rules related to IP addresses.
5002: #
5003: # @param {string} $thiskey - parameter key
5004: # @param {string} $showval - the current value
5005: # @param {boolean} $readonly - true if the fields should not be made editable
5006: # @returns {string}
1.549 raeburn 5007: sub string_ip_selector {
1.552 raeburn 5008: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 5009: my %access = (
5010: allow => [],
5011: deny => [],
5012: );
5013: if ($showval ne '') {
5014: my @current;
5015: if ($showval =~ /,/) {
5016: @current = split(/,/,$showval);
5017: } else {
5018: @current = ($showval);
5019: }
5020: foreach my $item (@current) {
5021: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
5022: push(@{$access{'deny'}},$1);
5023: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
5024: push(@{$access{'allow'}},$item);
5025: }
5026: }
5027: }
5028: if (!@{$access{'allow'}}) {
5029: @{$access{'allow'}} = ('');
5030: }
5031: if (!@{$access{'deny'}}) {
5032: @{$access{'deny'}} = ('');
5033: }
1.552 raeburn 5034: my ($disabled,$addmore);
1.567 raeburn 5035: if ($readonly) {
1.552 raeburn 5036: $disabled=' disabled="disabled"';
5037: } else {
5038: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5039: }
1.549 raeburn 5040: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5041: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5042: foreach my $acctype ('allow','deny') {
5043: $output .= '
5044: <td valign="top">
5045: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5046: <div class="LC_string_ipacc_inner">'."\n";
5047: my $num = 0;
5048: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5049: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5050: if ($num > 0) {
5051: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5052: }
5053: $output .= '</div>'."\n";
5054: $num ++;
5055: }
5056: $output .= '
1.552 raeburn 5057: </div>'.$addmore.'
1.549 raeburn 5058: </div>
5059: </td>';
5060: }
5061: $output .= '
5062: </tr>
5063: </table>'."\n";
5064: return $output;
5065: }
5066:
1.588 raeburn 5067: sub string_deeplink_selector {
5068: my ($thiskey, $showval, $readonly) = @_;
1.597 raeburn 5069: my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601 raeburn 5070: %selectnull,%domlti,%crslti,@possmenus);
5071: @components = ('state','others','listing','scope','protect','menus');
1.588 raeburn 5072: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5073: state => 'Access status',
5074: others => 'Hide other resources',
1.588 raeburn 5075: listing => 'In Contents and/or Gradebook',
5076: scope => 'Access scope for link',
1.601 raeburn 5077: protect => 'Link protection',
1.597 raeburn 5078: menus => 'Menu Items Displayed',
1.588 raeburn 5079: );
5080: %options = (
1.601 raeburn 5081: state => ['only','off','both'],
5082: others => ['hide','unhide'],
1.588 raeburn 5083: listing => ['full','absent','grades','details','datestatus'],
5084: scope => ['res','map','rec'],
1.601 raeburn 5085: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5086: menus => ['std','colls'],
1.588 raeburn 5087: );
5088: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5089: only => 'deep only',
5090: off => 'deeplink off',
5091: both => 'regular + deep',
5092: hide => 'Hidden',
5093: unhide => 'Unhidden',
1.588 raeburn 5094: full => 'Listed (linked) in both',
5095: absent => 'Not listed',
5096: grades => 'Listed in grades only',
5097: details => 'Listed (unlinked) in both',
5098: datestatus => 'Listed (unlinked) inc. status in both',
5099: res => 'resource only',
5100: map => 'enclosing map/folder',
5101: rec => 'recursive map/folder',
1.601 raeburn 5102: none => 'not in use',
5103: key => 'key access',
5104: ltic => 'LTI access (course)',
5105: ltid => 'LTI access (domain)' ,
1.597 raeburn 5106: std => 'Standard (all menus)',
5107: colls => 'Numbered collection',
5108: );
5109: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5110: ltic => 'Select Launcher',
5111: ltid => 'Select Launcher',
1.597 raeburn 5112: colls => 'Select',
1.588 raeburn 5113: );
5114: if ($showval =~ /,/) {
1.597 raeburn 5115: %values=();
1.588 raeburn 5116: @current = split(/,/,$showval);
1.601 raeburn 5117: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5118: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5119: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5120: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5121: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5122: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.588 raeburn 5123: } else {
1.601 raeburn 5124: $defaults{'state'} = 'off',
5125: $defaults{'others'} = 'unhide',
1.588 raeburn 5126: $defaults{'listing'} = 'full';
5127: $defaults{'scope'} = 'res';
1.601 raeburn 5128: $defaults{'protect'} = 'none';
1.597 raeburn 5129: $defaults{'menus'} = '0';
1.588 raeburn 5130: }
5131: my $disabled;
5132: if ($readonly) {
5133: $disabled=' disabled="disabled"';
5134: }
1.601 raeburn 5135: my %courselti =
5136: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
5137: $env{'course.'.$env{'request.course.id'}.'.domain'});
5138: foreach my $item (keys(%courselti)) {
5139: if (ref($courselti{$item}) eq 'HASH') {
5140: $crslti{$item} = $courselti{$item}{'name'};
5141: }
5142: }
5143: my %lti =
1.588 raeburn 5144: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 5145: 'linkprot');
1.588 raeburn 5146: foreach my $item (keys(%lti)) {
1.604 raeburn 5147: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
5148: $domlti{$item} = $lti{$item}{'name'};
1.588 raeburn 5149: }
5150: }
1.597 raeburn 5151: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5152: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5153: my ($num,$value) = split(/\%/,$item);
5154: if ($num =~ /^\d+$/) {
5155: push(@possmenus,$num);
5156: }
5157: }
5158: }
5159:
1.588 raeburn 5160: my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597 raeburn 5161: foreach my $item (@components) {
1.588 raeburn 5162: $output .= '<th>'.$titles{$item}.'</th>';
5163: }
5164: $output .= '</tr><tr>';
5165: foreach my $item (@components) {
5166: $output .= '<td>';
1.601 raeburn 5167: if (($item eq 'protect') || ($item eq 'menus')) {
1.588 raeburn 5168: my $selected = $values{$item};
5169: foreach my $option (@{$options{$item}}) {
1.601 raeburn 5170: if ($item eq 'protect') {
5171: if ($option eq 'ltid') {
5172: next unless (keys(%domlti));
5173: } elsif ($option eq 'ltic') {
5174: next unless (keys(%crslti));
5175: }
1.597 raeburn 5176: } elsif (($item eq 'menus') && ($option eq 'colls')) {
5177: next unless (@possmenus);
1.588 raeburn 5178: }
5179: my $checked;
1.597 raeburn 5180: if ($item eq 'menus') {
5181: if (($selected =~ /^\d+$/) && (@possmenus) &&
5182: (grep(/^\Q$selected\E$/,@possmenus))) {
5183: if ($option eq 'colls') {
5184: $checked = ' checked="checked"';
5185: }
5186: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
5187: $checked = ' checked="checked"';
5188: }
5189: } elsif ($selected =~ /^\Q$option\E/) {
1.588 raeburn 5190: $checked = ' checked="checked"';
5191: }
5192: my $onclick;
5193: unless ($readonly) {
5194: my $esc_key = &js_escape($thiskey);
5195: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
5196: }
5197: $output .= '<span class="LC_nobreak"><label>'.
5198: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
5199: $optiontext{$option}.'</label>';
1.601 raeburn 5200: if (($item eq 'protect') && ($option eq 'key')) {
1.588 raeburn 5201: my $visibility="hidden";
5202: my $currkey;
5203: if ($checked) {
5204: $visibility = "text";
5205: $currkey = (split(/\:/,$values{$item}))[1];
5206: }
5207: $output .= ' '.
1.597 raeburn 5208: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601 raeburn 5209: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588 raeburn 5210: my $display="none";
1.597 raeburn 5211: my ($current,$blankcheck,@possibles);
1.588 raeburn 5212: if ($checked) {
5213: $display = 'inline-block';
1.601 raeburn 5214: if (($option eq 'ltic') || ($option eq 'ltid')) {
1.597 raeburn 5215: $current = (split(/\:/,$selected))[1];
5216: } else {
5217: $current = $selected;
5218: }
1.588 raeburn 5219: } else {
5220: $blankcheck = ' selected="selected"';
5221: }
1.601 raeburn 5222: if ($option eq 'ltid') {
5223: @possibles = keys(%domlti);
5224: } elsif ($option eq 'ltic') {
5225: @possibles = keys(%crslti);
1.597 raeburn 5226: } else {
5227: @possibles = @possmenus;
5228: }
1.588 raeburn 5229: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
5230: ' style="display: '.$display.'"> <select name="'.
1.597 raeburn 5231: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
5232: if (@possibles > 1) {
5233: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
5234: '</option>'."\n";
5235: }
5236: foreach my $poss (sort { $a <=> $b } @possibles) {
1.588 raeburn 5237: my $selected;
1.597 raeburn 5238: if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588 raeburn 5239: $selected = ' selected="selected"';
5240: }
1.597 raeburn 5241: my $shown = $poss;
1.601 raeburn 5242: if ($option eq 'ltid') {
5243: $shown = $domlti{$poss};
5244: } elsif ($option eq 'ltic') {
5245: $shown = $crslti{$poss};
1.597 raeburn 5246: }
5247: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588 raeburn 5248: }
5249: $output .= '</select></div>';
5250: }
5251: $output .= '</span> ';
5252: }
5253: } else {
5254: my $selected = $values{$item};
5255: my $defsel;
5256: if ($selected eq '') {
5257: $defsel = ' selected="selected"';
5258: }
5259: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
5260: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
5261: foreach my $option (@{$options{$item}}) {
5262: $output .= '<option value="'.$option.'"';
5263: if ($option eq $selected) {
5264: $output .= ' selected="selected"';
5265: }
5266: $output .= '>'.$optiontext{$option}.'</option>';
5267: }
5268: $output .= '</select>';
5269: }
5270: $output .= '</td>';
5271: }
5272: $output .= '</tr></table>'."\n";
5273: return $output;
5274: }
5275:
1.560 damieng 5276:
5277: { # block using some constants related to parameter types (overview mode)
5278:
1.446 bisitz 5279: my %strings =
1.383 albertel 5280: (
5281: 'string_yesno'
5282: => [[ 'yes', 'Yes' ],
1.560 damieng 5283: [ 'no', 'No' ]],
1.383 albertel 5284: 'string_problemstatus'
5285: => [[ 'yes', 'Yes' ],
1.473 amueller 5286: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5287: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5288: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5289: 'string_questiontype'
5290: => [[ 'problem', 'Standard Problem'],
5291: [ 'survey', 'Survey'],
5292: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5293: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5294: [ 'anonsurvey', 'Anonymous Survey'],
5295: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5296: [ 'practice', 'Practice'],
5297: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5298: 'string_lenient'
5299: => [['yes', 'Yes' ],
5300: [ 'no', 'No' ],
1.549 raeburn 5301: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5302: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5303: 'string_discussvote'
5304: => [['yes','Yes'],
5305: ['notended','Yes, unless discussion ended'],
5306: ['no','No']],
1.549 raeburn 5307: 'string_ip'
5308: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5309: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5310: 'string_deeplink'
1.597 raeburn 5311: => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
1.587 raeburn 5312: );
5313:
1.383 albertel 5314:
1.549 raeburn 5315: my %stringmatches = (
5316: 'string_lenient'
5317: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5318: 'string_ip'
5319: => [['_allowfrom_','[^\!]+'],
5320: ['_denyfrom_','\!']],
1.588 raeburn 5321: 'string_deeplink'
1.602 raeburn 5322: => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)$']],
1.549 raeburn 5323: );
5324:
5325: my %stringtypes = (
5326: type => 'string_questiontype',
5327: lenient => 'string_lenient',
5328: retrypartial => 'string_yesno',
5329: discussvote => 'string_discussvote',
5330: examcode => 'string_examcode',
5331: acc => 'string_ip',
1.587 raeburn 5332: deeplink => 'string_deeplink',
1.549 raeburn 5333: );
5334:
1.563 damieng 5335: # Returns the possible values and titles for a given string type, or undef if there are none.
5336: # Used by courseprefs.
5337: #
5338: # @param {string} $string_type - a parameter type for strings
5339: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5340: sub standard_string_options {
5341: my ($string_type) = @_;
5342: if (ref($strings{$string_type}) eq 'ARRAY') {
5343: return $strings{$string_type};
5344: }
5345: return;
5346: }
1.383 albertel 5347:
1.563 damieng 5348: # Returns regular expressions to match kinds of string types, or undef if there are none.
5349: #
5350: # @param {string} $string_type - a parameter type for strings
5351: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5352: sub standard_string_matches {
5353: my ($string_type) = @_;
5354: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5355: return $stringmatches{$string_type};
5356: }
5357: return;
5358: }
5359:
1.563 damieng 5360: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5361: #
5362: # @param {string} $name - parameter name
5363: # @returns {string}
1.549 raeburn 5364: sub get_stringtype {
5365: my ($name) = @_;
5366: if (exists($stringtypes{$name})) {
5367: return $stringtypes{$name};
5368: }
5369: return;
5370: }
5371:
1.563 damieng 5372: # Returns HTML to edit a string parameter.
5373: #
5374: # @param {string} $thistype - parameter type
5375: # @param {string} $thiskey - parameter key
5376: # @param {string} $showval - parameter current value
5377: # @param {string} $name - parameter name
5378: # @param {boolean} $readonly - true if the values should not be made editable
5379: # @returns {string}
1.383 albertel 5380: sub string_selector {
1.552 raeburn 5381: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5382:
1.383 albertel 5383: if (!exists($strings{$thistype})) {
1.552 raeburn 5384: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5385: }
5386:
1.504 raeburn 5387: my %skiptype;
1.514 raeburn 5388: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5389: ($thistype eq 'string_lenient') ||
5390: ($thistype eq 'string_discussvote') ||
5391: ($thistype eq 'string_ip') ||
1.588 raeburn 5392: ($thistype eq 'string_deeplink') ||
1.560 damieng 5393: ($name eq 'retrypartial')) {
1.504 raeburn 5394: my ($got_chostname,$chostname,$cmajor,$cminor);
5395: foreach my $possibilities (@{ $strings{$thistype} }) {
5396: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5397: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5398: my $parmmatch;
5399: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5400: foreach my $item (@{$stringmatches{$thistype}}) {
5401: if (ref($item) eq 'ARRAY') {
5402: if ($parmval eq $item->[0]) {
5403: $parmmatch = $parmval;
5404: $parmval = '';
5405: last;
5406: }
5407: }
5408: }
5409: }
5410: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5411: if ($needsrelease) {
5412: unless ($got_chostname) {
1.514 raeburn 5413: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5414: $got_chostname = 1;
5415: }
1.557 raeburn 5416: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5417: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5418: if ($needsnewer) {
1.549 raeburn 5419: if ($parmmatch ne '') {
5420: $skiptype{$parmmatch} = 1;
5421: } elsif ($parmval ne '') {
5422: $skiptype{$parmval} = 1;
5423: }
1.504 raeburn 5424: }
5425: }
5426: }
5427: }
1.549 raeburn 5428:
5429: if ($thistype eq 'string_ip') {
1.552 raeburn 5430: return &string_ip_selector($thiskey,$showval,$readonly);
1.588 raeburn 5431: } elsif ($thistype eq 'string_deeplink') {
5432: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5433: }
1.504 raeburn 5434:
1.552 raeburn 5435: my ($result,$disabled);
5436:
5437: if ($readonly) {
5438: $disabled = ' disabled="disabled"';
5439: }
1.504 raeburn 5440: my $numinrow = 3;
5441: if ($thistype eq 'string_problemstatus') {
5442: $numinrow = 2;
5443: } elsif ($thistype eq 'string_questiontype') {
5444: if (keys(%skiptype) > 0) {
5445: $numinrow = 4;
5446: }
5447: }
5448: my $rem;
5449: if (ref($strings{$thistype}) eq 'ARRAY') {
5450: my $i=0;
5451: foreach my $possibilities (@{ $strings{$thistype} }) {
5452: next unless (ref($possibilities) eq 'ARRAY');
5453: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5454: next if ($skiptype{$name});
1.504 raeburn 5455: $rem = $i%($numinrow);
5456: if ($rem == 0) {
5457: if ($i > 0) {
5458: $result .= '</tr>';
5459: }
5460: $result .= '<tr>';
5461: }
1.549 raeburn 5462: my $colspan;
5463: if ($i == @{ $strings{$thistype} }-1) {
5464: $rem = @{ $strings{$thistype} }%($numinrow);
5465: if ($rem) {
5466: my $colsleft = $numinrow - $rem;
5467: if ($colsleft) {
5468: $colspan = $colsleft+1;
5469: $colspan = ' colspan="'.$colspan.'"';
5470: }
5471: }
5472: }
5473: my ($add,$onchange,$css_class);
5474: if ($thistype eq 'string_lenient') {
5475: if ($name eq 'weighted') {
5476: my $display;
5477: my %relatives = &Apache::lonlocal::texthash(
5478: corrchkd => 'Correct (checked)',
5479: corrunchkd => 'Correct (unchecked)',
5480: incorrchkd => 'Incorrect (checked)',
5481: incorrunchkd => 'Incorrect (unchecked)',
5482: );
5483: my %textval = (
5484: corrchkd => '1.0',
5485: corrunchkd => '1.0',
5486: incorrchkd => '0.0',
5487: incorrunchkd => '0.0',
5488: );
5489: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
5490: $textval{'corrchkd'} = $1;
5491: $textval{'corrunchkd'} = $2;
5492: $textval{'incorrchkd'} = $3;
5493: $textval{'incorrunchkd'} = $4;
5494: $display = 'inline';
5495: $showval = $name;
5496: } else {
5497: $display = 'none';
5498: }
5499: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
5500: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
5501: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
5502: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
5503: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 5504: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 5505: '</td></tr>';
5506: }
5507: $add .= '</table></div>'."\n";
5508: }
5509: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
5510: $css_class = ' class="LC_lenient_radio"';
5511: }
5512: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 5513: '<span class="LC_nobreak"><label>'.
5514: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 5515: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 5516: if ($showval eq $name) {
5517: $result .= ' checked="checked"';
5518: }
1.549 raeburn 5519: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 5520: $i++;
5521: }
5522: $result .= '</tr>';
1.473 amueller 5523: }
1.504 raeburn 5524: if ($result) {
5525: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 5526: }
5527: return $result;
5528: }
5529:
1.554 raeburn 5530: my %intervals =
5531: (
5532: 'date_interval'
5533: => [[ 'done', 'Yes' ],
1.558 raeburn 5534: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 5535: [ '', 'No' ]],
5536: );
5537:
5538: my %intervalmatches = (
5539: 'date_interval'
1.559 raeburn 5540: => [['done','\d+_done(|\:[^\:]+\:)$'],
5541: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 5542: );
5543:
5544: my %intervaltypes = (
5545: interval => 'date_interval',
5546: );
5547:
1.563 damieng 5548: # Returns regular expressions to match kinds of interval type, or undef if there are none.
5549: #
5550: # @param {string} $interval_type - a parameter type for intervals
5551: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 5552: sub standard_interval_matches {
5553: my ($interval_type) = @_;
5554: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
5555: return $intervalmatches{$interval_type};
5556: }
5557: return;
5558: }
5559:
1.563 damieng 5560: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
5561: #
5562: # @param {string} $name - parameter name
5563: # @returns {string}
1.554 raeburn 5564: sub get_intervaltype {
5565: my ($name) = @_;
5566: if (exists($intervaltypes{$name})) {
5567: return $intervaltypes{$name};
5568: }
5569: return;
5570: }
5571:
1.563 damieng 5572: # Returns the possible values and titles for a given interval type, or undef if there are none.
5573: # Used by courseprefs.
5574: #
5575: # @param {string} $interval_type - a parameter type for intervals
5576: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 5577: sub standard_interval_options {
5578: my ($interval_type) = @_;
5579: if (ref($intervals{$interval_type}) eq 'ARRAY') {
5580: return $intervals{$interval_type};
5581: }
5582: return;
5583: }
5584:
1.563 damieng 5585: # Returns HTML to edit a date interval parameter.
5586: #
5587: # @param {string} $thiskey - parameter key
5588: # @param {string} $name - parameter name
5589: # @param {string} $showval - parameter current value
5590: # @param {boolean} $readonly - true if the values should not be made editable
5591: # @returns {string}
1.554 raeburn 5592: sub date_interval_selector {
5593: my ($thiskey, $name, $showval, $readonly) = @_;
5594: my ($result,%skipval);
5595: if ($name eq 'interval') {
5596: my $intervaltype = &get_intervaltype($name);
5597: my ($got_chostname,$chostname,$cmajor,$cminor);
5598: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
5599: next unless (ref($possibilities) eq 'ARRAY');
5600: my ($parmval, $description) = @{ $possibilities };
5601: my $parmmatch;
5602: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
5603: foreach my $item (@{$intervalmatches{$intervaltype}}) {
5604: if (ref($item) eq 'ARRAY') {
5605: if ($parmval eq $item->[0]) {
5606: $parmmatch = $parmval;
5607: $parmval = '';
5608: last;
5609: }
5610: }
5611: }
5612: }
5613: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
5614: if ($needsrelease) {
5615: unless ($got_chostname) {
5616: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
5617: $got_chostname = 1;
5618: }
1.557 raeburn 5619: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 5620: $needsrelease,$cmajor,$cminor);
5621: if ($needsnewer) {
5622: if ($parmmatch ne '') {
5623: $skipval{$parmmatch} = 1;
5624: } elsif ($parmval ne '') {
5625: $skipval{$parmval} = 1;
5626: }
5627: }
5628: }
5629: }
5630: }
5631:
5632: my $currval = $showval;
5633: foreach my $which (['days', 86400, 31],
5634: ['hours', 3600, 23],
5635: ['minutes', 60, 59],
5636: ['seconds', 1, 59]) {
1.560 damieng 5637: my ($name, $factor, $max) = @{ $which };
5638: my $amount = int($showval/$factor);
5639: $showval %= $factor;
5640: my %select = ((map {$_ => $_} (0..$max)),
5641: 'select_form_order' => [0..$max]);
5642: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
5643: \%select,'',$readonly);
5644: $result .= ' '.&mt($name);
1.554 raeburn 5645: }
5646: if ($name eq 'interval') {
5647: unless ($skipval{'done'}) {
5648: my $checkedon = '';
1.558 raeburn 5649: my $checkedproc = '';
5650: my $currproctorkey = '';
5651: my $currprocdisplay = 'hidden';
1.559 raeburn 5652: my $currdonetext = &mt('Done');
1.554 raeburn 5653: my $checkedoff = ' checked="checked"';
1.559 raeburn 5654: if ($currval =~ /^(?:\d+)_done$/) {
5655: $checkedon = ' checked="checked"';
5656: $checkedoff = '';
5657: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
5658: $currdonetext = $1;
1.554 raeburn 5659: $checkedon = ' checked="checked"';
5660: $checkedoff = '';
1.558 raeburn 5661: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
5662: $currproctorkey = $1;
5663: $checkedproc = ' checked="checked"';
5664: $checkedoff = '';
5665: $currprocdisplay = 'text';
1.559 raeburn 5666: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
5667: $currdonetext = $1;
5668: $currproctorkey = $2;
5669: $checkedproc = ' checked="checked"';
5670: $checkedoff = '';
5671: $currprocdisplay = 'text';
1.554 raeburn 5672: }
1.558 raeburn 5673: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 5674: my $disabled;
5675: if ($readonly) {
5676: $disabled = ' disabled="disabled"';
5677: }
1.558 raeburn 5678: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 5679: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 5680: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 5681: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 5682: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 5683: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 5684: &mt('Yes, with proctor key').'</label>'.
5685: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 5686: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 5687: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567 raeburn 5688: '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 5689: }
5690: }
5691: unless ($readonly) {
5692: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
5693: }
5694: return $result;
5695: }
5696:
1.563 damieng 5697: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
5698: #
5699: # @param {string} $name - parameter name
5700: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
5701: # @param {string} $value - parameter value
5702: # @param {string} $chostname - course server name
5703: # @param {integer} $cmajor - major version number
5704: # @param {integer} $cminor - minor version number
5705: # @param {string} $needsrelease - release version needed (major.minor)
5706: # @returns {string}
1.549 raeburn 5707: sub oldversion_warning {
1.557 raeburn 5708: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
5709: my $standard_name = &standard_parameter_names($name);
5710: if ($namematch) {
5711: my $level = &standard_parameter_levels($namematch);
5712: my $msg = '';
5713: if ($level) {
5714: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
5715: $standard_name,'<b>','</b>','"'.$level.'"');
5716: } else {
5717: $msg = &mt('[_1] was [_2]not[_3] set.',
5718: $standard_name,'<b>','</b>');
5719: }
5720: return '<p class="LC_warning">'.$msg.'<br />'.
5721: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5722: $cmajor.'.'.$cminor,$chostname,
5723: $needsrelease).
5724: '</p>';
5725: }
1.549 raeburn 5726: my $desc;
5727: my $stringtype = &get_stringtype($name);
5728: if ($stringtype ne '') {
5729: if ($name eq 'examcode') {
5730: $desc = $value;
5731: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
5732: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
5733: next unless (ref($possibilities) eq 'ARRAY');
5734: my ($parmval, $description) = @{ $possibilities };
5735: my $parmmatch;
5736: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
5737: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
5738: if (ref($item) eq 'ARRAY') {
5739: my ($regexpname,$pattern) = @{$item};
5740: if ($parmval eq $regexpname) {
5741: if ($value =~ /$pattern/) {
5742: $desc = $description;
5743: $parmmatch = 1;
5744: last;
5745: }
5746: }
5747: }
5748: }
5749: last if ($parmmatch);
5750: } elsif ($parmval eq $value) {
5751: $desc = $description;
5752: last;
5753: }
5754: }
5755: }
5756: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
5757: my $now = time;
5758: if ($value =~ /^\d+$/) {
5759: if ($name eq 'printstartdate') {
5760: if ($value > $now) {
5761: $desc = &Apache::lonlocal::locallocaltime($value);
5762: }
5763: } elsif ($name eq 'printenddate') {
5764: if ($value < $now) {
5765: $desc = &Apache::lonlocal::locallocaltime($value);
5766: }
5767: }
5768: }
5769: }
5770: return '<p class="LC_warning">'.
1.557 raeburn 5771: &mt('[_1] was [_2]not[_3] set to [_4].',
5772: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
5773: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5774: $cmajor.'.'.$cminor,$chostname,
5775: $needsrelease).
5776: '</p>';
1.549 raeburn 5777: }
5778:
1.560 damieng 5779: } # end of block using some constants related to parameter types
5780:
1.549 raeburn 5781:
1.563 damieng 5782:
5783: # Shifts all start and end dates in the current course by $shift.
1.389 www 5784: #
1.563 damieng 5785: # @param {integer} $shift - time to shift, in seconds
5786: # @returns {string} - error name or 'ok'
1.389 www 5787: sub dateshift {
1.594 raeburn 5788: my ($shift,$numchanges)=@_;
1.389 www 5789: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5790: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 5791: my $sec = $env{'request.course.sec'};
1.595 raeburn 5792: my $secgrpregex;
5793: if ($sec ne '') {
5794: my @groups;
5795: if ($env{'request.course.groups'} ne '') {
5796: @groups = split(/:/,$env{'request.course.groups'});
5797: }
5798: if (@groups) {
5799: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
5800: } else {
5801: $secgrpregex = $sec;
5802: }
5803: }
1.389 www 5804: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
5805: # ugly retro fix for broken version of types
1.548 raeburn 5806: foreach my $key (keys(%data)) {
1.389 www 5807: if ($key=~/\wtype$/) {
5808: my $newkey=$key;
5809: $newkey=~s/type$/\.type/;
5810: $data{$newkey}=$data{$key};
5811: delete $data{$key};
5812: }
5813: }
1.391 www 5814: my %storecontent=();
1.389 www 5815: # go through all parameters and look for dates
1.548 raeburn 5816: foreach my $key (keys(%data)) {
1.389 www 5817: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 5818: if ($sec ne '') {
1.595 raeburn 5819: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 5820: }
1.389 www 5821: my $newdate=$data{$key}+$shift;
1.594 raeburn 5822: $$numchanges ++;
1.391 www 5823: $storecontent{$key}=$newdate;
1.389 www 5824: }
5825: }
1.391 www 5826: my $reply=&Apache::lonnet::cput
5827: ('resourcedata',\%storecontent,$dom,$crs);
5828: if ($reply eq 'ok') {
5829: &log_parmset(\%storecontent);
5830: }
5831: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
5832: return $reply;
1.389 www 5833: }
5834:
1.563 damieng 5835: # Overview mode UI to edit course parameters.
5836: #
5837: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 5838: sub newoverview {
1.568 raeburn 5839: my ($r,$parm_permission) = @_;
1.280 albertel 5840:
1.208 www 5841: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5842: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 5843: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 5844: my $readonly = 1;
5845: if ($parm_permission->{'edit'}) {
5846: undef($readonly);
5847: }
1.414 droeschl 5848: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 5849: text=>"Overview Mode"});
1.523 raeburn 5850:
5851: my %loaditems = (
1.549 raeburn 5852: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 5853: );
5854: my $js = '
5855: <script type="text/javascript">
5856: // <![CDATA[
5857: '.
5858: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
5859: &showhide_js()."\n".
1.549 raeburn 5860: &toggleparmtextbox_js()."\n".
5861: &validateparms_js()."\n".
5862: &ipacc_boxes_js()."\n".
1.558 raeburn 5863: &done_proctor_js()."\n".
1.588 raeburn 5864: &deeplink_js()."\n".
1.523 raeburn 5865: '// ]]>
5866: </script>
5867: ';
1.549 raeburn 5868:
1.523 raeburn 5869: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
5870: {'add_entries' => \%loaditems,});
1.298 albertel 5871: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 5872: $r->print($start_page.$breadcrumbs);
1.531 raeburn 5873: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 5874: $r->print(<<ENDOVER);
1.549 raeburn 5875: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208 www 5876: ENDOVER
1.211 www 5877: my @ids=();
5878: my %typep=();
5879: my %keyp=();
5880: my %allparms=();
5881: my %allparts=();
5882: my %allmaps=();
5883: my %mapp=();
5884: my %symbp=();
5885: my %maptitles=();
5886: my %uris=();
5887: my %keyorder=&standardkeyorder();
5888: my %defkeytype=();
5889:
5890: my %alllevs=();
5891: $alllevs{'Resource Level'}='full';
1.215 www 5892: $alllevs{'Map/Folder Level'}='map';
1.211 www 5893: $alllevs{'Course Level'}='general';
5894:
5895: my $csec=$env{'form.csec'};
1.269 raeburn 5896: my $cgroup=$env{'form.cgroup'};
1.211 www 5897:
5898: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
5899: my $pschp=$env{'form.pschp'};
1.506 www 5900:
1.211 www 5901: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 5902: if (!@psprt) { $psprt[0]='all'; }
1.211 www 5903:
1.446 bisitz 5904: my @selected_sections =
1.473 amueller 5905: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 5906: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 5907: foreach my $sec (@selected_sections) {
5908: if ($sec eq 'all') {
1.211 www 5909: @selected_sections = ('all');
5910: }
5911: }
1.552 raeburn 5912: if ($env{'request.course.sec'} ne '') {
5913: @selected_sections = ($env{'request.course.sec'});
5914: }
1.269 raeburn 5915: my @selected_groups =
5916: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 5917:
5918: my $pssymb='';
5919: my $parmlev='';
1.446 bisitz 5920:
1.211 www 5921: unless ($env{'form.parmlev'}) {
5922: $parmlev = 'map';
5923: } else {
5924: $parmlev = $env{'form.parmlev'};
5925: }
5926:
1.446 bisitz 5927: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 5928: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 5929: \%keyorder,\%defkeytype,$pssymb);
1.211 www 5930:
1.374 albertel 5931: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 5932: @psprt = keys(%allparts);
1.374 albertel 5933: }
1.211 www 5934: # Menu to select levels, etc
5935:
1.456 bisitz 5936: $r->print('<div class="LC_Box">');
1.445 neumanie 5937: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 5938: $r->print('<div>');
1.523 raeburn 5939: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 5940: &levelmenu($r,\%alllevs,$parmlev);
5941: if ($parmlev ne 'general') {
1.447 bisitz 5942: $r->print(&Apache::lonhtmlcommon::row_closure());
1.483 amueller 5943: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211 www 5944: }
1.447 bisitz 5945: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 5946: $r->print(&Apache::lonhtmlcommon::end_pick_box());
5947: $r->print('</div></div>');
1.446 bisitz 5948:
1.456 bisitz 5949: $r->print('<div class="LC_Box">');
1.452 bisitz 5950: $r->print('<div>');
1.581 raeburn 5951: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 5952: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 5953: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 5954: my $sectionselector = §ionmenu(\@selected_sections);
5955: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 5956: $r->print('<table>'.
1.553 raeburn 5957: '<tr><th>'.&mt('Parts').'</th>');
5958: if ($sectionselector) {
5959: $r->print('<th>'.&mt('Section(s)').'</th>');
5960: }
5961: if ($groupselector) {
5962: $r->print('<th>'.&mt('Group(s)').'</th>');
5963: }
5964: $r->print('</tr><tr><td>');
1.211 www 5965: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 5966: $r->print('</td>');
5967: if ($sectionselector) {
5968: $r->print('<td>'.$sectionselector.'</td>');
5969: }
5970: if ($groupselector) {
5971: $r->print('<td>'.$groupselector.'</td>');
5972: }
5973: $r->print('</tr></table>');
1.447 bisitz 5974: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 5975: $r->print(&Apache::lonhtmlcommon::end_pick_box());
5976: $r->print('</div></div>');
5977:
1.456 bisitz 5978: $r->print('<div class="LC_Box">');
1.452 bisitz 5979: $r->print('<div>');
1.214 www 5980: my $sortorder=$env{'form.sortorder'};
5981: unless ($sortorder) { $sortorder='realmstudent'; }
5982: &sortmenu($r,$sortorder);
1.445 neumanie 5983: $r->print('</div></div>');
1.446 bisitz 5984:
1.214 www 5985: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446 bisitz 5986:
1.211 www 5987: # Build the list data hash from the specified parms
5988:
5989: my $listdata;
5990: %{$listdata}=();
5991:
5992: foreach my $cat (@pscat) {
1.269 raeburn 5993: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
5994: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 5995: }
5996:
1.212 www 5997: if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211 www 5998:
1.481 amueller 5999: if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211 www 6000:
6001: # Read modified data
6002:
1.481 amueller 6003: my $resourcedata=&readdata($crs,$dom);
1.211 www 6004:
6005: # List data
6006:
1.568 raeburn 6007: &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
6008: }
6009: $r->print(&tableend());
6010: unless ($readonly) {
6011: $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211 www 6012: }
1.568 raeburn 6013: $r->print('</form>');
1.507 www 6014: &endSettingsScreen($r);
6015: $r->print(&Apache::loncommon::end_page());
1.208 www 6016: }
6017:
1.563 damieng 6018: # Fills $listdata with parameter information.
6019: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
6020: # The non-type value is always 1.
6021: #
6022: # @param {string} $cat - parameter name
1.566 damieng 6023: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 6024: # @param {string} $parmlev - selected level value (full|map|general), or ''
6025: # @param {hash reference} $listdata - the parameter data that will be modified
6026: # @param {array reference} $psprt - selected parts
6027: # @param {array reference} $selections - selected sections
6028: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6029: # @param {hash reference} $allmaps - hash map pc -> map src
6030: # @param {array reference} $ids - resource and map ids
6031: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6032: sub secgroup_lister {
6033: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6034: foreach my $item (@{$selections}) {
6035: foreach my $part (@{$psprt}) {
6036: my $rootparmkey=$env{'request.course.id'};
6037: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6038: $rootparmkey.='.['.$item.']';
6039: }
6040: if ($parmlev eq 'general') {
6041: # course-level parameter
6042: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6043: $$listdata{$newparmkey}=1;
6044: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6045: } elsif ($parmlev eq 'map') {
6046: # map-level parameter
1.548 raeburn 6047: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6048: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6049: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6050: $$listdata{$newparmkey}=1;
6051: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6052: }
6053: } else {
6054: # resource-level parameter
6055: foreach my $rid (@{$ids}) {
6056: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6057: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6058: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6059: $$listdata{$newparmkey}=1;
6060: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6061: }
6062: }
6063: }
6064: }
6065: }
6066:
1.563 damieng 6067: # UI to edit parameter settings starting with a list of all existing parameters.
6068: # (called by setoverview action)
6069: #
6070: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6071: sub overview {
1.568 raeburn 6072: my ($r,$parm_permission) = @_;
1.208 www 6073: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6074: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6075: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6076: my $readonly = 1;
6077: if ($parm_permission->{'edit'}) {
6078: undef($readonly);
6079: }
1.549 raeburn 6080: my $js = '<script type="text/javascript">'."\n".
6081: '// <![CDATA['."\n".
6082: &toggleparmtextbox_js()."\n".
6083: &validateparms_js()."\n".
6084: &ipacc_boxes_js()."\n".
1.558 raeburn 6085: &done_proctor_js()."\n".
1.588 raeburn 6086: &deeplink_js()."\n".
1.549 raeburn 6087: '// ]]>'."\n".
6088: '</script>'."\n";
1.414 droeschl 6089: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6090: text=>"Overview Mode"});
1.549 raeburn 6091: my %loaditems = (
6092: 'onload' => "showHideLenient();",
6093: );
6094:
6095: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6096: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6097: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6098: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6099: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6100:
1.208 www 6101: # Store modified
6102:
1.568 raeburn 6103: unless ($readonly) {
6104: &storedata($r,$crs,$dom);
6105: }
1.208 www 6106:
6107: # Read modified data
6108:
1.552 raeburn 6109: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6110:
1.214 www 6111:
6112: my $sortorder=$env{'form.sortorder'};
6113: unless ($sortorder) { $sortorder='realmstudent'; }
6114: &sortmenu($r,$sortorder);
6115:
1.568 raeburn 6116: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6117:
6118: if ($readonly) {
6119: $r->print('<p>'.$submitbutton.'</p>');
6120: }
6121:
1.208 www 6122: # List data
6123:
1.568 raeburn 6124: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6125: $r->print(&tableend().'<p>');
6126: if ($foundkeys) {
6127: unless ($readonly) {
6128: $r->print('<p>'.$submitbutton.'</p>');
6129: }
6130: } else {
6131: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6132: }
6133: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6134: }
1.121 www 6135:
1.560 damieng 6136: # Unused sub.
1.563 damieng 6137: #
6138: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6139: sub clean_parameters {
6140: my ($r) = @_;
6141: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6142: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6143:
1.414 droeschl 6144: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6145: text=>"Clean Parameters"});
1.333 albertel 6146: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6147: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6148: $r->print(<<ENDOVER);
6149: $start_page
6150: $breadcrumbs
6151: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6152: ENDOVER
6153: # Store modified
6154:
6155: &storedata($r,$crs,$dom);
6156:
6157: # Read modified data
6158:
6159: my $resourcedata=&readdata($crs,$dom);
6160:
6161: # List data
6162:
6163: $r->print('<h3>'.
1.473 amueller 6164: &mt('These parameters refer to resources that do not exist.').
6165: '</h3>'.
6166: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6167: '<br />');
1.333 albertel 6168: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6169: '<tr>'.
6170: '<th>'.&mt('Delete').'</th>'.
6171: '<th>'.&mt('Parameter').'</th>'.
6172: '</tr>');
1.333 albertel 6173: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6174: next if (!exists($resourcedata->{$thiskey.'.type'})
6175: && $thiskey=~/\.type$/);
6176: my %data = &parse_key($thiskey);
6177: if (1) { #exists($data{'realm_exists'})
6178: #&& !$data{'realm_exists'}) {
6179: $r->print(&Apache::loncommon::start_data_table_row().
6180: '<tr>'.
6181: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6182:
6183: $r->print('<td>');
6184: my $display_value = $resourcedata->{$thiskey};
6185: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6186: $display_value =
6187: &Apache::lonlocal::locallocaltime($display_value);
6188: }
1.470 raeburn 6189: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6190: $parmitem = &mt($parmitem);
1.560 damieng 6191: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6192: $parmitem,$resourcedata->{$thiskey}));
6193: $r->print('<br />');
6194: if ($data{'scope_type'} eq 'all') {
6195: $r->print(&mt('All users'));
6196: } elsif ($data{'scope_type'} eq 'user') {
6197: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6198: } elsif ($data{'scope_type'} eq 'secgroup') {
6199: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6200: }
6201: $r->print('<br />');
6202: if ($data{'realm_type'} eq 'all') {
6203: $r->print(&mt('All Resources'));
6204: } elsif ($data{'realm_type'} eq 'folder') {
6205: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6206: } elsif ($data{'realm_type'} eq 'symb') {
6207: my ($map,$resid,$url) =
6208: &Apache::lonnet::decode_symb($data{'realm'});
6209: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6210: $url.' <br /> ',
6211: $resid.' <br /> ',$map));
6212: }
6213: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6214: $r->print('</td></tr>');
6215:
1.473 amueller 6216: }
1.333 albertel 6217: }
6218: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6219: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6220: '</p></form>');
6221: &endSettingsScreen($r);
6222: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6223: }
6224:
1.563 damieng 6225: # UI to shift all dates (called by dateshift1 action).
6226: # Used by overview mode.
6227: #
6228: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6229: sub date_shift_one {
6230: my ($r) = @_;
6231: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6232: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6233: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6234: my $sec = $env{'request.course.sec'};
1.414 droeschl 6235: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6236: text=>"Shifting Dates"});
1.594 raeburn 6237: my $submit_text = &mt('Shift all dates accordingly');
6238: if ($sec ne '') {
1.595 raeburn 6239: my @groups;
6240: if ($env{'request.course.groups'} ne '') {
6241: @groups = split(/:/,$env{'request.course.groups'});
6242: }
6243: if (@groups) {
6244: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6245: } else {
6246: $submit_text = &mt("Shift dates set just for your section, accordingly");
6247: }
1.594 raeburn 6248: }
1.390 www 6249: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6250: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6251: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6252: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6253: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6254: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6255: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6256: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6257: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6258: 'timeshifted',
6259: $env{'form.timebase'},,
6260: '').
6261: '</td></tr></table>'.
6262: '<input type="hidden" name="action" value="dateshift2" />'.
6263: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6264: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6265: &endSettingsScreen($r);
1.390 www 6266: $r->print(&Apache::loncommon::end_page());
6267: }
6268:
1.563 damieng 6269: # UI to shift all dates (second form).
6270: #
6271: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6272: sub date_shift_two {
6273: my ($r) = @_;
6274: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6275: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6276: my $sec = $env{'request.course.sec'};
1.531 raeburn 6277: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6278: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6279: text=>"Shifting Dates"});
1.390 www 6280: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6281: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6282: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6283: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6284: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6285: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6286: if ($sec ne '') {
1.595 raeburn 6287: my @groups;
6288: if ($env{'request.course.groups'} ne '') {
6289: @groups = split(/:/,$env{'request.course.groups'});
6290: }
6291: if (@groups) {
6292: $r->print('<p>'.
6293: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6294: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6295: &Apache::lonlocal::locallocaltime($timeshifted)).
6296: '</p>');
6297: } else {
6298: $r->print('<p>'.
6299: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6300: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6301: &Apache::lonlocal::locallocaltime($timeshifted)).
6302: '</p>');
6303: }
1.594 raeburn 6304: } else {
6305: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6306: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6307: &Apache::lonlocal::locallocaltime($timeshifted)).
6308: '</p>');
6309: }
1.390 www 6310: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6311: my $numchanges = 0;
6312: my $result = &dateshift($delta,\$numchanges);
6313: if ($result eq 'ok') {
6314: $r->print(
6315: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6316: $numchanges)));
6317: } elsif ($result eq 'con_delayed') {
6318: $r->print(
6319: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6320: $numchanges)));
6321: } else {
6322: $r->print(
6323: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6324: }
1.543 bisitz 6325: $r->print(
6326: '<br /><br />'.
6327: &Apache::lonhtmlcommon::actionbox(
6328: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6329: &endSettingsScreen($r);
1.390 www 6330: $r->print(&Apache::loncommon::end_page());
6331: }
6332:
1.563 damieng 6333: # Returns the different components of a resourcedata key.
6334: # Keys: scope_type, scope, realm_type, realm, realm_title,
6335: # realm_exists, parameter_part, parameter_name.
6336: # Was used by clean_parameters (which is unused).
6337: #
6338: # @param {string} $key - the parameter key
6339: # @returns {hash}
1.333 albertel 6340: sub parse_key {
6341: my ($key) = @_;
6342: my %data;
6343: my ($middle,$part,$name)=
1.572 damieng 6344: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6345: $data{'scope_type'} = 'all';
6346: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6347: $data{'scope'} = $1;
6348: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6349: $data{'scope_type'} = 'user';
6350: $data{'scope'} = [$1,$2];
6351: } else {
1.581 raeburn 6352: $data{'scope_type'} = 'secgroup';
1.560 damieng 6353: }
6354: $middle=~s/^\[(.*)\]//;
1.333 albertel 6355: }
6356: $middle=~s/\.+$//;
6357: $middle=~s/^\.+//;
6358: $data{'realm_type'}='all';
6359: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6360: $data{'realm'} = $1;
6361: $data{'realm_type'} = 'folder';
6362: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6363: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6364: } elsif ($middle) {
1.560 damieng 6365: $data{'realm'} = $middle;
6366: $data{'realm_type'} = 'symb';
6367: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6368: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6369: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6370: }
1.446 bisitz 6371:
1.333 albertel 6372: $data{'parameter_part'} = $part;
6373: $data{'parameter_name'} = $name;
6374:
6375: return %data;
6376: }
6377:
1.239 raeburn 6378:
1.563 damieng 6379: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6380: sub header {
1.507 www 6381: return &Apache::loncommon::start_page('Settings');
1.416 jms 6382: }
1.193 albertel 6383:
6384:
6385:
1.560 damieng 6386: ##################################################
6387: # MAIN MENU
6388: ##################################################
6389:
1.563 damieng 6390: # Content and problem settings main menu.
6391: #
6392: # @param {Apache2::RequestRec} $r - the Apache request
6393: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 6394: sub print_main_menu {
6395: my ($r,$parm_permission)=@_;
6396: #
1.414 droeschl 6397: $r->print(&header());
1.507 www 6398: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 6399: my $crstype = &Apache::loncommon::course_type();
6400: my $lc_crstype = lc($crstype);
6401:
6402: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 6403: $r->print(<<ENDMAINFORMHEAD);
6404: <form method="post" enctype="multipart/form-data"
6405: action="/adm/parmset" name="studentform">
6406: ENDMAINFORMHEAD
6407: #
1.195 albertel 6408: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6409: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 6410: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 6411: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 6412: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 6413: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
6414: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 6415: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
6416: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
6417: '/'.$env{'request.course.sec'});
6418: }
1.568 raeburn 6419: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
6420: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
6421: '/'.$env{'request.course.sec'});
6422: }
6423: my (%linktext,%linktitle,%url);
6424: if ($parm_permission->{'edit'}) {
6425: %linktext = (
6426: newoverview => 'Edit Resource Parameters - Overview Mode',
6427: settable => 'Edit Resource Parameters - Table Mode',
6428: setoverview => 'Modify Resource Parameters - Overview Mode',
6429: );
6430: %linktitle = (
6431: newoverview => 'Set/Modify resource parameters in overview mode.',
6432: settable => 'Set/Modify resource parameters in table mode.',
6433: setoverview => 'Set/Modify existing resource parameters in overview mode.',
6434: );
6435: } else {
6436: %linktext = (
6437: newoverview => 'View Resource Parameters - Overview Mode',
6438: settable => 'View Resource Parameters - Table Mode',
6439: setoverview => 'View Resource Parameters - Overview Mode',
6440: );
6441: %linktitle = (
6442: newoverview => 'Display resource parameters in overview mode.',
6443: settable => 'Display resource parameters in table mode.',
6444: setoverview => 'Display existing resource parameters in overview mode.',
6445: );
6446: }
6447: if ($mgr) {
6448: $linktext{'resettimes'} = 'Reset Student Access Times';
6449: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
6450: $url{'resettimes'} = '/adm/helper/resettimes.helper';
6451: } elsif ($vgr) {
6452: $linktext{'resettimes'} = 'Display Student Access Times',
6453: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
6454: $url{'resettimes'} = '/adm/accesstimes';
6455: }
1.193 albertel 6456: my @menu =
1.507 www 6457: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 6458: items => [
6459: { linktext => 'Portfolio Metadata',
6460: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 6461: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 6462: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 6463: icon =>'contact-new.png' ,
6464: },
1.568 raeburn 6465: { linktext => $linktext{'resettimes'},
6466: url => $url{'resettimes'},
6467: permission => ($vgr || $mgr),
6468: linktitle => $linktitle{'resettimes'},
6469: icon => 'start-here.png',
1.473 amueller 6470: },
1.520 raeburn 6471: { linktext => 'Blocking Communication/Resource Access',
6472: url => '/adm/setblock',
1.568 raeburn 6473: permission => ($vcb || $dcm),
1.520 raeburn 6474: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
6475: icon => 'comblock.png',
6476: },
1.473 amueller 6477: { linktext => 'Set Parameter Setting Default Actions',
6478: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 6479: permission => $parm_permission->{'setdefaults'},
1.473 amueller 6480: linktitle =>'Set default actions for parameters.' ,
6481: icon => 'folder-new.png' ,
6482: }]},
6483: { categorytitle => 'New and Existing Parameter Settings for Resources',
6484: items => [
6485: { linktext => 'Edit Resource Parameters - Helper Mode',
6486: url => '/adm/helper/parameter.helper',
1.568 raeburn 6487: permission => $parm_permission->{'helper'},
1.473 amueller 6488: linktitle =>'Set/Modify resource parameters in helper mode.' ,
6489: icon => 'dialog-information.png' ,
6490: #help => 'Parameter_Helper',
6491: },
1.568 raeburn 6492: { linktext => $linktext{'newoverview'},
1.473 amueller 6493: url => '/adm/parmset?action=newoverview',
1.568 raeburn 6494: permission => $parm_permission->{'newoverview'},
6495: linktitle => $linktitle{'newoverview'},
6496: icon => 'edit-find.png',
1.473 amueller 6497: #help => 'Parameter_Overview',
6498: },
1.568 raeburn 6499: { linktext => $linktext{'settable'},
1.473 amueller 6500: url => '/adm/parmset?action=settable',
1.568 raeburn 6501: permission => $parm_permission->{'settable'},
6502: linktitle => $linktitle{'settable'},
6503: icon => 'edit-copy.png',
1.473 amueller 6504: #help => 'Table_Mode',
6505: }]},
1.417 droeschl 6506: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 6507: items => [
1.570 raeburn 6508: { linktext => $linktext{'setoverview'},
1.473 amueller 6509: url => '/adm/parmset?action=setoverview',
1.568 raeburn 6510: permission => $parm_permission->{'setoverview'},
6511: linktitle => $linktitle{'setoverview'},
6512: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 6513: #help => 'Parameter_Overview',
6514: },
6515: { linktext => 'Change Log',
6516: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 6517: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 6518: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 6519: icon => 'document-properties.png',
1.473 amueller 6520: }]}
1.193 albertel 6521: );
1.414 droeschl 6522: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 6523: $r->print('</form>');
1.507 www 6524: &endSettingsScreen($r);
1.539 raeburn 6525: $r->print(&Apache::loncommon::end_page());
1.193 albertel 6526: return;
6527: }
1.414 droeschl 6528:
1.416 jms 6529:
6530:
1.560 damieng 6531: ##################################################
6532: # PORTFOLIO METADATA
6533: ##################################################
6534:
1.563 damieng 6535: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
6536: # It looks like field titles are not localized.
6537: #
6538: # @param {Apache2::RequestRec} $r - the Apache request
6539: # @param {string} $field_name - metadata field name
6540: # @param {string} $field_text - metadata field title, in English unless manually added
6541: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 6542: sub output_row {
1.347 banghart 6543: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 6544: my $output;
1.263 banghart 6545: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
6546: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 6547: if (!defined($options)) {
1.254 banghart 6548: $options = 'active,stuadd';
1.261 banghart 6549: $values = '';
1.252 banghart 6550: }
1.337 banghart 6551: if (!($options =~ /deleted/)) {
6552: my @options= ( ['active', 'Show to student'],
1.418 schafran 6553: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 6554: ['choices','Provide choices for students to select from']);
1.473 amueller 6555: # ['onlyone','Student may select only one choice']);
1.337 banghart 6556: if ($added_flag) {
6557: push @options,['deleted', 'Delete Metadata Field'];
6558: }
1.351 banghart 6559: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 6560: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 6561: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 6562: foreach my $opt (@options) {
1.560 damieng 6563: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
6564: $output .= &Apache::loncommon::continue_data_table_row();
6565: $output .= '<td>'.(' ' x 5).'<label>
6566: <input type="checkbox" name="'.
6567: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
6568: &mt($opt->[1]).'</label></td>';
6569: $output .= &Apache::loncommon::end_data_table_row();
6570: }
1.351 banghart 6571: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 6572: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 6573: $output .= &Apache::loncommon::end_data_table_row();
6574: my $multiple_checked;
6575: my $single_checked;
6576: if ($options =~ m/onlyone/) {
1.422 bisitz 6577: $multiple_checked = '';
1.423 bisitz 6578: $single_checked = ' checked="checked"';
1.351 banghart 6579: } else {
1.423 bisitz 6580: $multiple_checked = ' checked="checked"';
1.422 bisitz 6581: $single_checked = '';
1.351 banghart 6582: }
1.560 damieng 6583: $output .= &Apache::loncommon::continue_data_table_row();
6584: $output .= '<td>'.(' ' x 10).'
6585: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
6586: '.&mt('Student may select multiple choices from list').'</td>';
6587: $output .= &Apache::loncommon::end_data_table_row();
6588: $output .= &Apache::loncommon::continue_data_table_row();
6589: $output .= '<td>'.(' ' x 10).'
6590: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
6591: '.&mt('Student may select only one choice from list').'</td>';
6592: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 6593: }
6594: return ($output);
6595: }
1.416 jms 6596:
6597:
1.560 damieng 6598: # UI to order portfolio metadata fields.
1.563 damieng 6599: # Currently useless because addmetafield does not work.
6600: #
6601: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 6602: sub order_meta_fields {
6603: my ($r)=@_;
6604: my $idx = 1;
6605: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6606: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6607: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 6608: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 6609: &Apache::lonhtmlcommon::add_breadcrumb(
6610: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6611: text=>"Add Metadata Field"});
1.560 damieng 6612: &Apache::lonhtmlcommon::add_breadcrumb(
6613: {href=>"/adm/parmset?action=setrestrictmeta",
6614: text=>"Restrict Metadata"},
6615: {text=>"Order Metadata"});
1.345 banghart 6616: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 6617: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 6618: if ($env{'form.storeorder'}) {
6619: my $newpos = $env{'form.newpos'} - 1;
6620: my $currentpos = $env{'form.currentpos'} - 1;
6621: my @neworder = ();
1.548 raeburn 6622: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6623: my $i;
1.341 banghart 6624: if ($newpos > $currentpos) {
1.340 banghart 6625: # moving stuff up
6626: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 6627: $neworder[$i]=$oldorder[$i];
1.340 banghart 6628: }
6629: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 6630: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 6631: }
6632: $neworder[$newpos]=$oldorder[$currentpos];
6633: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 6634: $neworder[$i]=$oldorder[$i];
1.340 banghart 6635: }
6636: } else {
6637: # moving stuff down
1.473 amueller 6638: for ($i=0;$i<$newpos;$i++) {
6639: $neworder[$i]=$oldorder[$i];
6640: }
6641: $neworder[$newpos]=$oldorder[$currentpos];
6642: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
6643: $neworder[$i]=$oldorder[$i-1];
6644: }
6645: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
6646: $neworder[$i]=$oldorder[$i];
6647: }
1.340 banghart 6648: }
1.560 damieng 6649: my $ordered_fields = join ",", @neworder;
1.343 banghart 6650: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 6651: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6652: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 6653: }
1.357 raeburn 6654: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 6655: my $ordered_fields;
1.548 raeburn 6656: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6657: if (!@fields_in_order) {
6658: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 6659: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 6660: push @fields_in_order, $key;
1.341 banghart 6661: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 6662: }
1.341 banghart 6663: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 6664: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6665: }
1.340 banghart 6666: $r->print('<table>');
6667: my $num_fields = scalar(@fields_in_order);
6668: foreach my $key (@fields_in_order) {
6669: $r->print('<tr><td>');
6670: $r->print('<form method="post" action="">');
1.537 bisitz 6671: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 6672: for (my $i = 1;$i le $num_fields;$i ++) {
6673: if ($i eq $idx) {
6674: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
6675: } else {
6676: $r->print('<option value="'.$i.'">'.$i.'</option>');
6677: }
6678: }
6679: $r->print('</select></td><td>');
6680: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
6681: $r->print('<input type="hidden" name="storeorder" value="true" />');
6682: $r->print('</form>');
6683: $r->print($$fields{$key}.'</td></tr>');
6684: $idx ++;
6685: }
6686: $r->print('</table>');
1.507 www 6687: &endSettingsScreen($r);
1.340 banghart 6688: return 'ok';
6689: }
1.416 jms 6690:
6691:
1.563 damieng 6692: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
6693: # @returns {string}
1.359 banghart 6694: sub continue {
6695: my $output;
6696: $output .= '<form action="" method="post">';
6697: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 6698: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 6699: return ($output);
6700: }
1.416 jms 6701:
6702:
1.563 damieng 6703: # UI to add a metadata field.
6704: # Currenly does not work because of an HTML error (the field is not visible).
6705: #
6706: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 6707: sub addmetafield {
6708: my ($r)=@_;
1.414 droeschl 6709: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6710: text=>"Add Metadata Field"});
1.334 banghart 6711: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
6712: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 6713: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6714: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6715: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6716: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 6717: if (exists($env{'form.undelete'})) {
1.358 banghart 6718: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 6719: foreach my $meta_field(@meta_fields) {
6720: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
6721: $options =~ s/deleted//;
6722: $options =~ s/,,/,/;
6723: my $put_result = &Apache::lonnet::put('environment',
6724: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 6725:
1.586 raeburn 6726: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
6727: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
6728: '</strong>',$put_result).
6729: '<br />');
1.339 banghart 6730: }
1.359 banghart 6731: $r->print(&continue());
1.339 banghart 6732: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 6733: my $meta_field = $env{'form.fieldname'};
6734: my $display_field = $env{'form.fieldname'};
6735: $meta_field =~ s/\W/_/g;
1.338 banghart 6736: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 6737: my $put_result = &Apache::lonnet::put('environment',
6738: {'metadata.'.$meta_field.'.values'=>"",
6739: 'metadata.'.$meta_field.'.added'=>"$display_field",
6740: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 6741: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
6742: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
6743: '<br />');
1.359 banghart 6744: $r->print(&continue());
1.335 banghart 6745: } else {
1.357 raeburn 6746: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 6747: if ($fields) {
1.586 raeburn 6748: $r->print(&mt('You may undelete previously deleted fields.').
6749: '<br />'.
6750: &mt('Check those you wish to undelete and click Undelete.').
6751: '<br />');
1.339 banghart 6752: $r->print('<form method="post" action="">');
6753: foreach my $key(keys(%$fields)) {
1.581 raeburn 6754: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 6755: }
1.586 raeburn 6756: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 6757: $r->print('</form>');
6758: }
1.586 raeburn 6759: $r->print('<hr />'.
6760: &mt('[_1]Or[_2] you may enter a new metadata field name.',
6761: '<strong>','</strong>').
1.581 raeburn 6762: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 6763: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 6764: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 6765: $r->print('</form>');
1.334 banghart 6766: }
1.507 www 6767: &endSettingsScreen($r);
1.334 banghart 6768: }
1.416 jms 6769:
6770:
6771:
1.560 damieng 6772: # Display or save portfolio metadata.
1.563 damieng 6773: #
6774: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 6775: sub setrestrictmeta {
1.240 banghart 6776: my ($r)=@_;
1.242 banghart 6777: my $next_meta;
1.244 banghart 6778: my $output;
1.245 banghart 6779: my $item_num;
1.246 banghart 6780: my $put_result;
1.414 droeschl 6781: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 6782: text=>"Restrict Metadata"});
1.280 albertel 6783: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 6784: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 6785: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6786: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6787: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6788: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 6789: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 6790: my $save_field = '';
1.586 raeburn 6791: my %lt = &Apache::lonlocal::texthash(
6792: addm => 'Add Metadata Field',
6793: ordm => 'Order Metadata Fields',
6794: save => 'Save',
6795: );
1.259 banghart 6796: if ($env{'form.restrictmeta'}) {
1.254 banghart 6797: foreach my $field (sort(keys(%env))) {
1.252 banghart 6798: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 6799: my $options;
1.252 banghart 6800: my $meta_field = $1;
6801: my $meta_key = $2;
1.253 banghart 6802: if ($save_field ne $meta_field) {
1.252 banghart 6803: $save_field = $meta_field;
1.473 amueller 6804: if ($env{'form.'.$meta_field.'_stuadd'}) {
6805: $options.='stuadd,';
6806: }
6807: if ($env{'form.'.$meta_field.'_choices'}) {
6808: $options.='choices,';
6809: }
6810: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
6811: $options.='onlyone,';
6812: }
6813: if ($env{'form.'.$meta_field.'_active'}) {
6814: $options.='active,';
6815: }
6816: if ($env{'form.'.$meta_field.'_deleted'}) {
6817: $options.='deleted,';
6818: }
1.259 banghart 6819: my $name = $save_field;
1.560 damieng 6820: $put_result = &Apache::lonnet::put('environment',
6821: {'metadata.'.$meta_field.'.options'=>$options,
6822: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
6823: },$dom,$crs);
1.252 banghart 6824: }
6825: }
6826: }
6827: }
1.296 albertel 6828: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 6829: {'freshen_cache' => 1});
1.335 banghart 6830: # Get the default metadata fields
1.258 albertel 6831: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 6832: # Now get possible added metadata fields
1.357 raeburn 6833: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 6834: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 6835: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 6836: if ($field ne 'courserestricted') {
1.586 raeburn 6837: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 6838: }
1.255 banghart 6839: }
1.351 banghart 6840: my $buttons = (<<ENDButtons);
1.586 raeburn 6841: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 6842: </form><br />
6843: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 6844: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 6845: </form>
6846: <br />
6847: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 6848: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 6849: ENDButtons
1.337 banghart 6850: my $added_flag = 1;
1.335 banghart 6851: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 6852: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 6853: }
1.347 banghart 6854: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 6855: $r->print(<<ENDenv);
1.259 banghart 6856: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 6857: $output
1.351 banghart 6858: $buttons
1.340 banghart 6859: </form>
1.244 banghart 6860: ENDenv
1.507 www 6861: &endSettingsScreen($r);
1.280 albertel 6862: $r->print(&Apache::loncommon::end_page());
1.240 banghart 6863: return 'ok';
6864: }
1.416 jms 6865:
6866:
1.563 damieng 6867: # Returns metadata fields that have been manually added.
6868: #
6869: # @param {string} $cid - course id
6870: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 6871: sub get_added_meta_fieldnames {
1.357 raeburn 6872: my ($cid) = @_;
1.335 banghart 6873: my %fields;
6874: foreach my $key(%env) {
1.357 raeburn 6875: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 6876: my $field_name = $1;
6877: my ($display_field_name) = $env{$key};
6878: $fields{$field_name} = $display_field_name;
6879: }
6880: }
6881: return \%fields;
6882: }
1.416 jms 6883:
6884:
1.563 damieng 6885: # Returns metadata fields that have been manually added and deleted.
6886: #
6887: # @param {string} $cid - course id
6888: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 6889: sub get_deleted_meta_fieldnames {
1.357 raeburn 6890: my ($cid) = @_;
1.339 banghart 6891: my %fields;
6892: foreach my $key(%env) {
1.357 raeburn 6893: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 6894: my $field_name = $1;
6895: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
6896: my ($display_field_name) = $env{$key};
6897: $fields{$field_name} = $display_field_name;
6898: }
6899: }
6900: }
6901: return \%fields;
6902: }
1.560 damieng 6903:
6904:
6905: ##################################################
6906: # PARAMETER SETTINGS DEFAULT ACTIONS
6907: ##################################################
6908:
6909: # UI to change parameter setting default actions
1.563 damieng 6910: #
6911: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 6912: sub defaultsetter {
1.280 albertel 6913: my ($r) = @_;
6914:
1.414 droeschl 6915: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 6916: text=>"Set Defaults"});
1.531 raeburn 6917: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6918: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6919: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 6920: my $start_page =
1.531 raeburn 6921: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 6922: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 6923: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6924: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 6925: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 6926:
1.221 www 6927: my @ids=();
6928: my %typep=();
6929: my %keyp=();
6930: my %allparms=();
6931: my %allparts=();
6932: my %allmaps=();
6933: my %mapp=();
6934: my %symbp=();
6935: my %maptitles=();
6936: my %uris=();
6937: my %keyorder=&standardkeyorder();
6938: my %defkeytype=();
6939:
1.446 bisitz 6940: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 6941: \%mapp, \%symbp,\%maptitles,\%uris,
6942: \%keyorder,\%defkeytype);
1.224 www 6943: if ($env{'form.storerules'}) {
1.560 damieng 6944: my %newrules=();
6945: my @delrules=();
6946: my %triggers=();
6947: foreach my $key (keys(%env)) {
1.225 albertel 6948: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 6949: my $tempkey=$1;
6950: my $action=$env{$key};
1.226 www 6951: if ($action) {
1.560 damieng 6952: $newrules{$tempkey.'_action'}=$action;
6953: if ($action ne 'default') {
6954: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
6955: $triggers{$whichparm}.=$tempkey.':';
6956: }
6957: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
6958: if (&isdateparm($defkeytype{$tempkey})) {
6959: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
6960: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
6961: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
6962: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
6963: } else {
6964: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
6965: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
6966: }
6967: } else {
6968: push(@delrules,$tempkey.'_action');
6969: push(@delrules,$tempkey.'_type');
6970: push(@delrules,$tempkey.'_hours');
6971: push(@delrules,$tempkey.'_min');
6972: push(@delrules,$tempkey.'_sec');
6973: push(@delrules,$tempkey.'_value');
6974: }
1.473 amueller 6975: }
6976: }
1.560 damieng 6977: foreach my $key (keys(%allparms)) {
6978: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 6979: }
1.560 damieng 6980: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
6981: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
6982: &resetrulescache();
1.224 www 6983: }
1.227 www 6984: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 6985: 'hours' => 'Hours',
6986: 'min' => 'Minutes',
6987: 'sec' => 'Seconds',
6988: 'yes' => 'Yes',
6989: 'no' => 'No');
1.222 www 6990: my @standardoptions=('','default');
6991: my @standarddisplay=('',&mt('Default value when manually setting'));
6992: my @dateoptions=('','default');
6993: my @datedisplay=('',&mt('Default value when manually setting'));
6994: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 6995: unless ($tempkey) { next; }
6996: push @standardoptions,'when_setting_'.$tempkey;
6997: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
6998: if (&isdateparm($defkeytype{$tempkey})) {
6999: push @dateoptions,'later_than_'.$tempkey;
7000: push @datedisplay,&mt('Automatically set later than ').$tempkey;
7001: push @dateoptions,'earlier_than_'.$tempkey;
7002: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
7003: }
1.222 www 7004: }
1.563 damieng 7005: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
7006: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 7007: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 7008: &Apache::loncommon::start_data_table_header_row().
7009: "<th>".&mt('Rule for parameter').'</th><th>'.
7010: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
7011: &Apache::loncommon::end_data_table_header_row());
1.221 www 7012: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7013: unless ($tempkey) { next; }
7014: $r->print("\n".&Apache::loncommon::start_data_table_row().
7015: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
7016: my $action=&rulescache($tempkey.'_action');
7017: $r->print('<select name="'.$tempkey.'_action">');
7018: if (&isdateparm($defkeytype{$tempkey})) {
7019: for (my $i=0;$i<=$#dateoptions;$i++) {
7020: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
7021: $r->print("\n<option value='$dateoptions[$i]'".
7022: ($dateoptions[$i] eq $action?' selected="selected"':'').
7023: ">$datedisplay[$i]</option>");
7024: }
7025: } else {
7026: for (my $i=0;$i<=$#standardoptions;$i++) {
7027: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
7028: $r->print("\n<option value='$standardoptions[$i]'".
7029: ($standardoptions[$i] eq $action?' selected="selected"':'').
7030: ">$standarddisplay[$i]</option>");
7031: }
1.473 amueller 7032: }
1.560 damieng 7033: $r->print('</select>');
7034: unless (&isdateparm($defkeytype{$tempkey})) {
7035: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7036: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7037: }
1.560 damieng 7038: $r->print("\n</td><td>\n");
1.222 www 7039:
1.221 www 7040: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7041: my $days=&rulescache($tempkey.'_days');
7042: my $hours=&rulescache($tempkey.'_hours');
7043: my $min=&rulescache($tempkey.'_min');
7044: my $sec=&rulescache($tempkey.'_sec');
7045: $r->print(<<ENDINPUTDATE);
7046: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7047: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7048: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7049: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7050: ENDINPUTDATE
1.560 damieng 7051: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7052: my $yeschecked='';
7053: my $nochecked='';
7054: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7055: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7056:
7057: $r->print(<<ENDYESNO);
7058: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7059: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7060: ENDYESNO
1.221 www 7061: } else {
1.560 damieng 7062: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7063: }
1.318 albertel 7064: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7065: }
1.318 albertel 7066: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7067: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7068: &mt('Save').'" /></form>'."\n");
7069: &endSettingsScreen($r);
7070: $r->print(&Apache::loncommon::end_page());
1.220 www 7071: return;
7072: }
1.193 albertel 7073:
1.560 damieng 7074: ##################################################
7075: # PARAMETER CHANGES LOG
7076: ##################################################
7077:
1.563 damieng 7078: # Returns some info for a parameter log entry.
7079: # Returned entries:
7080: # $realm - HTML title for the parameter level and resource
7081: # $section - parameter section
7082: # $name - parameter name
7083: # $part - parameter part
7084: # $what - $part.'.'.$name
7085: # $middle - resource symb ?
7086: # $uname - user name (same as given)
7087: # $udom - user domain (same as given)
7088: # $issection - section or group name
7089: # $realmdescription - title for the parameter level and resource (without using HTML)
7090: #
7091: # @param {string} $key - parameter log key
7092: # @param {string} $uname - user name
7093: # @param {string} $udom - user domain
7094: # @param {boolean} $typeflag - .type log entry
7095: # @returns {Array}
1.290 www 7096: sub components {
1.581 raeburn 7097: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7098:
7099: if ($typeflag) {
1.560 damieng 7100: $key=~s/\.type$//;
1.290 www 7101: }
1.330 albertel 7102:
7103: my ($middle,$part,$name)=
1.572 damieng 7104: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7105: my $issection;
1.330 albertel 7106:
1.290 www 7107: my $section=&mt('All Students');
7108: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7109: $issection=$1;
7110: $section=&mt('Group/Section').': '.$issection;
7111: $middle=~s/^\[(.*)\]//;
1.290 www 7112: }
7113: $middle=~s/\.+$//;
7114: $middle=~s/^\.+//;
1.291 www 7115: if ($uname) {
1.560 damieng 7116: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7117: $issection='';
1.291 www 7118: }
1.316 albertel 7119: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7120: my $realmdescription=&mt('all resources');
1.556 raeburn 7121: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7122: my $mapurl = $1;
7123: my $maplevel = $2;
7124: my $leveltitle = &mt('Folder/Map');
7125: if ($maplevel eq 'rec') {
7126: $leveltitle = &mt('Recursive');
7127: }
1.560 damieng 7128: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7129: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7130: $mapurl.')</span></span>';
7131: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7132: } elsif ($middle) {
7133: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7134: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7135: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7136: ' in '.$map.' id: '.$id.')</span></span>';
7137: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7138: }
1.291 www 7139: my $what=$part.'.'.$name;
1.330 albertel 7140: return ($realm,$section,$name,$part,
1.473 amueller 7141: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7142: }
1.293 www 7143:
1.563 damieng 7144: my %standard_parms; # hash parameter name -> parameter title (not localized)
7145: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7146:
1.563 damieng 7147: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7148: sub load_parameter_names {
1.583 raeburn 7149: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7150: while (my $configline=<$config>) {
1.560 damieng 7151: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7152: chomp($configline);
7153: my ($short,$plain)=split(/:/,$configline);
7154: my (undef,$name,$type)=split(/\&/,$short,3);
7155: if ($type eq 'display') {
7156: $standard_parms{$name} = $plain;
1.469 raeburn 7157: } elsif ($type eq 'type') {
1.560 damieng 7158: $standard_parms_types{$name} = $plain;
1.469 raeburn 7159: }
1.328 albertel 7160: }
7161: close($config);
7162: $standard_parms{'int_pos'} = 'Positive Integer';
7163: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7164: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7165: }
7166:
1.563 damieng 7167: # Returns a parameter title for standard parameters, the name for others.
7168: #
7169: # @param {string} $name - parameter name
7170: # @returns {string}
1.292 www 7171: sub standard_parameter_names {
7172: my ($name)=@_;
1.328 albertel 7173: if (!%standard_parms) {
1.560 damieng 7174: &load_parameter_names();
1.328 albertel 7175: }
1.292 www 7176: if ($standard_parms{$name}) {
1.560 damieng 7177: return $standard_parms{$name};
1.446 bisitz 7178: } else {
1.560 damieng 7179: return $name;
1.292 www 7180: }
7181: }
1.290 www 7182:
1.563 damieng 7183: # Returns a parameter type for standard parameters, undef for others.
7184: #
7185: # @param {string} $name - parameter name
7186: # @returns {string}
1.469 raeburn 7187: sub standard_parameter_types {
7188: my ($name)=@_;
7189: if (!%standard_parms_types) {
7190: &load_parameter_names();
7191: }
7192: if ($standard_parms_types{$name}) {
7193: return $standard_parms_types{$name};
7194: }
7195: return;
7196: }
1.309 www 7197:
1.563 damieng 7198: # Returns a parameter level title (not localized) from the parameter level name.
7199: #
7200: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7201: # @returns {string}
1.557 raeburn 7202: sub standard_parameter_levels {
7203: my ($name)=@_;
7204: my %levels = (
7205: 'resourcelevel' => 'a single resource',
7206: 'maplevel' => 'the enclosing map/folder',
7207: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7208: 'courselevel' => 'the general (course) level',
7209: );
7210: if ($levels{$name}) {
7211: return $levels{$name};
7212: }
7213: return;
7214: }
7215:
1.560 damieng 7216: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7217: #
7218: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7219: sub parm_change_log {
1.568 raeburn 7220: my ($r,$parm_permission)=@_;
1.531 raeburn 7221: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7222: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7223: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7224: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7225: text=>"Parameter Change Log"});
1.522 raeburn 7226: my $js = '<script type="text/javascript">'."\n".
7227: '// <![CDATA['."\n".
7228: &Apache::loncommon::display_filter_js('parmslog')."\n".
7229: '// ]]>'."\n".
7230: '</script>'."\n";
7231: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7232: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7233: &startSettingsScreen($r,'parmset',$crstype);
7234: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7235:
1.301 www 7236: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7237:
1.522 raeburn 7238: $r->print('<div class="LC_left_float">'.
7239: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7240: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7241: method="post" name="parameterlog">');
1.446 bisitz 7242:
1.311 albertel 7243: my %saveable_parameters = ('show' => 'scalar',);
7244: &Apache::loncommon::store_course_settings('parameter_log',
7245: \%saveable_parameters);
7246: &Apache::loncommon::restore_course_settings('parameter_log',
7247: \%saveable_parameters);
1.522 raeburn 7248: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7249: '<input type="submit" value="'.&mt('Display').'" />'.
7250: '</form></fieldset></div><br clear="all" />');
1.301 www 7251:
1.568 raeburn 7252: my $readonly = 1;
7253: if ($parm_permission->{'edit'}) {
7254: undef($readonly);
7255: }
1.531 raeburn 7256: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7257: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7258: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7259: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7260: unless ($readonly) {
7261: $r->print('<th>'.&mt('Announce').'</th>');
7262: }
7263: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7264: my $shown=0;
1.349 www 7265: my $folder='';
7266: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7267: my $last='';
7268: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7269: &GDBM_READER(),0640)) {
7270: $last=$hash{'last_known'};
7271: untie(%hash);
7272: }
7273: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7274: }
1.595 raeburn 7275: my $numgroups = 0;
7276: my @groups;
7277: if ($env{'request.course.groups'} ne '') {
7278: @groups = split(/:/,$env{'request.course.groups'});
7279: $numgroups = scalar(@groups);
7280: }
1.560 damieng 7281: foreach my $id (sort {
7282: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7283: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7284: }
7285: my $aid = (split('00000',$a))[-1];
7286: my $bid = (split('00000',$b))[-1];
7287: return $bid<=>$aid;
1.473 amueller 7288: } (keys(%parmlog))) {
1.294 www 7289: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7290: my $count = 0;
7291: my $time =
7292: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7293: my $plainname =
7294: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7295: $parmlog{$id}{'exe_udom'});
7296: my $about_me_link =
7297: &Apache::loncommon::aboutmewrapper($plainname,
7298: $parmlog{$id}{'exe_uname'},
7299: $parmlog{$id}{'exe_udom'});
7300: my $send_msg_link='';
1.568 raeburn 7301: if ((!$readonly) &&
7302: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7303: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7304: $send_msg_link ='<br />'.
7305: &Apache::loncommon::messagewrapper(&mt('Send message'),
7306: $parmlog{$id}{'exe_uname'},
7307: $parmlog{$id}{'exe_udom'});
7308: }
7309: my $row_start=&Apache::loncommon::start_data_table_row();
7310: my $makenewrow=0;
7311: my %istype=();
7312: my $output;
7313: foreach my $changed (reverse(sort(@changes))) {
7314: my $value=$parmlog{$id}{'logentry'}{$changed};
7315: my $typeflag = ($changed =~/\.type$/ &&
7316: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7317: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7318: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7319: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7320: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7321: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7322: if ($uname ne '') {
7323: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7324: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7325: }
7326: }
7327: if ($env{'form.displayfilter'} eq 'currentfolder') {
7328: if ($folder) {
7329: if ($middle!~/^\Q$folder\E/) { next; }
7330: }
7331: }
7332: if ($typeflag) {
7333: $istype{$parmname}=$value;
7334: if (!$env{'form.includetypes'}) { next; }
7335: }
7336: $count++;
7337: if ($makenewrow) {
7338: $output .= $row_start;
7339: } else {
7340: $makenewrow=1;
7341: }
1.470 raeburn 7342: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7343: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7344: &mt($parmitem).'</td><td>'.
7345: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7346: my $stillactive=0;
7347: if ($parmlog{$id}{'delflag'}) {
7348: $output .= &mt('Deleted');
7349: } else {
7350: if ($typeflag) {
1.470 raeburn 7351: my $parmitem = &standard_parameter_names($value);
7352: $parmitem = &mt($parmitem);
1.560 damieng 7353: $output .= &mt('Type: [_1]',$parmitem);
7354: } else {
1.584 raeburn 7355: my $toolsymb;
7356: if ($middle =~ /ext\.tool$/) {
7357: $toolsymb = $middle;
7358: }
1.560 damieng 7359: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7360: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7361: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7362: my $showvalue = $value;
7363: if ($istype{$parmname} eq '') {
7364: my $type = &standard_parameter_types($parmname);
7365: if ($type ne '') {
7366: if (&isdateparm($type)) {
7367: $showvalue =
7368: &Apache::lonlocal::locallocaltime($value);
7369: }
7370: }
7371: } else {
1.560 damieng 7372: if (&isdateparm($istype{$parmname})) {
7373: $showvalue = &Apache::lonlocal::locallocaltime($value);
7374: }
1.469 raeburn 7375: }
7376: $output .= $showvalue;
1.560 damieng 7377: if ($value ne $all[$level]) {
7378: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7379: } else {
7380: $stillactive=1;
7381: }
7382: }
1.473 amueller 7383: }
1.568 raeburn 7384: $output .= '</td>';
7385:
7386: unless ($readonly) {
7387: $output .= '<td>';
7388: if ($stillactive) {
7389: my $parmitem = &standard_parameter_names($parmname);
7390: $parmitem = &mt($parmitem);
7391: my $title=&mt('Changed [_1]',$parmitem);
7392: my $description=&mt('Changed [_1] for [_2] to [_3]',
7393: $parmitem,$realmdescription,
7394: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
7395: if (($uname) && ($udom)) {
7396: $output .=
7397: &Apache::loncommon::messagewrapper('Notify User',
7398: $uname,$udom,$title,
7399: $description);
7400: } else {
7401: $output .=
7402: &Apache::lonrss::course_blog_link($id,$title,
7403: $description);
7404: }
1.560 damieng 7405: }
1.568 raeburn 7406: $output .= '</td>';
1.560 damieng 7407: }
1.568 raeburn 7408: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 7409: }
1.560 damieng 7410: if ($env{'form.displayfilter'} eq 'containing') {
7411: my $wholeentry=$about_me_link.':'.
7412: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
7413: $output;
7414: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 7415: }
1.349 www 7416: if ($count) {
1.560 damieng 7417: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
7418: <td rowspan="'.$count.'">'.$about_me_link.
7419: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
7420: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
7421: $send_msg_link.'</td>'.$output);
7422: $shown++;
7423: }
7424: if (!($env{'form.show'} eq &mt('all')
7425: || $shown<=$env{'form.show'})) { last; }
1.286 www 7426: }
1.301 www 7427: $r->print(&Apache::loncommon::end_data_table());
1.507 www 7428: &endSettingsScreen($r);
1.284 www 7429: $r->print(&Apache::loncommon::end_page());
7430: }
7431:
1.560 damieng 7432: ##################################################
7433: # MISC !
7434: ##################################################
7435:
1.563 damieng 7436: # Stores slot information.
1.560 damieng 7437: # Used by table UI
1.563 damieng 7438: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7439: #
7440: # @param {string} $slot_name - slot name
7441: # @param {string} $cdom - course domain
7442: # @param {string} $cnum - course number
7443: # @param {string} $symb - resource symb
7444: # @param {string} $uname - user name
7445: # @param {string} $udom - user domain
7446: # @returns {string} - 'ok' or error name
1.437 raeburn 7447: sub update_slots {
7448: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
7449: my %slot=&Apache::lonnet::get_slot($slot_name);
7450: if (!keys(%slot)) {
7451: return 'error: slot does not exist';
7452: }
7453: my $max=$slot{'maxspace'};
7454: if (!defined($max)) { $max=99999; }
7455:
7456: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
7457: "^$slot_name\0");
7458: my ($tmp)=%consumed;
7459: if ($tmp=~/^error: 2 / ) {
7460: return 'error: unable to determine current slot status';
7461: }
7462: my $last=0;
7463: foreach my $key (keys(%consumed)) {
7464: my $num=(split('\0',$key))[1];
7465: if ($num > $last) { $last=$num; }
7466: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7467: return 'ok';
7468: }
7469: }
7470:
7471: if (scalar(keys(%consumed)) >= $max) {
7472: return 'error: no space left in slot';
7473: }
7474: my $wanted=$last+1;
7475:
7476: my %reservation=('name' => $uname.':'.$udom,
7477: 'timestamp' => time,
7478: 'symb' => $symb);
7479:
7480: my $success=&Apache::lonnet::newput('slot_reservations',
7481: {"$slot_name\0$wanted" =>
7482: \%reservation},
7483: $cdom, $cnum);
1.438 raeburn 7484: if ($success eq 'ok') {
7485: my %storehash = (
7486: symb => $symb,
7487: slot => $slot_name,
7488: action => 'reserve',
7489: context => 'parameter',
7490: );
1.526 raeburn 7491: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7492: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 7493:
1.526 raeburn 7494: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7495: '',$uname,$udom,$uname,$udom);
1.438 raeburn 7496: }
1.437 raeburn 7497: return $success;
7498: }
7499:
1.563 damieng 7500: # Deletes a slot reservation.
1.560 damieng 7501: # Used by table UI
1.563 damieng 7502: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7503: #
7504: # @param {string} $slot_name - slot name
7505: # @param {string} $cdom - course domain
7506: # @param {string} $cnum - course number
7507: # @param {string} $uname - user name
7508: # @param {string} $udom - user domain
7509: # @param {string} $symb - resource symb
7510: # @returns {string} - 'ok' or error name
1.437 raeburn 7511: sub delete_slots {
7512: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
7513: my $delresult;
7514: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
7515: $cnum, "^$slot_name\0");
7516: if (&Apache::lonnet::error(%consumed)) {
7517: return 'error: unable to determine current slot status';
7518: }
7519: my ($tmp)=%consumed;
7520: if ($tmp=~/^error: 2 /) {
7521: return 'error: unable to determine current slot status';
7522: }
7523: foreach my $key (keys(%consumed)) {
7524: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7525: my $num=(split('\0',$key))[1];
7526: my $entry = $slot_name.'\0'.$num;
7527: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
7528: $cdom,$cnum);
7529: if ($delresult eq 'ok') {
7530: my %storehash = (
7531: symb => $symb,
7532: slot => $slot_name,
7533: action => 'release',
7534: context => 'parameter',
7535: );
1.526 raeburn 7536: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7537: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 7538: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7539: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 7540: }
7541: }
7542: }
7543: return $delresult;
7544: }
7545:
1.563 damieng 7546: # Returns true if there is a current course.
1.560 damieng 7547: # Used by handler
1.563 damieng 7548: #
7549: # @returns {boolean}
1.355 albertel 7550: sub check_for_course_info {
7551: my $navmap = Apache::lonnavmaps::navmap->new();
7552: return 1 if ($navmap);
7553: return 0;
7554: }
7555:
1.563 damieng 7556: # Returns the current course host and host LON-CAPA version.
7557: #
7558: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 7559: sub parameter_release_vars {
1.504 raeburn 7560: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7561: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
7562: my $chostname = &Apache::lonnet::hostname($chome);
7563: my ($cmajor,$cminor) =
7564: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
7565: return ($chostname,$cmajor,$cminor);
7566: }
7567:
1.563 damieng 7568: # Checks if the course host version can handle a parameter required version,
7569: # and if it does, stores the release needed for the course.
7570: #
7571: # @param {string} $name - parameter name
7572: # @param {string} $value - parameter value
7573: # @param {string} $valmatch - name of the test used for checking the value
7574: # @param {string} $namematch - name of the test used for checking the name
7575: # @param {string} $needsrelease - version needed by the parameter, major.minor
7576: # @param {integer} $cmajor - course major version number
7577: # @param {integer} $cminor - course minor version number
7578: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 7579: sub parameter_releasecheck {
1.557 raeburn 7580: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 7581: my $needsnewer;
7582: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
7583: if (($cmajor < $needsmajor) ||
7584: ($cmajor == $needsmajor && $cminor < $needsminor)) {
7585: $needsnewer = 1;
1.557 raeburn 7586: } elsif ($name) {
7587: if ($valmatch) {
7588: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
7589: } elsif ($value) {
7590: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
7591: }
7592: } elsif ($namematch) {
7593: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 7594: }
7595: return $needsnewer;
7596: }
7597:
1.568 raeburn 7598: sub get_permission {
7599: my %permission;
7600: my $allowed = 0;
7601: return (\%permission,$allowed) unless ($env{'request.course.id'});
7602: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
7603: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
7604: $env{'request.course.sec'}))) {
7605: %permission= (
7606: 'edit' => 1,
7607: 'set' => 1,
7608: 'setoverview' => 1,
7609: 'addmetadata' => 1,
7610: 'ordermetadata' => 1,
7611: 'setrestrictmeta' => 1,
7612: 'newoverview' => 1,
7613: 'setdefaults' => 1,
7614: 'settable' => 1,
7615: 'parameterchangelog' => 1,
7616: 'cleanparameters' => 1,
7617: 'dateshift1' => 1,
7618: 'dateshift2' => 1,
7619: 'helper' => 1,
7620: );
7621: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
7622: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
7623: $env{'request.course.sec'}))) {
7624: %permission = (
7625: 'set' => 1,
7626: 'settable' => 1,
7627: 'newoverview' => 1,
7628: 'setoverview' => 1,
7629: 'parameterchangelog' => 1,
7630: );
7631: }
7632: foreach my $perm (values(%permission)) {
7633: if ($perm) { $allowed=1; last; }
7634: }
7635: return (\%permission,$allowed);
7636: }
7637:
1.560 damieng 7638: ##################################################
7639: # HANDLER
7640: ##################################################
7641:
7642: # Main handler for lonparmset.
7643: # Sub called based on request parameters action and command:
7644: # no command or action: print_main_menu
7645: # command 'set': assessparms (direct access to table mode for a resource)
7646: # (this can also be accessed simply with the symb parameter)
7647: # action 'setoverview': overview (display all existing parameter settings)
7648: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
7649: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
7650: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
7651: # action 'newoverview': newoverview (overview mode)
7652: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
7653: # action 'settable': assessparms (table mode)
7654: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
7655: # blog postings, user notification changes)
7656: # action 'cleanparameters': clean_parameters (unused)
7657: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
7658: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 7659: sub handler {
1.43 albertel 7660: my $r=shift;
1.30 www 7661:
1.376 albertel 7662: &reset_caches();
7663:
1.414 droeschl 7664: &Apache::loncommon::content_type($r,'text/html');
7665: $r->send_http_header;
7666: return OK if $r->header_only;
7667:
1.193 albertel 7668: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 7669: ['action','state',
1.205 www 7670: 'pres_marker',
7671: 'pres_value',
1.206 www 7672: 'pres_type',
1.506 www 7673: 'filter','part',
1.390 www 7674: 'udom','uname','symb','serial','timebase']);
1.131 www 7675:
1.83 bowersj2 7676:
1.193 albertel 7677: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 7678: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 7679: text=>"Content and Problem Settings",
1.473 amueller 7680: faq=>10,
7681: bug=>'Instructor Interface',
1.442 droeschl 7682: help =>
7683: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 7684:
1.30 www 7685: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 7686: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 7687: my $exists = &check_for_course_info();
7688:
1.568 raeburn 7689: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 7690: #
7691: # Main switch on form.action and form.state, as appropriate
7692: #
7693: # Check first if coming from someone else headed directly for
7694: # the table mode
1.568 raeburn 7695: if (($parm_permission->{'set'}) &&
7696: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
7697: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
7698: &assessparms($r,$parm_permission);
1.193 albertel 7699: } elsif (! exists($env{'form.action'})) {
7700: &print_main_menu($r,$parm_permission);
1.568 raeburn 7701: } elsif (!$parm_permission->{$env{'form.action'}}) {
7702: &print_main_menu($r,$parm_permission);
1.414 droeschl 7703: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 7704: &overview($r,$parm_permission);
1.560 damieng 7705: } elsif ($env{'form.action'} eq 'addmetadata') {
7706: &addmetafield($r);
7707: } elsif ($env{'form.action'} eq 'ordermetadata') {
7708: &order_meta_fields($r);
1.414 droeschl 7709: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 7710: &setrestrictmeta($r);
1.414 droeschl 7711: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 7712: &newoverview($r,$parm_permission);
1.414 droeschl 7713: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 7714: &defaultsetter($r);
7715: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 7716: &assessparms($r,$parm_permission);
1.414 droeschl 7717: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 7718: &parm_change_log($r,$parm_permission);
1.414 droeschl 7719: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 7720: &clean_parameters($r);
1.414 droeschl 7721: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 7722: &date_shift_one($r);
1.414 droeschl 7723: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 7724: &date_shift_two($r);
1.446 bisitz 7725: }
1.43 albertel 7726: } else {
1.1 www 7727: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 7728: if ($exists) {
7729: $env{'user.error.msg'}=
7730: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
7731: } else {
7732: $env{'user.error.msg'}=
7733: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
7734: }
7735: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 7736: }
1.376 albertel 7737: &reset_caches();
7738:
1.43 albertel 7739: return OK;
1.1 www 7740: }
7741:
7742: 1;
7743: __END__
7744:
7745:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>