Annotation of loncom/interface/lonparmset.pm, revision 1.603
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.603 ! raeburn 4: # $Id: lonparmset.pm,v 1.602 2021/08/12 20:43:26 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'},
1739: 'provider');
1.601 raeburn 1740: if (keys(%lti)) {
1741: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1742: if (ref($lti{$item}) eq 'HASH') {
1743: unless ($lti{$item}{'requser'}) {
1744: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'consumer'})).',';
1745: }
1.588 raeburn 1746: }
1747: }
1.601 raeburn 1748: $domltistr =~ s/,$//;
1749: if ($domltistr) {
1750: $extra = 'ltid_'.$domltistr;
1751: }
1.588 raeburn 1752: }
1.601 raeburn 1753: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
1754: if (keys(%courselti)) {
1755: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
1756: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
1757: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
1758: }
1759: }
1760: $crsltistr =~ s/,$//;
1761: if ($crsltistr) {
1762: if ($extra) {
1763: $extra .= '&';
1764: }
1765: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 1766: }
1767: }
1.597 raeburn 1768: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
1769: my @colls;
1770: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
1771: my ($num,$value) = split(/\%/,$item);
1772: if ($num =~ /^\d+$/) {
1773: push(@colls,$num);
1774: }
1775: }
1776: if (@colls) {
1777: if ($extra) {
1778: $extra .= '&';
1779: }
1780: $extra .= 'menus_'.join(',',@colls);
1781: }
1782: }
1.588 raeburn 1783: }
1.57 albertel 1784: if ($parmlev eq 'general') {
1785: if ($uname) {
1.588 raeburn 1786: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 1787: } elsif ($cgroup) {
1.588 raeburn 1788: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 1789: } elsif ($csec) {
1.588 raeburn 1790: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1791: } else {
1.588 raeburn 1792: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1793: }
1794: } elsif ($parmlev eq 'map') {
1795: if ($uname) {
1.588 raeburn 1796: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 1797: } elsif ($cgroup) {
1.588 raeburn 1798: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 1799: } elsif ($csec) {
1.588 raeburn 1800: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1801: } else {
1.588 raeburn 1802: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1803: }
1804: } else {
1.275 raeburn 1805: if ($uname) {
1806: if (@{$usersgroups} > 1) {
1.582 raeburn 1807: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 1808: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 1809: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 1810: if (($coursereply) && ($result > 4)) {
1.275 raeburn 1811: if (defined($controlgrp)) {
1812: if ($cgroup ne $controlgrp) {
1.582 raeburn 1813: $eff_groupparm = $grp_parm;
1814: undef($result);
1815: undef($effparm_rec);
1816: if ($grp_is_rec) {
1817: $effparm_rec = 1;
1818: }
1.275 raeburn 1819: }
1820: }
1821: }
1822: }
1823: }
1.57 albertel 1824:
1.588 raeburn 1825: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1826: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1827: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1828: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1829: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1830:
1831: if ($csec) {
1.588 raeburn 1832: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1833: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1834: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1835: }
1.269 raeburn 1836:
1837: if ($cgroup) {
1.588 raeburn 1838: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1839: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1840: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 1841: }
1.446 bisitz 1842:
1.548 raeburn 1843: if ($uname) {
1.275 raeburn 1844: if ($othergrp) {
1845: $r->print($othergrp);
1846: }
1.588 raeburn 1847: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1848: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1849: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1850: }
1.57 albertel 1851: } # end of $parmlev if/else
1.582 raeburn 1852: if (ref($recursinfo) eq 'ARRAY') {
1853: my $rectitle = &mt('recursive');
1854: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
1855: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
1856: $rectitle = &mt('set in: [_1]','"'.
1857: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
1858: "'$parmname','$$part{$which}'".');">'.
1859: $maptitles->{$recursinfo->[2]}.'</a>"');
1860:
1861: $numlinks ++;
1862: }
1863: }
1864: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 1865: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 1866: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1867: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
1868: $effparm_level.'</span></td>');
1869: } else {
1870: if ($result) {
1.593 raeburn 1871: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 1872: }
1873: if ($eff_groupparm) {
1874: $effective_parm = $eff_groupparm;
1875: }
1876: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1877: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
1878: '</span>':'').'</td>');
1879: }
1.203 www 1880: if ($parmlev eq 'full') {
1.136 albertel 1881: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 1882: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 1883: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 1884: if (!defined($sessionvaltype)) {
1885: $sessionvaltype=$$defaulttype{$which};
1886: }
1.419 bisitz 1887: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 1888: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 1889: '</font></td>');
1.136 albertel 1890: }
1.44 albertel 1891: $r->print('</tr>');
1.57 albertel 1892: $r->print("\n");
1.582 raeburn 1893: if (($numlinks) && (ref($reclinks))) {
1894: $$reclinks = $numlinks;
1895: }
1.44 albertel 1896: }
1.59 matthew 1897:
1.561 damieng 1898: # Prints a cell for table mode.
1899: #
1900: # FIXME: some of these parameter names are uninspired ($which and $value)
1901: # Also, it would make more sense to pass the display for this cell rather
1902: # than the full display hash and the key to use.
1903: #
1904: # @param {Apache2::RequestRec} $r - the Apache request
1905: # @param {integer} $which - level
1906: # @param {string} $defbg - cell background color
1907: # @param {integer} $result - the most specific level that is defined for that parameter
1908: # @param {array reference} $outpar - array level -> parameter value (when defined)
1909: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
1910: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
1911: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
1912: # @param {hash reference} $display - parameter key -> full title for the parameter
1913: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 1914: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 1915: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 1916: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 1917: sub print_td {
1.578 raeburn 1918: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 1919: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 1920: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
1921: $ineffect = 0;
1922: $currval = $$outpar[$which];
1923: $currtype = $$typeoutpar[$which];
1924: $currlevel = $which;
1925: if (($result) && ($result == $which)) {
1926: $ineffect = 1;
1927: }
1928: if ($ismaplevel) {
1929: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
1930: if (($result) && ($result == $which)) {
1931: $recursive = 1;
1932: }
1933: } elsif ($$outpar[$which+1] ne '') {
1934: $recursive = 1;
1935: $currlevel = $which+1;
1936: $currval = $$outpar[$currlevel];
1937: $currtype = $$typeoutpar[$currlevel];
1938: if (($result) && ($result == $currlevel)) {
1939: $ineffect = 1;
1940: }
1941: }
1942: }
1943: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 1944: ';" align="center">');
1.437 raeburn 1945: my $nolink = 0;
1.568 raeburn 1946: if ($readonly) {
1.552 raeburn 1947: $nolink = 1;
1.568 raeburn 1948: } else {
1.578 raeburn 1949: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 1950: $nolink = 1;
1.568 raeburn 1951: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 1952: $nolink = 1;
1.568 raeburn 1953: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
1954: if ($noeditgrp) {
1955: $nolink = 1;
1956: }
1957: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 1958: $nolink = 1;
1.568 raeburn 1959: } elsif ($mprefix =~ /examcode\&$/) {
1960: unless ($which == 2) {
1961: $nolink = 1;
1962: }
1.533 raeburn 1963: }
1.437 raeburn 1964: }
1965: if ($nolink) {
1.577 raeburn 1966: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 1967: $r->print(&valout($currval,$currtype));
1.114 www 1968: } else {
1.578 raeburn 1969: $r->print(&plink($currtype,
1970: $$display{$value},$currval,
1.588 raeburn 1971: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
1972: $extra));
1.114 www 1973: }
1974: $r->print('</td>'."\n");
1.57 albertel 1975: }
1976:
1.561 damieng 1977: # Returns HTML and other info for the cell added when a user is selected
1978: # and that user is in several groups. This is the cell with the title "Control by other group".
1979: #
1980: # @param {string} $what - parameter part.'.'.parameter name
1981: # @param {string} $rid - resource id
1982: # @param {string} $cgroup - group name
1983: # @param {string} $defbg - cell background color
1984: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1985: # @param {integer} $result - level
1986: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 1987: # @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 1988: sub check_other_groups {
1989: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 1990: my $courseid = $env{'request.course.id'};
1991: my $output;
1992: my $symb = &symbcache($rid);
1993: my $symbparm=$symb.'.'.$what;
1994: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 1995: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 1996: my $mapparm=$map.'___(all).'.$what;
1997: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 1998: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
1999: $recurseparm,$what,$courseopt);
1.275 raeburn 2000: my $bgcolor = $defbg;
1.582 raeburn 2001: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2002: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2003: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2004: if ($result > 3) {
1.419 bisitz 2005: $bgcolor = '#AAFFAA';
1.275 raeburn 2006: }
1.593 raeburn 2007: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2008: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2009: if ($resultgroup && $resultlevel) {
1.582 raeburn 2010: if ($resultlevel eq 'recursive') {
2011: $resultlevel = 'map/folder';
2012: $grp_is_rec = 1;
2013: }
2014: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2015: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2016:
1.275 raeburn 2017: } else {
2018: $output .= ' ';
2019: }
2020: $output .= '</td>';
2021: } else {
1.419 bisitz 2022: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2023: }
1.582 raeburn 2024: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2025: }
2026:
1.561 damieng 2027: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2028: # Used by check_other_groups.
1.561 damieng 2029: #
2030: # @param {string} $courseid - the course id
2031: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2032: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2033: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2034: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2035: # @param {string} $what - parameter part.'.'.parameter name
2036: # @param {hash reference} $courseopt - course parameters hash
2037: # @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 2038: sub parm_control_group {
1.556 raeburn 2039: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2040: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2041: my $grpfound = 0;
1.556 raeburn 2042: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2043: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2044: foreach my $group (@{$usersgroups}) {
2045: if ($grpfound) { last; }
2046: for (my $i=0; $i<@levels; $i++) {
2047: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2048: if (defined($$courseopt{$item})) {
2049: $coursereply = $$courseopt{$item};
2050: $resultitem = $item;
2051: $resultgroup = $group;
2052: $resultlevel = $levelnames[$i];
2053: $resulttype = $$courseopt{$item.'.type'};
2054: $grpfound = 1;
2055: last;
2056: }
2057: }
2058: }
2059: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2060: }
1.201 www 2061:
1.63 bowersj2 2062:
2063:
1.562 damieng 2064: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2065: # All the parameters are references and are filled by the sub.
2066: #
1.566 damieng 2067: # @param {array reference} $ids - resource and map ids
2068: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2069: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2070: # @param {hash reference} $allparms - hash parameter name -> parameter title
2071: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2072: # @param {hash reference} $allmaps - hash map pc -> map src
2073: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2074: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2075: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2076: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2077: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2078: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.63 bowersj2 2079: sub extractResourceInformation {
2080: my $ids = shift;
2081: my $typep = shift;
2082: my $keyp = shift;
2083: my $allparms = shift;
2084: my $allparts = shift;
2085: my $allmaps = shift;
2086: my $mapp = shift;
2087: my $symbp = shift;
1.82 www 2088: my $maptitles=shift;
1.196 www 2089: my $uris=shift;
1.210 www 2090: my $keyorder=shift;
1.211 www 2091: my $defkeytype=shift;
1.603 ! raeburn 2092: my $pssymb=shift;
1.196 www 2093:
1.210 www 2094: my $keyordercnt=100;
1.63 bowersj2 2095:
1.196 www 2096: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 ! raeburn 2097: return unless(ref($navmap));
! 2098: my @allres;
! 2099: if ($pssymb ne '') {
! 2100: my $res = $navmap->getBySymb($pssymb);
! 2101: if (ref($res)) {
! 2102: @allres = ($res);
! 2103: }
! 2104: }
! 2105: if (!@allres) {
! 2106: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
! 2107: }
1.196 www 2108: foreach my $resource (@allres) {
1.480 amueller 2109: my $id=$resource->id();
1.196 www 2110: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2111: if ($mapid eq '0') { next; }
2112: $$ids[$#$ids+1]=$id;
2113: my $srcf=$resource->src();
2114: $srcf=~/\.(\w+)$/;
2115: $$typep{$id}=$1;
1.584 raeburn 2116: my $toolsymb;
2117: if ($srcf =~ /ext\.tool$/) {
2118: $toolsymb = $resource->symb();
2119: }
1.480 amueller 2120: $$keyp{$id}='';
1.196 www 2121: $$uris{$id}=$srcf;
1.512 foxr 2122:
1.584 raeburn 2123: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2124: next if ($key!~/^parameter_/);
1.363 albertel 2125:
1.209 www 2126: # Hidden parameters
1.584 raeburn 2127: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2128: #
2129: # allparms is a hash of parameter names
2130: #
1.584 raeburn 2131: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2132: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2133: my ($display,$parmdis);
2134: $display = &standard_parameter_names($name);
2135: if ($display eq '') {
1.584 raeburn 2136: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2137: $parmdis = $display;
2138: $parmdis =~ s/\s*\[Part.*$//g;
2139: } else {
2140: $parmdis = &mt($display);
2141: }
2142: $$allparms{$name}=$parmdis;
2143: if (ref($defkeytype)) {
2144: $$defkeytype{$name}=
1.584 raeburn 2145: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2146: }
2147: }
1.363 albertel 2148:
1.209 www 2149: #
2150: # allparts is a hash of all parts
2151: #
1.584 raeburn 2152: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2153: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2154: #
2155: # Remember all keys going with this resource
2156: #
1.480 amueller 2157: if ($$keyp{$id}) {
2158: $$keyp{$id}.=','.$key;
2159: } else {
2160: $$keyp{$id}=$key;
2161: }
1.210 www 2162: #
2163: # Put in order
1.446 bisitz 2164: #
1.480 amueller 2165: unless ($$keyorder{$key}) {
2166: $$keyorder{$key}=$keyordercnt;
2167: $keyordercnt++;
2168: }
1.473 amueller 2169: }
2170:
2171:
1.480 amueller 2172: if (!exists($$mapp{$mapid})) {
2173: $$mapp{$id}=
2174: &Apache::lonnet::declutter($resource->enclosing_map_src());
2175: $$mapp{$mapid}=$$mapp{$id};
2176: $$allmaps{$mapid}=$$mapp{$id};
2177: if ($mapid eq '1') {
1.532 raeburn 2178: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2179: } else {
2180: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2181: }
2182: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2183: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2184: # Lines 1038 and 1114 which use $symbp{$mapid}
2185: # are commented out in rev. 1.57
1.473 amueller 2186: } else {
1.480 amueller 2187: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2188: }
1.480 amueller 2189: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2190: }
2191: }
2192:
1.582 raeburn 2193: sub get_recursive {
2194: my ($recurseup,$resdata,$what,$prefix) = @_;
2195: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2196: foreach my $item (@{$recurseup}) {
2197: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2198: if (defined($resdata->{$norecursechk})) {
2199: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2200: my $type = $resdata->{$norecursechk.'.type'};
2201: return [$resdata->{$norecursechk},$type,$item];
2202: } else {
2203: last;
2204: }
2205: }
2206: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2207: if (defined($resdata->{$recursechk})) {
2208: my $type = $resdata->{$recursechk.'.type'};
2209: return [$resdata->{$recursechk},$type,$item];
2210: }
2211: }
2212: }
2213: return;
2214: }
2215:
1.208 www 2216:
1.562 damieng 2217: # Tells if a parameter type is a date.
2218: #
2219: # @param {string} type - parameter type
2220: # @returns{boolean} - true if it is a date
1.213 www 2221: sub isdateparm {
2222: my $type=shift;
2223: return (($type=~/^date/) && (!($type eq 'date_interval')));
2224: }
2225:
1.589 raeburn 2226: # Determine if parameter type is specialized string type (i.e.,
2227: # not just string or string_yesno.
2228:
2229: sub is_specialstring {
2230: my $type=shift;
1.603 ! raeburn 2231: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2232: }
2233:
1.562 damieng 2234: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2235: #
1.581 raeburn 2236: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2237: sub parmmenu {
1.581 raeburn 2238: my ($r)=@_;
1.208 www 2239: $r->print(<<ENDSCRIPT);
2240: <script type="text/javascript">
1.454 bisitz 2241: // <![CDATA[
1.208 www 2242: function checkall(value, checkName) {
1.453 schualex 2243:
2244: var li = "_li";
2245: var displayOverview = "";
2246:
2247: if (value == false) {
2248: displayOverview = "none"
2249: }
2250:
1.562 damieng 2251: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2252: ele = document.forms.parmform.elements[i];
2253: if (ele.name == checkName) {
2254: document.forms.parmform.elements[i].checked=value;
2255: }
2256: }
2257: }
1.210 www 2258:
2259: function checkthis(thisvalue, checkName) {
1.562 damieng 2260: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2261: ele = document.forms.parmform.elements[i];
2262: if (ele.name == checkName) {
1.562 damieng 2263: if (ele.value == thisvalue) {
2264: document.forms.parmform.elements[i].checked=true;
2265: }
1.210 www 2266: }
2267: }
2268: }
2269:
2270: function checkdates() {
1.562 damieng 2271: checkthis('duedate','pscat');
2272: checkthis('opendate','pscat');
2273: checkthis('answerdate','pscat');
1.218 www 2274: }
2275:
2276: function checkdisset() {
1.562 damieng 2277: checkthis('discussend','pscat');
2278: checkthis('discusshide','pscat');
2279: checkthis('discussvote','pscat');
1.218 www 2280: }
2281:
2282: function checkcontdates() {
1.562 damieng 2283: checkthis('contentopen','pscat');
2284: checkthis('contentclose','pscat');
1.218 www 2285: }
1.446 bisitz 2286:
1.210 www 2287: function checkvisi() {
1.562 damieng 2288: checkthis('hiddenresource','pscat');
2289: checkthis('encrypturl','pscat');
2290: checkthis('problemstatus','pscat');
2291: checkthis('contentopen','pscat');
2292: checkthis('opendate','pscat');
1.210 www 2293: }
2294:
2295: function checkparts() {
1.562 damieng 2296: checkthis('hiddenparts','pscat');
2297: checkthis('display','pscat');
2298: checkthis('ordered','pscat');
1.210 www 2299: }
2300:
2301: function checkstandard() {
2302: checkall(false,'pscat');
1.562 damieng 2303: checkdates();
2304: checkthis('weight','pscat');
2305: checkthis('maxtries','pscat');
2306: checkthis('type','pscat');
2307: checkthis('problemstatus','pscat');
1.210 www 2308: }
2309:
1.454 bisitz 2310: // ]]>
1.208 www 2311: </script>
2312: ENDSCRIPT
1.453 schualex 2313:
1.491 bisitz 2314: $r->print('<hr />');
1.581 raeburn 2315: &shortCuts($r);
1.491 bisitz 2316: $r->print('<hr />');
1.453 schualex 2317: }
1.562 damieng 2318:
2319: # Returns parameter categories.
2320: #
2321: # @returns {hash} - category name -> title in English
1.465 amueller 2322: sub categories {
2323: return ('time_settings' => 'Time Settings',
2324: 'grading' => 'Grading',
2325: 'tries' => 'Tries',
2326: 'problem_appearance' => 'Problem Appearance',
2327: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2328: 'hiding' => 'Hiding',
2329: 'high_level_randomization' => 'High Level Randomization',
2330: 'slots' => 'Slots',
2331: 'file_submission' => 'File Submission',
2332: 'misc' => 'Miscellaneous' );
2333: }
2334:
1.562 damieng 2335: # Returns the category for each parameter.
2336: #
2337: # @returns {hash} - parameter name -> category name
1.465 amueller 2338: sub lookUpTableParameter {
2339:
2340: return (
2341: 'opendate' => 'time_settings',
2342: 'duedate' => 'time_settings',
2343: 'answerdate' => 'time_settings',
2344: 'interval' => 'time_settings',
2345: 'contentopen' => 'time_settings',
2346: 'contentclose' => 'time_settings',
2347: 'discussend' => 'time_settings',
1.560 damieng 2348: 'printstartdate' => 'time_settings',
2349: 'printenddate' => 'time_settings',
1.465 amueller 2350: 'weight' => 'grading',
2351: 'handgrade' => 'grading',
2352: 'maxtries' => 'tries',
2353: 'hinttries' => 'tries',
1.503 raeburn 2354: 'randomizeontries' => 'tries',
1.465 amueller 2355: 'type' => 'problem_appearance',
2356: 'problemstatus' => 'problem_appearance',
2357: 'display' => 'problem_appearance',
2358: 'ordered' => 'problem_appearance',
2359: 'numbubbles' => 'problem_appearance',
2360: 'tol' => 'behaviour_of_input_fields',
2361: 'sig' => 'behaviour_of_input_fields',
2362: 'turnoffunit' => 'behaviour_of_input_fields',
2363: 'hiddenresource' => 'hiding',
2364: 'hiddenparts' => 'hiding',
2365: 'discusshide' => 'hiding',
2366: 'buttonshide' => 'hiding',
2367: 'turnoffeditor' => 'hiding',
2368: 'encrypturl' => 'hiding',
1.587 raeburn 2369: 'deeplink' => 'hiding',
1.465 amueller 2370: 'randomorder' => 'high_level_randomization',
2371: 'randompick' => 'high_level_randomization',
2372: 'available' => 'slots',
2373: 'useslots' => 'slots',
2374: 'availablestudent' => 'slots',
2375: 'uploadedfiletypes' => 'file_submission',
2376: 'maxfilesize' => 'file_submission',
2377: 'cssfile' => 'misc',
2378: 'mapalias' => 'misc',
2379: 'acc' => 'misc',
2380: 'maxcollaborators' => 'misc',
2381: 'scoreformat' => 'misc',
1.514 raeburn 2382: 'lenient' => 'grading',
1.519 raeburn 2383: 'retrypartial' => 'tries',
1.521 raeburn 2384: 'discussvote' => 'misc',
1.584 raeburn 2385: 'examcode' => 'high_level_randomization',
1.575 raeburn 2386: );
1.465 amueller 2387: }
2388:
1.562 damieng 2389: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2390: #
2391: # @param {string} $name - parameter name
2392: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2393: sub whatIsMyCategory {
2394: my $name = shift;
2395: my $catList = shift;
2396: my @list;
2397: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2398: my $cat = $lookUpList{$name};
2399: if (defined($cat)) {
2400: if (!defined($$catList{$cat})){
2401: push @list, ($name);
2402: $$catList{$cat} = \@list;
2403: } else {
2404: push @{${$catList}{$cat}}, ($name);
2405: }
2406: } else {
2407: if (!defined($$catList{'misc'})){
2408: push @list, ($name);
2409: $$catList{'misc'} = \@list;
2410: } else {
2411: push @{${$catList}{'misc'}}, ($name);
2412: }
2413: }
2414: }
2415:
1.562 damieng 2416: # Sorts parameter names based on appearance order.
2417: #
2418: # @param {array reference} name - array reference of parameter names
2419: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2420: # @returns {Array} - array of parameter names
1.465 amueller 2421: sub keysindisplayorderCategory {
2422: my ($name,$keyorder)=@_;
2423: return sort {
1.473 amueller 2424: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2425: } ( @{$name});
2426: }
2427:
1.562 damieng 2428: # Returns a hash category name -> order, starting at 1 (integer)
2429: #
2430: # @returns {hash}
1.467 amueller 2431: sub category_order {
2432: return (
2433: 'time_settings' => 1,
2434: 'grading' => 2,
2435: 'tries' => 3,
2436: 'problem_appearance' => 4,
2437: 'hiding' => 5,
2438: 'behaviour_of_input_fields' => 6,
2439: 'high_level_randomization' => 7,
2440: 'slots' => 8,
2441: 'file_submission' => 9,
2442: 'misc' => 10
2443: );
2444:
2445: }
1.453 schualex 2446:
1.562 damieng 2447: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2448: #
2449: # @param {Apache2::RequestRec} $r - the Apache request
2450: # @param {hash reference} $allparms - hash parameter name -> parameter title
2451: # @param {array reference} $pscat - list of selected parameter names
2452: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2453: sub parmboxes {
2454: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2455: my %categories = &categories();
1.467 amueller 2456: my %category_order = &category_order();
1.465 amueller 2457: my %categoryList = (
2458: 'time_settings' => [],
2459: 'grading' => [],
2460: 'tries' => [],
2461: 'problem_appearance' => [],
2462: 'behaviour_of_input_fields' => [],
2463: 'hiding' => [],
2464: 'high_level_randomization' => [],
2465: 'slots' => [],
2466: 'file_submission' => [],
2467: 'misc' => [],
1.489 bisitz 2468: );
1.510 www 2469:
1.548 raeburn 2470: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2471: &whatIsMyCategory($tempparameter, \%categoryList);
2472: }
1.453 schualex 2473: #part to print the parm-list
1.536 raeburn 2474: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2475: next if (@{$categoryList{$key}} == 0);
2476: next if ($key eq '');
2477: $r->print('<div class="LC_Box LC_400Box">'
2478: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2479: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2480: next if ($tempkey eq '');
1.536 raeburn 2481: $r->print('<span class="LC_nobreak">'
2482: .'<label><input type="checkbox" name="pscat" '
2483: .'value="'.$tempkey.'" ');
2484: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2485: $r->print( ' checked="checked"');
2486: }
2487: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465 amueller 2488: : $tempkey)
1.536 raeburn 2489: .'</label></span><br />'."\n");
1.465 amueller 2490: }
1.536 raeburn 2491: $r->print('</div>');
1.465 amueller 2492: }
1.536 raeburn 2493: $r->print("\n");
1.453 schualex 2494: }
1.562 damieng 2495:
2496: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2497: #
1.562 damieng 2498: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2499: sub shortCuts {
1.581 raeburn 2500: my ($r)=@_;
1.453 schualex 2501:
1.491 bisitz 2502: # Parameter Selection
2503: $r->print(
2504: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2505: .&Apache::lonhtmlcommon::add_item_funclist(
2506: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2507: .&Apache::lonhtmlcommon::add_item_funclist(
2508: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2509: .&Apache::lonhtmlcommon::add_item_funclist(
2510: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2511: .&Apache::lonhtmlcommon::end_funclist()
2512: );
2513:
2514: # Add Selection for...
2515: $r->print(
2516: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2517: .&Apache::lonhtmlcommon::add_item_funclist(
2518: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2519: .&Apache::lonhtmlcommon::add_item_funclist(
2520: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2521: .&Apache::lonhtmlcommon::add_item_funclist(
2522: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2523: .&Apache::lonhtmlcommon::add_item_funclist(
2524: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2525: .&Apache::lonhtmlcommon::add_item_funclist(
2526: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2527: .&Apache::lonhtmlcommon::end_funclist()
2528: );
1.208 www 2529: }
2530:
1.562 damieng 2531: # Prints HTML to select parts to view (except for the title).
2532: # Used by table and overview modes.
2533: #
2534: # @param {Apache2::RequestRec} $r - the Apache request
2535: # @param {hash reference} $allparts - hash parameter part -> part title
2536: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2537: sub partmenu {
1.446 bisitz 2538: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2539: my $selsize = 1+scalar(keys(%{$allparts}));
2540: if ($selsize > 8) {
2541: $selsize = 8;
2542: }
1.446 bisitz 2543:
1.523 raeburn 2544: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2545: $r->print('<option value="all"');
1.562 damieng 2546: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2547: $r->print('>'.&mt('All Parts').'</option>');
2548: my %temphash=();
2549: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2550: foreach my $tempkey (sort {
1.560 damieng 2551: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2552: } keys(%{$allparts})) {
2553: unless ($tempkey =~ /\./) {
2554: $r->print('<option value="'.$tempkey.'"');
2555: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2556: $r->print(' selected="selected"');
2557: }
2558: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2559: }
1.208 www 2560: }
1.446 bisitz 2561: $r->print('</select>');
1.209 www 2562: }
2563:
1.562 damieng 2564: # Prints HTML to select a user and/or a group.
2565: # Used by table mode.
2566: #
2567: # @param {Apache2::RequestRec} $r - the Apache request
2568: # @param {string} $uname - selected user name
2569: # @param {string} $id - selected Student/Employee ID
2570: # @param {string} $udom - selected user domain
2571: # @param {string} $csec - selected section name
2572: # @param {string} $cgroup - selected group name
2573: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2574: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2575: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2576: sub usermenu {
1.553 raeburn 2577: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2578: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2579: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2580: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2581: function setCourseadv(form,caller) {
2582: if (caller.value == 'st') {
2583: form.courseadv.value = 'none';
2584: } else {
2585: form.courseadv.value = '';
2586: }
2587: return;
2588: }
2589: ENDJS
1.412 bisitz 2590:
1.596 raeburn 2591: my (%chkroles,$stuonly,$courseadv);
2592: if ($env{'form.userroles'} eq 'any') {
2593: $chkroles{'any'} = ' checked="checked"';
2594: } else {
2595: $chkroles{'st'} = ' checked="checked"';
2596: $courseadv = 'none';
2597: }
2598: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2599: if ($crstype eq 'Community') {
2600: $stuonly = &mt('member only');
2601: } else {
2602: $stuonly = &mt('student only');
2603: }
2604: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2605: &mt("User's role").': '.
2606: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2607: $stuonly.'</label> '.
2608: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2609: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2610: my $sections='';
1.300 albertel 2611: my %sectionhash = &Apache::loncommon::get_sections();
2612:
1.269 raeburn 2613: my $groups;
1.553 raeburn 2614: my %grouphash;
2615: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2616: %grouphash = &Apache::longroup::coursegroups();
2617: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2618: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2619: }
1.299 albertel 2620:
1.412 bisitz 2621: my $g_s_header='';
2622: my $g_s_footer='';
1.446 bisitz 2623:
1.552 raeburn 2624: my $currsec = $env{'request.course.sec'};
2625: if ($currsec) {
2626: $sections=&mt('Section:').' '.$currsec;
2627: if (%grouphash) {
2628: $sections .= ';'.(' ' x2);
2629: }
2630: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2631: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2632: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2633: $sections .= qq| onchange="group_or_section('csec')" |;
2634: }
2635: $sections .= '>';
1.548 raeburn 2636: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2637: $sections.='<option value="'.$section.'" '.
2638: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2639: '</option>';
1.209 www 2640: }
2641: $sections.='</select>';
1.269 raeburn 2642: }
1.412 bisitz 2643:
1.552 raeburn 2644: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2645: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2646: $sections .= qq|
2647: <script type="text/javascript">
1.454 bisitz 2648: // <![CDATA[
1.269 raeburn 2649: function group_or_section(caller) {
2650: if (caller == "cgroup") {
2651: if (document.parmform.cgroup.selectedIndex != 0) {
2652: document.parmform.csec.selectedIndex = 0;
2653: }
2654: } else {
2655: if (document.parmform.csec.selectedIndex != 0) {
2656: document.parmform.cgroup.selectedIndex = 0;
2657: }
2658: }
2659: }
1.454 bisitz 2660: // ]]>
1.269 raeburn 2661: </script>
2662: |;
1.554 raeburn 2663: } else {
1.269 raeburn 2664: $sections .= qq|
2665: <script type="text/javascript">
1.454 bisitz 2666: // <![CDATA[
1.269 raeburn 2667: function group_or_section(caller) {
2668: return;
2669: }
1.454 bisitz 2670: // ]]>
1.269 raeburn 2671: </script>
2672: |;
1.446 bisitz 2673: }
1.299 albertel 2674:
2675: if (%grouphash) {
1.597 raeburn 2676: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2677: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2678: $groups .= qq| onchange="group_or_section('cgroup')" |;
2679: }
2680: $groups .= '>';
1.548 raeburn 2681: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2682: $groups.='<option value="'.$grp.'" ';
2683: if ($grp eq $cgroup) {
2684: unless ((defined($uname)) && ($grp eq '')) {
2685: $groups .= 'selected="selected" ';
2686: }
2687: } elsif (!defined($cgroup)) {
2688: if (@{$usersgroups} == 1) {
2689: if ($grp eq $$usersgroups[0]) {
2690: $groups .= 'selected="selected" ';
2691: }
2692: }
2693: }
2694: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2695: }
2696: $groups.='</select>';
2697: }
1.412 bisitz 2698:
1.445 neumanie 2699: if (%sectionhash || %grouphash) {
1.446 bisitz 2700: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2701: $r->print($sections.$groups);
1.448 bisitz 2702: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 2703: } else {
2704: $r->print($sections);
1.445 neumanie 2705: }
1.446 bisitz 2706:
2707: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 2708: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 2709: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
2710: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 2711: ,$chooseopt));
1.209 www 2712: }
2713:
1.562 damieng 2714: # Prints HTML to select parameters from a list of all parameters.
2715: # Uses parmmenu and parmboxes.
2716: # Used by table and overview modes.
1.468 amueller 2717: #
1.562 damieng 2718: # @param {Apache2::RequestRec} $r - the Apache request
2719: # @param {hash reference} $allparms - hash parameter name -> parameter title
2720: # @param {array reference} $pscat - list of selected parameter names
2721: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2722: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 2723: sub displaymenu {
1.581 raeburn 2724: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 2725:
1.445 neumanie 2726: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 2727: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
2728:
1.581 raeburn 2729: &parmmenu($r);
1.536 raeburn 2730: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 2731: &parmboxes($r,$allparms,$pscat,$keyorder);
2732: $r->print(&Apache::loncommon::end_scrollbox());
2733:
2734: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 2735: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 2736:
1.209 www 2737: }
2738:
1.562 damieng 2739: # Prints HTML to select a map.
2740: # Used by table mode and overview mode.
2741: #
2742: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 2743: # @param {hash reference} $allmaps - hash map pc -> map src
2744: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 2745: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 2746: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445 neumanie 2747: sub mapmenu {
1.499 raeburn 2748: my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468 amueller 2749: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 2750: my $navmap = Apache::lonnavmaps::navmap->new();
2751: my $tree=[];
2752: my $treeinfo={};
2753: if (defined($navmap)) {
1.499 raeburn 2754: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 2755: my $curRes;
2756: my $depth = 0;
1.468 amueller 2757: my %parent = ();
2758: my $startcount = 5;
2759: my $lastcontainer = $startcount;
2760: # preparing what is to show ...
1.461 neumanie 2761: while ($curRes = $it->next()) {
2762: if ($curRes == $it->BEGIN_MAP()) {
2763: $depth++;
1.468 amueller 2764: $parent{$depth}= $lastcontainer;
1.461 neumanie 2765: }
2766: if ($curRes == $it->END_MAP()) {
2767: $depth--;
1.468 amueller 2768: $lastcontainer = $parent{$depth};
1.461 neumanie 2769: }
2770: if (ref($curRes)) {
1.468 amueller 2771: my $symb = $curRes->symb();
2772: my $ressymb = $symb;
1.461 neumanie 2773: if (($curRes->is_sequence()) || ($curRes->is_page())) {
2774: my $type = 'sequence';
2775: if ($curRes->is_page()) {
2776: $type = 'page';
2777: }
2778: my $id= $curRes->id();
1.468 amueller 2779: my $srcf = $curRes->src();
2780: my $resource_name = &Apache::lonnet::gettitle($srcf);
2781: if(!exists($treeinfo->{$id})) {
2782: push(@$tree,$id);
1.473 amueller 2783: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 2784: $treeinfo->{$id} = {
1.461 neumanie 2785: depth => $depth,
2786: type => $type,
1.468 amueller 2787: name => $resource_name,
2788: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 2789: };
1.462 neumanie 2790: }
1.461 neumanie 2791: }
2792: }
2793: }
1.462 neumanie 2794: }
1.473 amueller 2795: # Show it ...
1.484 amueller 2796: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461 neumanie 2797: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
2798: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 2799: my $whitespace =
2800: '<img src="'
2801: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
2802: .'" alt="" />';
2803:
1.498 bisitz 2804: # Info about selectable folders/maps
2805: $r->print(
2806: '<div class="LC_info">'
1.508 www 2807: .&mt('You can only select maps and folders which have modifiable settings.')
2808: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 2809: .'</div>'
2810: );
2811:
1.536 raeburn 2812: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 2813: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 2814:
1.498 bisitz 2815: # Display row: "All Maps or Folders"
2816: $r->print(
1.523 raeburn 2817: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 2818: .'<td>'
2819: .'<label>'
2820: .'<input type="radio" name="pschp"'
1.497 bisitz 2821: );
2822: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 2823: $r->print(
2824: ' value="all" /> '.$icon.' '
2825: .&mt('All Maps or Folders')
2826: .'</label>'
2827: .'<hr /></td>'
2828: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2829: );
1.497 bisitz 2830:
1.532 raeburn 2831: # Display row: "Main Content"
1.468 amueller 2832: if (exists($$allmaps{1})) {
1.498 bisitz 2833: $r->print(
2834: &Apache::loncommon::start_data_table_row()
2835: .'<td>'
2836: .'<label>'
2837: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 2838: );
1.497 bisitz 2839: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 2840: $r->print(
2841: '/> '.$icon.' '
2842: .$$maptitles{1}
2843: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
2844: .'</label>'
2845: .'</td>'
2846: .&Apache::loncommon::end_data_table_row()
1.468 amueller 2847: );
2848: }
1.497 bisitz 2849:
2850: # Display rows for all course maps and folders
1.468 amueller 2851: foreach my $id (@{$tree}) {
2852: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 2853: # Indentation
1.468 amueller 2854: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 2855: my $indent;
2856: for (my $i = 0; $i < $depth; $i++) {
2857: $indent.= $whitespace;
2858: }
1.461 neumanie 2859: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 2860: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 2861: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
2862: }
1.468 amueller 2863: my $symb_name = $$symbp{$id};
2864: my ($front, $tail) = split (/___${resid}___/, $symb_name);
2865: $symb_name = $tail;
1.498 bisitz 2866: $r->print(
2867: &Apache::loncommon::start_data_table_row()
2868: .'<td>'
2869: .'<label>'
1.463 bisitz 2870: );
1.498 bisitz 2871: # Only offer radio button for folders/maps which can be parameterized
2872: if ($allmaps_inverted{$symb_name}) {
2873: $r->print(
2874: '<input type ="radio" name="pschp"'
2875: .' value="'.$allmaps_inverted{$symb_name}.'"'
2876: );
2877: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
2878: $r->print('/>');
2879: } else {
2880: $r->print($whitespace);
1.461 neumanie 2881: }
1.498 bisitz 2882: $r->print(
2883: $indent.$icon.' '
2884: .$treeinfo->{$id}->{name}
2885: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
2886: .'</label>'
2887: .'</td>'
2888: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2889: );
1.461 neumanie 2890: }
1.497 bisitz 2891:
1.523 raeburn 2892: $r->print(&Apache::loncommon::end_data_table().
2893: '<br style="line-height:2px;" />'.
2894: &Apache::loncommon::end_scrollbox());
1.209 www 2895: }
2896: }
2897:
1.563 damieng 2898: # Prints HTML to select the parameter level (resource, map/folder or course).
2899: # Used by table and overview modes.
2900: #
2901: # @param {Apache2::RequestRec} $r - the Apache request
2902: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
2903: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 2904: sub levelmenu {
1.446 bisitz 2905: my ($r,$alllevs,$parmlev)=@_;
2906:
1.548 raeburn 2907: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
2908: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 2909: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 2910: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
2911: $r->print('<option value="'.$$alllevs{$lev}.'"');
2912: if ($parmlev eq $$alllevs{$lev}) {
2913: $r->print(' selected="selected"');
2914: }
2915: $r->print('>'.&mt($lev).'</option>');
1.208 www 2916: }
1.446 bisitz 2917: $r->print("</select>");
1.208 www 2918: }
2919:
1.211 www 2920:
1.563 damieng 2921: # Returns HTML to select a section (with a select HTML element).
2922: # Used by overview mode.
2923: #
2924: # @param {array reference} $selectedsections - list of selected section ids
2925: # @returns {string}
1.211 www 2926: sub sectionmenu {
1.553 raeburn 2927: my ($selectedsections)=@_;
1.300 albertel 2928: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 2929: return '' if (!%sectionhash);
1.300 albertel 2930:
1.552 raeburn 2931: my (@possibles,$disabled);
2932: if ($env{'request.course.sec'} ne '') {
2933: @possibles = ($env{'request.course.sec'});
2934: $selectedsections = [$env{'request.course.sec'}];
2935: $disabled = ' disabled="disabled"';
2936: } else {
2937: @possibles = ('all',sort(keys(%sectionhash)));
2938: }
1.553 raeburn 2939: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 2940: foreach my $s (@possibles) {
1.553 raeburn 2941: $output .= ' <option value="'.$s.'"';
2942: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
2943: $output .= ' selected="selected"';
1.473 amueller 2944: }
1.553 raeburn 2945: $output .= '>'."$s</option>\n";
1.300 albertel 2946: }
1.553 raeburn 2947: $output .= "</select>\n";
2948: return $output;
1.269 raeburn 2949: }
2950:
1.563 damieng 2951: # Returns HTML to select a group (with a select HTML element).
2952: # Used by overview mode.
2953: #
2954: # @param {array reference} $selectedgroups - list of selected group names
2955: # @returns {string}
1.269 raeburn 2956: sub groupmenu {
1.553 raeburn 2957: my ($selectedgroups)=@_;
2958: my %grouphash;
2959: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2960: %grouphash = &Apache::longroup::coursegroups();
2961: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2962: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2963: }
2964: return '' if (!%grouphash);
1.299 albertel 2965:
1.553 raeburn 2966: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 2967: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 2968: $output .= ' <option value="'.$group.'"';
2969: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
2970: $output .= ' selected="selected"';
1.473 amueller 2971: }
1.553 raeburn 2972: $output .= '>'."$group</option>\n";
1.211 www 2973: }
1.553 raeburn 2974: $output .= "</select>\n";
2975: return $output;
1.211 www 2976: }
2977:
1.563 damieng 2978: # Returns an array with the given parameter split by comma.
2979: # Used by assessparms (table mode).
2980: #
2981: # @param {string} $keyp - the string to split
2982: # @returns {Array<string>}
1.210 www 2983: sub keysplit {
2984: my $keyp=shift;
2985: return (split(/\,/,$keyp));
2986: }
2987:
1.563 damieng 2988: # Returns the keys in $name, sorted using $keyorder.
2989: # Parameters are sorted by key, which means they are sorted by part first, then by name.
2990: # Used by assessparms (table mode) for resource level.
2991: #
2992: # @param {hash reference} $name - parameter key -> parameter name
2993: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2994: # @returns {Array<string>}
1.210 www 2995: sub keysinorder {
2996: my ($name,$keyorder)=@_;
2997: return sort {
1.560 damieng 2998: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 2999: } (keys(%{$name}));
1.210 www 3000: }
3001:
1.563 damieng 3002: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3003: # Used by assessparms (table mode) for map and general levels.
3004: #
3005: # @param {hash reference} $name - parameter key -> parameter name
3006: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3007: # @returns {Array<string>}
1.236 albertel 3008: sub keysinorder_bytype {
3009: my ($name,$keyorder)=@_;
3010: return sort {
1.563 damieng 3011: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3012: my $tb=(split('_',$b))[-1];
3013: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3014: return ($a cmp $b);
3015: }
3016: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3017: } (keys(%{$name}));
1.236 albertel 3018: }
3019:
1.563 damieng 3020: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3021: # Used by defaultsetter (parameter settings default actions).
3022: #
3023: # @param {hash reference} $name - hash parameter name -> parameter title
3024: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3025: # @returns {Array<string>}
1.211 www 3026: sub keysindisplayorder {
3027: my ($name,$keyorder)=@_;
3028: return sort {
1.560 damieng 3029: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3030: } (keys(%{$name}));
1.211 www 3031: }
3032:
1.563 damieng 3033: # Prints HTML with a choice to sort results by realm or student first.
3034: # Used by overview mode.
3035: #
3036: # @param {Apache2::RequestRec} $r - the Apache request
3037: # @param {string} $sortorder - realmstudent|studentrealm
1.214 www 3038: sub sortmenu {
3039: my ($r,$sortorder)=@_;
1.236 albertel 3040: $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214 www 3041: if ($sortorder eq 'realmstudent') {
1.422 bisitz 3042: $r->print(' checked="checked"');
1.214 www 3043: }
3044: $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236 albertel 3045: $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214 www 3046: if ($sortorder eq 'studentrealm') {
1.422 bisitz 3047: $r->print(' checked="checked"');
1.214 www 3048: }
1.236 albertel 3049: $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473 amueller 3050: '</label>');
1.214 www 3051: }
3052:
1.563 damieng 3053: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3054: #
3055: # @returns {hash}
1.211 www 3056: sub standardkeyorder {
3057: return ('parameter_0_opendate' => 1,
1.473 amueller 3058: 'parameter_0_duedate' => 2,
3059: 'parameter_0_answerdate' => 3,
3060: 'parameter_0_interval' => 4,
3061: 'parameter_0_weight' => 5,
3062: 'parameter_0_maxtries' => 6,
3063: 'parameter_0_hinttries' => 7,
3064: 'parameter_0_contentopen' => 8,
3065: 'parameter_0_contentclose' => 9,
3066: 'parameter_0_type' => 10,
3067: 'parameter_0_problemstatus' => 11,
3068: 'parameter_0_hiddenresource' => 12,
3069: 'parameter_0_hiddenparts' => 13,
3070: 'parameter_0_display' => 14,
3071: 'parameter_0_ordered' => 15,
3072: 'parameter_0_tol' => 16,
3073: 'parameter_0_sig' => 17,
3074: 'parameter_0_turnoffunit' => 18,
1.521 raeburn 3075: 'parameter_0_discussend' => 19,
3076: 'parameter_0_discusshide' => 20,
3077: 'parameter_0_discussvote' => 21,
1.560 damieng 3078: 'parameter_0_printstartdate' => 22,
3079: 'parameter_0_printenddate' => 23);
1.211 www 3080: }
3081:
1.59 matthew 3082:
1.560 damieng 3083: # Table mode UI.
1.563 damieng 3084: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3085: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3086: #
3087: # Parameters used from the request:
3088: # action - handler action (see handler), usermenu is checking for value 'settable'
3089: # cgroup - selected group
3090: # command - 'set': direct access to table mode for a resource
3091: # csec - selected section
3092: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3093: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3094: # id - student/employee ID
3095: # parmlev - selected level (full|map|general)
3096: # part - selected part (unused ?)
3097: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3098: # pres_type - &&&-separated parameter types
3099: # pres_value - &&&-separated parameter values
3100: # prevvisit - '1' if the user has submitted the form before
3101: # pscat (multiple values) - selected parameter names
1.566 damieng 3102: # pschp - selected map pc, or 'all'
1.563 damieng 3103: # psprt (multiple values) - list of selected parameter parts
3104: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3105: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3106: # symb - resource symb (when a single resource is selected)
3107: # udom - selected user domain
3108: # uname - selected user name
3109: # url - used only with command 'set', the resource url
3110: #
3111: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3112: # @param $parm_permission - ref to hash of permissions
3113: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3114: sub assessparms {
1.1 www 3115:
1.568 raeburn 3116: my ($r,$parm_permission) = @_;
1.201 www 3117:
1.512 foxr 3118:
3119: # -------------------------------------------------------- Variable declaration
1.566 damieng 3120: my @ids=(); # resource and map ids
3121: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3122: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3123: my %typep=(); # hash resource/map id -> resource type (file extension)
3124: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3125: my %uris=(); # hash resource/map id -> resource src
3126: my %maptitles=(); # hash map pc or src -> map title
3127: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3128: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3129: my %alllevs=(); # hash English level title -> value
3130:
3131: my $uname; # selected user name
3132: my $udom; # selected user domain
3133: my $uhome; # server with the user's files, or 'no_host'
3134: my $csec; # selected section name
3135: my $cgroup; # selected group name
3136: my @usersgroups = (); # list of the user groups
1.582 raeburn 3137: my $numreclinks = 0;
1.446 bisitz 3138:
1.190 albertel 3139: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3140:
1.57 albertel 3141: $alllevs{'Resource Level'}='full';
1.215 www 3142: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3143: $alllevs{'Course Level'}='general';
3144:
1.563 damieng 3145: my %allparms; # hash parameter name -> parameter title
3146: my %allparts; # hash parameter part -> part title
1.512 foxr 3147: # ------------------------------------------------------------------------------
3148:
1.210 www 3149: #
3150: # Order in which these parameters will be displayed
3151: #
1.211 www 3152: my %keyorder=&standardkeyorder();
3153:
1.512 foxr 3154: # @ids=();
3155: # %symbp=(); # These seem defined above already.
3156: # %typep=();
1.43 albertel 3157:
3158: my $message='';
3159:
1.190 albertel 3160: $csec=$env{'form.csec'};
1.552 raeburn 3161: if ($env{'request.course.sec'} ne '') {
3162: $csec = $env{'request.course.sec'};
3163: }
3164:
1.553 raeburn 3165: # Check group privs.
1.269 raeburn 3166: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3167: my $noeditgrp;
3168: if ($cgroup ne '') {
3169: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3170: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3171: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3172: $noeditgrp = 1;
3173: }
3174: }
3175: }
1.188 www 3176:
1.190 albertel 3177: if ($udom=$env{'form.udom'}) {
3178: } elsif ($udom=$env{'request.role.domain'}) {
3179: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3180: } else {
1.473 amueller 3181: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3182: }
1.468 amueller 3183:
1.43 albertel 3184:
1.134 albertel 3185: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3186: my $pschp=$env{'form.pschp'};
1.506 www 3187:
3188:
1.134 albertel 3189: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3190: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3191: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3192:
1.43 albertel 3193: my $pssymb='';
1.57 albertel 3194: my $parmlev='';
1.446 bisitz 3195:
1.190 albertel 3196: unless ($env{'form.parmlev'}) {
1.57 albertel 3197: $parmlev = 'map';
3198: } else {
1.190 albertel 3199: $parmlev = $env{'form.parmlev'};
1.57 albertel 3200: }
1.26 www 3201:
1.29 www 3202: # ----------------------------------------------- Was this started from grades?
3203:
1.560 damieng 3204: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3205: (!$env{'form.dis'})) {
1.473 amueller 3206: my $url=$env{'form.url'};
3207: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3208: $pssymb=&Apache::lonnet::symbread($url);
3209: if (!@pscat) { @pscat=('all'); }
3210: $pschp='';
1.57 albertel 3211: $parmlev = 'full';
1.190 albertel 3212: } elsif ($env{'form.symb'}) {
1.473 amueller 3213: $pssymb=$env{'form.symb'};
3214: if (!@pscat) { @pscat=('all'); }
3215: $pschp='';
1.57 albertel 3216: $parmlev = 'full';
1.43 albertel 3217: } else {
1.473 amueller 3218: $env{'form.url'}='';
1.43 albertel 3219: }
3220:
1.190 albertel 3221: my $id=$env{'form.id'};
1.43 albertel 3222: if (($id) && ($udom)) {
1.555 raeburn 3223: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3224: if ($uname) {
3225: $id='';
3226: } else {
3227: $message=
1.540 bisitz 3228: '<p class="LC_warning">'.
3229: &mt('Unknown ID [_1] at domain [_2]',
3230: "'".$id."'","'".$udom."'").
3231: '</p>';
1.473 amueller 3232: }
1.43 albertel 3233: } else {
1.473 amueller 3234: $uname=$env{'form.uname'};
1.43 albertel 3235: }
3236: unless ($udom) { $uname=''; }
3237: $uhome='';
3238: if ($uname) {
1.473 amueller 3239: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3240: if ($uhome eq 'no_host') {
1.473 amueller 3241: $message=
1.540 bisitz 3242: '<p class="LC_warning">'.
3243: &mt('Unknown user [_1] at domain [_2]',
3244: "'".$uname."'","'".$udom."'").
3245: '</p>';
1.473 amueller 3246: $uname='';
1.12 www 3247: } else {
1.473 amueller 3248: $csec=&Apache::lonnet::getsection($udom,$uname,
3249: $env{'request.course.id'});
3250: if ($csec eq '-1') {
1.596 raeburn 3251: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3252: if ($env{'form.userroles'} eq 'any') {
3253: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3254: $csec = $env{'request.course.sec'};
3255: $message = '<span class="LC_info">';
3256: if ($crstype eq 'Community') {
3257: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3258: $uname,$udom);
3259: } else {
3260: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3261: $uname,$udom);
3262: }
3263: $message .= '</span>';
3264: } else {
3265: my @possroles = ('in','ep','ta','cr');
3266: if ($crstype eq 'Community') {
3267: unshift(@possroles,'co');
3268: } else {
3269: unshift(@possroles,'cc');
3270: }
3271: my %not_student_roles =
3272: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3273: \@possroles,[$udom],1,1);
3274: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3275: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3276: my %sections_by_role;
3277: foreach my $role (keys(%not_student_roles)) {
3278: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3279: my ($rolename,$sec) = ($1,$2);
3280: if ($rolename =~ m{^cr/}) {
3281: $rolename = 'cr';
3282: }
3283: push(@{$sections_by_role{$rolename}},$sec);
3284: }
3285: }
3286: my $numroles = scalar(keys(%sections_by_role));
3287: if ($numroles) {
3288: foreach my $role (@possroles) {
3289: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3290: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3291: $csec = $secs[0];
3292: last;
3293: }
3294: }
3295: }
3296: if ($csec eq '-1') {
3297: $message = '<span class="LC_warning">';
3298: if ($crstype eq 'Community') {
3299: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3300: $uname,$udom);
3301: } else {
3302: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3303: $uname,$udom);
3304: }
3305: $message .= '</span>';
3306: $uname='';
3307: if ($env{'request.course.sec'} ne '') {
3308: $csec=$env{'request.course.sec'};
3309: } else {
3310: $csec=$env{'form.csec'};
3311: }
3312: $cgroup=$env{'form.cgroup'};
3313: } else {
3314: $message = '<span class="LC_info">';
3315: if ($crstype eq 'Community') {
3316: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3317: $uname,$udom);
3318: } else {
3319: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3320: $uname,$udom);
3321: }
3322: $message .= '</span>';
3323: }
3324: }
1.594 raeburn 3325: } else {
1.596 raeburn 3326: $message = '<span class="LC_warning">';
3327: if ($crstype eq 'Community') {
3328: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3329: $uname,$udom);
3330: } else {
3331: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3332: $uname,$udom);
3333: }
3334: $message .= '</span>';
3335: $uname='';
3336: if ($env{'request.course.sec'} ne '') {
3337: $csec=$env{'request.course.sec'};
3338: } else {
3339: $csec=$env{'form.csec'};
3340: }
3341: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3342: }
3343: } elsif ($env{'request.course.sec'} ne '') {
3344: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3345: $message='<span class="LC_warning">'.
1.594 raeburn 3346: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3347: $uname,$udom,$env{'request.course.sec'}).
3348: '</span>';
3349: $uname='';
3350: $csec=$env{'request.course.sec'};
3351: }
1.269 raeburn 3352: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3353: }
3354: if ($uname ne '') {
1.473 amueller 3355: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3356: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3357: $message .= "\n<p>\n".&mt('Full Name').': '
3358: .$name{'firstname'}.' '.$name{'middlename'}.' '
3359: .$name{'lastname'}.' '.$name{'generation'}
3360: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3361: @usersgroups = &Apache::lonnet::get_users_groups(
3362: $udom,$uname,$env{'request.course.id'});
3363: if (@usersgroups > 0) {
3364: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3365: $cgroup = $usersgroups[0];
3366: }
3367: } else {
3368: $cgroup = '';
1.297 raeburn 3369: }
1.269 raeburn 3370: }
1.12 www 3371: }
1.43 albertel 3372: }
1.2 www 3373:
1.43 albertel 3374: unless ($csec) { $csec=''; }
1.269 raeburn 3375: unless ($cgroup) { $cgroup=''; }
1.12 www 3376:
1.14 www 3377: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3378: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3379: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 ! raeburn 3380: \%keyorder,undef,$pssymb);
1.63 bowersj2 3381:
1.582 raeburn 3382: %allmaps_inverted = reverse(%allmaps);
3383:
1.57 albertel 3384: $mapp{'0.0'} = '';
3385: $symbp{'0.0'} = '';
1.99 albertel 3386:
1.14 www 3387: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3388: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3389: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3390: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3391: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3392: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3393: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3394: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3395: my ($got_chostname,$chostname,$cmajor,$cminor);
3396: my $totalstored = 0;
1.546 raeburn 3397: my $now = time;
1.473 amueller 3398: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3399: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3400: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3401: next if ($csec ne $env{'request.course.sec'});
3402: }
1.556 raeburn 3403: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3404: next if ($noeditgrp);
1.557 raeburn 3405: }
3406: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3407: $namematch = 'maplevelrecurse';
3408: }
1.556 raeburn 3409: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3410: my (@ok_slots,@fail_slots,@del_slots);
3411: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3412: my ($level,@all) =
3413: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3414: $csec,$cgroup,$courseopt);
3415: foreach my $slot_name (split(/:/,$values[$i])) {
3416: next if ($slot_name eq '');
3417: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3418: push(@ok_slots,$slot_name);
3419:
3420: } else {
3421: push(@fail_slots,$slot_name);
3422: }
3423: }
3424: if (@ok_slots) {
3425: $values[$i] = join(':',@ok_slots);
3426: } else {
3427: $values[$i] = '';
3428: }
3429: if ($all[$level] ne '') {
3430: my @existing = split(/:/,$all[$level]);
3431: foreach my $slot_name (@existing) {
3432: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3433: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3434: push(@del_slots,$slot_name);
3435: }
3436: }
3437: }
3438: }
1.554 raeburn 3439: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3440: $name = $1;
1.533 raeburn 3441: my $val = $values[$i];
1.549 raeburn 3442: my $valmatch = '';
1.533 raeburn 3443: if ($name eq 'examcode') {
1.544 raeburn 3444: if (&Apache::lonnet::validCODE($values[$i])) {
3445: $val = 'valid';
3446: }
1.546 raeburn 3447: } elsif ($name eq 'printstartdate') {
3448: if ($val =~ /^\d+$/) {
3449: if ($val > $now) {
3450: $val = 'future';
3451: }
3452: }
3453: } elsif ($name eq 'printenddate') {
3454: if ($val =~ /^\d+$/) {
3455: if ($val < $now) {
3456: $val = 'past';
3457: }
3458: }
1.549 raeburn 3459: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3460: my $stringtype = &get_stringtype($name);
3461: my $stringmatch = &standard_string_matches($stringtype);
3462: if (ref($stringmatch) eq 'ARRAY') {
3463: foreach my $item (@{$stringmatch}) {
3464: if (ref($item) eq 'ARRAY') {
3465: my ($regexpname,$pattern) = @{$item};
3466: if ($pattern ne '') {
3467: if ($val =~ /$pattern/) {
3468: $valmatch = $regexpname;
3469: $val = '';
3470: last;
3471: }
3472: }
3473: }
3474: }
3475: }
1.554 raeburn 3476: } elsif ($name eq 'interval') {
3477: my $intervaltype = &get_intervaltype($name);
3478: my $intervalmatch = &standard_interval_matches($intervaltype);
3479: if (ref($intervalmatch) eq 'ARRAY') {
3480: foreach my $item (@{$intervalmatch}) {
3481: if (ref($item) eq 'ARRAY') {
3482: my ($regexpname,$pattern) = @{$item};
3483: if ($pattern ne '') {
3484: if ($val =~ /$pattern/) {
3485: $valmatch = $regexpname;
3486: $val = '';
3487: last;
3488: }
3489: }
3490: }
3491: }
3492: }
1.533 raeburn 3493: }
1.504 raeburn 3494: $needsrelease =
1.557 raeburn 3495: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3496: if ($needsrelease) {
1.505 raeburn 3497: unless ($got_chostname) {
1.514 raeburn 3498: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3499: $got_chostname = 1;
1.546 raeburn 3500: }
1.557 raeburn 3501: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3502: $needsrelease,
3503: $cmajor,$cminor);
1.500 raeburn 3504: }
1.437 raeburn 3505: }
1.504 raeburn 3506: if ($needsnewer) {
1.557 raeburn 3507: undef($namematch);
3508: } else {
3509: my $currneeded;
3510: if ($needsrelease) {
3511: $currneeded = $needsrelease;
3512: }
3513: if ($namematch) {
3514: $needsrelease =
3515: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3516: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3517: unless ($got_chostname) {
3518: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3519: $got_chostname = 1;
3520: }
3521: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3522: $needsrelease,
3523: $cmajor,$cminor);
3524: } else {
3525: undef($namematch);
3526: }
3527: }
3528: }
3529: if ($needsnewer) {
3530: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3531: $cminor,$needsrelease);
3532: } else {
3533: $message.=&storeparm(split(/\&/,$markers[$i]),
3534: $values[$i],
3535: $types[$i],
3536: $uname,$udom,$csec,$cgroup);
3537: $totalstored ++;
3538: }
1.473 amueller 3539: }
1.68 www 3540: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3541: if ($totalstored) {
3542: $message.='<p class="LC_warning">'
3543: .&mt('Changes can take up to 10 minutes before being active for all students.')
3544: .&Apache::loncommon::help_open_topic('Caching')
3545: .'</p>';
3546: }
1.68 www 3547: }
1.584 raeburn 3548:
1.57 albertel 3549: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3550: if ($pscat[0] eq "all") {
3551: @pscat = (keys(%allparms));
3552: }
3553: if (!@pscat) {
3554: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3555: };
3556: if ($psprt[0] eq "all" || !@psprt) {
3557: @psprt = (keys(%allparts));
3558: }
1.2 www 3559: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3560:
1.531 raeburn 3561: my $crstype = &Apache::loncommon::course_type();
3562: &startpage($r,$pssymb,$crstype);
1.57 albertel 3563:
1.548 raeburn 3564: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3565: 'date_interval','int','float','string','string_lenient',
3566: 'string_examcode','string_deeplink','string_discussvote',
3567: 'string_useslots','string_problemstatus','string_ip',
3568: 'string_questiontype') {
1.473 amueller 3569: $r->print('<input type="hidden" value="'.
1.563 damieng 3570: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3571: '" name="recent_'.$item.'" />');
1.44 albertel 3572: }
1.446 bisitz 3573:
1.459 bisitz 3574: # ----- Start Parameter Selection
3575:
3576: # Hide parm selection?
3577: $r->print(<<ENDPARMSELSCRIPT);
3578: <script type="text/javascript">
3579: // <![CDATA[
3580: function parmsel_show() {
1.562 damieng 3581: document.getElementById('parmsel').style.display = "";
3582: document.getElementById('parmsellink').style.display = "none";
1.459 bisitz 3583: }
3584: // ]]>
3585: </script>
3586: ENDPARMSELSCRIPT
1.474 amueller 3587:
1.445 neumanie 3588: if (!$pssymb) {
1.563 damieng 3589: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3590: my $parmselhiddenstyle=' style="display:none"';
3591: if($env{'form.hideparmsel'} eq 'hidden') {
3592: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3593: } else {
3594: $r->print('<div id="parmsel">');
3595: }
3596:
1.491 bisitz 3597: # Step 1
1.523 raeburn 3598: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3599: $r->print('
1.474 amueller 3600: <script type="text/javascript">
1.523 raeburn 3601: // <![CDATA['.
3602: &showhide_js().'
1.474 amueller 3603: // ]]>
3604: </script>
1.523 raeburn 3605: ');
3606: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3607: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3608: $r->print(&Apache::lonhtmlcommon::row_closure());
1.474 amueller 3609: &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491 bisitz 3610: $r->print(&Apache::lonhtmlcommon::row_closure());
3611: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3612: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3613: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3614: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3615:
3616: # Step 2
1.523 raeburn 3617: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3618: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3619:
3620: # Step 3
1.523 raeburn 3621: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3622: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3623: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3624: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3625: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3626:
3627: # Update Display Button
1.486 www 3628: $r->print('<p>'
3629: .'<input type="submit" name="dis"'
1.511 www 3630: .' value="'.&mt('Update Display').'" />'
1.486 www 3631: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3632: .'</p>');
3633: $r->print('</div>');
1.491 bisitz 3634:
1.486 www 3635: # Offer link to display parameter selection again
3636: $r->print('<p id="parmsellink"');
3637: if ($env{'form.hideparmsel'} ne 'hidden') {
3638: $r->print($parmselhiddenstyle);
3639: }
3640: $r->print('>'
3641: .'<a href="javascript:parmsel_show()">'
3642: .&mt('Change Parameter Selection')
3643: .'</a>'
3644: .'</p>');
1.44 albertel 3645: } else {
1.478 amueller 3646: # parameter screen for a single resource.
1.486 www 3647: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3648: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3649: $r->print(&mt('Specific Resource: [_1] ([_2])',
3650: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3651: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 3652: '<br />');
3653: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
3654: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3655: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3656: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3657: $r->print(&Apache::lonhtmlcommon::end_pick_box());
3658: $r->print('<p>'
1.459 bisitz 3659: .'<input type="submit" name="dis"'
1.511 www 3660: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 3661: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 3662: .'</p>');
1.459 bisitz 3663: }
1.478 amueller 3664:
1.486 www 3665: # ----- End Parameter Selection
1.57 albertel 3666:
1.459 bisitz 3667: # Display Messages
3668: $r->print('<div>'.$message.'</div>');
1.210 www 3669:
1.57 albertel 3670:
3671: my @temp_pscat;
3672: map {
3673: my $cat = $_;
3674: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
3675: } @pscat;
3676:
3677: @pscat = @temp_pscat;
3678:
1.548 raeburn 3679:
1.209 www 3680: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 3681: # ----------------------------------------------------------------- Start Table
1.57 albertel 3682: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 3683: my $csuname=$env{'user.name'};
3684: my $csudom=$env{'user.domain'};
1.568 raeburn 3685: my $readonly = 1;
3686: if ($parm_permission->{'edit'}) {
3687: undef($readonly);
3688: }
1.57 albertel 3689:
1.203 www 3690: if ($parmlev eq 'full') {
1.506 www 3691: #
3692: # This produces the cascading table output of parameters
3693: #
1.578 raeburn 3694: my $coursespan=$csec?8:5;
3695: my $userspan=3;
1.560 damieng 3696: if ($cgroup ne '') {
1.578 raeburn 3697: $coursespan += 3;
1.560 damieng 3698: }
1.473 amueller 3699:
1.560 damieng 3700: $r->print(&Apache::loncommon::start_data_table());
3701: #
3702: # This produces the headers
3703: #
3704: $r->print('<tr><td colspan="5"></td>');
3705: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
3706: if ($uname) {
1.473 amueller 3707: if (@usersgroups > 1) {
1.560 damieng 3708: $userspan ++;
3709: }
3710: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
3711: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
3712: }
3713: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 3714: 'pie' => "Parameter in Effect",
3715: 'csv' => "Current Session Value",
1.472 amueller 3716: 'rl' => "Resource Level",
1.473 amueller 3717: 'ic' => 'in Course',
3718: 'aut' => "Assessment URL and Title",
3719: 'type' => 'Type',
3720: 'emof' => "Enclosing Map or Folder",
3721: 'part' => 'Part',
1.472 amueller 3722: 'pn' => 'Parameter Name',
1.473 amueller 3723: 'def' => 'default',
3724: 'femof' => 'from Enclosing Map or Folder',
3725: 'gen' => 'general',
3726: 'foremf' => 'for Enclosing Map or Folder',
3727: 'fr' => 'for Resource'
3728: );
1.560 damieng 3729: $r->print(<<ENDTABLETWO);
1.419 bisitz 3730: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 3731: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 3732: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 3733: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 3734:
1.10 www 3735: ENDTABLETWO
1.560 damieng 3736: if ($csec) {
1.578 raeburn 3737: $r->print('<th colspan="3">'.
1.560 damieng 3738: &mt("in Section")." $csec</th>");
3739: }
3740: if ($cgroup) {
1.578 raeburn 3741: $r->print('<th colspan="3">'.
1.472 amueller 3742: &mt("in Group")." $cgroup</th>");
1.560 damieng 3743: }
3744: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 3745: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
3746: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 3747: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 3748: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 3749: ENDTABLEHEADFOUR
1.57 albertel 3750:
1.560 damieng 3751: if ($csec) {
1.578 raeburn 3752: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3753: }
1.473 amueller 3754:
1.560 damieng 3755: if ($cgroup) {
1.578 raeburn 3756: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3757: }
3758:
3759: if ($uname) {
3760: if (@usersgroups > 1) {
3761: $r->print('<th>'.&mt('Control by other group?').'</th>');
3762: }
1.578 raeburn 3763: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3764: }
3765:
3766: $r->print('</tr>');
1.506 www 3767: #
3768: # Done with the headers
3769: #
1.560 damieng 3770: my $defbgone='';
3771: my $defbgtwo='';
3772: my $defbgthree = '';
1.57 albertel 3773:
1.560 damieng 3774: foreach my $rid (@ids) {
1.57 albertel 3775:
3776: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 3777: if ((!$pssymb &&
1.560 damieng 3778: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
3779: ||
3780: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 3781: # ------------------------------------------------------ Entry for one resource
1.473 amueller 3782: if ($defbgone eq '#E0E099') {
3783: $defbgone='#E0E0DD';
1.57 albertel 3784: } else {
1.419 bisitz 3785: $defbgone='#E0E099';
1.57 albertel 3786: }
1.419 bisitz 3787: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 3788: $defbgtwo='#FFFFDD';
1.57 albertel 3789: } else {
1.473 amueller 3790: $defbgtwo='#FFFF99';
1.57 albertel 3791: }
1.419 bisitz 3792: if ($defbgthree eq '#FFBB99') {
3793: $defbgthree='#FFBBDD';
1.269 raeburn 3794: } else {
1.419 bisitz 3795: $defbgthree='#FFBB99';
1.269 raeburn 3796: }
3797:
1.57 albertel 3798: my $thistitle='';
3799: my %name= ();
3800: undef %name;
3801: my %part= ();
3802: my %display=();
3803: my %type= ();
3804: my %default=();
1.196 www 3805: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3806: my $toolsymb;
3807: if ($uri =~ /ext\.tool$/) {
3808: $toolsymb = $symbp{$rid};
3809: }
1.57 albertel 3810:
1.506 www 3811: my $filter=$env{'form.filter'};
1.548 raeburn 3812: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 3813: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 3814: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 3815: # We may only want certain parameters listed
3816: if ($filter) {
3817: unless ($filter=~/\Q$parmname\E/) { next; }
3818: }
3819: $name{$tempkeyp}=$parmname;
1.584 raeburn 3820: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 3821:
1.584 raeburn 3822: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 3823: if ($allparms{$name{$tempkeyp}} ne '') {
3824: my $identifier;
3825: if ($parmdis =~ /(\s*\[Part.*)$/) {
3826: $identifier = $1;
3827: }
3828: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3829: } else {
3830: $display{$tempkeyp} = $parmdis;
3831: }
3832: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3833: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 3834: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
3835: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
3836: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 3837: }
3838: }
1.548 raeburn 3839: my $totalparms=scalar(keys(%name));
1.57 albertel 3840: if ($totalparms>0) {
1.560 damieng 3841: my $firstrow=1;
1.473 amueller 3842: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 3843: my $navmap = Apache::lonnavmaps::navmap->new();
3844: my @recurseup;
3845: if (ref($navmap) && $mapp{$rid}) {
3846: @recurseup = $navmap->recurseup_maps($mapp{$rid});
3847: }
1.419 bisitz 3848: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 3849: ' rowspan='.$totalparms.
1.419 bisitz 3850: '><tt><font size="-1">'.
1.57 albertel 3851: join(' / ',split(/\//,$uri)).
3852: '</font></tt><p><b>'.
1.154 albertel 3853: "<a href=\"javascript:openWindow('".
1.473 amueller 3854: &Apache::lonnet::clutter($uri).'?symb='.
3855: &escape($symbp{$rid}).
1.336 albertel 3856: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
3857: " target=\"_self\">$title");
1.57 albertel 3858:
3859: if ($thistitle) {
1.473 amueller 3860: $r->print(' ('.$thistitle.')');
1.57 albertel 3861: }
3862: $r->print('</a></b></td>');
1.419 bisitz 3863: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 3864: ' rowspan='.$totalparms.'>'.$typep{$rid}.
3865: '</td>');
3866:
1.419 bisitz 3867: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 3868: ' rowspan='.$totalparms.
1.238 www 3869: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 3870: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 3871: unless ($firstrow) {
3872: $r->print('<tr>');
3873: } else {
3874: undef $firstrow;
3875: }
1.548 raeburn 3876: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 3877: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 3878: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 3879: $cgroup,\@usersgroups,$noeditgrp,$readonly,
3880: \@recurseup,\%maptitles,\%allmaps_inverted,
3881: \$numreclinks);
1.57 albertel 3882: }
3883: }
3884: }
3885: } # end foreach ids
1.43 albertel 3886: # -------------------------------------------------- End entry for one resource
1.517 www 3887: $r->print(&Apache::loncommon::end_data_table);
1.203 www 3888: } # end of full
1.57 albertel 3889: #--------------------------------------------------- Entry for parm level map
3890: if ($parmlev eq 'map') {
1.419 bisitz 3891: my $defbgone = '#E0E099';
3892: my $defbgtwo = '#FFFF99';
3893: my $defbgthree = '#FFBB99';
1.57 albertel 3894:
3895: my %maplist;
3896:
3897: if ($pschp eq 'all') {
1.446 bisitz 3898: %maplist = %allmaps;
1.57 albertel 3899: } else {
3900: %maplist = ($pschp => $mapp{$pschp});
3901: }
3902:
3903: #-------------------------------------------- for each map, gather information
3904: my $mapid;
1.560 damieng 3905: foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {
1.60 albertel 3906: my $maptitle = $maplist{$mapid};
1.57 albertel 3907:
3908: #----------------------- loop through ids and get all parameter types for map
3909: #----------------------------------------- and associated information
3910: my %name = ();
3911: my %part = ();
3912: my %display = ();
3913: my %type = ();
3914: my %default = ();
3915: my $map = 0;
3916:
1.473 amueller 3917: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 3918:
1.548 raeburn 3919: foreach my $id (@ids) {
3920: ($map)=($id =~ /([\d]*?)\./);
3921: my $rid = $id;
1.446 bisitz 3922:
1.57 albertel 3923: # $r->print("$mapid:$map: $rid <br /> \n");
3924:
1.560 damieng 3925: if ($map eq $mapid) {
1.473 amueller 3926: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3927: my $toolsymb;
3928: if ($uri =~ /ext\.tool$/) {
3929: $toolsymb = $symbp{$rid};
3930: }
1.582 raeburn 3931:
1.57 albertel 3932: # $r->print("Keys: $keyp{$rid} <br />\n");
3933:
3934: #--------------------------------------------------------------------
3935: # @catmarker contains list of all possible parameters including part #s
3936: # $fullkeyp contains the full part/id # for the extraction of proper parameters
3937: # $tempkeyp contains part 0 only (no ids - ie, subparts)
3938: # When storing information, store as part 0
3939: # When requesting information, request from full part
3940: #-------------------------------------------------------------------
1.548 raeburn 3941: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
3942: my $tempkeyp = $fullkeyp;
3943: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 3944:
1.548 raeburn 3945: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 3946: $part{$tempkeyp}="0";
1.584 raeburn 3947: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
3948: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 3949: if ($allparms{$name{$tempkeyp}} ne '') {
3950: my $identifier;
3951: if ($parmdis =~ /(\s*\[Part.*)$/) {
3952: $identifier = $1;
3953: }
3954: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3955: } else {
3956: $display{$tempkeyp} = $parmdis;
3957: }
3958: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3959: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
3960: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 3961: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
3962: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 3963: }
3964: } # end loop through keys
1.560 damieng 3965: }
1.57 albertel 3966: } # end loop through ids
1.446 bisitz 3967:
1.57 albertel 3968: #---------------------------------------------------- print header information
1.133 www 3969: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 3970: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 3971: my $tmp="";
1.57 albertel 3972: if ($uname) {
1.473 amueller 3973: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 3974: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
3975: &mt('in')." \n";
1.57 albertel 3976: } else {
1.401 bisitz 3977: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 3978: }
1.269 raeburn 3979: if ($cgroup) {
1.401 bisitz 3980: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
3981: "</i></font> ".&mt('of')." \n";
1.269 raeburn 3982: $csec = '';
3983: } elsif ($csec) {
1.401 bisitz 3984: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
3985: "</i></font> ".&mt('of')." \n";
1.269 raeburn 3986: }
1.401 bisitz 3987: $r->print('<div align="center"><h4>'
3988: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 3989: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 3990: ,$tmp
3991: ,'<font color="red"><i>'.$coursename.'</i></font>'
3992: )
3993: ."<br /></h4>\n"
1.422 bisitz 3994: );
1.57 albertel 3995: #---------------------------------------------------------------- print table
1.419 bisitz 3996: $r->print('<p>'.&Apache::loncommon::start_data_table()
3997: .&Apache::loncommon::start_data_table_header_row()
3998: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 3999: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4000: .'<th>'.&mt('Parameter in Effect').'</th>'
4001: .&Apache::loncommon::end_data_table_header_row()
4002: );
1.57 albertel 4003:
1.582 raeburn 4004: my $navmap = Apache::lonnavmaps::navmap->new();
4005: my @recurseup;
4006: if (ref($navmap)) {
4007: my $mapres = $navmap->getByMapPc($mapid);
4008: if (ref($mapres)) {
4009: @recurseup = $navmap->recurseup_maps($mapres->src());
4010: }
4011: }
4012:
4013:
1.548 raeburn 4014: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4015: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4016: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4017: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4018: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4019: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4020: \$numreclinks);
1.57 albertel 4021: }
1.422 bisitz 4022: $r->print(&Apache::loncommon::end_data_table().'</p>'
4023: .'</div>'
4024: );
1.57 albertel 4025: } # end each map
4026: } # end of $parmlev eq map
4027: #--------------------------------- Entry for parm level general (Course level)
4028: if ($parmlev eq 'general') {
1.473 amueller 4029: my $defbgone = '#E0E099';
1.419 bisitz 4030: my $defbgtwo = '#FFFF99';
4031: my $defbgthree = '#FFBB99';
1.57 albertel 4032:
4033: #-------------------------------------------- for each map, gather information
4034: my $mapid="0.0";
4035: #----------------------- loop through ids and get all parameter types for map
4036: #----------------------------------------- and associated information
4037: my %name = ();
4038: my %part = ();
4039: my %display = ();
4040: my %type = ();
4041: my %default = ();
1.446 bisitz 4042:
1.548 raeburn 4043: foreach $id (@ids) {
4044: my $rid = $id;
1.446 bisitz 4045:
1.196 www 4046: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4047: my $toolsymb;
4048: if ($uri =~ /ext\.tool$/) {
4049: $toolsymb = $symbp{$rid};
4050: }
1.57 albertel 4051:
4052: #--------------------------------------------------------------------
4053: # @catmarker contains list of all possible parameters including part #s
4054: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4055: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4056: # When storing information, store as part 0
4057: # When requesting information, request from full part
4058: #-------------------------------------------------------------------
1.548 raeburn 4059: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4060: my $tempkeyp = $fullkeyp;
4061: $tempkeyp =~ s/_\w+_/_0_/;
4062: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4063: $part{$tempkeyp}="0";
1.584 raeburn 4064: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4065: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4066: if ($allparms{$name{$tempkeyp}} ne '') {
4067: my $identifier;
4068: if ($parmdis =~ /(\s*\[Part.*)$/) {
4069: $identifier = $1;
4070: }
4071: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4072: } else {
4073: $display{$tempkeyp} = $parmdis;
4074: }
4075: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4076: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4077: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4078: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4079: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4080: }
1.57 albertel 4081: } # end loop through keys
4082: } # end loop through ids
1.446 bisitz 4083:
1.57 albertel 4084: #---------------------------------------------------- print header information
1.473 amueller 4085: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4086: $r->print(<<ENDMAPONE);
1.419 bisitz 4087: <center>
4088: <h4>$setdef
1.135 albertel 4089: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4090: ENDMAPONE
4091: if ($uname) {
1.473 amueller 4092: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4093: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4094: } else {
1.135 albertel 4095: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4096: }
1.446 bisitz 4097:
1.135 albertel 4098: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4099: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4100: $r->print("</h4>\n");
1.57 albertel 4101: #---------------------------------------------------------------- print table
1.419 bisitz 4102: $r->print('<p>'.&Apache::loncommon::start_data_table()
4103: .&Apache::loncommon::start_data_table_header_row()
4104: .'<th>'.&mt('Parameter Name').'</th>'
4105: .'<th>'.&mt('Default Value').'</th>'
4106: .'<th>'.&mt('Parameter in Effect').'</th>'
4107: .&Apache::loncommon::end_data_table_header_row()
4108: );
1.57 albertel 4109:
1.548 raeburn 4110: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4111: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4112: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4113: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4114: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4115: $readonly);
1.57 albertel 4116: }
1.419 bisitz 4117: $r->print(&Apache::loncommon::end_data_table()
4118: .'</p>'
4119: .'</center>'
4120: );
1.57 albertel 4121: } # end of $parmlev eq general
1.43 albertel 4122: }
1.507 www 4123: $r->print('</form>');
1.582 raeburn 4124: if ($numreclinks) {
4125: $r->print(<<"END");
4126: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4127: <input type="hidden" name="pschp" />
4128: <input type="hidden" name="pscat" />
4129: <input type="hidden" name="psprt" />
4130: <input type="hidden" name="hideparmsel" value="hidden" />
4131: </form>
4132: <script type="text/javascript">
4133: function pjumprec(rid,name,part) {
4134: document.forms.recurseform.pschp.value = rid;
4135: document.forms.recurseform.pscat.value = name;
4136: document.forms.recurseform.psprt.value = part;
4137: document.forms.recurseform.submit();
4138: return false;
4139: }
4140: </script>
4141: END
4142: }
1.507 www 4143: &endSettingsScreen($r);
4144: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4145: } # end sub assessparms
1.30 www 4146:
1.560 damieng 4147:
4148:
1.120 www 4149: ##################################################
1.560 damieng 4150: # OVERVIEW MODE
1.207 www 4151: ##################################################
1.124 www 4152:
1.563 damieng 4153: my $tableopen; # boolean, true if HTML table is already opened
4154:
4155: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4156: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4157: # @returns {string}
1.124 www 4158: sub tablestart {
1.576 raeburn 4159: my ($readonly,$is_map) = @_;
1.124 www 4160: if ($tableopen) {
1.552 raeburn 4161: return '';
1.124 www 4162: } else {
1.552 raeburn 4163: $tableopen=1;
4164: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4165: if ($readonly) {
4166: $output .= '<th>'.&mt('Current value').'</th>';
4167: } else {
1.576 raeburn 4168: $output .= '<th>'.&mt('Delete').'</th>'.
4169: '<th>'.&mt('Set to ...').'</th>';
4170: if ($is_map) {
4171: $output .= '<th>'.&mt('Recursive?').'</th>';
4172: }
1.552 raeburn 4173: }
4174: $output .= '</tr>';
4175: return $output;
1.124 www 4176: }
4177: }
4178:
1.563 damieng 4179: # Returns HTML with the HTML table end tag, unless the table is not opened.
4180: # @returns {string}
1.124 www 4181: sub tableend {
4182: if ($tableopen) {
1.560 damieng 4183: $tableopen=0;
4184: return &Apache::loncommon::end_data_table();
1.124 www 4185: } else {
1.560 damieng 4186: return'';
1.124 www 4187: }
4188: }
4189:
1.563 damieng 4190: # Reads course and user information.
4191: # 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).
4192: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4193: # If the context is looking for a list, returns a list with the scalar data and the class list.
4194: # @param {string} $crs - course number
4195: # @param {string} $dom - course domain
4196: # @returns {hash reference|Array}
1.207 www 4197: sub readdata {
4198: my ($crs,$dom)=@_;
4199: # Read coursedata
4200: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4201: # Read userdata
4202:
4203: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4204: foreach my $user (keys(%$classlist)) {
4205: if ($user=~/^($match_username)\:($match_domain)$/) {
4206: my ($tuname,$tudom)=($1,$2);
4207: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4208: foreach my $userkey (keys(%{$useropt})) {
4209: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4210: my $newkey=$userkey;
1.548 raeburn 4211: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4212: $$resourcedata{$newkey}=$$useropt{$userkey};
4213: }
4214: }
1.473 amueller 4215: }
4216: }
1.552 raeburn 4217: if (wantarray) {
4218: return ($resourcedata,$classlist);
4219: } else {
4220: return $resourcedata;
4221: }
1.207 www 4222: }
4223:
4224:
1.563 damieng 4225: # Stores parameter data, using form parameters directly.
4226: #
4227: # 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 4228: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563 damieng 4229: # del_* - remove a parameter
4230: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4231: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4232: # key_* - date values
4233: # days_* - for date intervals
4234: # hours_* - for date intervals
4235: # minutes_* - for date intervals
4236: # seconds_* - for date intervals
4237: # done_* - for date intervals
4238: # typeof_* - parameter type
4239: #
4240: # @param {Apache2::RequestRec} $r - the Apache request
4241: # @param {string} $crs - course number
4242: # @param {string} $dom - course domain
1.208 www 4243: sub storedata {
4244: my ($r,$crs,$dom)=@_;
1.207 www 4245: # Set userlevel immediately
4246: # Do an intermediate store of course level
4247: my $olddata=&readdata($crs,$dom);
1.124 www 4248: my %newdata=();
4249: undef %newdata;
4250: my @deldata=();
1.576 raeburn 4251: my @delrec=();
4252: my @delnonrec=();
1.124 www 4253: undef @deldata;
1.504 raeburn 4254: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4255: my $now = time;
1.560 damieng 4256: foreach my $key (keys(%env)) {
4257: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4258: my $cmd=$1;
4259: my $thiskey=$2;
1.576 raeburn 4260: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588 raeburn 4261: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576 raeburn 4262: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4263: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4264: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4265: $altkey = $thiskey;
4266: $altkey =~ s/\Q___(all)\E/___(rec)/;
4267: if ($env{'form.rec_'.$thiskey}) {
4268: $recursive = 1;
4269: }
4270: }
4271: }
1.560 damieng 4272: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4273: if ($tuname) {
1.576 raeburn 4274: $tkey=$thiskey;
1.560 damieng 4275: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4276: if ($altkey) {
4277: $tkeynonrec = $tkey;
4278: $tkeyrec = $altkey;
4279: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4280: }
1.560 damieng 4281: }
4282: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4283: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4284: if ($cmd eq 'set') {
4285: $data=$env{$key};
4286: $valmatch = '';
4287: $valchk = $data;
4288: $typeof=$env{'form.typeof_'.$thiskey};
4289: $text = &mt('Saved modified parameter for');
4290: if ($typeof eq 'string_questiontype') {
4291: $name = 'type';
1.588 raeburn 4292: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4293: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4294: my $stringmatch = &standard_string_matches($typeof);
4295: if (ref($stringmatch) eq 'ARRAY') {
4296: foreach my $item (@{$stringmatch}) {
4297: if (ref($item) eq 'ARRAY') {
4298: my ($regexpname,$pattern) = @{$item};
4299: if ($pattern ne '') {
4300: if ($data =~ /$pattern/) {
4301: $valmatch = $regexpname;
4302: $valchk = '';
4303: last;
4304: }
1.560 damieng 4305: }
1.549 raeburn 4306: }
4307: }
4308: }
1.563 damieng 4309: } elsif ($typeof eq 'string_discussvote') {
4310: $name = 'discussvote';
4311: } elsif ($typeof eq 'string_examcode') {
4312: $name = 'examcode';
4313: if (&Apache::lonnet::validCODE($data)) {
4314: $valchk = 'valid';
4315: }
4316: } elsif ($typeof eq 'string_yesno') {
4317: if ($thiskey =~ /\.retrypartial$/) {
4318: $name = 'retrypartial';
4319: }
1.549 raeburn 4320: }
1.563 damieng 4321: } elsif ($cmd eq 'datepointer') {
4322: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4323: $typeof=$env{'form.typeof_'.$thiskey};
4324: $text = &mt('Saved modified date for');
4325: if ($typeof eq 'date_start') {
4326: if ($thiskey =~ /\.printstartdate$/) {
4327: $name = 'printstartdate';
4328: if (($data) && ($data > $now)) {
4329: $valchk = 'future';
4330: }
1.560 damieng 4331: }
1.563 damieng 4332: } elsif ($typeof eq 'date_end') {
4333: if ($thiskey =~ /\.printenddate$/) {
4334: $name = 'printenddate';
4335: if (($data) && ($data < $now)) {
4336: $valchk = 'past';
4337: }
1.560 damieng 4338: }
1.504 raeburn 4339: }
1.563 damieng 4340: } elsif ($cmd eq 'dateinterval') {
4341: $data=&get_date_interval_from_form($thiskey);
4342: if ($thiskey =~ /\.interval$/) {
4343: $name = 'interval';
4344: my $intervaltype = &get_intervaltype($name);
4345: my $intervalmatch = &standard_interval_matches($intervaltype);
4346: if (ref($intervalmatch) eq 'ARRAY') {
4347: foreach my $item (@{$intervalmatch}) {
4348: if (ref($item) eq 'ARRAY') {
4349: my ($regexpname,$pattern) = @{$item};
4350: if ($pattern ne '') {
4351: if ($data =~ /$pattern/) {
4352: $valmatch = $regexpname;
4353: $valchk = '';
4354: last;
4355: }
1.560 damieng 4356: }
1.554 raeburn 4357: }
4358: }
4359: }
4360: }
1.563 damieng 4361: $typeof=$env{'form.typeof_'.$thiskey};
4362: $text = &mt('Saved modified date for');
1.554 raeburn 4363: }
1.576 raeburn 4364: if ($recursive) {
1.563 damieng 4365: $namematch = 'maplevelrecurse';
1.560 damieng 4366: }
1.563 damieng 4367: if (($name ne '') || ($namematch ne '')) {
4368: my ($needsrelease,$needsnewer);
4369: if ($name ne '') {
4370: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4371: if ($needsrelease) {
4372: unless ($got_chostname) {
1.563 damieng 4373: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4374: $got_chostname = 1;
4375: }
1.563 damieng 4376: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4377: $needsrelease,
4378: $cmajor,$cminor);
4379: }
4380: }
4381: if ($namematch ne '') {
4382: if ($needsnewer) {
4383: undef($namematch);
1.560 damieng 4384: } else {
1.563 damieng 4385: my $currneeded;
4386: if ($needsrelease) {
4387: $currneeded = $needsrelease;
4388: }
4389: $needsrelease =
4390: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4391: if (($needsrelease) &&
4392: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4393: unless ($got_chostname) {
4394: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4395: $got_chostname = 1;
4396: }
4397: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4398: $namematch, $needsrelease,$cmajor,$cminor);
4399: } else {
4400: undef($namematch);
4401: }
1.560 damieng 4402: }
1.557 raeburn 4403: }
1.563 damieng 4404: if ($needsnewer) {
4405: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4406: $chostname,$cmajor,
4407: $cminor,$needsrelease));
4408: next;
4409: }
1.504 raeburn 4410: }
1.576 raeburn 4411: my ($reconlychg,$haschange,$storekey);
4412: if ($tuname) {
4413: my $ustorekey;
4414: if ($altkey) {
4415: if ($recursive) {
4416: if (exists($$olddata{$thiskey})) {
4417: if ($$olddata{$thiskey} eq $data) {
4418: $reconlychg = 1;
4419: }
4420: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4421: }
4422: if (exists($$olddata{$altkey})) {
4423: if (defined($data) && $$olddata{$altkey} ne $data) {
4424: $haschange = 1;
4425: }
4426: } elsif ((!$reconlychg) && ($data ne '')) {
4427: $haschange = 1;
4428: }
4429: $ustorekey = $tkeyrec;
4430: } else {
4431: if (exists($$olddata{$altkey})) {
4432: if ($$olddata{$altkey} eq $data) {
4433: $reconlychg = 1;
4434: }
4435: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4436: }
4437: if (exists($$olddata{$thiskey})) {
4438: if (defined($data) && $$olddata{$thiskey} ne $data) {
4439: $haschange = 1;
4440: }
4441: } elsif ((!$reconlychg) && ($data ne '')) {
4442: $haschange = 1;
4443: }
4444: $ustorekey = $tkeynonrec;
4445: }
4446: } else {
4447: if (exists($$olddata{$tkey})) {
4448: if (defined($data) && $$olddata{$tkey} ne $data) {
4449: $haschange = 1;
4450: }
4451: $ustorekey = $tkey;
4452: }
4453: }
4454: if ($haschange || $reconlychg) {
4455: unless ($env{'form.del_'.$thiskey}) {
4456: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4457: $ustorekey.'.type' => $typeof},
4458: $tudom,$tuname) eq 'ok') {
4459: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4460: $r->print('<br />'.$text.' '.
4461: &Apache::loncommon::plainname($tuname,$tudom));
4462: } else {
4463: $r->print('<div class="LC_error">'.
4464: &mt('Error saving parameters').'</div>');
4465: }
4466: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4467: }
4468: }
4469: } else {
4470: if ($altkey) {
4471: if ($recursive) {
4472: if (exists($$olddata{$thiskey})) {
4473: if ($$olddata{$thiskey} eq $data) {
4474: $reconlychg = 1;
4475: }
4476: push(@delnonrec,($thiskey,$thiskey.'.type'));
4477: }
4478: if (exists($$olddata{$altkey})) {
4479: if (defined($data) && $$olddata{$altkey} ne $data) {
4480: $haschange = 1;
4481: }
4482: } elsif (($data ne '') && (!$reconlychg)) {
4483: $haschange = 1;
4484: }
4485: $storekey = $altkey;
1.563 damieng 4486: } else {
1.576 raeburn 4487: if (exists($$olddata{$altkey})) {
4488: if ($$olddata{$altkey} eq $data) {
4489: $reconlychg = 1;
4490: }
4491: push(@delrec,($altkey,$altkey.'.type'));
4492: }
4493: if (exists($$olddata{$thiskey})) {
4494: if (defined($data) && $$olddata{$thiskey} ne $data) {
4495: $haschange = 1;
4496: }
4497: } elsif (($data ne '') && (!$reconlychg)) {
4498: $haschange = 1;
4499: }
4500: $storekey = $thiskey;
1.563 damieng 4501: }
1.560 damieng 4502: } else {
1.576 raeburn 4503: if (defined($data) && $$olddata{$thiskey} ne $data) {
4504: $haschange = 1;
4505: $storekey = $thiskey;
4506: }
4507: }
4508: }
4509: if ($reconlychg || $haschange) {
4510: unless ($env{'form.del_'.$thiskey}) {
4511: $newdata{$storekey}=$data;
4512: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4513: }
4514: }
4515: } elsif ($cmd eq 'del') {
4516: if ($tuname) {
1.576 raeburn 4517: my $error;
4518: if ($altkey) {
4519: if (exists($$olddata{$altkey})) {
4520: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4521: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4522: if ($recursive) {
4523: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4524: }
4525: } elsif ($recursive) {
4526: $error = 1;
4527: }
4528: }
4529: if (exists($$olddata{$thiskey})) {
4530: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4531: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4532: unless ($recursive) {
4533: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4534: }
4535: } elsif (!$recursive) {
4536: $error = 1;
4537: }
4538: }
1.560 damieng 4539: } else {
1.576 raeburn 4540: if (exists($$olddata{$thiskey})) {
4541: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4542: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4543: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4544: } else {
4545: $error = 1;
4546: }
4547: }
4548: }
4549: if ($error) {
1.560 damieng 4550: $r->print('<div class="LC_error">'.
4551: &mt('Error deleting parameters').'</div>');
4552: }
4553: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4554: } else {
1.576 raeburn 4555: if ($altkey) {
4556: if (exists($$olddata{$altkey})) {
4557: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4558: push(@deldata,($altkey,$altkey.'.type'));
4559: }
4560: }
4561: if (exists($$olddata{$thiskey})) {
4562: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4563: push(@deldata,($thiskey,$thiskey.'.type'));
4564: }
4565: }
4566: } elsif (exists($$olddata{$thiskey})) {
4567: push(@deldata,($thiskey,$thiskey.'.type'));
4568: }
1.560 damieng 4569: }
1.473 amueller 4570: }
4571: }
4572: }
1.207 www 4573: # Store all course level
1.144 www 4574: my $delentries=$#deldata+1;
1.576 raeburn 4575: my @alldels;
4576: if (@delrec) {
4577: push(@alldels,@delrec);
4578: }
4579: if (@delnonrec) {
4580: push(@alldels,@delnonrec);
4581: }
4582: if (@deldata) {
4583: push(@alldels,@deldata);
4584: }
1.548 raeburn 4585: my @newdatakeys=keys(%newdata);
1.144 www 4586: my $putentries=$#newdatakeys+1;
1.576 raeburn 4587: my ($delresult,$devalidate);
4588: if (@alldels) {
4589: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4590: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4591: &log_parmset(\%loghash,1);
1.576 raeburn 4592: if ($delentries) {
4593: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4594: }
4595: } elsif ($delentries) {
1.560 damieng 4596: $r->print('<div class="LC_error">'.
4597: &mt('Error deleting parameters').'</div>');
4598: }
1.576 raeburn 4599: $devalidate = 1;
1.144 www 4600: }
4601: if ($putentries) {
1.560 damieng 4602: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4603: &log_parmset(\%newdata,0);
4604: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4605: } else {
4606: $r->print('<div class="LC_error">'.
4607: &mt('Error saving parameters').'</div>');
4608: }
1.576 raeburn 4609: $devalidate = 1;
4610: }
4611: if ($devalidate) {
1.560 damieng 4612: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4613: }
1.208 www 4614: }
1.207 www 4615:
1.563 damieng 4616: # Returns the username and domain from a key created in readdata from a resourcedata key.
4617: #
4618: # @param {string} $key - the key
4619: # @returns {Array}
1.208 www 4620: sub extractuser {
4621: my $key=shift;
1.350 albertel 4622: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4623: }
1.206 www 4624:
1.563 damieng 4625: # Parses a parameter key and returns the components.
4626: #
4627: # @param {string} $key -
4628: # @param {hash reference} $listdata -
4629: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4630: sub parse_listdata_key {
4631: my ($key,$listdata) = @_;
4632: # split into student/section affected, and
4633: # the realm (folder/resource part and parameter
1.446 bisitz 4634: my ($student,$realm) =
1.473 amueller 4635: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4636: # if course wide student would be undefined
4637: if (!defined($student)) {
1.560 damieng 4638: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4639: }
4640: # strip off the .type if it's not the Question type parameter
4641: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4642: $realm=~s/\.type//;
1.381 albertel 4643: }
4644: # split into resource+part and parameter name
1.388 albertel 4645: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4646: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4647: return ($student,$res,$part,$parm);
4648: }
4649:
1.563 damieng 4650: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
4651: #
4652: # @param {Apache2::RequestRec} $r - the Apache request
4653: # @param {hash reference} $resourcedata - parameter data returned by readdata
4654: # @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
4655: # @param {string} $sortorder - realmstudent|studentrealm
4656: # @param {string} $caller - name of the calling sub (overview|newoverview)
4657: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 4658: # @param {boolean} $readonly - true if editing not allowed
1.563 damieng 4659: # @returns{integer} - number of $listdata parameters processed
1.208 www 4660: sub listdata {
1.568 raeburn 4661: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552 raeburn 4662:
1.207 www 4663: # Start list output
1.206 www 4664:
1.122 www 4665: my $oldsection='';
4666: my $oldrealm='';
4667: my $oldpart='';
1.123 www 4668: my $pointer=0;
1.124 www 4669: $tableopen=0;
1.145 www 4670: my $foundkeys=0;
1.248 albertel 4671: my %keyorder=&standardkeyorder();
1.594 raeburn 4672: my $readonlyall = $readonly;
1.381 albertel 4673:
1.552 raeburn 4674: my ($secidx,%grouphash);
4675: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4676: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 4677: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4678: %grouphash = &Apache::longroup::coursegroups();
4679: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 4680: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 4681: }
1.552 raeburn 4682: }
4683:
1.576 raeburn 4684: foreach my $key (sort {
1.560 damieng 4685: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
4686: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381 albertel 4687:
1.560 damieng 4688: # get the numerical order for the param
4689: $aparm=$keyorder{'parameter_0_'.$aparm};
4690: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 4691:
1.560 damieng 4692: my $result=0;
1.381 albertel 4693:
1.560 damieng 4694: if ($sortorder eq 'realmstudent') {
1.381 albertel 4695: if ($ares ne $bres ) {
1.560 damieng 4696: $result = ($ares cmp $bres);
1.446 bisitz 4697: } elsif ($astudent ne $bstudent) {
1.560 damieng 4698: $result = ($astudent cmp $bstudent);
4699: } elsif ($apart ne $bpart ) {
4700: $result = ($apart cmp $bpart);
4701: }
4702: } else {
4703: if ($astudent ne $bstudent) {
4704: $result = ($astudent cmp $bstudent);
4705: } elsif ($ares ne $bres ) {
4706: $result = ($ares cmp $bres);
4707: } elsif ($apart ne $bpart ) {
4708: $result = ($apart cmp $bpart);
4709: }
1.473 amueller 4710: }
1.446 bisitz 4711:
1.560 damieng 4712: if (!$result) {
1.381 albertel 4713: if (defined($aparm) && defined($bparm)) {
1.560 damieng 4714: $result = ($aparm <=> $bparm);
1.381 albertel 4715: } elsif (defined($aparm)) {
1.560 damieng 4716: $result = -1;
1.381 albertel 4717: } elsif (defined($bparm)) {
1.560 damieng 4718: $result = 1;
4719: }
1.473 amueller 4720: }
1.381 albertel 4721:
1.560 damieng 4722: $result;
4723:
1.576 raeburn 4724: } keys(%{$listdata})) { # foreach my $key
4725: my $thiskey = $key;
1.560 damieng 4726: if ($$listdata{$thiskey.'.type'}) {
4727: my $thistype=$$listdata{$thiskey.'.type'};
4728: if ($$resourcedata{$thiskey.'.type'}) {
4729: $thistype=$$resourcedata{$thiskey.'.type'};
4730: }
4731: my ($middle,$part,$name)=
1.572 damieng 4732: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 4733: my $section=&mt('All Students');
1.594 raeburn 4734: $readonly = $readonlyall;
1.599 raeburn 4735: my $userscope;
1.576 raeburn 4736: my $showval = $$resourcedata{$thiskey};
1.560 damieng 4737: if ($middle=~/^\[(.*)\]/) {
4738: my $issection=$1;
4739: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
4740: my ($stuname,$studom) = ($1,$2);
4741: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4742: if (ref($classlist) eq 'HASH') {
4743: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
4744: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
4745: }
4746: }
4747: }
4748: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 4749: $userscope = 1;
1.560 damieng 4750: } else {
4751: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4752: if (exists($grouphash{$issection})) {
4753: $section=&mt('Group').': '.$issection;
4754: } elsif ($issection eq $env{'request.course.sec'}) {
4755: $section = &mt('Section').': '.$issection;
4756: } else {
4757: next;
1.552 raeburn 4758: }
1.560 damieng 4759: } else {
4760: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 4761: }
4762: }
1.560 damieng 4763: $middle=~s/^\[(.*)\]//;
4764: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4765: $readonly = 1;
4766: }
4767: $middle=~s/\.+$//;
4768: $middle=~s/^\.+//;
4769: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 4770: my ($is_map,$is_recursive,$mapurl,$maplevel);
4771: if ($caller eq 'overview') {
4772: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
4773: $mapurl = $1;
4774: $maplevel = $2;
4775: $is_map = 1;
4776: }
4777: } elsif ($caller eq 'newoverview') {
4778: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
4779: $mapurl = $1;
4780: $maplevel = $2;
4781: $is_map = 1;
4782: }
4783: }
4784: if ($is_map) {
1.560 damieng 4785: my $leveltitle = &mt('Folder/Map');
1.576 raeburn 4786: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
4787: if ($caller eq 'newoverview') {
4788: my $altkey = $thiskey;
4789: $altkey =~ s/\Q___(all)\E/___(rec)/;
4790: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
4791: $is_recursive = 1;
4792: if ($$resourcedata{$altkey.'.type'}) {
4793: $thistype=$$resourcedata{$altkey.'.type'};
4794: }
4795: $showval = $$resourcedata{$altkey};
4796: }
4797: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
4798: $thiskey =~ s/\Q___(rec)\E/___(all)/;
4799: $is_recursive = 1;
4800: }
1.560 damieng 4801: }
4802: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
4803: } elsif ($middle) {
4804: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
4805: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
4806: ': '.&Apache::lonnet::gettitle($middle).
4807: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
4808: $id.')</span></span>';
4809: }
4810: if ($sortorder eq 'realmstudent') {
4811: if ($realm ne $oldrealm) {
4812: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
4813: $oldrealm=$realm;
4814: $oldsection='';
4815: }
4816: if ($section ne $oldsection) {
4817: $r->print(&tableend()."\n<h2>$section</h2>");
4818: $oldsection=$section;
4819: $oldpart='';
4820: }
1.552 raeburn 4821: } else {
1.560 damieng 4822: if ($section ne $oldsection) {
4823: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
4824: $oldsection=$section;
4825: $oldrealm='';
4826: }
4827: if ($realm ne $oldrealm) {
4828: $r->print(&tableend()."\n<h2>$realm</h2>");
4829: $oldrealm=$realm;
4830: $oldpart='';
1.552 raeburn 4831: }
4832: }
1.560 damieng 4833: if ($part ne $oldpart) {
4834: $r->print(&tableend().
4835: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
4836: $oldpart=$part;
1.556 raeburn 4837: }
1.560 damieng 4838: #
4839: # Ready to print
4840: #
1.470 raeburn 4841: my $parmitem = &standard_parameter_names($name);
1.576 raeburn 4842: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 4843: &Apache::loncommon::start_data_table_row().
4844: '<td><b>'.&mt($parmitem).
4845: '</b></td>');
4846: unless ($readonly) {
1.599 raeburn 4847: my $disabled;
4848: if (($name eq 'availablestudent') &&
4849: (($showval eq '') || ($userscope))) {
4850: $disabled = ' disabled="disabled"';
4851: }
1.560 damieng 4852: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 4853: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 4854: }
4855: $r->print('<td>');
4856: $foundkeys++;
4857: if (&isdateparm($thistype)) {
4858: my $jskey='key_'.$pointer;
4859: my $state;
4860: $pointer++;
4861: if ($readonly) {
4862: $state = 'disabled';
4863: }
4864: $r->print(
4865: &Apache::lonhtmlcommon::date_setter('parmform',
4866: $jskey,
1.576 raeburn 4867: $showval,
1.560 damieng 4868: '',1,$state));
4869: unless ($readonly) {
4870: $r->print(
4871: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 4872: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 4873: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 4874: &date_sanity_info($showval)
1.560 damieng 4875: );
4876: }
4877: } elsif ($thistype eq 'date_interval') {
4878: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 4879: $showval,$readonly));
1.560 damieng 4880: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 4881: if ($name eq 'availablestudent') {
4882: $readonly = 1;
4883: }
1.560 damieng 4884: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 4885: $showval,$name,$readonly));
1.560 damieng 4886: } else {
1.576 raeburn 4887: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 4888: }
1.560 damieng 4889: unless ($readonly) {
4890: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
4891: $thistype.'" />');
1.552 raeburn 4892: }
1.576 raeburn 4893: $r->print('</td>');
4894: if ($is_map) {
4895: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
4896: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
4897: } else {
4898: my ($disabled,$recon,$recoff);
4899: if ($readonly) {
4900: $disabled = ' disabled="disabled"';
4901: }
4902: if ($is_recursive) {
4903: $recon = ' checked="checked"';
4904: } else {
4905: $recoff = ' checked="checked"';
4906: }
4907: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
4908: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
4909: }
4910: }
4911: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 4912: }
1.121 www 4913: }
1.208 www 4914: return $foundkeys;
4915: }
4916:
1.563 damieng 4917: # Returns a string representing the interval, directly using form data matching the given key.
4918: # The returned string may also include information related to proctored exams.
4919: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
4920: #
4921: # @param {string} $key - suffix for form fields related to the interval
4922: # @returns {string}
1.385 albertel 4923: sub get_date_interval_from_form {
4924: my ($key) = @_;
4925: my $seconds = 0;
4926: foreach my $which (['days', 86400],
1.473 amueller 4927: ['hours', 3600],
4928: ['minutes', 60],
4929: ['seconds', 1]) {
1.560 damieng 4930: my ($name, $factor) = @{ $which };
4931: if (defined($env{'form.'.$name.'_'.$key})) {
4932: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
4933: }
1.473 amueller 4934: }
1.560 damieng 4935: if (($key =~ /\.interval$/) &&
4936: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 4937: if ($env{'form.done_'.$key.'_buttontext'}) {
4938: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
4939: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
4940: if ($env{'form.done_'.$key} eq '_done_proctor') {
4941: $seconds .= '_proctor';
4942: }
4943: } else {
4944: $seconds .= $env{'form.done_'.$key};
4945: }
4946: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 4947: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 4948: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
4949: }
1.554 raeburn 4950: }
1.385 albertel 4951: return $seconds;
4952: }
4953:
4954:
1.563 damieng 4955: # Returns HTML to enter a text value for a parameter.
4956: #
4957: # @param {string} $thiskey - parameter key
4958: # @param {string} $showval - the current value
4959: # @param {boolean} $readonly - true if the field should not be made editable
4960: # @returns {string}
1.383 albertel 4961: sub default_selector {
1.552 raeburn 4962: my ($thiskey, $showval, $readonly) = @_;
4963: my $disabled;
4964: if ($readonly) {
4965: $disabled = ' disabled="disabled"';
4966: }
4967: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 4968: }
4969:
1.563 damieng 4970: # Returns HTML to enter allow/deny rules related to IP addresses.
4971: #
4972: # @param {string} $thiskey - parameter key
4973: # @param {string} $showval - the current value
4974: # @param {boolean} $readonly - true if the fields should not be made editable
4975: # @returns {string}
1.549 raeburn 4976: sub string_ip_selector {
1.552 raeburn 4977: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 4978: my %access = (
4979: allow => [],
4980: deny => [],
4981: );
4982: if ($showval ne '') {
4983: my @current;
4984: if ($showval =~ /,/) {
4985: @current = split(/,/,$showval);
4986: } else {
4987: @current = ($showval);
4988: }
4989: foreach my $item (@current) {
4990: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
4991: push(@{$access{'deny'}},$1);
4992: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
4993: push(@{$access{'allow'}},$item);
4994: }
4995: }
4996: }
4997: if (!@{$access{'allow'}}) {
4998: @{$access{'allow'}} = ('');
4999: }
5000: if (!@{$access{'deny'}}) {
5001: @{$access{'deny'}} = ('');
5002: }
1.552 raeburn 5003: my ($disabled,$addmore);
1.567 raeburn 5004: if ($readonly) {
1.552 raeburn 5005: $disabled=' disabled="disabled"';
5006: } else {
5007: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5008: }
1.549 raeburn 5009: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5010: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5011: foreach my $acctype ('allow','deny') {
5012: $output .= '
5013: <td valign="top">
5014: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5015: <div class="LC_string_ipacc_inner">'."\n";
5016: my $num = 0;
5017: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5018: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5019: if ($num > 0) {
5020: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5021: }
5022: $output .= '</div>'."\n";
5023: $num ++;
5024: }
5025: $output .= '
1.552 raeburn 5026: </div>'.$addmore.'
1.549 raeburn 5027: </div>
5028: </td>';
5029: }
5030: $output .= '
5031: </tr>
5032: </table>'."\n";
5033: return $output;
5034: }
5035:
1.588 raeburn 5036: sub string_deeplink_selector {
5037: my ($thiskey, $showval, $readonly) = @_;
1.597 raeburn 5038: my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601 raeburn 5039: %selectnull,%domlti,%crslti,@possmenus);
5040: @components = ('state','others','listing','scope','protect','menus');
1.588 raeburn 5041: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5042: state => 'Access status',
5043: others => 'Hide other resources',
1.588 raeburn 5044: listing => 'In Contents and/or Gradebook',
5045: scope => 'Access scope for link',
1.601 raeburn 5046: protect => 'Link protection',
1.597 raeburn 5047: menus => 'Menu Items Displayed',
1.588 raeburn 5048: );
5049: %options = (
1.601 raeburn 5050: state => ['only','off','both'],
5051: others => ['hide','unhide'],
1.588 raeburn 5052: listing => ['full','absent','grades','details','datestatus'],
5053: scope => ['res','map','rec'],
1.601 raeburn 5054: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5055: menus => ['std','colls'],
1.588 raeburn 5056: );
5057: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5058: only => 'deep only',
5059: off => 'deeplink off',
5060: both => 'regular + deep',
5061: hide => 'Hidden',
5062: unhide => 'Unhidden',
1.588 raeburn 5063: full => 'Listed (linked) in both',
5064: absent => 'Not listed',
5065: grades => 'Listed in grades only',
5066: details => 'Listed (unlinked) in both',
5067: datestatus => 'Listed (unlinked) inc. status in both',
5068: res => 'resource only',
5069: map => 'enclosing map/folder',
5070: rec => 'recursive map/folder',
1.601 raeburn 5071: none => 'not in use',
5072: key => 'key access',
5073: ltic => 'LTI access (course)',
5074: ltid => 'LTI access (domain)' ,
1.597 raeburn 5075: std => 'Standard (all menus)',
5076: colls => 'Numbered collection',
5077: );
5078: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5079: ltic => 'Select Launcher',
5080: ltid => 'Select Launcher',
1.597 raeburn 5081: colls => 'Select',
1.588 raeburn 5082: );
5083: if ($showval =~ /,/) {
1.597 raeburn 5084: %values=();
1.588 raeburn 5085: @current = split(/,/,$showval);
1.601 raeburn 5086: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5087: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5088: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5089: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5090: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5091: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.588 raeburn 5092: } else {
1.601 raeburn 5093: $defaults{'state'} = 'off',
5094: $defaults{'others'} = 'unhide',
1.588 raeburn 5095: $defaults{'listing'} = 'full';
5096: $defaults{'scope'} = 'res';
1.601 raeburn 5097: $defaults{'protect'} = 'none';
1.597 raeburn 5098: $defaults{'menus'} = '0';
1.588 raeburn 5099: }
5100: my $disabled;
5101: if ($readonly) {
5102: $disabled=' disabled="disabled"';
5103: }
1.601 raeburn 5104: my %courselti =
5105: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
5106: $env{'course.'.$env{'request.course.id'}.'.domain'});
5107: foreach my $item (keys(%courselti)) {
5108: if (ref($courselti{$item}) eq 'HASH') {
5109: $crslti{$item} = $courselti{$item}{'name'};
5110: }
5111: }
5112: my %lti =
1.588 raeburn 5113: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
5114: 'provider');
5115: foreach my $item (keys(%lti)) {
5116: if (ref($lti{$item}) eq 'HASH') {
5117: unless ($lti{$item}{'requser'}) {
1.601 raeburn 5118: $domlti{$item} = $lti{$item}{'consumer'};
1.588 raeburn 5119: }
5120: }
5121: }
1.597 raeburn 5122: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5123: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5124: my ($num,$value) = split(/\%/,$item);
5125: if ($num =~ /^\d+$/) {
5126: push(@possmenus,$num);
5127: }
5128: }
5129: }
5130:
1.588 raeburn 5131: my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597 raeburn 5132: foreach my $item (@components) {
1.588 raeburn 5133: $output .= '<th>'.$titles{$item}.'</th>';
5134: }
5135: $output .= '</tr><tr>';
5136: foreach my $item (@components) {
5137: $output .= '<td>';
1.601 raeburn 5138: if (($item eq 'protect') || ($item eq 'menus')) {
1.588 raeburn 5139: my $selected = $values{$item};
5140: foreach my $option (@{$options{$item}}) {
1.601 raeburn 5141: if ($item eq 'protect') {
5142: if ($option eq 'ltid') {
5143: next unless (keys(%domlti));
5144: } elsif ($option eq 'ltic') {
5145: next unless (keys(%crslti));
5146: }
1.597 raeburn 5147: } elsif (($item eq 'menus') && ($option eq 'colls')) {
5148: next unless (@possmenus);
1.588 raeburn 5149: }
5150: my $checked;
1.597 raeburn 5151: if ($item eq 'menus') {
5152: if (($selected =~ /^\d+$/) && (@possmenus) &&
5153: (grep(/^\Q$selected\E$/,@possmenus))) {
5154: if ($option eq 'colls') {
5155: $checked = ' checked="checked"';
5156: }
5157: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
5158: $checked = ' checked="checked"';
5159: }
5160: } elsif ($selected =~ /^\Q$option\E/) {
1.588 raeburn 5161: $checked = ' checked="checked"';
5162: }
5163: my $onclick;
5164: unless ($readonly) {
5165: my $esc_key = &js_escape($thiskey);
5166: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
5167: }
5168: $output .= '<span class="LC_nobreak"><label>'.
5169: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
5170: $optiontext{$option}.'</label>';
1.601 raeburn 5171: if (($item eq 'protect') && ($option eq 'key')) {
1.588 raeburn 5172: my $visibility="hidden";
5173: my $currkey;
5174: if ($checked) {
5175: $visibility = "text";
5176: $currkey = (split(/\:/,$values{$item}))[1];
5177: }
5178: $output .= ' '.
1.597 raeburn 5179: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601 raeburn 5180: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588 raeburn 5181: my $display="none";
1.597 raeburn 5182: my ($current,$blankcheck,@possibles);
1.588 raeburn 5183: if ($checked) {
5184: $display = 'inline-block';
1.601 raeburn 5185: if (($option eq 'ltic') || ($option eq 'ltid')) {
1.597 raeburn 5186: $current = (split(/\:/,$selected))[1];
5187: } else {
5188: $current = $selected;
5189: }
1.588 raeburn 5190: } else {
5191: $blankcheck = ' selected="selected"';
5192: }
1.601 raeburn 5193: if ($option eq 'ltid') {
5194: @possibles = keys(%domlti);
5195: } elsif ($option eq 'ltic') {
5196: @possibles = keys(%crslti);
1.597 raeburn 5197: } else {
5198: @possibles = @possmenus;
5199: }
1.588 raeburn 5200: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
5201: ' style="display: '.$display.'"> <select name="'.
1.597 raeburn 5202: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
5203: if (@possibles > 1) {
5204: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
5205: '</option>'."\n";
5206: }
5207: foreach my $poss (sort { $a <=> $b } @possibles) {
1.588 raeburn 5208: my $selected;
1.597 raeburn 5209: if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588 raeburn 5210: $selected = ' selected="selected"';
5211: }
1.597 raeburn 5212: my $shown = $poss;
1.601 raeburn 5213: if ($option eq 'ltid') {
5214: $shown = $domlti{$poss};
5215: } elsif ($option eq 'ltic') {
5216: $shown = $crslti{$poss};
1.597 raeburn 5217: }
5218: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588 raeburn 5219: }
5220: $output .= '</select></div>';
5221: }
5222: $output .= '</span> ';
5223: }
5224: } else {
5225: my $selected = $values{$item};
5226: my $defsel;
5227: if ($selected eq '') {
5228: $defsel = ' selected="selected"';
5229: }
5230: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
5231: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
5232: foreach my $option (@{$options{$item}}) {
5233: $output .= '<option value="'.$option.'"';
5234: if ($option eq $selected) {
5235: $output .= ' selected="selected"';
5236: }
5237: $output .= '>'.$optiontext{$option}.'</option>';
5238: }
5239: $output .= '</select>';
5240: }
5241: $output .= '</td>';
5242: }
5243: $output .= '</tr></table>'."\n";
5244: return $output;
5245: }
5246:
1.560 damieng 5247:
5248: { # block using some constants related to parameter types (overview mode)
5249:
1.446 bisitz 5250: my %strings =
1.383 albertel 5251: (
5252: 'string_yesno'
5253: => [[ 'yes', 'Yes' ],
1.560 damieng 5254: [ 'no', 'No' ]],
1.383 albertel 5255: 'string_problemstatus'
5256: => [[ 'yes', 'Yes' ],
1.473 amueller 5257: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5258: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5259: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5260: 'string_questiontype'
5261: => [[ 'problem', 'Standard Problem'],
5262: [ 'survey', 'Survey'],
5263: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5264: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5265: [ 'anonsurvey', 'Anonymous Survey'],
5266: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5267: [ 'practice', 'Practice'],
5268: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5269: 'string_lenient'
5270: => [['yes', 'Yes' ],
5271: [ 'no', 'No' ],
1.549 raeburn 5272: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5273: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5274: 'string_discussvote'
5275: => [['yes','Yes'],
5276: ['notended','Yes, unless discussion ended'],
5277: ['no','No']],
1.549 raeburn 5278: 'string_ip'
5279: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5280: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5281: 'string_deeplink'
1.597 raeburn 5282: => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
1.587 raeburn 5283: );
5284:
1.383 albertel 5285:
1.549 raeburn 5286: my %stringmatches = (
5287: 'string_lenient'
5288: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5289: 'string_ip'
5290: => [['_allowfrom_','[^\!]+'],
5291: ['_denyfrom_','\!']],
1.588 raeburn 5292: 'string_deeplink'
1.602 raeburn 5293: => [['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 5294: );
5295:
5296: my %stringtypes = (
5297: type => 'string_questiontype',
5298: lenient => 'string_lenient',
5299: retrypartial => 'string_yesno',
5300: discussvote => 'string_discussvote',
5301: examcode => 'string_examcode',
5302: acc => 'string_ip',
1.587 raeburn 5303: deeplink => 'string_deeplink',
1.549 raeburn 5304: );
5305:
1.563 damieng 5306: # Returns the possible values and titles for a given string type, or undef if there are none.
5307: # Used by courseprefs.
5308: #
5309: # @param {string} $string_type - a parameter type for strings
5310: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5311: sub standard_string_options {
5312: my ($string_type) = @_;
5313: if (ref($strings{$string_type}) eq 'ARRAY') {
5314: return $strings{$string_type};
5315: }
5316: return;
5317: }
1.383 albertel 5318:
1.563 damieng 5319: # Returns regular expressions to match kinds of string types, or undef if there are none.
5320: #
5321: # @param {string} $string_type - a parameter type for strings
5322: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5323: sub standard_string_matches {
5324: my ($string_type) = @_;
5325: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5326: return $stringmatches{$string_type};
5327: }
5328: return;
5329: }
5330:
1.563 damieng 5331: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5332: #
5333: # @param {string} $name - parameter name
5334: # @returns {string}
1.549 raeburn 5335: sub get_stringtype {
5336: my ($name) = @_;
5337: if (exists($stringtypes{$name})) {
5338: return $stringtypes{$name};
5339: }
5340: return;
5341: }
5342:
1.563 damieng 5343: # Returns HTML to edit a string parameter.
5344: #
5345: # @param {string} $thistype - parameter type
5346: # @param {string} $thiskey - parameter key
5347: # @param {string} $showval - parameter current value
5348: # @param {string} $name - parameter name
5349: # @param {boolean} $readonly - true if the values should not be made editable
5350: # @returns {string}
1.383 albertel 5351: sub string_selector {
1.552 raeburn 5352: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5353:
1.383 albertel 5354: if (!exists($strings{$thistype})) {
1.552 raeburn 5355: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5356: }
5357:
1.504 raeburn 5358: my %skiptype;
1.514 raeburn 5359: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5360: ($thistype eq 'string_lenient') ||
5361: ($thistype eq 'string_discussvote') ||
5362: ($thistype eq 'string_ip') ||
1.588 raeburn 5363: ($thistype eq 'string_deeplink') ||
1.560 damieng 5364: ($name eq 'retrypartial')) {
1.504 raeburn 5365: my ($got_chostname,$chostname,$cmajor,$cminor);
5366: foreach my $possibilities (@{ $strings{$thistype} }) {
5367: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5368: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5369: my $parmmatch;
5370: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5371: foreach my $item (@{$stringmatches{$thistype}}) {
5372: if (ref($item) eq 'ARRAY') {
5373: if ($parmval eq $item->[0]) {
5374: $parmmatch = $parmval;
5375: $parmval = '';
5376: last;
5377: }
5378: }
5379: }
5380: }
5381: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5382: if ($needsrelease) {
5383: unless ($got_chostname) {
1.514 raeburn 5384: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5385: $got_chostname = 1;
5386: }
1.557 raeburn 5387: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5388: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5389: if ($needsnewer) {
1.549 raeburn 5390: if ($parmmatch ne '') {
5391: $skiptype{$parmmatch} = 1;
5392: } elsif ($parmval ne '') {
5393: $skiptype{$parmval} = 1;
5394: }
1.504 raeburn 5395: }
5396: }
5397: }
5398: }
1.549 raeburn 5399:
5400: if ($thistype eq 'string_ip') {
1.552 raeburn 5401: return &string_ip_selector($thiskey,$showval,$readonly);
1.588 raeburn 5402: } elsif ($thistype eq 'string_deeplink') {
5403: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5404: }
1.504 raeburn 5405:
1.552 raeburn 5406: my ($result,$disabled);
5407:
5408: if ($readonly) {
5409: $disabled = ' disabled="disabled"';
5410: }
1.504 raeburn 5411: my $numinrow = 3;
5412: if ($thistype eq 'string_problemstatus') {
5413: $numinrow = 2;
5414: } elsif ($thistype eq 'string_questiontype') {
5415: if (keys(%skiptype) > 0) {
5416: $numinrow = 4;
5417: }
5418: }
5419: my $rem;
5420: if (ref($strings{$thistype}) eq 'ARRAY') {
5421: my $i=0;
5422: foreach my $possibilities (@{ $strings{$thistype} }) {
5423: next unless (ref($possibilities) eq 'ARRAY');
5424: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5425: next if ($skiptype{$name});
1.504 raeburn 5426: $rem = $i%($numinrow);
5427: if ($rem == 0) {
5428: if ($i > 0) {
5429: $result .= '</tr>';
5430: }
5431: $result .= '<tr>';
5432: }
1.549 raeburn 5433: my $colspan;
5434: if ($i == @{ $strings{$thistype} }-1) {
5435: $rem = @{ $strings{$thistype} }%($numinrow);
5436: if ($rem) {
5437: my $colsleft = $numinrow - $rem;
5438: if ($colsleft) {
5439: $colspan = $colsleft+1;
5440: $colspan = ' colspan="'.$colspan.'"';
5441: }
5442: }
5443: }
5444: my ($add,$onchange,$css_class);
5445: if ($thistype eq 'string_lenient') {
5446: if ($name eq 'weighted') {
5447: my $display;
5448: my %relatives = &Apache::lonlocal::texthash(
5449: corrchkd => 'Correct (checked)',
5450: corrunchkd => 'Correct (unchecked)',
5451: incorrchkd => 'Incorrect (checked)',
5452: incorrunchkd => 'Incorrect (unchecked)',
5453: );
5454: my %textval = (
5455: corrchkd => '1.0',
5456: corrunchkd => '1.0',
5457: incorrchkd => '0.0',
5458: incorrunchkd => '0.0',
5459: );
5460: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
5461: $textval{'corrchkd'} = $1;
5462: $textval{'corrunchkd'} = $2;
5463: $textval{'incorrchkd'} = $3;
5464: $textval{'incorrunchkd'} = $4;
5465: $display = 'inline';
5466: $showval = $name;
5467: } else {
5468: $display = 'none';
5469: }
5470: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
5471: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
5472: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
5473: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
5474: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 5475: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 5476: '</td></tr>';
5477: }
5478: $add .= '</table></div>'."\n";
5479: }
5480: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
5481: $css_class = ' class="LC_lenient_radio"';
5482: }
5483: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 5484: '<span class="LC_nobreak"><label>'.
5485: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 5486: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 5487: if ($showval eq $name) {
5488: $result .= ' checked="checked"';
5489: }
1.549 raeburn 5490: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 5491: $i++;
5492: }
5493: $result .= '</tr>';
1.473 amueller 5494: }
1.504 raeburn 5495: if ($result) {
5496: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 5497: }
5498: return $result;
5499: }
5500:
1.554 raeburn 5501: my %intervals =
5502: (
5503: 'date_interval'
5504: => [[ 'done', 'Yes' ],
1.558 raeburn 5505: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 5506: [ '', 'No' ]],
5507: );
5508:
5509: my %intervalmatches = (
5510: 'date_interval'
1.559 raeburn 5511: => [['done','\d+_done(|\:[^\:]+\:)$'],
5512: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 5513: );
5514:
5515: my %intervaltypes = (
5516: interval => 'date_interval',
5517: );
5518:
1.563 damieng 5519: # Returns regular expressions to match kinds of interval type, or undef if there are none.
5520: #
5521: # @param {string} $interval_type - a parameter type for intervals
5522: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 5523: sub standard_interval_matches {
5524: my ($interval_type) = @_;
5525: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
5526: return $intervalmatches{$interval_type};
5527: }
5528: return;
5529: }
5530:
1.563 damieng 5531: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
5532: #
5533: # @param {string} $name - parameter name
5534: # @returns {string}
1.554 raeburn 5535: sub get_intervaltype {
5536: my ($name) = @_;
5537: if (exists($intervaltypes{$name})) {
5538: return $intervaltypes{$name};
5539: }
5540: return;
5541: }
5542:
1.563 damieng 5543: # Returns the possible values and titles for a given interval type, or undef if there are none.
5544: # Used by courseprefs.
5545: #
5546: # @param {string} $interval_type - a parameter type for intervals
5547: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 5548: sub standard_interval_options {
5549: my ($interval_type) = @_;
5550: if (ref($intervals{$interval_type}) eq 'ARRAY') {
5551: return $intervals{$interval_type};
5552: }
5553: return;
5554: }
5555:
1.563 damieng 5556: # Returns HTML to edit a date interval parameter.
5557: #
5558: # @param {string} $thiskey - parameter key
5559: # @param {string} $name - parameter name
5560: # @param {string} $showval - parameter current value
5561: # @param {boolean} $readonly - true if the values should not be made editable
5562: # @returns {string}
1.554 raeburn 5563: sub date_interval_selector {
5564: my ($thiskey, $name, $showval, $readonly) = @_;
5565: my ($result,%skipval);
5566: if ($name eq 'interval') {
5567: my $intervaltype = &get_intervaltype($name);
5568: my ($got_chostname,$chostname,$cmajor,$cminor);
5569: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
5570: next unless (ref($possibilities) eq 'ARRAY');
5571: my ($parmval, $description) = @{ $possibilities };
5572: my $parmmatch;
5573: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
5574: foreach my $item (@{$intervalmatches{$intervaltype}}) {
5575: if (ref($item) eq 'ARRAY') {
5576: if ($parmval eq $item->[0]) {
5577: $parmmatch = $parmval;
5578: $parmval = '';
5579: last;
5580: }
5581: }
5582: }
5583: }
5584: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
5585: if ($needsrelease) {
5586: unless ($got_chostname) {
5587: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
5588: $got_chostname = 1;
5589: }
1.557 raeburn 5590: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 5591: $needsrelease,$cmajor,$cminor);
5592: if ($needsnewer) {
5593: if ($parmmatch ne '') {
5594: $skipval{$parmmatch} = 1;
5595: } elsif ($parmval ne '') {
5596: $skipval{$parmval} = 1;
5597: }
5598: }
5599: }
5600: }
5601: }
5602:
5603: my $currval = $showval;
5604: foreach my $which (['days', 86400, 31],
5605: ['hours', 3600, 23],
5606: ['minutes', 60, 59],
5607: ['seconds', 1, 59]) {
1.560 damieng 5608: my ($name, $factor, $max) = @{ $which };
5609: my $amount = int($showval/$factor);
5610: $showval %= $factor;
5611: my %select = ((map {$_ => $_} (0..$max)),
5612: 'select_form_order' => [0..$max]);
5613: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
5614: \%select,'',$readonly);
5615: $result .= ' '.&mt($name);
1.554 raeburn 5616: }
5617: if ($name eq 'interval') {
5618: unless ($skipval{'done'}) {
5619: my $checkedon = '';
1.558 raeburn 5620: my $checkedproc = '';
5621: my $currproctorkey = '';
5622: my $currprocdisplay = 'hidden';
1.559 raeburn 5623: my $currdonetext = &mt('Done');
1.554 raeburn 5624: my $checkedoff = ' checked="checked"';
1.559 raeburn 5625: if ($currval =~ /^(?:\d+)_done$/) {
5626: $checkedon = ' checked="checked"';
5627: $checkedoff = '';
5628: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
5629: $currdonetext = $1;
1.554 raeburn 5630: $checkedon = ' checked="checked"';
5631: $checkedoff = '';
1.558 raeburn 5632: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
5633: $currproctorkey = $1;
5634: $checkedproc = ' checked="checked"';
5635: $checkedoff = '';
5636: $currprocdisplay = 'text';
1.559 raeburn 5637: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
5638: $currdonetext = $1;
5639: $currproctorkey = $2;
5640: $checkedproc = ' checked="checked"';
5641: $checkedoff = '';
5642: $currprocdisplay = 'text';
1.554 raeburn 5643: }
1.558 raeburn 5644: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 5645: my $disabled;
5646: if ($readonly) {
5647: $disabled = ' disabled="disabled"';
5648: }
1.558 raeburn 5649: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 5650: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 5651: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 5652: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 5653: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 5654: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 5655: &mt('Yes, with proctor key').'</label>'.
5656: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 5657: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 5658: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567 raeburn 5659: '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 5660: }
5661: }
5662: unless ($readonly) {
5663: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
5664: }
5665: return $result;
5666: }
5667:
1.563 damieng 5668: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
5669: #
5670: # @param {string} $name - parameter name
5671: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
5672: # @param {string} $value - parameter value
5673: # @param {string} $chostname - course server name
5674: # @param {integer} $cmajor - major version number
5675: # @param {integer} $cminor - minor version number
5676: # @param {string} $needsrelease - release version needed (major.minor)
5677: # @returns {string}
1.549 raeburn 5678: sub oldversion_warning {
1.557 raeburn 5679: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
5680: my $standard_name = &standard_parameter_names($name);
5681: if ($namematch) {
5682: my $level = &standard_parameter_levels($namematch);
5683: my $msg = '';
5684: if ($level) {
5685: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
5686: $standard_name,'<b>','</b>','"'.$level.'"');
5687: } else {
5688: $msg = &mt('[_1] was [_2]not[_3] set.',
5689: $standard_name,'<b>','</b>');
5690: }
5691: return '<p class="LC_warning">'.$msg.'<br />'.
5692: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5693: $cmajor.'.'.$cminor,$chostname,
5694: $needsrelease).
5695: '</p>';
5696: }
1.549 raeburn 5697: my $desc;
5698: my $stringtype = &get_stringtype($name);
5699: if ($stringtype ne '') {
5700: if ($name eq 'examcode') {
5701: $desc = $value;
5702: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
5703: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
5704: next unless (ref($possibilities) eq 'ARRAY');
5705: my ($parmval, $description) = @{ $possibilities };
5706: my $parmmatch;
5707: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
5708: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
5709: if (ref($item) eq 'ARRAY') {
5710: my ($regexpname,$pattern) = @{$item};
5711: if ($parmval eq $regexpname) {
5712: if ($value =~ /$pattern/) {
5713: $desc = $description;
5714: $parmmatch = 1;
5715: last;
5716: }
5717: }
5718: }
5719: }
5720: last if ($parmmatch);
5721: } elsif ($parmval eq $value) {
5722: $desc = $description;
5723: last;
5724: }
5725: }
5726: }
5727: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
5728: my $now = time;
5729: if ($value =~ /^\d+$/) {
5730: if ($name eq 'printstartdate') {
5731: if ($value > $now) {
5732: $desc = &Apache::lonlocal::locallocaltime($value);
5733: }
5734: } elsif ($name eq 'printenddate') {
5735: if ($value < $now) {
5736: $desc = &Apache::lonlocal::locallocaltime($value);
5737: }
5738: }
5739: }
5740: }
5741: return '<p class="LC_warning">'.
1.557 raeburn 5742: &mt('[_1] was [_2]not[_3] set to [_4].',
5743: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
5744: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5745: $cmajor.'.'.$cminor,$chostname,
5746: $needsrelease).
5747: '</p>';
1.549 raeburn 5748: }
5749:
1.560 damieng 5750: } # end of block using some constants related to parameter types
5751:
1.549 raeburn 5752:
1.563 damieng 5753:
5754: # Shifts all start and end dates in the current course by $shift.
1.389 www 5755: #
1.563 damieng 5756: # @param {integer} $shift - time to shift, in seconds
5757: # @returns {string} - error name or 'ok'
1.389 www 5758: sub dateshift {
1.594 raeburn 5759: my ($shift,$numchanges)=@_;
1.389 www 5760: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5761: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 5762: my $sec = $env{'request.course.sec'};
1.595 raeburn 5763: my $secgrpregex;
5764: if ($sec ne '') {
5765: my @groups;
5766: if ($env{'request.course.groups'} ne '') {
5767: @groups = split(/:/,$env{'request.course.groups'});
5768: }
5769: if (@groups) {
5770: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
5771: } else {
5772: $secgrpregex = $sec;
5773: }
5774: }
1.389 www 5775: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
5776: # ugly retro fix for broken version of types
1.548 raeburn 5777: foreach my $key (keys(%data)) {
1.389 www 5778: if ($key=~/\wtype$/) {
5779: my $newkey=$key;
5780: $newkey=~s/type$/\.type/;
5781: $data{$newkey}=$data{$key};
5782: delete $data{$key};
5783: }
5784: }
1.391 www 5785: my %storecontent=();
1.389 www 5786: # go through all parameters and look for dates
1.548 raeburn 5787: foreach my $key (keys(%data)) {
1.389 www 5788: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 5789: if ($sec ne '') {
1.595 raeburn 5790: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 5791: }
1.389 www 5792: my $newdate=$data{$key}+$shift;
1.594 raeburn 5793: $$numchanges ++;
1.391 www 5794: $storecontent{$key}=$newdate;
1.389 www 5795: }
5796: }
1.391 www 5797: my $reply=&Apache::lonnet::cput
5798: ('resourcedata',\%storecontent,$dom,$crs);
5799: if ($reply eq 'ok') {
5800: &log_parmset(\%storecontent);
5801: }
5802: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
5803: return $reply;
1.389 www 5804: }
5805:
1.563 damieng 5806: # Overview mode UI to edit course parameters.
5807: #
5808: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 5809: sub newoverview {
1.568 raeburn 5810: my ($r,$parm_permission) = @_;
1.280 albertel 5811:
1.208 www 5812: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5813: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 5814: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 5815: my $readonly = 1;
5816: if ($parm_permission->{'edit'}) {
5817: undef($readonly);
5818: }
1.414 droeschl 5819: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 5820: text=>"Overview Mode"});
1.523 raeburn 5821:
5822: my %loaditems = (
1.549 raeburn 5823: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 5824: );
5825: my $js = '
5826: <script type="text/javascript">
5827: // <![CDATA[
5828: '.
5829: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
5830: &showhide_js()."\n".
1.549 raeburn 5831: &toggleparmtextbox_js()."\n".
5832: &validateparms_js()."\n".
5833: &ipacc_boxes_js()."\n".
1.558 raeburn 5834: &done_proctor_js()."\n".
1.588 raeburn 5835: &deeplink_js()."\n".
1.523 raeburn 5836: '// ]]>
5837: </script>
5838: ';
1.549 raeburn 5839:
1.523 raeburn 5840: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
5841: {'add_entries' => \%loaditems,});
1.298 albertel 5842: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 5843: $r->print($start_page.$breadcrumbs);
1.531 raeburn 5844: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 5845: $r->print(<<ENDOVER);
1.549 raeburn 5846: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208 www 5847: ENDOVER
1.211 www 5848: my @ids=();
5849: my %typep=();
5850: my %keyp=();
5851: my %allparms=();
5852: my %allparts=();
5853: my %allmaps=();
5854: my %mapp=();
5855: my %symbp=();
5856: my %maptitles=();
5857: my %uris=();
5858: my %keyorder=&standardkeyorder();
5859: my %defkeytype=();
5860:
5861: my %alllevs=();
5862: $alllevs{'Resource Level'}='full';
1.215 www 5863: $alllevs{'Map/Folder Level'}='map';
1.211 www 5864: $alllevs{'Course Level'}='general';
5865:
5866: my $csec=$env{'form.csec'};
1.269 raeburn 5867: my $cgroup=$env{'form.cgroup'};
1.211 www 5868:
5869: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
5870: my $pschp=$env{'form.pschp'};
1.506 www 5871:
1.211 www 5872: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 5873: if (!@psprt) { $psprt[0]='all'; }
1.211 www 5874:
1.446 bisitz 5875: my @selected_sections =
1.473 amueller 5876: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 5877: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 5878: foreach my $sec (@selected_sections) {
5879: if ($sec eq 'all') {
1.211 www 5880: @selected_sections = ('all');
5881: }
5882: }
1.552 raeburn 5883: if ($env{'request.course.sec'} ne '') {
5884: @selected_sections = ($env{'request.course.sec'});
5885: }
1.269 raeburn 5886: my @selected_groups =
5887: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 5888:
5889: my $pssymb='';
5890: my $parmlev='';
1.446 bisitz 5891:
1.211 www 5892: unless ($env{'form.parmlev'}) {
5893: $parmlev = 'map';
5894: } else {
5895: $parmlev = $env{'form.parmlev'};
5896: }
5897:
1.446 bisitz 5898: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 5899: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 ! raeburn 5900: \%keyorder,\%defkeytype,$pssymb);
1.211 www 5901:
1.374 albertel 5902: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 5903: @psprt = keys(%allparts);
1.374 albertel 5904: }
1.211 www 5905: # Menu to select levels, etc
5906:
1.456 bisitz 5907: $r->print('<div class="LC_Box">');
1.445 neumanie 5908: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 5909: $r->print('<div>');
1.523 raeburn 5910: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 5911: &levelmenu($r,\%alllevs,$parmlev);
5912: if ($parmlev ne 'general') {
1.447 bisitz 5913: $r->print(&Apache::lonhtmlcommon::row_closure());
1.483 amueller 5914: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211 www 5915: }
1.447 bisitz 5916: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 5917: $r->print(&Apache::lonhtmlcommon::end_pick_box());
5918: $r->print('</div></div>');
1.446 bisitz 5919:
1.456 bisitz 5920: $r->print('<div class="LC_Box">');
1.452 bisitz 5921: $r->print('<div>');
1.581 raeburn 5922: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 5923: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 5924: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 5925: my $sectionselector = §ionmenu(\@selected_sections);
5926: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 5927: $r->print('<table>'.
1.553 raeburn 5928: '<tr><th>'.&mt('Parts').'</th>');
5929: if ($sectionselector) {
5930: $r->print('<th>'.&mt('Section(s)').'</th>');
5931: }
5932: if ($groupselector) {
5933: $r->print('<th>'.&mt('Group(s)').'</th>');
5934: }
5935: $r->print('</tr><tr><td>');
1.211 www 5936: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 5937: $r->print('</td>');
5938: if ($sectionselector) {
5939: $r->print('<td>'.$sectionselector.'</td>');
5940: }
5941: if ($groupselector) {
5942: $r->print('<td>'.$groupselector.'</td>');
5943: }
5944: $r->print('</tr></table>');
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>');
5948:
1.456 bisitz 5949: $r->print('<div class="LC_Box">');
1.452 bisitz 5950: $r->print('<div>');
1.214 www 5951: my $sortorder=$env{'form.sortorder'};
5952: unless ($sortorder) { $sortorder='realmstudent'; }
5953: &sortmenu($r,$sortorder);
1.445 neumanie 5954: $r->print('</div></div>');
1.446 bisitz 5955:
1.214 www 5956: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446 bisitz 5957:
1.211 www 5958: # Build the list data hash from the specified parms
5959:
5960: my $listdata;
5961: %{$listdata}=();
5962:
5963: foreach my $cat (@pscat) {
1.269 raeburn 5964: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
5965: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 5966: }
5967:
1.212 www 5968: if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211 www 5969:
1.481 amueller 5970: if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211 www 5971:
5972: # Read modified data
5973:
1.481 amueller 5974: my $resourcedata=&readdata($crs,$dom);
1.211 www 5975:
5976: # List data
5977:
1.568 raeburn 5978: &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
5979: }
5980: $r->print(&tableend());
5981: unless ($readonly) {
5982: $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211 www 5983: }
1.568 raeburn 5984: $r->print('</form>');
1.507 www 5985: &endSettingsScreen($r);
5986: $r->print(&Apache::loncommon::end_page());
1.208 www 5987: }
5988:
1.563 damieng 5989: # Fills $listdata with parameter information.
5990: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
5991: # The non-type value is always 1.
5992: #
5993: # @param {string} $cat - parameter name
1.566 damieng 5994: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 5995: # @param {string} $parmlev - selected level value (full|map|general), or ''
5996: # @param {hash reference} $listdata - the parameter data that will be modified
5997: # @param {array reference} $psprt - selected parts
5998: # @param {array reference} $selections - selected sections
5999: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6000: # @param {hash reference} $allmaps - hash map pc -> map src
6001: # @param {array reference} $ids - resource and map ids
6002: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6003: sub secgroup_lister {
6004: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6005: foreach my $item (@{$selections}) {
6006: foreach my $part (@{$psprt}) {
6007: my $rootparmkey=$env{'request.course.id'};
6008: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6009: $rootparmkey.='.['.$item.']';
6010: }
6011: if ($parmlev eq 'general') {
6012: # course-level parameter
6013: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6014: $$listdata{$newparmkey}=1;
6015: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6016: } elsif ($parmlev eq 'map') {
6017: # map-level parameter
1.548 raeburn 6018: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6019: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6020: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6021: $$listdata{$newparmkey}=1;
6022: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6023: }
6024: } else {
6025: # resource-level parameter
6026: foreach my $rid (@{$ids}) {
6027: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6028: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6029: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6030: $$listdata{$newparmkey}=1;
6031: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6032: }
6033: }
6034: }
6035: }
6036: }
6037:
1.563 damieng 6038: # UI to edit parameter settings starting with a list of all existing parameters.
6039: # (called by setoverview action)
6040: #
6041: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6042: sub overview {
1.568 raeburn 6043: my ($r,$parm_permission) = @_;
1.208 www 6044: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6045: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6046: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6047: my $readonly = 1;
6048: if ($parm_permission->{'edit'}) {
6049: undef($readonly);
6050: }
1.549 raeburn 6051: my $js = '<script type="text/javascript">'."\n".
6052: '// <![CDATA['."\n".
6053: &toggleparmtextbox_js()."\n".
6054: &validateparms_js()."\n".
6055: &ipacc_boxes_js()."\n".
1.558 raeburn 6056: &done_proctor_js()."\n".
1.588 raeburn 6057: &deeplink_js()."\n".
1.549 raeburn 6058: '// ]]>'."\n".
6059: '</script>'."\n";
1.414 droeschl 6060: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6061: text=>"Overview Mode"});
1.549 raeburn 6062: my %loaditems = (
6063: 'onload' => "showHideLenient();",
6064: );
6065:
6066: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6067: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6068: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6069: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6070: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6071:
1.208 www 6072: # Store modified
6073:
1.568 raeburn 6074: unless ($readonly) {
6075: &storedata($r,$crs,$dom);
6076: }
1.208 www 6077:
6078: # Read modified data
6079:
1.552 raeburn 6080: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6081:
1.214 www 6082:
6083: my $sortorder=$env{'form.sortorder'};
6084: unless ($sortorder) { $sortorder='realmstudent'; }
6085: &sortmenu($r,$sortorder);
6086:
1.568 raeburn 6087: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6088:
6089: if ($readonly) {
6090: $r->print('<p>'.$submitbutton.'</p>');
6091: }
6092:
1.208 www 6093: # List data
6094:
1.568 raeburn 6095: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6096: $r->print(&tableend().'<p>');
6097: if ($foundkeys) {
6098: unless ($readonly) {
6099: $r->print('<p>'.$submitbutton.'</p>');
6100: }
6101: } else {
6102: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6103: }
6104: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6105: }
1.121 www 6106:
1.560 damieng 6107: # Unused sub.
1.563 damieng 6108: #
6109: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6110: sub clean_parameters {
6111: my ($r) = @_;
6112: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6113: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6114:
1.414 droeschl 6115: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6116: text=>"Clean Parameters"});
1.333 albertel 6117: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6118: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6119: $r->print(<<ENDOVER);
6120: $start_page
6121: $breadcrumbs
6122: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6123: ENDOVER
6124: # Store modified
6125:
6126: &storedata($r,$crs,$dom);
6127:
6128: # Read modified data
6129:
6130: my $resourcedata=&readdata($crs,$dom);
6131:
6132: # List data
6133:
6134: $r->print('<h3>'.
1.473 amueller 6135: &mt('These parameters refer to resources that do not exist.').
6136: '</h3>'.
6137: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6138: '<br />');
1.333 albertel 6139: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6140: '<tr>'.
6141: '<th>'.&mt('Delete').'</th>'.
6142: '<th>'.&mt('Parameter').'</th>'.
6143: '</tr>');
1.333 albertel 6144: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6145: next if (!exists($resourcedata->{$thiskey.'.type'})
6146: && $thiskey=~/\.type$/);
6147: my %data = &parse_key($thiskey);
6148: if (1) { #exists($data{'realm_exists'})
6149: #&& !$data{'realm_exists'}) {
6150: $r->print(&Apache::loncommon::start_data_table_row().
6151: '<tr>'.
6152: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6153:
6154: $r->print('<td>');
6155: my $display_value = $resourcedata->{$thiskey};
6156: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6157: $display_value =
6158: &Apache::lonlocal::locallocaltime($display_value);
6159: }
1.470 raeburn 6160: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6161: $parmitem = &mt($parmitem);
1.560 damieng 6162: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6163: $parmitem,$resourcedata->{$thiskey}));
6164: $r->print('<br />');
6165: if ($data{'scope_type'} eq 'all') {
6166: $r->print(&mt('All users'));
6167: } elsif ($data{'scope_type'} eq 'user') {
6168: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6169: } elsif ($data{'scope_type'} eq 'secgroup') {
6170: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6171: }
6172: $r->print('<br />');
6173: if ($data{'realm_type'} eq 'all') {
6174: $r->print(&mt('All Resources'));
6175: } elsif ($data{'realm_type'} eq 'folder') {
6176: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6177: } elsif ($data{'realm_type'} eq 'symb') {
6178: my ($map,$resid,$url) =
6179: &Apache::lonnet::decode_symb($data{'realm'});
6180: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6181: $url.' <br /> ',
6182: $resid.' <br /> ',$map));
6183: }
6184: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6185: $r->print('</td></tr>');
6186:
1.473 amueller 6187: }
1.333 albertel 6188: }
6189: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6190: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6191: '</p></form>');
6192: &endSettingsScreen($r);
6193: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6194: }
6195:
1.563 damieng 6196: # UI to shift all dates (called by dateshift1 action).
6197: # Used by overview mode.
6198: #
6199: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6200: sub date_shift_one {
6201: my ($r) = @_;
6202: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6203: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6204: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6205: my $sec = $env{'request.course.sec'};
1.414 droeschl 6206: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6207: text=>"Shifting Dates"});
1.594 raeburn 6208: my $submit_text = &mt('Shift all dates accordingly');
6209: if ($sec ne '') {
1.595 raeburn 6210: my @groups;
6211: if ($env{'request.course.groups'} ne '') {
6212: @groups = split(/:/,$env{'request.course.groups'});
6213: }
6214: if (@groups) {
6215: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6216: } else {
6217: $submit_text = &mt("Shift dates set just for your section, accordingly");
6218: }
1.594 raeburn 6219: }
1.390 www 6220: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6221: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6222: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6223: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6224: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6225: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6226: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6227: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6228: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6229: 'timeshifted',
6230: $env{'form.timebase'},,
6231: '').
6232: '</td></tr></table>'.
6233: '<input type="hidden" name="action" value="dateshift2" />'.
6234: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6235: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6236: &endSettingsScreen($r);
1.390 www 6237: $r->print(&Apache::loncommon::end_page());
6238: }
6239:
1.563 damieng 6240: # UI to shift all dates (second form).
6241: #
6242: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6243: sub date_shift_two {
6244: my ($r) = @_;
6245: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6246: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6247: my $sec = $env{'request.course.sec'};
1.531 raeburn 6248: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6249: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6250: text=>"Shifting Dates"});
1.390 www 6251: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6252: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6253: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6254: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6255: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6256: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6257: if ($sec ne '') {
1.595 raeburn 6258: my @groups;
6259: if ($env{'request.course.groups'} ne '') {
6260: @groups = split(/:/,$env{'request.course.groups'});
6261: }
6262: if (@groups) {
6263: $r->print('<p>'.
6264: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6265: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6266: &Apache::lonlocal::locallocaltime($timeshifted)).
6267: '</p>');
6268: } else {
6269: $r->print('<p>'.
6270: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6271: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6272: &Apache::lonlocal::locallocaltime($timeshifted)).
6273: '</p>');
6274: }
1.594 raeburn 6275: } else {
6276: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6277: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6278: &Apache::lonlocal::locallocaltime($timeshifted)).
6279: '</p>');
6280: }
1.390 www 6281: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6282: my $numchanges = 0;
6283: my $result = &dateshift($delta,\$numchanges);
6284: if ($result eq 'ok') {
6285: $r->print(
6286: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6287: $numchanges)));
6288: } elsif ($result eq 'con_delayed') {
6289: $r->print(
6290: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6291: $numchanges)));
6292: } else {
6293: $r->print(
6294: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6295: }
1.543 bisitz 6296: $r->print(
6297: '<br /><br />'.
6298: &Apache::lonhtmlcommon::actionbox(
6299: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6300: &endSettingsScreen($r);
1.390 www 6301: $r->print(&Apache::loncommon::end_page());
6302: }
6303:
1.563 damieng 6304: # Returns the different components of a resourcedata key.
6305: # Keys: scope_type, scope, realm_type, realm, realm_title,
6306: # realm_exists, parameter_part, parameter_name.
6307: # Was used by clean_parameters (which is unused).
6308: #
6309: # @param {string} $key - the parameter key
6310: # @returns {hash}
1.333 albertel 6311: sub parse_key {
6312: my ($key) = @_;
6313: my %data;
6314: my ($middle,$part,$name)=
1.572 damieng 6315: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6316: $data{'scope_type'} = 'all';
6317: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6318: $data{'scope'} = $1;
6319: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6320: $data{'scope_type'} = 'user';
6321: $data{'scope'} = [$1,$2];
6322: } else {
1.581 raeburn 6323: $data{'scope_type'} = 'secgroup';
1.560 damieng 6324: }
6325: $middle=~s/^\[(.*)\]//;
1.333 albertel 6326: }
6327: $middle=~s/\.+$//;
6328: $middle=~s/^\.+//;
6329: $data{'realm_type'}='all';
6330: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6331: $data{'realm'} = $1;
6332: $data{'realm_type'} = 'folder';
6333: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6334: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6335: } elsif ($middle) {
1.560 damieng 6336: $data{'realm'} = $middle;
6337: $data{'realm_type'} = 'symb';
6338: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6339: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6340: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6341: }
1.446 bisitz 6342:
1.333 albertel 6343: $data{'parameter_part'} = $part;
6344: $data{'parameter_name'} = $name;
6345:
6346: return %data;
6347: }
6348:
1.239 raeburn 6349:
1.563 damieng 6350: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6351: sub header {
1.507 www 6352: return &Apache::loncommon::start_page('Settings');
1.416 jms 6353: }
1.193 albertel 6354:
6355:
6356:
1.560 damieng 6357: ##################################################
6358: # MAIN MENU
6359: ##################################################
6360:
1.563 damieng 6361: # Content and problem settings main menu.
6362: #
6363: # @param {Apache2::RequestRec} $r - the Apache request
6364: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 6365: sub print_main_menu {
6366: my ($r,$parm_permission)=@_;
6367: #
1.414 droeschl 6368: $r->print(&header());
1.507 www 6369: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 6370: my $crstype = &Apache::loncommon::course_type();
6371: my $lc_crstype = lc($crstype);
6372:
6373: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 6374: $r->print(<<ENDMAINFORMHEAD);
6375: <form method="post" enctype="multipart/form-data"
6376: action="/adm/parmset" name="studentform">
6377: ENDMAINFORMHEAD
6378: #
1.195 albertel 6379: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6380: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 6381: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 6382: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 6383: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 6384: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
6385: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 6386: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
6387: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
6388: '/'.$env{'request.course.sec'});
6389: }
1.568 raeburn 6390: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
6391: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
6392: '/'.$env{'request.course.sec'});
6393: }
6394: my (%linktext,%linktitle,%url);
6395: if ($parm_permission->{'edit'}) {
6396: %linktext = (
6397: newoverview => 'Edit Resource Parameters - Overview Mode',
6398: settable => 'Edit Resource Parameters - Table Mode',
6399: setoverview => 'Modify Resource Parameters - Overview Mode',
6400: );
6401: %linktitle = (
6402: newoverview => 'Set/Modify resource parameters in overview mode.',
6403: settable => 'Set/Modify resource parameters in table mode.',
6404: setoverview => 'Set/Modify existing resource parameters in overview mode.',
6405: );
6406: } else {
6407: %linktext = (
6408: newoverview => 'View Resource Parameters - Overview Mode',
6409: settable => 'View Resource Parameters - Table Mode',
6410: setoverview => 'View Resource Parameters - Overview Mode',
6411: );
6412: %linktitle = (
6413: newoverview => 'Display resource parameters in overview mode.',
6414: settable => 'Display resource parameters in table mode.',
6415: setoverview => 'Display existing resource parameters in overview mode.',
6416: );
6417: }
6418: if ($mgr) {
6419: $linktext{'resettimes'} = 'Reset Student Access Times';
6420: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
6421: $url{'resettimes'} = '/adm/helper/resettimes.helper';
6422: } elsif ($vgr) {
6423: $linktext{'resettimes'} = 'Display Student Access Times',
6424: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
6425: $url{'resettimes'} = '/adm/accesstimes';
6426: }
1.193 albertel 6427: my @menu =
1.507 www 6428: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 6429: items => [
6430: { linktext => 'Portfolio Metadata',
6431: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 6432: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 6433: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 6434: icon =>'contact-new.png' ,
6435: },
1.568 raeburn 6436: { linktext => $linktext{'resettimes'},
6437: url => $url{'resettimes'},
6438: permission => ($vgr || $mgr),
6439: linktitle => $linktitle{'resettimes'},
6440: icon => 'start-here.png',
1.473 amueller 6441: },
1.520 raeburn 6442: { linktext => 'Blocking Communication/Resource Access',
6443: url => '/adm/setblock',
1.568 raeburn 6444: permission => ($vcb || $dcm),
1.520 raeburn 6445: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
6446: icon => 'comblock.png',
6447: },
1.473 amueller 6448: { linktext => 'Set Parameter Setting Default Actions',
6449: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 6450: permission => $parm_permission->{'setdefaults'},
1.473 amueller 6451: linktitle =>'Set default actions for parameters.' ,
6452: icon => 'folder-new.png' ,
6453: }]},
6454: { categorytitle => 'New and Existing Parameter Settings for Resources',
6455: items => [
6456: { linktext => 'Edit Resource Parameters - Helper Mode',
6457: url => '/adm/helper/parameter.helper',
1.568 raeburn 6458: permission => $parm_permission->{'helper'},
1.473 amueller 6459: linktitle =>'Set/Modify resource parameters in helper mode.' ,
6460: icon => 'dialog-information.png' ,
6461: #help => 'Parameter_Helper',
6462: },
1.568 raeburn 6463: { linktext => $linktext{'newoverview'},
1.473 amueller 6464: url => '/adm/parmset?action=newoverview',
1.568 raeburn 6465: permission => $parm_permission->{'newoverview'},
6466: linktitle => $linktitle{'newoverview'},
6467: icon => 'edit-find.png',
1.473 amueller 6468: #help => 'Parameter_Overview',
6469: },
1.568 raeburn 6470: { linktext => $linktext{'settable'},
1.473 amueller 6471: url => '/adm/parmset?action=settable',
1.568 raeburn 6472: permission => $parm_permission->{'settable'},
6473: linktitle => $linktitle{'settable'},
6474: icon => 'edit-copy.png',
1.473 amueller 6475: #help => 'Table_Mode',
6476: }]},
1.417 droeschl 6477: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 6478: items => [
1.570 raeburn 6479: { linktext => $linktext{'setoverview'},
1.473 amueller 6480: url => '/adm/parmset?action=setoverview',
1.568 raeburn 6481: permission => $parm_permission->{'setoverview'},
6482: linktitle => $linktitle{'setoverview'},
6483: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 6484: #help => 'Parameter_Overview',
6485: },
6486: { linktext => 'Change Log',
6487: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 6488: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 6489: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 6490: icon => 'document-properties.png',
1.473 amueller 6491: }]}
1.193 albertel 6492: );
1.414 droeschl 6493: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 6494: $r->print('</form>');
1.507 www 6495: &endSettingsScreen($r);
1.539 raeburn 6496: $r->print(&Apache::loncommon::end_page());
1.193 albertel 6497: return;
6498: }
1.414 droeschl 6499:
1.416 jms 6500:
6501:
1.560 damieng 6502: ##################################################
6503: # PORTFOLIO METADATA
6504: ##################################################
6505:
1.563 damieng 6506: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
6507: # It looks like field titles are not localized.
6508: #
6509: # @param {Apache2::RequestRec} $r - the Apache request
6510: # @param {string} $field_name - metadata field name
6511: # @param {string} $field_text - metadata field title, in English unless manually added
6512: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 6513: sub output_row {
1.347 banghart 6514: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 6515: my $output;
1.263 banghart 6516: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
6517: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 6518: if (!defined($options)) {
1.254 banghart 6519: $options = 'active,stuadd';
1.261 banghart 6520: $values = '';
1.252 banghart 6521: }
1.337 banghart 6522: if (!($options =~ /deleted/)) {
6523: my @options= ( ['active', 'Show to student'],
1.418 schafran 6524: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 6525: ['choices','Provide choices for students to select from']);
1.473 amueller 6526: # ['onlyone','Student may select only one choice']);
1.337 banghart 6527: if ($added_flag) {
6528: push @options,['deleted', 'Delete Metadata Field'];
6529: }
1.351 banghart 6530: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 6531: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 6532: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 6533: foreach my $opt (@options) {
1.560 damieng 6534: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
6535: $output .= &Apache::loncommon::continue_data_table_row();
6536: $output .= '<td>'.(' ' x 5).'<label>
6537: <input type="checkbox" name="'.
6538: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
6539: &mt($opt->[1]).'</label></td>';
6540: $output .= &Apache::loncommon::end_data_table_row();
6541: }
1.351 banghart 6542: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 6543: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 6544: $output .= &Apache::loncommon::end_data_table_row();
6545: my $multiple_checked;
6546: my $single_checked;
6547: if ($options =~ m/onlyone/) {
1.422 bisitz 6548: $multiple_checked = '';
1.423 bisitz 6549: $single_checked = ' checked="checked"';
1.351 banghart 6550: } else {
1.423 bisitz 6551: $multiple_checked = ' checked="checked"';
1.422 bisitz 6552: $single_checked = '';
1.351 banghart 6553: }
1.560 damieng 6554: $output .= &Apache::loncommon::continue_data_table_row();
6555: $output .= '<td>'.(' ' x 10).'
6556: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
6557: '.&mt('Student may select multiple choices from list').'</td>';
6558: $output .= &Apache::loncommon::end_data_table_row();
6559: $output .= &Apache::loncommon::continue_data_table_row();
6560: $output .= '<td>'.(' ' x 10).'
6561: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
6562: '.&mt('Student may select only one choice from list').'</td>';
6563: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 6564: }
6565: return ($output);
6566: }
1.416 jms 6567:
6568:
1.560 damieng 6569: # UI to order portfolio metadata fields.
1.563 damieng 6570: # Currently useless because addmetafield does not work.
6571: #
6572: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 6573: sub order_meta_fields {
6574: my ($r)=@_;
6575: my $idx = 1;
6576: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6577: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6578: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 6579: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 6580: &Apache::lonhtmlcommon::add_breadcrumb(
6581: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6582: text=>"Add Metadata Field"});
1.560 damieng 6583: &Apache::lonhtmlcommon::add_breadcrumb(
6584: {href=>"/adm/parmset?action=setrestrictmeta",
6585: text=>"Restrict Metadata"},
6586: {text=>"Order Metadata"});
1.345 banghart 6587: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 6588: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 6589: if ($env{'form.storeorder'}) {
6590: my $newpos = $env{'form.newpos'} - 1;
6591: my $currentpos = $env{'form.currentpos'} - 1;
6592: my @neworder = ();
1.548 raeburn 6593: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6594: my $i;
1.341 banghart 6595: if ($newpos > $currentpos) {
1.340 banghart 6596: # moving stuff up
6597: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 6598: $neworder[$i]=$oldorder[$i];
1.340 banghart 6599: }
6600: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 6601: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 6602: }
6603: $neworder[$newpos]=$oldorder[$currentpos];
6604: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 6605: $neworder[$i]=$oldorder[$i];
1.340 banghart 6606: }
6607: } else {
6608: # moving stuff down
1.473 amueller 6609: for ($i=0;$i<$newpos;$i++) {
6610: $neworder[$i]=$oldorder[$i];
6611: }
6612: $neworder[$newpos]=$oldorder[$currentpos];
6613: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
6614: $neworder[$i]=$oldorder[$i-1];
6615: }
6616: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
6617: $neworder[$i]=$oldorder[$i];
6618: }
1.340 banghart 6619: }
1.560 damieng 6620: my $ordered_fields = join ",", @neworder;
1.343 banghart 6621: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 6622: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6623: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 6624: }
1.357 raeburn 6625: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 6626: my $ordered_fields;
1.548 raeburn 6627: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6628: if (!@fields_in_order) {
6629: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 6630: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 6631: push @fields_in_order, $key;
1.341 banghart 6632: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 6633: }
1.341 banghart 6634: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 6635: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6636: }
1.340 banghart 6637: $r->print('<table>');
6638: my $num_fields = scalar(@fields_in_order);
6639: foreach my $key (@fields_in_order) {
6640: $r->print('<tr><td>');
6641: $r->print('<form method="post" action="">');
1.537 bisitz 6642: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 6643: for (my $i = 1;$i le $num_fields;$i ++) {
6644: if ($i eq $idx) {
6645: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
6646: } else {
6647: $r->print('<option value="'.$i.'">'.$i.'</option>');
6648: }
6649: }
6650: $r->print('</select></td><td>');
6651: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
6652: $r->print('<input type="hidden" name="storeorder" value="true" />');
6653: $r->print('</form>');
6654: $r->print($$fields{$key}.'</td></tr>');
6655: $idx ++;
6656: }
6657: $r->print('</table>');
1.507 www 6658: &endSettingsScreen($r);
1.340 banghart 6659: return 'ok';
6660: }
1.416 jms 6661:
6662:
1.563 damieng 6663: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
6664: # @returns {string}
1.359 banghart 6665: sub continue {
6666: my $output;
6667: $output .= '<form action="" method="post">';
6668: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 6669: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 6670: return ($output);
6671: }
1.416 jms 6672:
6673:
1.563 damieng 6674: # UI to add a metadata field.
6675: # Currenly does not work because of an HTML error (the field is not visible).
6676: #
6677: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 6678: sub addmetafield {
6679: my ($r)=@_;
1.414 droeschl 6680: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6681: text=>"Add Metadata Field"});
1.334 banghart 6682: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
6683: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 6684: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6685: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6686: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6687: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 6688: if (exists($env{'form.undelete'})) {
1.358 banghart 6689: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 6690: foreach my $meta_field(@meta_fields) {
6691: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
6692: $options =~ s/deleted//;
6693: $options =~ s/,,/,/;
6694: my $put_result = &Apache::lonnet::put('environment',
6695: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 6696:
1.586 raeburn 6697: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
6698: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
6699: '</strong>',$put_result).
6700: '<br />');
1.339 banghart 6701: }
1.359 banghart 6702: $r->print(&continue());
1.339 banghart 6703: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 6704: my $meta_field = $env{'form.fieldname'};
6705: my $display_field = $env{'form.fieldname'};
6706: $meta_field =~ s/\W/_/g;
1.338 banghart 6707: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 6708: my $put_result = &Apache::lonnet::put('environment',
6709: {'metadata.'.$meta_field.'.values'=>"",
6710: 'metadata.'.$meta_field.'.added'=>"$display_field",
6711: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 6712: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
6713: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
6714: '<br />');
1.359 banghart 6715: $r->print(&continue());
1.335 banghart 6716: } else {
1.357 raeburn 6717: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 6718: if ($fields) {
1.586 raeburn 6719: $r->print(&mt('You may undelete previously deleted fields.').
6720: '<br />'.
6721: &mt('Check those you wish to undelete and click Undelete.').
6722: '<br />');
1.339 banghart 6723: $r->print('<form method="post" action="">');
6724: foreach my $key(keys(%$fields)) {
1.581 raeburn 6725: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 6726: }
1.586 raeburn 6727: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 6728: $r->print('</form>');
6729: }
1.586 raeburn 6730: $r->print('<hr />'.
6731: &mt('[_1]Or[_2] you may enter a new metadata field name.',
6732: '<strong>','</strong>').
1.581 raeburn 6733: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 6734: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 6735: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 6736: $r->print('</form>');
1.334 banghart 6737: }
1.507 www 6738: &endSettingsScreen($r);
1.334 banghart 6739: }
1.416 jms 6740:
6741:
6742:
1.560 damieng 6743: # Display or save portfolio metadata.
1.563 damieng 6744: #
6745: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 6746: sub setrestrictmeta {
1.240 banghart 6747: my ($r)=@_;
1.242 banghart 6748: my $next_meta;
1.244 banghart 6749: my $output;
1.245 banghart 6750: my $item_num;
1.246 banghart 6751: my $put_result;
1.414 droeschl 6752: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 6753: text=>"Restrict Metadata"});
1.280 albertel 6754: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 6755: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 6756: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6757: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6758: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6759: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 6760: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 6761: my $save_field = '';
1.586 raeburn 6762: my %lt = &Apache::lonlocal::texthash(
6763: addm => 'Add Metadata Field',
6764: ordm => 'Order Metadata Fields',
6765: save => 'Save',
6766: );
1.259 banghart 6767: if ($env{'form.restrictmeta'}) {
1.254 banghart 6768: foreach my $field (sort(keys(%env))) {
1.252 banghart 6769: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 6770: my $options;
1.252 banghart 6771: my $meta_field = $1;
6772: my $meta_key = $2;
1.253 banghart 6773: if ($save_field ne $meta_field) {
1.252 banghart 6774: $save_field = $meta_field;
1.473 amueller 6775: if ($env{'form.'.$meta_field.'_stuadd'}) {
6776: $options.='stuadd,';
6777: }
6778: if ($env{'form.'.$meta_field.'_choices'}) {
6779: $options.='choices,';
6780: }
6781: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
6782: $options.='onlyone,';
6783: }
6784: if ($env{'form.'.$meta_field.'_active'}) {
6785: $options.='active,';
6786: }
6787: if ($env{'form.'.$meta_field.'_deleted'}) {
6788: $options.='deleted,';
6789: }
1.259 banghart 6790: my $name = $save_field;
1.560 damieng 6791: $put_result = &Apache::lonnet::put('environment',
6792: {'metadata.'.$meta_field.'.options'=>$options,
6793: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
6794: },$dom,$crs);
1.252 banghart 6795: }
6796: }
6797: }
6798: }
1.296 albertel 6799: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 6800: {'freshen_cache' => 1});
1.335 banghart 6801: # Get the default metadata fields
1.258 albertel 6802: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 6803: # Now get possible added metadata fields
1.357 raeburn 6804: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 6805: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 6806: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 6807: if ($field ne 'courserestricted') {
1.586 raeburn 6808: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 6809: }
1.255 banghart 6810: }
1.351 banghart 6811: my $buttons = (<<ENDButtons);
1.586 raeburn 6812: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 6813: </form><br />
6814: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 6815: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 6816: </form>
6817: <br />
6818: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 6819: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 6820: ENDButtons
1.337 banghart 6821: my $added_flag = 1;
1.335 banghart 6822: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 6823: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 6824: }
1.347 banghart 6825: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 6826: $r->print(<<ENDenv);
1.259 banghart 6827: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 6828: $output
1.351 banghart 6829: $buttons
1.340 banghart 6830: </form>
1.244 banghart 6831: ENDenv
1.507 www 6832: &endSettingsScreen($r);
1.280 albertel 6833: $r->print(&Apache::loncommon::end_page());
1.240 banghart 6834: return 'ok';
6835: }
1.416 jms 6836:
6837:
1.563 damieng 6838: # Returns metadata fields that have been manually added.
6839: #
6840: # @param {string} $cid - course id
6841: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 6842: sub get_added_meta_fieldnames {
1.357 raeburn 6843: my ($cid) = @_;
1.335 banghart 6844: my %fields;
6845: foreach my $key(%env) {
1.357 raeburn 6846: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 6847: my $field_name = $1;
6848: my ($display_field_name) = $env{$key};
6849: $fields{$field_name} = $display_field_name;
6850: }
6851: }
6852: return \%fields;
6853: }
1.416 jms 6854:
6855:
1.563 damieng 6856: # Returns metadata fields that have been manually added and deleted.
6857: #
6858: # @param {string} $cid - course id
6859: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 6860: sub get_deleted_meta_fieldnames {
1.357 raeburn 6861: my ($cid) = @_;
1.339 banghart 6862: my %fields;
6863: foreach my $key(%env) {
1.357 raeburn 6864: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 6865: my $field_name = $1;
6866: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
6867: my ($display_field_name) = $env{$key};
6868: $fields{$field_name} = $display_field_name;
6869: }
6870: }
6871: }
6872: return \%fields;
6873: }
1.560 damieng 6874:
6875:
6876: ##################################################
6877: # PARAMETER SETTINGS DEFAULT ACTIONS
6878: ##################################################
6879:
6880: # UI to change parameter setting default actions
1.563 damieng 6881: #
6882: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 6883: sub defaultsetter {
1.280 albertel 6884: my ($r) = @_;
6885:
1.414 droeschl 6886: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 6887: text=>"Set Defaults"});
1.531 raeburn 6888: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6889: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6890: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 6891: my $start_page =
1.531 raeburn 6892: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 6893: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 6894: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6895: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 6896: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 6897:
1.221 www 6898: my @ids=();
6899: my %typep=();
6900: my %keyp=();
6901: my %allparms=();
6902: my %allparts=();
6903: my %allmaps=();
6904: my %mapp=();
6905: my %symbp=();
6906: my %maptitles=();
6907: my %uris=();
6908: my %keyorder=&standardkeyorder();
6909: my %defkeytype=();
6910:
1.446 bisitz 6911: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 6912: \%mapp, \%symbp,\%maptitles,\%uris,
6913: \%keyorder,\%defkeytype);
1.224 www 6914: if ($env{'form.storerules'}) {
1.560 damieng 6915: my %newrules=();
6916: my @delrules=();
6917: my %triggers=();
6918: foreach my $key (keys(%env)) {
1.225 albertel 6919: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 6920: my $tempkey=$1;
6921: my $action=$env{$key};
1.226 www 6922: if ($action) {
1.560 damieng 6923: $newrules{$tempkey.'_action'}=$action;
6924: if ($action ne 'default') {
6925: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
6926: $triggers{$whichparm}.=$tempkey.':';
6927: }
6928: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
6929: if (&isdateparm($defkeytype{$tempkey})) {
6930: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
6931: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
6932: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
6933: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
6934: } else {
6935: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
6936: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
6937: }
6938: } else {
6939: push(@delrules,$tempkey.'_action');
6940: push(@delrules,$tempkey.'_type');
6941: push(@delrules,$tempkey.'_hours');
6942: push(@delrules,$tempkey.'_min');
6943: push(@delrules,$tempkey.'_sec');
6944: push(@delrules,$tempkey.'_value');
6945: }
1.473 amueller 6946: }
6947: }
1.560 damieng 6948: foreach my $key (keys(%allparms)) {
6949: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 6950: }
1.560 damieng 6951: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
6952: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
6953: &resetrulescache();
1.224 www 6954: }
1.227 www 6955: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 6956: 'hours' => 'Hours',
6957: 'min' => 'Minutes',
6958: 'sec' => 'Seconds',
6959: 'yes' => 'Yes',
6960: 'no' => 'No');
1.222 www 6961: my @standardoptions=('','default');
6962: my @standarddisplay=('',&mt('Default value when manually setting'));
6963: my @dateoptions=('','default');
6964: my @datedisplay=('',&mt('Default value when manually setting'));
6965: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 6966: unless ($tempkey) { next; }
6967: push @standardoptions,'when_setting_'.$tempkey;
6968: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
6969: if (&isdateparm($defkeytype{$tempkey})) {
6970: push @dateoptions,'later_than_'.$tempkey;
6971: push @datedisplay,&mt('Automatically set later than ').$tempkey;
6972: push @dateoptions,'earlier_than_'.$tempkey;
6973: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
6974: }
1.222 www 6975: }
1.563 damieng 6976: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
6977: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 6978: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 6979: &Apache::loncommon::start_data_table_header_row().
6980: "<th>".&mt('Rule for parameter').'</th><th>'.
6981: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
6982: &Apache::loncommon::end_data_table_header_row());
1.221 www 6983: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 6984: unless ($tempkey) { next; }
6985: $r->print("\n".&Apache::loncommon::start_data_table_row().
6986: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
6987: my $action=&rulescache($tempkey.'_action');
6988: $r->print('<select name="'.$tempkey.'_action">');
6989: if (&isdateparm($defkeytype{$tempkey})) {
6990: for (my $i=0;$i<=$#dateoptions;$i++) {
6991: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
6992: $r->print("\n<option value='$dateoptions[$i]'".
6993: ($dateoptions[$i] eq $action?' selected="selected"':'').
6994: ">$datedisplay[$i]</option>");
6995: }
6996: } else {
6997: for (my $i=0;$i<=$#standardoptions;$i++) {
6998: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
6999: $r->print("\n<option value='$standardoptions[$i]'".
7000: ($standardoptions[$i] eq $action?' selected="selected"':'').
7001: ">$standarddisplay[$i]</option>");
7002: }
1.473 amueller 7003: }
1.560 damieng 7004: $r->print('</select>');
7005: unless (&isdateparm($defkeytype{$tempkey})) {
7006: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7007: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7008: }
1.560 damieng 7009: $r->print("\n</td><td>\n");
1.222 www 7010:
1.221 www 7011: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7012: my $days=&rulescache($tempkey.'_days');
7013: my $hours=&rulescache($tempkey.'_hours');
7014: my $min=&rulescache($tempkey.'_min');
7015: my $sec=&rulescache($tempkey.'_sec');
7016: $r->print(<<ENDINPUTDATE);
7017: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7018: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7019: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7020: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7021: ENDINPUTDATE
1.560 damieng 7022: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7023: my $yeschecked='';
7024: my $nochecked='';
7025: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7026: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7027:
7028: $r->print(<<ENDYESNO);
7029: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7030: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7031: ENDYESNO
1.221 www 7032: } else {
1.560 damieng 7033: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7034: }
1.318 albertel 7035: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7036: }
1.318 albertel 7037: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7038: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7039: &mt('Save').'" /></form>'."\n");
7040: &endSettingsScreen($r);
7041: $r->print(&Apache::loncommon::end_page());
1.220 www 7042: return;
7043: }
1.193 albertel 7044:
1.560 damieng 7045: ##################################################
7046: # PARAMETER CHANGES LOG
7047: ##################################################
7048:
1.563 damieng 7049: # Returns some info for a parameter log entry.
7050: # Returned entries:
7051: # $realm - HTML title for the parameter level and resource
7052: # $section - parameter section
7053: # $name - parameter name
7054: # $part - parameter part
7055: # $what - $part.'.'.$name
7056: # $middle - resource symb ?
7057: # $uname - user name (same as given)
7058: # $udom - user domain (same as given)
7059: # $issection - section or group name
7060: # $realmdescription - title for the parameter level and resource (without using HTML)
7061: #
7062: # @param {string} $key - parameter log key
7063: # @param {string} $uname - user name
7064: # @param {string} $udom - user domain
7065: # @param {boolean} $typeflag - .type log entry
7066: # @returns {Array}
1.290 www 7067: sub components {
1.581 raeburn 7068: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7069:
7070: if ($typeflag) {
1.560 damieng 7071: $key=~s/\.type$//;
1.290 www 7072: }
1.330 albertel 7073:
7074: my ($middle,$part,$name)=
1.572 damieng 7075: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7076: my $issection;
1.330 albertel 7077:
1.290 www 7078: my $section=&mt('All Students');
7079: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7080: $issection=$1;
7081: $section=&mt('Group/Section').': '.$issection;
7082: $middle=~s/^\[(.*)\]//;
1.290 www 7083: }
7084: $middle=~s/\.+$//;
7085: $middle=~s/^\.+//;
1.291 www 7086: if ($uname) {
1.560 damieng 7087: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7088: $issection='';
1.291 www 7089: }
1.316 albertel 7090: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7091: my $realmdescription=&mt('all resources');
1.556 raeburn 7092: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7093: my $mapurl = $1;
7094: my $maplevel = $2;
7095: my $leveltitle = &mt('Folder/Map');
7096: if ($maplevel eq 'rec') {
7097: $leveltitle = &mt('Recursive');
7098: }
1.560 damieng 7099: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7100: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7101: $mapurl.')</span></span>';
7102: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7103: } elsif ($middle) {
7104: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7105: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7106: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7107: ' in '.$map.' id: '.$id.')</span></span>';
7108: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7109: }
1.291 www 7110: my $what=$part.'.'.$name;
1.330 albertel 7111: return ($realm,$section,$name,$part,
1.473 amueller 7112: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7113: }
1.293 www 7114:
1.563 damieng 7115: my %standard_parms; # hash parameter name -> parameter title (not localized)
7116: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7117:
1.563 damieng 7118: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7119: sub load_parameter_names {
1.583 raeburn 7120: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7121: while (my $configline=<$config>) {
1.560 damieng 7122: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7123: chomp($configline);
7124: my ($short,$plain)=split(/:/,$configline);
7125: my (undef,$name,$type)=split(/\&/,$short,3);
7126: if ($type eq 'display') {
7127: $standard_parms{$name} = $plain;
1.469 raeburn 7128: } elsif ($type eq 'type') {
1.560 damieng 7129: $standard_parms_types{$name} = $plain;
1.469 raeburn 7130: }
1.328 albertel 7131: }
7132: close($config);
7133: $standard_parms{'int_pos'} = 'Positive Integer';
7134: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7135: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7136: }
7137:
1.563 damieng 7138: # Returns a parameter title for standard parameters, the name for others.
7139: #
7140: # @param {string} $name - parameter name
7141: # @returns {string}
1.292 www 7142: sub standard_parameter_names {
7143: my ($name)=@_;
1.328 albertel 7144: if (!%standard_parms) {
1.560 damieng 7145: &load_parameter_names();
1.328 albertel 7146: }
1.292 www 7147: if ($standard_parms{$name}) {
1.560 damieng 7148: return $standard_parms{$name};
1.446 bisitz 7149: } else {
1.560 damieng 7150: return $name;
1.292 www 7151: }
7152: }
1.290 www 7153:
1.563 damieng 7154: # Returns a parameter type for standard parameters, undef for others.
7155: #
7156: # @param {string} $name - parameter name
7157: # @returns {string}
1.469 raeburn 7158: sub standard_parameter_types {
7159: my ($name)=@_;
7160: if (!%standard_parms_types) {
7161: &load_parameter_names();
7162: }
7163: if ($standard_parms_types{$name}) {
7164: return $standard_parms_types{$name};
7165: }
7166: return;
7167: }
1.309 www 7168:
1.563 damieng 7169: # Returns a parameter level title (not localized) from the parameter level name.
7170: #
7171: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7172: # @returns {string}
1.557 raeburn 7173: sub standard_parameter_levels {
7174: my ($name)=@_;
7175: my %levels = (
7176: 'resourcelevel' => 'a single resource',
7177: 'maplevel' => 'the enclosing map/folder',
7178: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7179: 'courselevel' => 'the general (course) level',
7180: );
7181: if ($levels{$name}) {
7182: return $levels{$name};
7183: }
7184: return;
7185: }
7186:
1.560 damieng 7187: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7188: #
7189: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7190: sub parm_change_log {
1.568 raeburn 7191: my ($r,$parm_permission)=@_;
1.531 raeburn 7192: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7193: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7194: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7195: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7196: text=>"Parameter Change Log"});
1.522 raeburn 7197: my $js = '<script type="text/javascript">'."\n".
7198: '// <![CDATA['."\n".
7199: &Apache::loncommon::display_filter_js('parmslog')."\n".
7200: '// ]]>'."\n".
7201: '</script>'."\n";
7202: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7203: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7204: &startSettingsScreen($r,'parmset',$crstype);
7205: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7206:
1.301 www 7207: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7208:
1.522 raeburn 7209: $r->print('<div class="LC_left_float">'.
7210: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7211: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7212: method="post" name="parameterlog">');
1.446 bisitz 7213:
1.311 albertel 7214: my %saveable_parameters = ('show' => 'scalar',);
7215: &Apache::loncommon::store_course_settings('parameter_log',
7216: \%saveable_parameters);
7217: &Apache::loncommon::restore_course_settings('parameter_log',
7218: \%saveable_parameters);
1.522 raeburn 7219: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7220: '<input type="submit" value="'.&mt('Display').'" />'.
7221: '</form></fieldset></div><br clear="all" />');
1.301 www 7222:
1.568 raeburn 7223: my $readonly = 1;
7224: if ($parm_permission->{'edit'}) {
7225: undef($readonly);
7226: }
1.531 raeburn 7227: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7228: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7229: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7230: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7231: unless ($readonly) {
7232: $r->print('<th>'.&mt('Announce').'</th>');
7233: }
7234: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7235: my $shown=0;
1.349 www 7236: my $folder='';
7237: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7238: my $last='';
7239: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7240: &GDBM_READER(),0640)) {
7241: $last=$hash{'last_known'};
7242: untie(%hash);
7243: }
7244: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7245: }
1.595 raeburn 7246: my $numgroups = 0;
7247: my @groups;
7248: if ($env{'request.course.groups'} ne '') {
7249: @groups = split(/:/,$env{'request.course.groups'});
7250: $numgroups = scalar(@groups);
7251: }
1.560 damieng 7252: foreach my $id (sort {
7253: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7254: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7255: }
7256: my $aid = (split('00000',$a))[-1];
7257: my $bid = (split('00000',$b))[-1];
7258: return $bid<=>$aid;
1.473 amueller 7259: } (keys(%parmlog))) {
1.294 www 7260: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7261: my $count = 0;
7262: my $time =
7263: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7264: my $plainname =
7265: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7266: $parmlog{$id}{'exe_udom'});
7267: my $about_me_link =
7268: &Apache::loncommon::aboutmewrapper($plainname,
7269: $parmlog{$id}{'exe_uname'},
7270: $parmlog{$id}{'exe_udom'});
7271: my $send_msg_link='';
1.568 raeburn 7272: if ((!$readonly) &&
7273: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7274: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7275: $send_msg_link ='<br />'.
7276: &Apache::loncommon::messagewrapper(&mt('Send message'),
7277: $parmlog{$id}{'exe_uname'},
7278: $parmlog{$id}{'exe_udom'});
7279: }
7280: my $row_start=&Apache::loncommon::start_data_table_row();
7281: my $makenewrow=0;
7282: my %istype=();
7283: my $output;
7284: foreach my $changed (reverse(sort(@changes))) {
7285: my $value=$parmlog{$id}{'logentry'}{$changed};
7286: my $typeflag = ($changed =~/\.type$/ &&
7287: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7288: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7289: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7290: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7291: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7292: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7293: if ($uname ne '') {
7294: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7295: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7296: }
7297: }
7298: if ($env{'form.displayfilter'} eq 'currentfolder') {
7299: if ($folder) {
7300: if ($middle!~/^\Q$folder\E/) { next; }
7301: }
7302: }
7303: if ($typeflag) {
7304: $istype{$parmname}=$value;
7305: if (!$env{'form.includetypes'}) { next; }
7306: }
7307: $count++;
7308: if ($makenewrow) {
7309: $output .= $row_start;
7310: } else {
7311: $makenewrow=1;
7312: }
1.470 raeburn 7313: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7314: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7315: &mt($parmitem).'</td><td>'.
7316: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7317: my $stillactive=0;
7318: if ($parmlog{$id}{'delflag'}) {
7319: $output .= &mt('Deleted');
7320: } else {
7321: if ($typeflag) {
1.470 raeburn 7322: my $parmitem = &standard_parameter_names($value);
7323: $parmitem = &mt($parmitem);
1.560 damieng 7324: $output .= &mt('Type: [_1]',$parmitem);
7325: } else {
1.584 raeburn 7326: my $toolsymb;
7327: if ($middle =~ /ext\.tool$/) {
7328: $toolsymb = $middle;
7329: }
1.560 damieng 7330: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7331: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7332: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7333: my $showvalue = $value;
7334: if ($istype{$parmname} eq '') {
7335: my $type = &standard_parameter_types($parmname);
7336: if ($type ne '') {
7337: if (&isdateparm($type)) {
7338: $showvalue =
7339: &Apache::lonlocal::locallocaltime($value);
7340: }
7341: }
7342: } else {
1.560 damieng 7343: if (&isdateparm($istype{$parmname})) {
7344: $showvalue = &Apache::lonlocal::locallocaltime($value);
7345: }
1.469 raeburn 7346: }
7347: $output .= $showvalue;
1.560 damieng 7348: if ($value ne $all[$level]) {
7349: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7350: } else {
7351: $stillactive=1;
7352: }
7353: }
1.473 amueller 7354: }
1.568 raeburn 7355: $output .= '</td>';
7356:
7357: unless ($readonly) {
7358: $output .= '<td>';
7359: if ($stillactive) {
7360: my $parmitem = &standard_parameter_names($parmname);
7361: $parmitem = &mt($parmitem);
7362: my $title=&mt('Changed [_1]',$parmitem);
7363: my $description=&mt('Changed [_1] for [_2] to [_3]',
7364: $parmitem,$realmdescription,
7365: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
7366: if (($uname) && ($udom)) {
7367: $output .=
7368: &Apache::loncommon::messagewrapper('Notify User',
7369: $uname,$udom,$title,
7370: $description);
7371: } else {
7372: $output .=
7373: &Apache::lonrss::course_blog_link($id,$title,
7374: $description);
7375: }
1.560 damieng 7376: }
1.568 raeburn 7377: $output .= '</td>';
1.560 damieng 7378: }
1.568 raeburn 7379: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 7380: }
1.560 damieng 7381: if ($env{'form.displayfilter'} eq 'containing') {
7382: my $wholeentry=$about_me_link.':'.
7383: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
7384: $output;
7385: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 7386: }
1.349 www 7387: if ($count) {
1.560 damieng 7388: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
7389: <td rowspan="'.$count.'">'.$about_me_link.
7390: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
7391: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
7392: $send_msg_link.'</td>'.$output);
7393: $shown++;
7394: }
7395: if (!($env{'form.show'} eq &mt('all')
7396: || $shown<=$env{'form.show'})) { last; }
1.286 www 7397: }
1.301 www 7398: $r->print(&Apache::loncommon::end_data_table());
1.507 www 7399: &endSettingsScreen($r);
1.284 www 7400: $r->print(&Apache::loncommon::end_page());
7401: }
7402:
1.560 damieng 7403: ##################################################
7404: # MISC !
7405: ##################################################
7406:
1.563 damieng 7407: # Stores slot information.
1.560 damieng 7408: # Used by table UI
1.563 damieng 7409: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7410: #
7411: # @param {string} $slot_name - slot name
7412: # @param {string} $cdom - course domain
7413: # @param {string} $cnum - course number
7414: # @param {string} $symb - resource symb
7415: # @param {string} $uname - user name
7416: # @param {string} $udom - user domain
7417: # @returns {string} - 'ok' or error name
1.437 raeburn 7418: sub update_slots {
7419: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
7420: my %slot=&Apache::lonnet::get_slot($slot_name);
7421: if (!keys(%slot)) {
7422: return 'error: slot does not exist';
7423: }
7424: my $max=$slot{'maxspace'};
7425: if (!defined($max)) { $max=99999; }
7426:
7427: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
7428: "^$slot_name\0");
7429: my ($tmp)=%consumed;
7430: if ($tmp=~/^error: 2 / ) {
7431: return 'error: unable to determine current slot status';
7432: }
7433: my $last=0;
7434: foreach my $key (keys(%consumed)) {
7435: my $num=(split('\0',$key))[1];
7436: if ($num > $last) { $last=$num; }
7437: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7438: return 'ok';
7439: }
7440: }
7441:
7442: if (scalar(keys(%consumed)) >= $max) {
7443: return 'error: no space left in slot';
7444: }
7445: my $wanted=$last+1;
7446:
7447: my %reservation=('name' => $uname.':'.$udom,
7448: 'timestamp' => time,
7449: 'symb' => $symb);
7450:
7451: my $success=&Apache::lonnet::newput('slot_reservations',
7452: {"$slot_name\0$wanted" =>
7453: \%reservation},
7454: $cdom, $cnum);
1.438 raeburn 7455: if ($success eq 'ok') {
7456: my %storehash = (
7457: symb => $symb,
7458: slot => $slot_name,
7459: action => 'reserve',
7460: context => 'parameter',
7461: );
1.526 raeburn 7462: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7463: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 7464:
1.526 raeburn 7465: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7466: '',$uname,$udom,$uname,$udom);
1.438 raeburn 7467: }
1.437 raeburn 7468: return $success;
7469: }
7470:
1.563 damieng 7471: # Deletes a slot reservation.
1.560 damieng 7472: # Used by table UI
1.563 damieng 7473: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7474: #
7475: # @param {string} $slot_name - slot name
7476: # @param {string} $cdom - course domain
7477: # @param {string} $cnum - course number
7478: # @param {string} $uname - user name
7479: # @param {string} $udom - user domain
7480: # @param {string} $symb - resource symb
7481: # @returns {string} - 'ok' or error name
1.437 raeburn 7482: sub delete_slots {
7483: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
7484: my $delresult;
7485: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
7486: $cnum, "^$slot_name\0");
7487: if (&Apache::lonnet::error(%consumed)) {
7488: return 'error: unable to determine current slot status';
7489: }
7490: my ($tmp)=%consumed;
7491: if ($tmp=~/^error: 2 /) {
7492: return 'error: unable to determine current slot status';
7493: }
7494: foreach my $key (keys(%consumed)) {
7495: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7496: my $num=(split('\0',$key))[1];
7497: my $entry = $slot_name.'\0'.$num;
7498: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
7499: $cdom,$cnum);
7500: if ($delresult eq 'ok') {
7501: my %storehash = (
7502: symb => $symb,
7503: slot => $slot_name,
7504: action => 'release',
7505: context => 'parameter',
7506: );
1.526 raeburn 7507: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7508: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 7509: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7510: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 7511: }
7512: }
7513: }
7514: return $delresult;
7515: }
7516:
1.563 damieng 7517: # Returns true if there is a current course.
1.560 damieng 7518: # Used by handler
1.563 damieng 7519: #
7520: # @returns {boolean}
1.355 albertel 7521: sub check_for_course_info {
7522: my $navmap = Apache::lonnavmaps::navmap->new();
7523: return 1 if ($navmap);
7524: return 0;
7525: }
7526:
1.563 damieng 7527: # Returns the current course host and host LON-CAPA version.
7528: #
7529: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 7530: sub parameter_release_vars {
1.504 raeburn 7531: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7532: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
7533: my $chostname = &Apache::lonnet::hostname($chome);
7534: my ($cmajor,$cminor) =
7535: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
7536: return ($chostname,$cmajor,$cminor);
7537: }
7538:
1.563 damieng 7539: # Checks if the course host version can handle a parameter required version,
7540: # and if it does, stores the release needed for the course.
7541: #
7542: # @param {string} $name - parameter name
7543: # @param {string} $value - parameter value
7544: # @param {string} $valmatch - name of the test used for checking the value
7545: # @param {string} $namematch - name of the test used for checking the name
7546: # @param {string} $needsrelease - version needed by the parameter, major.minor
7547: # @param {integer} $cmajor - course major version number
7548: # @param {integer} $cminor - course minor version number
7549: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 7550: sub parameter_releasecheck {
1.557 raeburn 7551: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 7552: my $needsnewer;
7553: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
7554: if (($cmajor < $needsmajor) ||
7555: ($cmajor == $needsmajor && $cminor < $needsminor)) {
7556: $needsnewer = 1;
1.557 raeburn 7557: } elsif ($name) {
7558: if ($valmatch) {
7559: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
7560: } elsif ($value) {
7561: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
7562: }
7563: } elsif ($namematch) {
7564: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 7565: }
7566: return $needsnewer;
7567: }
7568:
1.568 raeburn 7569: sub get_permission {
7570: my %permission;
7571: my $allowed = 0;
7572: return (\%permission,$allowed) unless ($env{'request.course.id'});
7573: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
7574: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
7575: $env{'request.course.sec'}))) {
7576: %permission= (
7577: 'edit' => 1,
7578: 'set' => 1,
7579: 'setoverview' => 1,
7580: 'addmetadata' => 1,
7581: 'ordermetadata' => 1,
7582: 'setrestrictmeta' => 1,
7583: 'newoverview' => 1,
7584: 'setdefaults' => 1,
7585: 'settable' => 1,
7586: 'parameterchangelog' => 1,
7587: 'cleanparameters' => 1,
7588: 'dateshift1' => 1,
7589: 'dateshift2' => 1,
7590: 'helper' => 1,
7591: );
7592: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
7593: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
7594: $env{'request.course.sec'}))) {
7595: %permission = (
7596: 'set' => 1,
7597: 'settable' => 1,
7598: 'newoverview' => 1,
7599: 'setoverview' => 1,
7600: 'parameterchangelog' => 1,
7601: );
7602: }
7603: foreach my $perm (values(%permission)) {
7604: if ($perm) { $allowed=1; last; }
7605: }
7606: return (\%permission,$allowed);
7607: }
7608:
1.560 damieng 7609: ##################################################
7610: # HANDLER
7611: ##################################################
7612:
7613: # Main handler for lonparmset.
7614: # Sub called based on request parameters action and command:
7615: # no command or action: print_main_menu
7616: # command 'set': assessparms (direct access to table mode for a resource)
7617: # (this can also be accessed simply with the symb parameter)
7618: # action 'setoverview': overview (display all existing parameter settings)
7619: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
7620: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
7621: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
7622: # action 'newoverview': newoverview (overview mode)
7623: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
7624: # action 'settable': assessparms (table mode)
7625: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
7626: # blog postings, user notification changes)
7627: # action 'cleanparameters': clean_parameters (unused)
7628: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
7629: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 7630: sub handler {
1.43 albertel 7631: my $r=shift;
1.30 www 7632:
1.376 albertel 7633: &reset_caches();
7634:
1.414 droeschl 7635: &Apache::loncommon::content_type($r,'text/html');
7636: $r->send_http_header;
7637: return OK if $r->header_only;
7638:
1.193 albertel 7639: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 7640: ['action','state',
1.205 www 7641: 'pres_marker',
7642: 'pres_value',
1.206 www 7643: 'pres_type',
1.506 www 7644: 'filter','part',
1.390 www 7645: 'udom','uname','symb','serial','timebase']);
1.131 www 7646:
1.83 bowersj2 7647:
1.193 albertel 7648: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 7649: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 7650: text=>"Content and Problem Settings",
1.473 amueller 7651: faq=>10,
7652: bug=>'Instructor Interface',
1.442 droeschl 7653: help =>
7654: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 7655:
1.30 www 7656: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 7657: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 7658: my $exists = &check_for_course_info();
7659:
1.568 raeburn 7660: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 7661: #
7662: # Main switch on form.action and form.state, as appropriate
7663: #
7664: # Check first if coming from someone else headed directly for
7665: # the table mode
1.568 raeburn 7666: if (($parm_permission->{'set'}) &&
7667: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
7668: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
7669: &assessparms($r,$parm_permission);
1.193 albertel 7670: } elsif (! exists($env{'form.action'})) {
7671: &print_main_menu($r,$parm_permission);
1.568 raeburn 7672: } elsif (!$parm_permission->{$env{'form.action'}}) {
7673: &print_main_menu($r,$parm_permission);
1.414 droeschl 7674: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 7675: &overview($r,$parm_permission);
1.560 damieng 7676: } elsif ($env{'form.action'} eq 'addmetadata') {
7677: &addmetafield($r);
7678: } elsif ($env{'form.action'} eq 'ordermetadata') {
7679: &order_meta_fields($r);
1.414 droeschl 7680: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 7681: &setrestrictmeta($r);
1.414 droeschl 7682: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 7683: &newoverview($r,$parm_permission);
1.414 droeschl 7684: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 7685: &defaultsetter($r);
7686: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 7687: &assessparms($r,$parm_permission);
1.414 droeschl 7688: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 7689: &parm_change_log($r,$parm_permission);
1.414 droeschl 7690: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 7691: &clean_parameters($r);
1.414 droeschl 7692: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 7693: &date_shift_one($r);
1.414 droeschl 7694: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 7695: &date_shift_two($r);
1.446 bisitz 7696: }
1.43 albertel 7697: } else {
1.1 www 7698: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 7699: if ($exists) {
7700: $env{'user.error.msg'}=
7701: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
7702: } else {
7703: $env{'user.error.msg'}=
7704: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
7705: }
7706: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 7707: }
1.376 albertel 7708: &reset_caches();
7709:
1.43 albertel 7710: return OK;
1.1 www 7711: }
7712:
7713: 1;
7714: __END__
7715:
7716:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>