Annotation of loncom/interface/lonparmset.pm, revision 1.616
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.616 ! raeburn 4: # $Id: lonparmset.pm,v 1.615 2022/07/03 04:31:07 raeburn Exp $
1.40 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.59 matthew 28: ###################################################################
29: ###################################################################
30:
31: =pod
32:
33: =head1 NAME
34:
35: lonparmset - Handler to set parameters for assessments and course
36:
37: =head1 SYNOPSIS
38:
1.579 raeburn 39: lonparmset provides an interface to setting content parameters in a
40: course.
1.560 damieng 41:
42: It contains all the code for the "Content and Problem Settings" UI, except
43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
44: and lonblockingmenu.pm.
1.59 matthew 45:
46: =head1 DESCRIPTION
47:
48: This module sets coursewide and assessment parameters.
49:
50: =head1 INTERNAL SUBROUTINES
51:
1.416 jms 52: =over
1.59 matthew 53:
1.416 jms 54: =item parmval()
1.59 matthew 55:
56: Figure out a cascading parameter.
57:
1.71 albertel 58: Inputs: $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162 albertel 59: $id - a bighash Id number
1.71 albertel 60: $def - the resource's default value 'stupid emacs
61:
1.556 raeburn 62: Returns: A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71 albertel 63:
1.556 raeburn 64: 18 - General Course
65: 17 - Map or Folder level in course (recursive)
66: 16 - Map or Folder level in course (non-recursive)
67: 15 - resource default
68: 14 - map default
69: 13 - resource level in course
70: 12 - General for section
71: 11 - Map or Folder level for section (recursive)
72: 10 - Map or Folder level for section (non-recursive)
73: 9 - resource level in section
74: 8 - General for group
75: 7 - Map or Folder level for group (recursive)
76: 6 - Map or Folder level for group (non-recursive)
77: 5 - resource level in group
78: 4 - General for specific student
79: 3 - Map or Folder level for specific student (recursive)
80: 2 - Map or Folder level for specific student (non-recursive)
1.71 albertel 81: 1 - resource level for specific student
1.2 www 82:
1.416 jms 83: =item parmval_by_symb()
84:
85: =item reset_caches()
86:
87: =item cacheparmhash()
88:
89: =item parmhash()
90:
91: =item symbcache()
92:
93: =item preset_defaults()
94:
95: =item date_sanity_info()
96:
97: =item storeparm()
98:
99: Store a parameter by symb
100:
101: Takes
102: - symb
103: - name of parameter
104: - level
105: - new value
106: - new type
107: - username
108: - userdomain
109:
110: =item log_parmset()
111:
112: =item storeparm_by_symb_inner()
113:
114: =item valout()
115:
116: Format a value for output.
117:
118: Inputs: $value, $type, $editable
119:
120: Returns: $value, formatted for output. If $type indicates it is a date,
121: localtime($value) is returned.
122: $editable will return an icon to click on
123:
124: =item plink()
125:
126: Produces a link anchor.
127:
128: Inputs: $type,$dis,$value,$marker,$return,$call
129:
130: Returns: scalar with html code for a link which will envoke the
131: javascript function 'pjump'.
132:
133: =item page_js()
134:
135: =item startpage()
136:
137: =item print_row()
138:
139: =item print_td()
140:
1.580 raeburn 141: =item check_other_groups()
1.416 jms 142:
143: =item parm_control_group()
144:
145: =item extractResourceInformation() :
146:
1.512 foxr 147: extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416 jms 148:
1.542 raeburn 149: Input: See list below
150:
151: =over 4
1.416 jms 152:
1.512 foxr 153: =item * B<env{'user.name'}> : Current username
1.416 jms 154:
1.512 foxr 155: =item * B<env{'user.domain'}> : Domain of current user.
1.416 jms 156:
1.542 raeburn 157: =item * B<env{"request.course.fn"}> : Course
158:
159: =back
1.416 jms 160:
1.512 foxr 161: Outputs: See list below:
1.416 jms 162:
1.542 raeburn 163: =over 4
164:
1.512 foxr 165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416 jms 166:
1.512 foxr 167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416 jms 168:
1.512 foxr 169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416 jms 170:
1.512 foxr 171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416 jms 172:
1.512 foxr 173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
174:
175: =item * B<allmaps> (out) : hash, ???
1.416 jms 176:
177: =item * B<mapp> : ??
178:
179: =item * B<symbp> : hash, id->full sym?
180:
1.512 foxr 181: =item * B<maptitles>
182:
183: =item * B<uris>
1.416 jms 184:
1.512 foxr 185: =item * B<keyorder>
186:
187: =item * B<defkeytype>
1.416 jms 188:
1.542 raeburn 189: =back
190:
1.416 jms 191: =item isdateparm()
192:
193: =item parmmenu()
194:
195: =item partmenu()
196:
197: =item usermenu()
198:
199: =item displaymenu()
200:
201: =item mapmenu()
202:
203: =item levelmenu()
204:
205: =item sectionmenu()
206:
207: =item keysplit()
208:
209: =item keysinorder()
210:
211: =item keysinorder_bytype()
212:
213: =item keysindisplayorder()
214:
215: =item standardkeyorder()
216:
217: =item assessparms() :
218:
219: Show assessment data and parameters. This is a large routine that should
220: be simplified and shortened... someday.
221:
1.513 foxr 222: Inputs: $r - the Apache request object.
223:
1.416 jms 224: Returns: nothing
225:
226: Variables used (guessed by Jeremy):
227:
1.542 raeburn 228: =over
229:
1.416 jms 230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
231:
232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
233:
234: =item * B<@catmarker> contains list of all possible parameters including part #s
235:
236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
237:
238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
239: When storing information, store as part 0
240: When requesting information, request from full part
241:
1.542 raeburn 242: =back
243:
1.416 jms 244: =item tablestart()
245:
246: =item tableend()
247:
248: =item extractuser()
249:
250: =item parse_listdata_key()
251:
252: =item listdata()
253:
254: =item date_interval_selector()
255:
256: =item get_date_interval_from_form()
257:
258: =item default_selector()
259:
260: =item string_selector()
261:
262: =item dateshift()
263:
264: =item newoverview()
265:
266: =item secgroup_lister()
267:
268: =item overview()
269:
270: =item clean_parameters()
271:
272: =item date_shift_one()
273:
274: =item date_shift_two()
275:
276: =item parse_key()
277:
278: =item header()
279:
280: Output html header for page
281:
282: =item print_main_menu()
283:
284: =item output_row()
285:
286: Set portfolio metadata
287:
288: =item order_meta_fields()
289:
290: =item addmetafield()
291:
292: =item setrestrictmeta()
293:
294: =item get_added_meta_fieldnames()
295:
296: =item get_deleted_meta_fieldnames()
297:
298: =item defaultsetter()
299:
300: =item components()
301:
302: =item load_parameter_names()
303:
304: =item parm_change_log()
305:
306: =item handler() :
307:
1.450 raeburn 308: Main handler. Calls &assessparms subroutine.
1.416 jms 309:
310: =back
311:
1.59 matthew 312: =cut
313:
1.416 jms 314: ###################################################################
315: ###################################################################
316:
317: package Apache::lonparmset;
318:
319: use strict;
320: use Apache::lonnet;
321: use Apache::Constants qw(:common :http REDIRECT);
322: use Apache::lonhtmlcommon();
323: use Apache::loncommon;
324: use GDBM_File;
325: use Apache::lonhomework;
326: use Apache::lonxml;
327: use Apache::lonlocal;
328: use Apache::lonnavmaps;
329: use Apache::longroup;
330: use Apache::lonrss;
1.506 www 331: use HTML::Entities;
1.416 jms 332: use LONCAPA qw(:DEFAULT :match);
333:
334:
1.560 damieng 335: ##################################################
336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
337: ##################################################
338:
339: # Page header
1.561 damieng 340: #
341: # @param {Apache2::RequestRec} $r - Apache request object
342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
343: # @param {string} $crstype - course type ('Community' for community settings)
1.507 www 344: sub startSettingsScreen {
1.531 raeburn 345: my ($r,$mode,$crstype)=@_;
1.507 www 346:
1.531 raeburn 347: my $tabtext = &mt('Course Settings');
348: if ($crstype eq 'Community') {
349: $tabtext = &mt('Community Settings');
350: }
1.507 www 351: $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
352: $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b> '.
1.531 raeburn 353: $tabtext.
1.507 www 354: ' </b></a></li>');
355:
1.523 raeburn 356: $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507 www 357: &mt('Content and Problem Settings').'</b></a></li>');
358: $r->print("\n".'</ul>'."\n");
1.523 raeburn 359: $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507 www 360: }
361:
1.560 damieng 362: # Page footer
1.507 www 363: sub endSettingsScreen {
364: my ($r)=@_;
365: $r->print('</div></div></div>');
366: }
367:
368:
369:
1.560 damieng 370: ##################################################
1.563 damieng 371: # (mostly) TABLE MODE
1.560 damieng 372: # (parmval is also used for the log of parameter changes)
373: ##################################################
374:
1.566 damieng 375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561 damieng 376: #
377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 378: # @param {string} $id - resource id or map pc
1.561 damieng 379: # @param {string} $def - the resource's default value for this parameter
380: # @param {string} $uname - user name
381: # @param {string} $udom - user domain
382: # @param {string} $csec - section name
383: # @param {string} $cgroup - group name
384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
385: # @returns {Array}
1.2 www 386: sub parmval {
1.275 raeburn 387: my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
388: return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
389: $cgroup,$courseopt);
1.201 www 390: }
391:
1.561 damieng 392: # Returns an array containing
393: # - the most specific level that is defined for that parameter (integer)
394: # - an array with the level as index and the parameter value as value (when defined)
395: # (level 1 is the most specific and will have precedence)
396: #
397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 398: # @param {string} $symb - resource symb or map src
1.561 damieng 399: # @param {string} $def - the resource's default value for this parameter
400: # @param {string} $uname - user name
401: # @param {string} $udom - user domain
402: # @param {string} $csec - section name
403: # @param {string} $cgroup - group name
404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
405: # @returns {Array}
1.201 www 406: sub parmval_by_symb {
1.275 raeburn 407: my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200 www 408:
1.352 albertel 409: my $useropt;
410: if ($uname ne '' && $udom ne '') {
1.561 damieng 411: $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352 albertel 412: }
1.200 www 413:
1.8 www 414: my $result='';
1.44 albertel 415: my @outpar=();
1.2 www 416: # ----------------------------------------------------- Cascading lookup scheme
1.446 bisitz 417: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 418: $map = &Apache::lonnet::deversion($map);
1.561 damieng 419:
420: # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
421: # any change should be reflected there.
422:
1.201 www 423: my $symbparm=$symb.'.'.$what;
1.556 raeburn 424: my $recurseparm=$map.'___(rec).'.$what;
1.201 www 425: my $mapparm=$map.'___(all).'.$what;
1.10 www 426:
1.269 raeburn 427: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
428: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 429: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 430: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
431:
1.190 albertel 432: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
433: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 434: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 435: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
436:
437: my $courselevel=$env{'request.course.id'}.'.'.$what;
438: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 439: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 440: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2 www 441:
1.11 www 442:
1.182 albertel 443: # --------------------------------------------------------- first, check course
1.11 www 444:
1.561 damieng 445: # 18 - General Course
1.200 www 446: if (defined($$courseopt{$courselevel})) {
1.556 raeburn 447: $outpar[18]=$$courseopt{$courselevel};
448: $result=18;
449: }
450:
1.561 damieng 451: # 17 - Map or Folder level in course (recursive)
1.556 raeburn 452: if (defined($$courseopt{$courseleveli})) {
453: $outpar[17]=$$courseopt{$courseleveli};
454: $result=17;
1.43 albertel 455: }
1.11 www 456:
1.561 damieng 457: # 16 - Map or Folder level in course (non-recursive)
1.200 www 458: if (defined($$courseopt{$courselevelm})) {
1.556 raeburn 459: $outpar[16]=$$courseopt{$courselevelm};
460: $result=16;
1.43 albertel 461: }
1.11 www 462:
1.182 albertel 463: # ------------------------------------------------------- second, check default
464:
1.561 damieng 465: # 15 - resource default
1.556 raeburn 466: if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182 albertel 467:
468: # ------------------------------------------------------ third, check map parms
469:
1.556 raeburn 470:
1.561 damieng 471: # 14 - map default
1.376 albertel 472: my $thisparm=&parmhash($symbparm);
1.556 raeburn 473: if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182 albertel 474:
1.561 damieng 475: # 13 - resource level in course
1.200 www 476: if (defined($$courseopt{$courselevelr})) {
1.556 raeburn 477: $outpar[13]=$$courseopt{$courselevelr};
478: $result=13;
1.43 albertel 479: }
1.11 www 480:
1.182 albertel 481: # ------------------------------------------------------ fourth, back to course
1.352 albertel 482: if ($csec ne '') {
1.561 damieng 483: # 12 - General for section
1.200 www 484: if (defined($$courseopt{$seclevel})) {
1.556 raeburn 485: $outpar[12]=$$courseopt{$seclevel};
486: $result=12;
487: }
1.561 damieng 488: # 11 - Map or Folder level for section (recursive)
1.556 raeburn 489: if (defined($$courseopt{$secleveli})) {
490: $outpar[11]=$$courseopt{$secleveli};
491: $result=11;
492: }
1.561 damieng 493: # 10 - Map or Folder level for section (non-recursive)
1.200 www 494: if (defined($$courseopt{$seclevelm})) {
1.556 raeburn 495: $outpar[10]=$$courseopt{$seclevelm};
496: $result=10;
497: }
1.561 damieng 498: # 9 - resource level in section
1.200 www 499: if (defined($$courseopt{$seclevelr})) {
1.556 raeburn 500: $outpar[9]=$$courseopt{$seclevelr};
501: $result=9;
502: }
1.43 albertel 503: }
1.275 raeburn 504: # ------------------------------------------------------ fifth, check course group
1.352 albertel 505: if ($cgroup ne '') {
1.561 damieng 506: # 8 - General for group
1.269 raeburn 507: if (defined($$courseopt{$grplevel})) {
1.556 raeburn 508: $outpar[8]=$$courseopt{$grplevel};
509: $result=8;
510: }
1.561 damieng 511: # 7 - Map or Folder level for group (recursive)
1.556 raeburn 512: if (defined($$courseopt{$grpleveli})) {
513: $outpar[7]=$$courseopt{$grpleveli};
514: $result=7;
1.269 raeburn 515: }
1.561 damieng 516: # 6 - Map or Folder level for group (non-recursive)
1.269 raeburn 517: if (defined($$courseopt{$grplevelm})) {
1.556 raeburn 518: $outpar[6]=$$courseopt{$grplevelm};
519: $result=6;
1.269 raeburn 520: }
1.561 damieng 521: # 5 - resource level in group
1.269 raeburn 522: if (defined($$courseopt{$grplevelr})) {
1.556 raeburn 523: $outpar[5]=$$courseopt{$grplevelr};
524: $result=5;
1.269 raeburn 525: }
526: }
1.11 www 527:
1.556 raeburn 528: # ---------------------------------------------------------- sixth, check user
1.11 www 529:
1.352 albertel 530: if ($uname ne '') {
1.561 damieng 531: # 4 - General for specific student
532: if (defined($$useropt{$courselevel})) {
533: $outpar[4]=$$useropt{$courselevel};
534: $result=4;
535: }
1.556 raeburn 536:
1.561 damieng 537: # 3 - Map or Folder level for specific student (recursive)
538: if (defined($$useropt{$courseleveli})) {
539: $outpar[3]=$$useropt{$courseleveli};
540: $result=3;
541: }
1.473 amueller 542:
1.561 damieng 543: # 2 - Map or Folder level for specific student (non-recursive)
544: if (defined($$useropt{$courselevelm})) {
545: $outpar[2]=$$useropt{$courselevelm};
546: $result=2;
547: }
1.473 amueller 548:
1.561 damieng 549: # 1 - resource level for specific student
550: if (defined($$useropt{$courselevelr})) {
551: $outpar[1]=$$useropt{$courselevelr};
552: $result=1;
553: }
1.43 albertel 554: }
1.44 albertel 555: return ($result,@outpar);
1.2 www 556: }
557:
1.198 www 558:
559:
1.376 albertel 560: # --- Caches local to lonparmset
561:
1.446 bisitz 562:
1.561 damieng 563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376 albertel 564: sub reset_caches {
565: &resetparmhash();
566: &resetsymbcache();
567: &resetrulescache();
1.203 www 568: }
569:
1.561 damieng 570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376 albertel 572: {
1.561 damieng 573: my $parmhashid; # course identifier, to initialize the cache only once for a course
574: my %parmhash; # the parameter cache
575: # reset map parameter hash
1.376 albertel 576: sub resetparmhash {
1.560 damieng 577: undef($parmhashid);
578: undef(%parmhash);
1.376 albertel 579: }
1.446 bisitz 580:
1.561 damieng 581: # dump the _parms.db database into %parmhash
1.376 albertel 582: sub cacheparmhash {
1.560 damieng 583: if ($parmhashid eq $env{'request.course.fn'}) { return; }
584: my %parmhashfile;
585: if (tie(%parmhashfile,'GDBM_File',
586: $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
587: %parmhash=%parmhashfile;
588: untie(%parmhashfile);
589: $parmhashid=$env{'request.course.fn'};
590: }
1.201 www 591: }
1.446 bisitz 592:
1.561 damieng 593: # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376 albertel 594: sub parmhash {
1.560 damieng 595: my ($id) = @_;
596: &cacheparmhash();
597: return $parmhash{$id};
1.376 albertel 598: }
1.560 damieng 599: }
1.376 albertel 600:
1.566 damieng 601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446 bisitz 602: {
1.561 damieng 603: my $symbsid; # course identifier, to initialize the cache only once for a course
604: my %symbs; # hash id->symb
605: # reset the id->symb cache
1.376 albertel 606: sub resetsymbcache {
1.560 damieng 607: undef($symbsid);
608: undef(%symbs);
1.376 albertel 609: }
1.446 bisitz 610:
1.566 damieng 611: # returns the resource symb or map src corresponding to a resource id or map pc
612: # (using lonnavmaps and a cache)
1.376 albertel 613: sub symbcache {
1.560 damieng 614: my $id=shift;
615: if ($symbsid ne $env{'request.course.id'}) {
616: undef(%symbs);
617: }
618: if (!$symbs{$id}) {
619: my $navmap = Apache::lonnavmaps::navmap->new();
620: if ($id=~/\./) {
621: my $resource=$navmap->getById($id);
622: $symbs{$id}=$resource->symb();
623: } else {
624: my $resource=$navmap->getByMapPc($id);
625: $symbs{$id}=&Apache::lonnet::declutter($resource->src());
626: }
627: $symbsid=$env{'request.course.id'};
1.473 amueller 628: }
1.560 damieng 629: return $symbs{$id};
1.473 amueller 630: }
1.560 damieng 631: }
1.201 www 632:
1.561 damieng 633: # cache for parameter default actions (stored in parmdefactions.db)
1.446 bisitz 634: {
1.561 damieng 635: my $rulesid; # course identifier, to initialize the cache only once for a course
636: my %rules; # parameter default actions hash
1.376 albertel 637: sub resetrulescache {
1.560 damieng 638: undef($rulesid);
639: undef(%rules);
1.376 albertel 640: }
1.446 bisitz 641:
1.561 damieng 642: # returns the value for a given key in the parameter default action hash
1.376 albertel 643: sub rulescache {
1.560 damieng 644: my $id=shift;
645: if ($rulesid ne $env{'request.course.id'}
646: && !defined($rules{$id})) {
647: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
648: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
649: %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
650: $rulesid=$env{'request.course.id'};
651: }
652: return $rules{$id};
1.221 www 653: }
654: }
655:
1.416 jms 656:
1.561 damieng 657: # Returns the values of the parameter type default action
658: # "default value when manually setting".
659: # If none is defined, ('','','','','') is returned.
660: #
661: # @param {string} $type - parameter type
662: # @returns {Array<string>} - (hours, min, sec, value)
1.229 www 663: sub preset_defaults {
664: my $type=shift;
665: if (&rulescache($type.'_action') eq 'default') {
1.560 damieng 666: # yes, there is something
667: return (&rulescache($type.'_hours'),
668: &rulescache($type.'_min'),
669: &rulescache($type.'_sec'),
670: &rulescache($type.'_value'));
1.229 www 671: } else {
1.560 damieng 672: # nothing there or something else
673: return ('','','','','');
1.229 www 674: }
675: }
676:
1.416 jms 677:
1.561 damieng 678: # Checks that a date is after enrollment start date and before
679: # enrollment end date.
680: # Returns HTML with a warning if it is not, or the empty string otherwise.
681: # This is used by both overview and table modes.
682: #
683: # @param {integer} $checkdate - the date to check.
684: # @returns {string} - HTML possibly containing a localized warning message.
1.277 www 685: sub date_sanity_info {
686: my $checkdate=shift;
687: unless ($checkdate) { return ''; }
688: my $result='';
689: my $crsprefix='course.'.$env{'request.course.id'}.'.';
690: if ($env{$crsprefix.'default_enrollment_end_date'}) {
691: if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413 bisitz 692: $result.='<div class="LC_warning">'
693: .&mt('After course enrollment end!')
694: .'</div>';
1.277 www 695: }
696: }
697: if ($env{$crsprefix.'default_enrollment_start_date'}) {
698: if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413 bisitz 699: $result.='<div class="LC_warning">'
700: .&mt('Before course enrollment start!')
701: .'</div>';
1.277 www 702: }
703: }
1.413 bisitz 704: # Preparation for additional warnings about dates in the past/future.
705: # An improved, more context sensitive version is recommended,
706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
707: # if ($checkdate<time) {
708: # $result.='<div class="LC_info">'
709: # .'('.&mt('in the past').')'
710: # .'</div>';
711: # }
712: # if ($checkdate>time) {
713: # $result.='<div class="LC_info">'
714: # .'('.&mt('in the future').')'
715: # .'</div>';
716: # }
1.277 www 717: return $result;
718: }
1.561 damieng 719:
720:
721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186 www 722: #
1.566 damieng 723: # @param {string} $sresid - resource id or map pc
1.565 damieng 724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 725: # @param {integer} $snum - level
726: # @param {string} $nval - new value
727: # @param {string} $ntype - new type
728: # @param {string} $uname - username
729: # @param {string} $udom - userdomain
730: # @param {string} $csec - section name
731: # @param {string} $cgroup - group name
1.186 www 732: sub storeparm {
1.269 raeburn 733: my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275 raeburn 734: &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197 www 735: }
736:
1.561 damieng 737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
738:
739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
741: #
1.566 damieng 742: # @param {string} $symb - resource symb or map src
1.565 damieng 743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 744: # @param {integer} $snum - level
745: # @param {string} $nval - new value
746: # @param {string} $ntype - new type
747: # @param {string} $uname - username
748: # @param {string} $udom - userdomain
749: # @param {string} $csec - section name
750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
751: # @param {string} $cgroup - group name
1.197 www 752: sub storeparm_by_symb {
1.275 raeburn 753: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226 www 754: unless ($recflag) {
1.560 damieng 755: # first time call
756: %recstack=();
757: $recflag=1;
1.226 www 758: }
1.560 damieng 759: # store parameter
1.226 www 760: &storeparm_by_symb_inner
1.473 amueller 761: ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560 damieng 762: # don't do anything if parameter was reset
1.266 www 763: unless ($nval) { return; }
1.226 www 764: my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560 damieng 765: # remember that this was set
1.226 www 766: $recstack{$parm}=1;
1.560 damieng 767: # what does this trigger?
1.226 www 768: foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560 damieng 769: # don't backfire
770: unless ((!$triggered) || ($recstack{$triggered})) {
771: my $action=&rulescache($triggered.'_action');
772: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
773: # set triggered parameter on same level
774: my $newspnam=$prefix.$triggered;
775: my $newvalue='';
776: my $active=1;
777: if ($action=~/^when\_setting/) {
778: # are there restrictions?
779: if (&rulescache($triggered.'_triggervalue')=~/\w/) {
780: $active=0;
1.565 damieng 781: foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560 damieng 782: if (lc($possiblevalue) eq lc($nval)) { $active=1; }
783: }
784: }
785: $newvalue=&rulescache($triggered.'_value');
786: } else {
787: my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
788: if ($action=~/^later\_than/) {
789: $newvalue=$nval+$totalsecs;
790: } else {
791: $newvalue=$nval-$totalsecs;
792: }
793: }
794: if ($active) {
795: &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
796: $uname,$udom,$csec,$recflag,$cgroup);
797: }
798: }
1.226 www 799: }
800: return '';
801: }
802:
1.561 damieng 803: # Adds all given arguments to the course parameter log.
804: # @returns {string} - the answer to the lonnet query.
1.293 www 805: sub log_parmset {
1.525 raeburn 806: return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284 www 807: }
808:
1.561 damieng 809: # Store a parameter value and type by symb, without using the parameter default actions.
810: # Expire related sheets.
811: #
1.566 damieng 812: # @param {string} $symb - resource symb or map src
1.561 damieng 813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
814: # @param {integer} $snum - level
815: # @param {string} $nval - new value
816: # @param {string} $ntype - new type
817: # @param {string} $uname - username
818: # @param {string} $udom - userdomain
819: # @param {string} $csec - section name
820: # @param {string} $cgroup - group name
821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226 www 822: sub storeparm_by_symb_inner {
1.197 www 823: # ---------------------------------------------------------- Get symb, map, etc
1.269 raeburn 824: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197 www 825: # ---------------------------------------------------------- Construct prefixes
1.186 www 826: $spnam=~s/\_([^\_]+)$/\.$1/;
1.446 bisitz 827: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 828: $map = &Apache::lonnet::deversion($map);
829:
1.197 www 830: my $symbparm=$symb.'.'.$spnam;
1.556 raeburn 831: my $recurseparm=$map.'___(rec).'.$spnam;
1.197 www 832: my $mapparm=$map.'___(all).'.$spnam;
833:
1.269 raeburn 834: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
835: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 836: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 837: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
838:
1.190 albertel 839: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
840: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 841: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 842: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446 bisitz 843:
1.190 albertel 844: my $courselevel=$env{'request.course.id'}.'.'.$spnam;
845: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 846: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 847: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446 bisitz 848:
1.186 www 849: my $storeunder='';
1.578 raeburn 850: my $possreplace='';
1.556 raeburn 851: if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578 raeburn 852: if (($snum==17) || ($snum==3)) {
853: $storeunder=$courseleveli;
854: $possreplace=$courselevelm;
855: }
856: if (($snum==16) || ($snum==2)) {
857: $storeunder=$courselevelm;
858: $possreplace=$courseleveli;
859: }
1.556 raeburn 860: if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
861: if ($snum==12) { $storeunder=$seclevel; }
1.578 raeburn 862: if ($snum==11) {
863: $storeunder=$secleveli;
864: $possreplace=$seclevelm;
865: }
866: if ($snum==10) {
867: $storeunder=$seclevelm;
868: $possreplace=$secleveli;
869: }
1.556 raeburn 870: if ($snum==9) { $storeunder=$seclevelr; }
871: if ($snum==8) { $storeunder=$grplevel; }
1.578 raeburn 872: if ($snum==7) {
873: $storeunder=$grpleveli;
874: $possreplace=$grplevelm;
875: }
876: if ($snum==6) {
877: $storeunder=$grplevelm;
878: $possreplace=$grpleveli;
879: }
1.556 raeburn 880: if ($snum==5) { $storeunder=$grplevelr; }
1.269 raeburn 881:
1.446 bisitz 882:
1.186 www 883: my $delete;
884: if ($nval eq '') { $delete=1;}
885: my %storecontent = ($storeunder => $nval,
1.473 amueller 886: $storeunder.'.type' => $ntype);
1.186 www 887: my $reply='';
1.560 damieng 888:
1.556 raeburn 889: if ($snum>4) {
1.186 www 890: # ---------------------------------------------------------------- Store Course
891: #
1.560 damieng 892: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
893: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
894: # Expire sheets
895: &Apache::lonnet::expirespread('','','studentcalc');
896: if (($snum==13) || ($snum==9) || ($snum==5)) {
897: &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578 raeburn 898: } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560 damieng 899: &Apache::lonnet::expirespread('','','assesscalc',$map);
900: } else {
901: &Apache::lonnet::expirespread('','','assesscalc');
902: }
903: # Store parameter
904: if ($delete) {
905: $reply=&Apache::lonnet::del
906: ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
907: &log_parmset(\%storecontent,1);
908: } else {
909: $reply=&Apache::lonnet::cput
910: ('resourcedata',\%storecontent,$cdom,$cnum);
911: &log_parmset(\%storecontent);
1.578 raeburn 912: if ($possreplace) {
913: my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
914: if (ref($resdata) eq 'HASH') {
915: if (exists($resdata->{$possreplace})) {
916: if (&Apache::lonnet::del
917: ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
918: &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);
919: }
920: }
921: }
922: }
1.560 damieng 923: }
924: &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186 www 925: } else {
926: # ------------------------------------------------------------------ Store User
927: #
1.560 damieng 928: # Expire sheets
929: &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
930: if ($snum==1) {
931: &Apache::lonnet::expirespread
932: ($uname,$udom,'assesscalc',$symb);
1.578 raeburn 933: } elsif (($snum==2) || ($snum==3)) {
1.560 damieng 934: &Apache::lonnet::expirespread
935: ($uname,$udom,'assesscalc',$map);
936: } else {
937: &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
938: }
939: # Store parameter
940: if ($delete) {
941: $reply=&Apache::lonnet::del
942: ('resourcedata',[keys(%storecontent)],$udom,$uname);
943: &log_parmset(\%storecontent,1,$uname,$udom);
944: } else {
945: $reply=&Apache::lonnet::cput
946: ('resourcedata',\%storecontent,$udom,$uname);
947: &log_parmset(\%storecontent,0,$uname,$udom);
1.578 raeburn 948: if ($possreplace) {
949: my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
950: if (ref($resdata) eq 'HASH') {
951: if (exists($resdata->{$possreplace})) {
952: if (&Apache::lonnet::del
953: ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
954: &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
955: $uname,$udom);
956: }
957: }
958: }
959: }
1.560 damieng 960: }
961: &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186 www 962: }
1.446 bisitz 963:
1.186 www 964: if ($reply=~/^error\:(.*)/) {
1.560 damieng 965: return "<span class=\"LC_error\">Write Error: $1</span>";
1.186 www 966: }
967: return '';
968: }
969:
1.9 www 970:
1.561 damieng 971: # Returns HTML with the value of the given parameter,
972: # using a readable format for dates, and
973: # a warning if there is a problem with a date.
974: # Used by table mode.
975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
976: #
977: # @param {string} $value - the parameter value
978: # @param {string} $type - the parameter type
979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9 www 980: sub valout {
1.600 raeburn 981: my ($value,$type,$editable)=@_;
1.59 matthew 982: my $result = '';
983: # Values of zero are valid.
984: if (! $value && $value ne '0') {
1.528 bisitz 985: if ($editable) {
986: $result =
987: '<img src="/res/adm/pages/editmap.png"'
988: .' alt="'.&mt('Change').'"'
1.539 raeburn 989: .' title="'.&mt('Change').'" style="border:0;" />';
1.528 bisitz 990: } else {
991: $result=' ';
992: }
1.59 matthew 993: } else {
1.66 www 994: if ($type eq 'date_interval') {
1.559 raeburn 995: my ($totalsecs,$donesuffix) = split(/_/,$value,2);
996: my ($usesdone,$donebuttontext,$proctor,$secretkey);
997: if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
998: $donebuttontext = $1;
999: (undef,$proctor,$secretkey) = split(/_/,$2);
1000: $usesdone = 'done';
1001: } elsif ($donesuffix =~ /^done(|_.+)$/) {
1002: $donebuttontext = &mt('Done');
1003: ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
1004: }
1.554 raeburn 1005: my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413 bisitz 1006: my @timer;
1.66 www 1007: $year=$year-70;
1008: $mday--;
1009: if ($year) {
1.413 bisitz 1010: # $result.=&mt('[quant,_1,yr]',$year).' ';
1011: push(@timer,&mt('[quant,_1,yr]',$year));
1.66 www 1012: }
1013: if ($mon) {
1.413 bisitz 1014: # $result.=&mt('[quant,_1,mth]',$mon).' ';
1015: push(@timer,&mt('[quant,_1,mth]',$mon));
1.66 www 1016: }
1017: if ($mday) {
1.413 bisitz 1018: # $result.=&mt('[quant,_1,day]',$mday).' ';
1019: push(@timer,&mt('[quant,_1,day]',$mday));
1.66 www 1020: }
1021: if ($hour) {
1.413 bisitz 1022: # $result.=&mt('[quant,_1,hr]',$hour).' ';
1023: push(@timer,&mt('[quant,_1,hr]',$hour));
1.66 www 1024: }
1025: if ($min) {
1.413 bisitz 1026: # $result.=&mt('[quant,_1,min]',$min).' ';
1027: push(@timer,&mt('[quant,_1,min]',$min));
1.66 www 1028: }
1029: if ($sec) {
1.413 bisitz 1030: # $result.=&mt('[quant,_1,sec]',$sec).' ';
1031: push(@timer,&mt('[quant,_1,sec]',$sec));
1.66 www 1032: }
1.413 bisitz 1033: # $result=~s/\s+$//;
1034: if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
1035: push(@timer,&mt('[quant,_1,sec]',0));
1036: }
1037: $result.=join(", ",@timer);
1.559 raeburn 1038: if ($usesdone eq 'done') {
1.558 raeburn 1039: if ($secretkey) {
1.559 raeburn 1040: $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
1.558 raeburn 1041: } else {
1.559 raeburn 1042: $result .= ' + "'.$donebuttontext.'"';
1043: }
1.554 raeburn 1044: }
1.213 www 1045: } elsif (&isdateparm($type)) {
1.361 albertel 1046: $result = &Apache::lonlocal::locallocaltime($value).
1.560 damieng 1047: &date_sanity_info($value);
1.59 matthew 1048: } else {
1049: $result = $value;
1.517 www 1050: $result=~s/\,/\, /gs;
1.560 damieng 1051: $result = &HTML::Entities::encode($result,'"<>&');
1.59 matthew 1052: }
1053: }
1054: return $result;
1.9 www 1055: }
1056:
1.59 matthew 1057:
1.561 damieng 1058: # Returns HTML containing a link on a parameter value, for table mode.
1059: # The link uses the javascript function 'pjump'.
1060: #
1061: # @param {string} $type - parameter type
1062: # @param {string} $dis - dialog title for editing the parameter value and type
1063: # @param {string} $value - parameter value
1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588 raeburn 1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5 www 1069: sub plink {
1.588 raeburn 1070: my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23 www 1071: my $winvalue=$value;
1072: unless ($winvalue) {
1.592 raeburn 1073: if (&isdateparm($type) || (&is_specialstring($type))) {
1.190 albertel 1074: $winvalue=$env{'form.recent_'.$type};
1.591 raeburn 1075: } elsif ($type eq 'string_yesno') {
1076: if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
1077: $winvalue=$env{'form.recent_string'};
1078: }
1.23 www 1079: } else {
1.190 albertel 1080: $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23 www 1081: }
1082: }
1.229 www 1083: my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
1084: my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
1085: unless (defined($winvalue)) { $winvalue=$val; }
1.593 raeburn 1086: my $valout = &valout($value,$type,1);
1.429 raeburn 1087: my $unencmarker = $marker;
1.378 albertel 1088: foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588 raeburn 1089: \$hour, \$min, \$sec, \$extra) {
1.560 damieng 1090: $$item = &HTML::Entities::encode($$item,'"<>&');
1091: $$item =~ s/\'/\\\'/g;
1.378 albertel 1092: }
1.429 raeburn 1093: return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473 amueller 1094: '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588 raeburn 1095: .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578 raeburn 1096: $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
1097: &mt('recursive').'</td></tr>' : '').'</table>';
1098:
1.5 www 1099: }
1100:
1.561 damieng 1101: # Javascript for table mode.
1.280 albertel 1102: sub page_js {
1103:
1.81 www 1104: my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88 matthew 1105: my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280 albertel 1106:
1107: return(<<ENDJS);
1108: <script type="text/javascript">
1.454 bisitz 1109: // <![CDATA[
1.44 albertel 1110:
1.88 matthew 1111: $pjump_def
1.44 albertel 1112:
1113: function psub() {
1.591 raeburn 1114: var specstring = /^string_!(yesno|any)/i;
1.44 albertel 1115: if (document.parmform.pres_marker.value!='') {
1116: document.parmform.action+='#'+document.parmform.pres_marker.value;
1117: var typedef=new Array();
1118: typedef=document.parmform.pres_type.value.split('_');
1.562 damieng 1119: if (document.parmform.pres_type.value!='') {
1.589 raeburn 1120: if ((typedef[0]=='date') ||
1.591 raeburn 1121: (specstring.test(document.parmform.pres_type.value))) {
1.562 damieng 1122: eval('document.parmform.recent_'+
1123: document.parmform.pres_type.value+
1124: '.value=document.parmform.pres_value.value;');
1125: } else {
1126: eval('document.parmform.recent_'+typedef[0]+
1127: '.value=document.parmform.pres_value.value;');
1128: }
1.44 albertel 1129: }
1130: document.parmform.submit();
1131: } else {
1132: document.parmform.pres_value.value='';
1133: document.parmform.pres_marker.value='';
1134: }
1135: }
1136:
1.57 albertel 1137: function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
1138: var options = "width=" + w + ",height=" + h + ",";
1139: options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
1140: options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
1141: var newWin = window.open(url, wdwName, options);
1142: newWin.focus();
1143: }
1.523 raeburn 1144:
1.454 bisitz 1145: // ]]>
1.523 raeburn 1146:
1.44 albertel 1147: </script>
1.81 www 1148: $selscript
1.280 albertel 1149: ENDJS
1150:
1151: }
1.507 www 1152:
1.561 damieng 1153: # Javascript to show or hide the map selection (function showHide_courseContent),
1154: # for table and overview modes.
1.523 raeburn 1155: sub showhide_js {
1156: return <<"COURSECONTENTSCRIPT";
1157:
1158: function showHide_courseContent() {
1159: var parmlevValue=document.getElementById("parmlev").value;
1160: if (parmlevValue == 'general') {
1161: document.getElementById('mapmenu').style.display="none";
1162: } else {
1163: if ((parmlevValue == "full") || (parmlevValue == "map")) {
1164: document.getElementById('mapmenu').style.display ="";
1165: } else {
1166: document.getElementById('mapmenu').style.display="none";
1167: }
1168: }
1169: return;
1170: }
1171:
1172: COURSECONTENTSCRIPT
1173: }
1174:
1.561 damieng 1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549 raeburn 1176: sub toggleparmtextbox_js {
1177: return <<"ENDSCRIPT";
1178:
1179: if (!document.getElementsByClassName) {
1180: function getElementsByClassName(node, classname) {
1181: var a = [];
1182: var re = new RegExp('(^| )'+classname+'( |$)');
1183: var els = node.getElementsByTagName("*");
1184: for(var i=0,j=els.length; i<j; i++)
1185: if(re.test(els[i].className))a.push(els[i]);
1186: return a;
1187: }
1188: }
1189:
1190: function showHideLenient() {
1191: var lenients;
1192: var setRegExp = /^set_/;
1193: if (document.getElementsByClassName) {
1194: lenients = document.getElementsByClassName('LC_lenient_radio');
1195: } else {
1196: lenients = getElementsByClassName(document.body,'LC_lenient_radio');
1197: }
1198: if (lenients != 'undefined') {
1199: for (var i=0; i<lenients.length; i++) {
1200: if (lenients[i].checked) {
1201: if (lenients[i].value == 'weighted') {
1202: if (setRegExp.test(lenients[i].name)) {
1203: var identifier = lenients[i].name.replace(setRegExp,'');
1204: toggleParmTextbox(document.parmform,identifier);
1205: }
1206: }
1207: }
1208: }
1209: }
1210: return;
1211: }
1212:
1213: function toggleParmTextbox(form,key) {
1214: var divfortext = document.getElementById('LC_parmtext_'+key);
1215: if (divfortext) {
1216: var caller = form.elements['set_'+key];
1217: if (caller.length) {
1218: for (i=0; i<caller.length; i++) {
1219: if (caller[i].checked) {
1220: if (caller[i].value == 'weighted') {
1221: divfortext.style.display = 'inline';
1222: } else {
1223: divfortext.style.display = 'none';
1224: }
1225: }
1226: }
1227: }
1228: }
1229: return;
1230: }
1231:
1232: ENDSCRIPT
1233: }
1234:
1.561 damieng 1235: # Javascript function validateParms, for overview mode
1.549 raeburn 1236: sub validateparms_js {
1237: return <<'ENDSCRIPT';
1238:
1239: function validateParms() {
1240: var textRegExp = /^settext_/;
1241: var tailLenient = /\.lenient$/;
1242: var patternRelWeight = /^\-?[\d.]+$/;
1243: var patternLenientStd = /^(yes|no|default)$/;
1.597 raeburn 1244: var ipRegExp = /^setip/;
1.549 raeburn 1245: var ipallowRegExp = /^setipallow_/;
1246: var ipdenyRegExp = /^setipdeny_/;
1.597 raeburn 1247: var deeplinkRegExp = /^deeplink_/;
1.601 raeburn 1248: var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;
1249: var dlLinkProtectRegExp = /^deeplink_protect_/;
1250: var dlLtidRegExp = /^deeplink_ltid_/;
1251: var dlLticRegExp = /^deeplink_ltic_/;
1.597 raeburn 1252: var dlKeyRegExp = /^deeplink_key_/;
1253: var dlMenusRegExp = /^deeplink_menus_/;
1254: var dlCollsRegExp = /^deeplink_colls_/;
1.613 raeburn 1255: var dlTargetRegExp = /^deeplink_target_/;
1.616 ! raeburn 1256: var dlExitRegExp = /^deeplink_exit_/;
! 1257: var dlExitTextRegExp = /^deeplink_exittext_/;
1.549 raeburn 1258: var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1.616 ! raeburn 1259: var numelements = document.parmform.elements.length;
! 1260: if ((typeof(numelements) != 'undefined') && (numelements != null)) {
! 1261: if (numelements) {
! 1262: for (i=0; i<numelements; i++) {
1.549 raeburn 1263: var name=document.parmform.elements[i].name;
1.588 raeburn 1264: if (textRegExp.test(name)) {
1.549 raeburn 1265: var identifier = name.replace(textRegExp,'');
1266: if (tailLenient.test(identifier)) {
1267: if (document.parmform.elements['set_'+identifier].length) {
1268: for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
1269: if (document.parmform.elements['set_'+identifier][j].checked) {
1270: if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
1271: var relweight = document.parmform.elements[i].value;
1272: relweight = relweight.replace(/^\s+|\s+$/g,'');
1273: if (!patternRelWeight.test(relweight)) {
1274: relweight = '0.0';
1275: }
1276: if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
1277: document.parmform.elements['set_'+identifier][j].value = relweight;
1278: } else {
1279: document.parmform.elements['set_'+identifier][j].value += ','+relweight;
1280: }
1281: }
1282: break;
1283: }
1284: }
1285: }
1286: }
1.597 raeburn 1287: } else if (ipRegExp.test(name)) {
1288: if (ipallowRegExp.test(name)) {
1289: var identifier = name.replace(ipallowRegExp,'');
1290: var possallow = document.parmform.elements[i].value;
1291: possallow = possallow.replace(/^\s+|\s+$/g,'');
1292: if (patternIP.test(possallow)) {
1293: if (document.parmform.elements['set_'+identifier].value) {
1294: possallow = ','+possallow;
1295: }
1296: document.parmform.elements['set_'+identifier].value += possallow;
1297: }
1298: } else if (ipdenyRegExp.test(name)) {
1299: var identifier = name.replace(ipdenyRegExp,'');
1300: var possdeny = document.parmform.elements[i].value;
1301: possdeny = possdeny.replace(/^\s+|\s+$/g,'');
1302: if (patternIP.test(possdeny)) {
1303: possdeny = '!'+possdeny;
1304: if (document.parmform.elements['set_'+identifier].value) {
1305: possdeny = ','+possdeny;
1306: }
1307: document.parmform.elements['set_'+identifier].value += possdeny;
1.588 raeburn 1308: }
1309: }
1310: } else if (deeplinkRegExp.test(name)) {
1.597 raeburn 1311: if (dlListScopeRegExp.test(name)) {
1312: var identifier = name.replace(dlListScopeRegExp,'');
1313: var idx = document.parmform.elements[i].selectedIndex;
1314: if (idx > 0) {
1315: var possdeeplink = document.parmform.elements[i].options[idx].value
1316: possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
1317: if (document.parmform.elements['set_'+identifier].value) {
1318: possdeeplink = ','+possdeeplink;
1319: }
1320: document.parmform.elements['set_'+identifier].value += possdeeplink;
1321: }
1.601 raeburn 1322: } else if (dlLinkProtectRegExp.test(name)) {
1.597 raeburn 1323: if (document.parmform.elements[i].checked) {
1.601 raeburn 1324: var identifier = name.replace(dlLinkProtectRegExp,'');
1.597 raeburn 1325: var posslinkurl = document.parmform.elements[i].value;
1326: posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
1327: if (document.parmform.elements['set_'+identifier].value) {
1328: posslinkurl = ','+posslinkurl;
1329: }
1330: document.parmform.elements['set_'+identifier].value += posslinkurl;
1331: }
1.601 raeburn 1332: } else if (dlLtidRegExp.test(name)) {
1333: var identifier = name.replace(dlLtidRegExp,'');
1334: if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
1335: var possltid = document.parmform.elements[i].value;
1336: possltid = possltid.replace(/\D+/g,'');
1337: if (possltid.length) {
1.597 raeburn 1338: if (document.parmform.elements['set_'+identifier].value) {
1.601 raeburn 1339: possltid = ':'+possltid;
1.597 raeburn 1340: }
1.601 raeburn 1341: document.parmform.elements['set_'+identifier].value += possltid;
1.597 raeburn 1342: } else {
1343: document.parmform.elements['set_'+identifier].value = '';
1.601 raeburn 1344: 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 1345: return false;
1346: }
1347: }
1.601 raeburn 1348: } else if (dlLticRegExp.test(name)) {
1349: var identifier = name.replace(dlLticRegExp,'');
1350: if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
1351: var possltic = document.parmform.elements[i].value;
1352: possltic = possltic.replace(/\D+/g,'');
1353: if (possltic.length) {
1354: if (document.parmform.elements['set_'+identifier].value) {
1355: possltic = ':'+possltic;
1356: }
1357: document.parmform.elements['set_'+identifier].value += possltic;
1358: } else {
1359: document.parmform.elements['set_'+identifier].value = '';
1360: 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.");
1361: return false;
1362: }
1363: }
1.597 raeburn 1364: } else if (dlKeyRegExp.test(name)) {
1365: var identifier = name.replace(dlKeyRegExp,'');
1.601 raeburn 1366: if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597 raeburn 1367: var posskey = document.parmform.elements[i].value;
1368: posskey = posskey.replace(/^\s+|\s+$/g,'');
1369: var origlength = posskey.length;
1370: posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
1371: var newlength = posskey.length;
1372: if (newlength > 0) {
1373: var change = origlength - newlength;
1374: if (change) {
1375: alert(change+' disallowed character(s) removed from deeplink key');
1376: }
1377: if (document.parmform.elements['set_'+identifier].value) {
1378: posskey = ':'+posskey;
1379: }
1380: document.parmform.elements['set_'+identifier].value += posskey;
1381: } else {
1382: document.parmform.elements['set_'+identifier].value = '';
1383: if (newlength < origlength) {
1384: 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_.!@#$%^&*()+=-");
1385: } else {
1386: alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
1387: }
1388: return false;
1389: }
1390: }
1391: } else if (dlMenusRegExp.test(name)) {
1392: if (document.parmform.elements[i].checked) {
1393: var identifier = name.replace(dlMenusRegExp,'');
1394: var posslinkmenu = document.parmform.elements[i].value;
1395: posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
1396: if (posslinkmenu == 'std') {
1397: posslinkmenu = '0';
1398: if (document.parmform.elements['set_'+identifier].value) {
1399: posslinkmenu = ','+posslinkmenu;
1400: }
1401: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1402: }
1403: }
1404: } else if (dlCollsRegExp.test(name)) {
1405: var identifier = name.replace(dlCollsRegExp,'');
1406: if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
1407: var posslinkmenu = document.parmform.elements[i].value;
1408: if (document.parmform.elements['set_'+identifier].value) {
1409: posslinkmenu = ','+posslinkmenu;
1410: }
1411: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1412: }
1.614 raeburn 1413: } else if (dlTargetRegExp.test(name)) {
1414: var identifier = name.replace(dlTargetRegExp,'');
1.613 raeburn 1415: var idx = document.parmform.elements[i].selectedIndex;
1416: if (idx > 0) {
1.616 ! raeburn 1417: var linktarget = document.parmform.elements[i].options[idx].value
! 1418: linktarget = linktarget.replace(/^\s+|\s+$/g,'');
! 1419: if (document.parmform.elements['set_'+identifier].value) {
! 1420: linktarget = ','+linktarget;
! 1421: }
! 1422: document.parmform.elements['set_'+identifier].value += linktarget;
! 1423: }
! 1424: } else if (dlExitRegExp.test(name)) {
! 1425: if (document.parmform.elements[i].checked) {
! 1426: var identifier = name.replace(dlExitRegExp,'');
! 1427: var posslinkexit = document.parmform.elements[i].value;
! 1428: posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');
1.613 raeburn 1429: if (document.parmform.elements['set_'+identifier].value) {
1.616 ! raeburn 1430: posslinkexit = ','+posslinkexit;
! 1431: }
! 1432: document.parmform.elements['set_'+identifier].value += posslinkexit;
! 1433: }
! 1434: } else if (dlExitTextRegExp.test(name)) {
! 1435: var identifier = name.replace(dlExitTextRegExp,'');
! 1436: if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
! 1437: (isRadioSet('deeplink_exit_'+identifier,'url'))) {
! 1438: var posstext = document.parmform.elements[i].value;
! 1439: posstext = posstext.replace(/^\s+|\s+$/g,'');
! 1440: var origlength = posstext.length;
! 1441: posstext = posstext.replace(/[:;'",]/g,'');
! 1442: var newlength = posstext.length;
! 1443: if (newlength > 0) {
! 1444: var change = origlength - newlength;
! 1445: if (change) {
! 1446: alert(change+' disallowed character(s) removed from Exit Button text');
! 1447: }
! 1448: if (posstext !== 'Exit Tool') {
! 1449: posstext = ':'+posstext;
! 1450: document.parmform.elements['set_'+identifier].value += posstext;
! 1451: }
! 1452: } else {
! 1453: document.parmform.elements['set_'+identifier].value = '';
! 1454: if (newlength < origlength) {
! 1455: alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");
! 1456: } else {
! 1457: alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");
! 1458: }
! 1459: return false;
1.613 raeburn 1460: }
1461: }
1.549 raeburn 1462: }
1463: }
1464: }
1465: }
1466: }
1467: return true;
1468: }
1469:
1.597 raeburn 1470: function isRadioSet(name,expected) {
1471: var menuitems = document.getElementsByName(name);
1472: var radioLength = menuitems.length;
1473: result = false;
1474: if (radioLength > 1) {
1475: for (var j=0; j<radioLength; j++) {
1476: if (menuitems[j].checked) {
1477: if (menuitems[j].value == expected) {
1478: result = true;
1479: break;
1480: }
1481: }
1482: }
1483: }
1484: return result;
1485: }
1486:
1.549 raeburn 1487: ENDSCRIPT
1488: }
1489:
1.561 damieng 1490: # Javascript initialization, for overview mode
1.549 raeburn 1491: sub ipacc_boxes_js {
1492: my $remove = &mt('Remove');
1493: return <<"END";
1494: \$(document).ready(function() {
1495: var wrapper = \$(".LC_string_ipacc_wrap");
1496: var add_button = \$(".LC_add_ipacc_button");
1497: var ipaccRegExp = /^LC_string_ipacc_/;
1498:
1499: \$(add_button).click(function(e){
1500: e.preventDefault();
1501: var identifier = \$(this).closest("div").attr("id");
1502: identifier = identifier.replace(ipaccRegExp,'');
1.551 raeburn 1503: \$(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 1504: });
1505:
1506: \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
1507: e.preventDefault(); \$(this).closest("div").remove();
1508: })
1509: });
1510:
1511:
1512: END
1513: }
1514:
1.561 damieng 1515: # Javascript function toggleSecret, for overview mode.
1.558 raeburn 1516: sub done_proctor_js {
1.611 raeburn 1517: my $defaultdone = &mt('Done');
1518: &js_escape(\$defaultdone);
1.558 raeburn 1519: return <<"END";
1520: function toggleSecret(form,radio,key) {
1521: var radios = form[radio+key];
1522: if (radios.length) {
1523: for (var i=0; i<radios.length; i++) {
1524: if (radios[i].checked) {
1525: if (radios[i].value == '_done_proctor') {
1526: if (document.getElementById('done_'+key+'_proctorkey')) {
1527: document.getElementById('done_'+key+'_proctorkey').type='text';
1528: }
1529: } else {
1530: if (document.getElementById('done_'+key+'_proctorkey')) {
1531: document.getElementById('done_'+key+'_proctorkey').type='hidden';
1532: document.getElementById('done_'+key+'_proctorkey').value='';
1533: }
1534: }
1.611 raeburn 1535: if (document.getElementById('done_'+key+'_buttontext')) {
1536: if (radios[i].value == '') {
1537: document.getElementById('done_'+key+'_buttontext').value = '';
1538: } else {
1539: if (document.getElementById('done_'+key+'_buttontext').value == '') {
1540: document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
1541: }
1542: }
1543: }
1.558 raeburn 1544: }
1545: }
1546: }
1547: }
1548: END
1549:
1550: }
1551:
1.588 raeburn 1552: # Javascript function toggle
1553: sub deeplink_js {
1554: return <<"END";
1555: function toggleDeepLink(form,item,key) {
1556: var radios = form['deeplink_'+item+'_'+key];
1557: if (radios.length) {
1558: var keybox;
1559: if (document.getElementById('deeplink_key_'+item+'_'+key)) {
1560: keybox = document.getElementById('deeplink_key_'+item+'_'+key);
1561: }
1.601 raeburn 1562: var divoptions = new Array();
1563: if (item == 'protect') {
1564: divoptions = ['ltic','ltid'];
1.597 raeburn 1565: } else {
1566: if (item == 'menus') {
1.601 raeburn 1567: divoptions = ['colls'];
1.597 raeburn 1568: }
1569: }
1.601 raeburn 1570: var seldivs = new Array();
1571: if ((item == 'protect') || (item == 'menus')) {
1572: for (var i=0; i<divoptions.length; i++) {
1573: if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
1574: seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
1575: } else {
1576: seldivs[i] = '';
1577: }
1578: }
1.588 raeburn 1579: }
1580: for (var i=0; i<radios.length; i++) {
1581: if (radios[i].checked) {
1.601 raeburn 1582: if ((item == 'protect') || (item == 'menus')) {
1583: for (var j=0; j<seldivs.length; j++) {
1584: if (radios[i].value == divoptions[j]) {
1585: if (seldivs[j] != '') {
1586: seldivs[j].style.display = 'inline-block';
1587: }
1588: if (item == 'protect') {
1589: keybox.type = 'hidden';
1590: keybox.value = '';
1591: }
1592: } else {
1593: if (seldivs[j] != '') {
1594: seldivs[j].style.display = 'none';
1595: form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
1596: }
1597: }
1.597 raeburn 1598: }
1.601 raeburn 1599: if (item == 'protect') {
1.597 raeburn 1600: if (radios[i].value == 'key') {
1601: keybox.type = 'text';
1602: } else {
1603: keybox.type = 'hidden';
1604: }
1.588 raeburn 1605: }
1.616 ! raeburn 1606: } else if (item == 'exit') {
! 1607: if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
! 1608: if (radios[i].value == 'no') {
! 1609: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';
! 1610: if (document.getElementById('deeplink_exittext_'+key)) {
! 1611: if (document.getElementById('deeplink_exittext_'+key).value != '') {
! 1612: document.getElementById('deeplink_exittext_'+key).value = '';
! 1613: }
! 1614: }
! 1615: } else {
! 1616: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
! 1617: if (document.getElementById('deeplink_exittext_'+key)) {
! 1618: if (document.getElementById('deeplink_exittext_'+key).value == '') {
! 1619: document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
! 1620: }
! 1621: }
! 1622: }
! 1623: }
1.588 raeburn 1624: }
1625: }
1626: }
1627: }
1628: }
1629: END
1630:
1631: }
1632:
1.561 damieng 1633: # Prints HTML page start for table mode.
1634: # @param {Apache2::RequestRec} $r - the Apache request
1635: # @param {string} $psymb - resource symb
1636: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280 albertel 1637: sub startpage {
1.531 raeburn 1638: my ($r,$psymb,$crstype) = @_;
1.281 albertel 1639:
1.515 raeburn 1640: my %loaditems = (
1641: 'onload' => "group_or_section('cgroup')",
1642: );
1643: if (!$psymb) {
1.523 raeburn 1644: $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515 raeburn 1645: }
1.280 albertel 1646:
1.560 damieng 1647: if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
1648: (!$env{'form.dis'})) || ($env{'form.symb'})) {
1649: &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
1650: text=>"Problem Parameters"});
1.414 droeschl 1651: } else {
1.560 damieng 1652: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1653: text=>"Table Mode",
1654: help => 'Course_Setting_Parameters'});
1.414 droeschl 1655: }
1.523 raeburn 1656: my $js = &page_js().'
1657: <script type="text/javascript">
1658: // <![CDATA[
1659: '.
1660: &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
1661: // ]]>
1662: </script>
1663: ';
1.446 bisitz 1664: my $start_page =
1.523 raeburn 1665: &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
1666: {'add_entries' => \%loaditems,});
1.446 bisitz 1667: my $breadcrumbs =
1.473 amueller 1668: &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506 www 1669: my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
1670: my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507 www 1671: $r->print($start_page.$breadcrumbs);
1.531 raeburn 1672: &startSettingsScreen($r,'parmset',$crstype);
1.280 albertel 1673: $r->print(<<ENDHEAD);
1.193 albertel 1674: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419 bisitz 1675: <input type="hidden" value="" name="pres_value" />
1676: <input type="hidden" value="" name="pres_type" />
1677: <input type="hidden" value="" name="pres_marker" />
1678: <input type="hidden" value="1" name="prevvisit" />
1.506 www 1679: <input type="hidden" value="$escfilter" name="filter" />
1680: <input type="hidden" value="$escpart" name="part" />
1.44 albertel 1681: ENDHEAD
1682: }
1683:
1.209 www 1684:
1.561 damieng 1685: # Prints a row for table mode (except for the tr start).
1686: # Every time a hash reference is passed, a single entry is used, so print_row
1687: # could just use these values, but why make it simple when it can be complicated ?
1688: #
1689: # @param {Apache2::RequestRec} $r - the Apache request
1690: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
1691: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
1692: # @param {hash reference} $name - parameter key -> parameter name
1.566 damieng 1693: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561 damieng 1694: # @param {string} $rid - resource id
1695: # @param {hash reference} $default - parameter key -> resource parameter default value
1696: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
1697: # @param {hash reference} $display - parameter key -> full title for the parameter
1698: # @param {string} $defbgone - user level and other levels background color
1699: # @param {string} $defbgtwo - section level background color, also used for part number
1700: # @param {string} $defbgthree - group level background color
1701: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1702: # @param {string} $uname - user name
1703: # @param {string} $udom - user domain
1704: # @param {string} $csec - section name
1705: # @param {string} $cgroup - group name
1706: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1707: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582 raeburn 1708: # @param {boolean} $readonly - true if no editing allowed.
1709: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
1710: # @param {hash reference} - $maptitles - - hash map id or src -> map title
1711: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
1712: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set
1.44 albertel 1713: sub print_row {
1.201 www 1714: my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568 raeburn 1715: $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582 raeburn 1716: $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275 raeburn 1717: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1718: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1719: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582 raeburn 1720: my $numlinks = 0;
1.553 raeburn 1721:
1.560 damieng 1722: # get the values for the parameter in cascading order
1723: # empty levels will remain empty
1.44 albertel 1724: my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473 amueller 1725: $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1726: # get the type for the parameters
1727: # problem: these may not be set for all levels
1.66 www 1728: my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275 raeburn 1729: $$name{$which}.'.type',$rid,
1.473 amueller 1730: $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1731: # cascade down manually
1.182 albertel 1732: my $cascadetype=$$defaulttype{$which};
1.556 raeburn 1733: for (my $i=18;$i>0;$i--) {
1.560 damieng 1734: if ($typeoutpar[$i]) {
1.66 www 1735: $cascadetype=$typeoutpar[$i];
1.560 damieng 1736: } else {
1.66 www 1737: $typeoutpar[$i]=$cascadetype;
1738: }
1739: }
1.57 albertel 1740: my $parm=$$display{$which};
1741:
1.203 www 1742: if ($parmlev eq 'full') {
1.419 bisitz 1743: $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506 www 1744: .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433 raeburn 1745: } else {
1.57 albertel 1746: $parm=~s|\[.*\]\s||g;
1747: }
1.231 www 1748: my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
1749: if ($automatic) {
1.560 damieng 1750: $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231 www 1751: }
1.427 bisitz 1752: $r->print('<td>'.$parm.'</td>');
1.446 bisitz 1753:
1.44 albertel 1754: my $thismarker=$which;
1755: $thismarker=~s/^parameter\_//;
1756: my $mprefix=$rid.'&'.$thismarker.'&';
1.582 raeburn 1757: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1758: my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588 raeburn 1759: $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582 raeburn 1760: if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
1761: if ($result eq '') {
1762: $recurse_check = 1;
1763: } elsif (($uname ne '') && ($result > 3)) {
1764: $recurse_check = 1;
1765: } elsif (($cgroup ne '') && ($result > 7)) {
1766: $recurse_check = 1;
1767: } elsif (($csec ne '') && ($result > 11)) {
1768: $recurse_check = 1;
1769: } elsif ($result > 17) {
1770: $recurse_check = 1;
1771: }
1772: if ($recurse_check) {
1773: my $what = $$part{$which}.'.'.$$name{$which};
1774: my $prefix;
1775: if (($uname ne '') && ($udom ne '')) {
1776: my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1777: $prefix = $env{'request.course.id'};
1778: $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
1779: if (ref($recursinfo) eq 'ARRAY') {
1780: $effparm_rec = 1;
1781: $effparm_level = &mt('user: [_1]',$uname);
1782: }
1783: }
1784: if (($cgroup ne '') && (!$effparm_rec)) {
1785: $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
1786: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1787: if (ref($recursinfo) eq 'ARRAY') {
1788: $effparm_rec = 1;
1789: $effparm_level = &mt('group: [_1]',$cgroup);
1790: }
1791: }
1792: if (($csec ne '') && (!$effparm_rec)) {
1793: $prefix = $env{'request.course.id'}.'.['.$csec.']';
1794: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1795: if (ref($recursinfo) eq 'ARRAY') {
1796: $effparm_rec = 1;
1797: $effparm_level = &mt('section: [_1]',$csec);
1798: }
1799: }
1800: if (!$effparm_rec) {
1801: $prefix = $env{'request.course.id'};
1802: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1803: if (ref($recursinfo) eq 'ARRAY') {
1804: $effparm_rec = 1;
1805: }
1806: }
1807: }
1808: }
1809: if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
1810: $effparm_rec = 1;
1811: }
1812: if ((!$effparm_rec) &&
1813: (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) &&
1814: ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578 raeburn 1815: $effparm_rec = 1;
1816: }
1.588 raeburn 1817: if ($parmname eq 'deeplink') {
1.601 raeburn 1818: my ($domltistr,$crsltistr);
1.588 raeburn 1819: my %lti =
1820: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 1821: 'linkprot');
1.601 raeburn 1822: if (keys(%lti)) {
1823: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1.604 raeburn 1824: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
1825: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588 raeburn 1826: }
1827: }
1.601 raeburn 1828: $domltistr =~ s/,$//;
1829: if ($domltistr) {
1830: $extra = 'ltid_'.$domltistr;
1831: }
1.588 raeburn 1832: }
1.601 raeburn 1833: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
1834: if (keys(%courselti)) {
1835: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
1836: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
1837: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
1838: }
1839: }
1840: $crsltistr =~ s/,$//;
1841: if ($crsltistr) {
1842: if ($extra) {
1843: $extra .= '&';
1844: }
1845: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 1846: }
1847: }
1.597 raeburn 1848: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
1849: my @colls;
1850: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
1851: my ($num,$value) = split(/\%/,$item);
1852: if ($num =~ /^\d+$/) {
1853: push(@colls,$num);
1854: }
1855: }
1856: if (@colls) {
1857: if ($extra) {
1858: $extra .= '&';
1859: }
1860: $extra .= 'menus_'.join(',',@colls);
1861: }
1862: }
1.588 raeburn 1863: }
1.57 albertel 1864: if ($parmlev eq 'general') {
1865: if ($uname) {
1.588 raeburn 1866: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 1867: } elsif ($cgroup) {
1.588 raeburn 1868: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 1869: } elsif ($csec) {
1.588 raeburn 1870: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1871: } else {
1.588 raeburn 1872: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1873: }
1874: } elsif ($parmlev eq 'map') {
1875: if ($uname) {
1.588 raeburn 1876: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 1877: } elsif ($cgroup) {
1.588 raeburn 1878: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 1879: } elsif ($csec) {
1.588 raeburn 1880: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1881: } else {
1.588 raeburn 1882: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1883: }
1884: } else {
1.275 raeburn 1885: if ($uname) {
1886: if (@{$usersgroups} > 1) {
1.582 raeburn 1887: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 1888: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 1889: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 1890: if (($coursereply) && ($result > 4)) {
1.275 raeburn 1891: if (defined($controlgrp)) {
1892: if ($cgroup ne $controlgrp) {
1.582 raeburn 1893: $eff_groupparm = $grp_parm;
1894: undef($result);
1895: undef($effparm_rec);
1896: if ($grp_is_rec) {
1897: $effparm_rec = 1;
1898: }
1.275 raeburn 1899: }
1900: }
1901: }
1902: }
1903: }
1.57 albertel 1904:
1.588 raeburn 1905: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1906: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1907: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1908: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1909: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1910:
1911: if ($csec) {
1.588 raeburn 1912: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1913: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1914: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1915: }
1.269 raeburn 1916:
1917: if ($cgroup) {
1.588 raeburn 1918: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1919: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1920: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 1921: }
1.446 bisitz 1922:
1.548 raeburn 1923: if ($uname) {
1.275 raeburn 1924: if ($othergrp) {
1925: $r->print($othergrp);
1926: }
1.588 raeburn 1927: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1928: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1929: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1930: }
1.57 albertel 1931: } # end of $parmlev if/else
1.582 raeburn 1932: if (ref($recursinfo) eq 'ARRAY') {
1933: my $rectitle = &mt('recursive');
1934: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
1935: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
1936: $rectitle = &mt('set in: [_1]','"'.
1937: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
1938: "'$parmname','$$part{$which}'".');">'.
1939: $maptitles->{$recursinfo->[2]}.'</a>"');
1940:
1941: $numlinks ++;
1942: }
1943: }
1944: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 1945: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 1946: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1947: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
1948: $effparm_level.'</span></td>');
1949: } else {
1950: if ($result) {
1.593 raeburn 1951: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 1952: }
1953: if ($eff_groupparm) {
1954: $effective_parm = $eff_groupparm;
1955: }
1956: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1957: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
1958: '</span>':'').'</td>');
1959: }
1.203 www 1960: if ($parmlev eq 'full') {
1.136 albertel 1961: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 1962: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 1963: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 1964: if (!defined($sessionvaltype)) {
1965: $sessionvaltype=$$defaulttype{$which};
1966: }
1.419 bisitz 1967: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 1968: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 1969: '</font></td>');
1.136 albertel 1970: }
1.44 albertel 1971: $r->print('</tr>');
1.57 albertel 1972: $r->print("\n");
1.582 raeburn 1973: if (($numlinks) && (ref($reclinks))) {
1974: $$reclinks = $numlinks;
1975: }
1.44 albertel 1976: }
1.59 matthew 1977:
1.561 damieng 1978: # Prints a cell for table mode.
1979: #
1980: # FIXME: some of these parameter names are uninspired ($which and $value)
1981: # Also, it would make more sense to pass the display for this cell rather
1982: # than the full display hash and the key to use.
1983: #
1984: # @param {Apache2::RequestRec} $r - the Apache request
1985: # @param {integer} $which - level
1986: # @param {string} $defbg - cell background color
1987: # @param {integer} $result - the most specific level that is defined for that parameter
1988: # @param {array reference} $outpar - array level -> parameter value (when defined)
1989: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
1990: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
1991: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
1992: # @param {hash reference} $display - parameter key -> full title for the parameter
1993: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 1994: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 1995: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 1996: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 1997: sub print_td {
1.578 raeburn 1998: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 1999: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 2000: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
2001: $ineffect = 0;
2002: $currval = $$outpar[$which];
2003: $currtype = $$typeoutpar[$which];
2004: $currlevel = $which;
2005: if (($result) && ($result == $which)) {
2006: $ineffect = 1;
2007: }
2008: if ($ismaplevel) {
2009: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
2010: if (($result) && ($result == $which)) {
2011: $recursive = 1;
2012: }
2013: } elsif ($$outpar[$which+1] ne '') {
2014: $recursive = 1;
2015: $currlevel = $which+1;
2016: $currval = $$outpar[$currlevel];
2017: $currtype = $$typeoutpar[$currlevel];
2018: if (($result) && ($result == $currlevel)) {
2019: $ineffect = 1;
2020: }
2021: }
2022: }
2023: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 2024: ';" align="center">');
1.437 raeburn 2025: my $nolink = 0;
1.568 raeburn 2026: if ($readonly) {
1.552 raeburn 2027: $nolink = 1;
1.568 raeburn 2028: } else {
1.578 raeburn 2029: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 2030: $nolink = 1;
1.568 raeburn 2031: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 2032: $nolink = 1;
1.568 raeburn 2033: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
2034: if ($noeditgrp) {
2035: $nolink = 1;
2036: }
2037: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 2038: $nolink = 1;
1.568 raeburn 2039: } elsif ($mprefix =~ /examcode\&$/) {
2040: unless ($which == 2) {
2041: $nolink = 1;
2042: }
1.533 raeburn 2043: }
1.437 raeburn 2044: }
2045: if ($nolink) {
1.577 raeburn 2046: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 2047: $r->print(&valout($currval,$currtype));
1.114 www 2048: } else {
1.578 raeburn 2049: $r->print(&plink($currtype,
2050: $$display{$value},$currval,
1.588 raeburn 2051: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
2052: $extra));
1.114 www 2053: }
2054: $r->print('</td>'."\n");
1.57 albertel 2055: }
2056:
1.561 damieng 2057: # Returns HTML and other info for the cell added when a user is selected
2058: # and that user is in several groups. This is the cell with the title "Control by other group".
2059: #
2060: # @param {string} $what - parameter part.'.'.parameter name
2061: # @param {string} $rid - resource id
2062: # @param {string} $cgroup - group name
2063: # @param {string} $defbg - cell background color
2064: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2065: # @param {integer} $result - level
2066: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 2067: # @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 2068: sub check_other_groups {
2069: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 2070: my $courseid = $env{'request.course.id'};
2071: my $output;
2072: my $symb = &symbcache($rid);
2073: my $symbparm=$symb.'.'.$what;
2074: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 2075: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 2076: my $mapparm=$map.'___(all).'.$what;
2077: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 2078: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
2079: $recurseparm,$what,$courseopt);
1.275 raeburn 2080: my $bgcolor = $defbg;
1.582 raeburn 2081: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2082: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2083: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2084: if ($result > 3) {
1.419 bisitz 2085: $bgcolor = '#AAFFAA';
1.275 raeburn 2086: }
1.593 raeburn 2087: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2088: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2089: if ($resultgroup && $resultlevel) {
1.582 raeburn 2090: if ($resultlevel eq 'recursive') {
2091: $resultlevel = 'map/folder';
2092: $grp_is_rec = 1;
2093: }
2094: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2095: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2096:
1.275 raeburn 2097: } else {
2098: $output .= ' ';
2099: }
2100: $output .= '</td>';
2101: } else {
1.419 bisitz 2102: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2103: }
1.582 raeburn 2104: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2105: }
2106:
1.561 damieng 2107: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2108: # Used by check_other_groups.
1.561 damieng 2109: #
2110: # @param {string} $courseid - the course id
2111: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2112: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2113: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2114: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2115: # @param {string} $what - parameter part.'.'.parameter name
2116: # @param {hash reference} $courseopt - course parameters hash
2117: # @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 2118: sub parm_control_group {
1.556 raeburn 2119: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2120: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2121: my $grpfound = 0;
1.556 raeburn 2122: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2123: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2124: foreach my $group (@{$usersgroups}) {
2125: if ($grpfound) { last; }
2126: for (my $i=0; $i<@levels; $i++) {
2127: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2128: if (defined($$courseopt{$item})) {
2129: $coursereply = $$courseopt{$item};
2130: $resultitem = $item;
2131: $resultgroup = $group;
2132: $resultlevel = $levelnames[$i];
2133: $resulttype = $$courseopt{$item.'.type'};
2134: $grpfound = 1;
2135: last;
2136: }
2137: }
2138: }
2139: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2140: }
1.201 www 2141:
1.63 bowersj2 2142:
2143:
1.562 damieng 2144: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2145: # All the parameters are references and are filled by the sub.
2146: #
1.566 damieng 2147: # @param {array reference} $ids - resource and map ids
2148: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2149: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2150: # @param {hash reference} $allparms - hash parameter name -> parameter title
2151: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2152: # @param {hash reference} $allmaps - hash map pc -> map src
2153: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2154: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2155: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2156: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2157: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2158: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608 raeburn 2159: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63 bowersj2 2160: sub extractResourceInformation {
2161: my $ids = shift;
2162: my $typep = shift;
2163: my $keyp = shift;
2164: my $allparms = shift;
2165: my $allparts = shift;
2166: my $allmaps = shift;
2167: my $mapp = shift;
2168: my $symbp = shift;
1.82 www 2169: my $maptitles=shift;
1.196 www 2170: my $uris=shift;
1.210 www 2171: my $keyorder=shift;
1.211 www 2172: my $defkeytype=shift;
1.603 raeburn 2173: my $pssymb=shift;
1.196 www 2174:
1.210 www 2175: my $keyordercnt=100;
1.63 bowersj2 2176:
1.196 www 2177: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 raeburn 2178: return unless(ref($navmap));
2179: my @allres;
2180: if ($pssymb ne '') {
2181: my $res = $navmap->getBySymb($pssymb);
2182: if (ref($res)) {
2183: @allres = ($res);
2184: }
2185: }
2186: if (!@allres) {
2187: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
2188: }
1.196 www 2189: foreach my $resource (@allres) {
1.480 amueller 2190: my $id=$resource->id();
1.196 www 2191: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2192: if ($mapid eq '0') { next; }
2193: $$ids[$#$ids+1]=$id;
2194: my $srcf=$resource->src();
2195: $srcf=~/\.(\w+)$/;
2196: $$typep{$id}=$1;
1.584 raeburn 2197: my $toolsymb;
2198: if ($srcf =~ /ext\.tool$/) {
2199: $toolsymb = $resource->symb();
2200: }
1.480 amueller 2201: $$keyp{$id}='';
1.196 www 2202: $$uris{$id}=$srcf;
1.512 foxr 2203:
1.584 raeburn 2204: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2205: next if ($key!~/^parameter_/);
1.363 albertel 2206:
1.209 www 2207: # Hidden parameters
1.584 raeburn 2208: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2209: #
2210: # allparms is a hash of parameter names
2211: #
1.584 raeburn 2212: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2213: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2214: my ($display,$parmdis);
2215: $display = &standard_parameter_names($name);
2216: if ($display eq '') {
1.584 raeburn 2217: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2218: $parmdis = $display;
2219: $parmdis =~ s/\s*\[Part.*$//g;
2220: } else {
2221: $parmdis = &mt($display);
2222: }
2223: $$allparms{$name}=$parmdis;
2224: if (ref($defkeytype)) {
2225: $$defkeytype{$name}=
1.584 raeburn 2226: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2227: }
2228: }
1.363 albertel 2229:
1.209 www 2230: #
2231: # allparts is a hash of all parts
2232: #
1.584 raeburn 2233: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2234: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2235: #
2236: # Remember all keys going with this resource
2237: #
1.480 amueller 2238: if ($$keyp{$id}) {
2239: $$keyp{$id}.=','.$key;
2240: } else {
2241: $$keyp{$id}=$key;
2242: }
1.210 www 2243: #
2244: # Put in order
1.446 bisitz 2245: #
1.480 amueller 2246: unless ($$keyorder{$key}) {
2247: $$keyorder{$key}=$keyordercnt;
2248: $keyordercnt++;
2249: }
1.473 amueller 2250: }
2251:
2252:
1.480 amueller 2253: if (!exists($$mapp{$mapid})) {
2254: $$mapp{$id}=
2255: &Apache::lonnet::declutter($resource->enclosing_map_src());
2256: $$mapp{$mapid}=$$mapp{$id};
2257: $$allmaps{$mapid}=$$mapp{$id};
2258: if ($mapid eq '1') {
1.532 raeburn 2259: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2260: } else {
2261: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2262: }
2263: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2264: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2265: # Lines 1038 and 1114 which use $symbp{$mapid}
2266: # are commented out in rev. 1.57
1.473 amueller 2267: } else {
1.480 amueller 2268: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2269: }
1.480 amueller 2270: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2271: }
2272: }
2273:
1.582 raeburn 2274: sub get_recursive {
2275: my ($recurseup,$resdata,$what,$prefix) = @_;
2276: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2277: foreach my $item (@{$recurseup}) {
2278: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2279: if (defined($resdata->{$norecursechk})) {
2280: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2281: my $type = $resdata->{$norecursechk.'.type'};
2282: return [$resdata->{$norecursechk},$type,$item];
2283: } else {
2284: last;
2285: }
2286: }
2287: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2288: if (defined($resdata->{$recursechk})) {
2289: my $type = $resdata->{$recursechk.'.type'};
2290: return [$resdata->{$recursechk},$type,$item];
2291: }
2292: }
2293: }
2294: return;
2295: }
2296:
1.208 www 2297:
1.562 damieng 2298: # Tells if a parameter type is a date.
2299: #
2300: # @param {string} type - parameter type
2301: # @returns{boolean} - true if it is a date
1.213 www 2302: sub isdateparm {
2303: my $type=shift;
2304: return (($type=~/^date/) && (!($type eq 'date_interval')));
2305: }
2306:
1.589 raeburn 2307: # Determine if parameter type is specialized string type (i.e.,
2308: # not just string or string_yesno.
2309:
2310: sub is_specialstring {
2311: my $type=shift;
1.603 raeburn 2312: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2313: }
2314:
1.562 damieng 2315: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2316: #
1.581 raeburn 2317: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2318: sub parmmenu {
1.581 raeburn 2319: my ($r)=@_;
1.208 www 2320: $r->print(<<ENDSCRIPT);
2321: <script type="text/javascript">
1.454 bisitz 2322: // <![CDATA[
1.208 www 2323: function checkall(value, checkName) {
1.453 schualex 2324:
2325: var li = "_li";
2326: var displayOverview = "";
2327:
2328: if (value == false) {
2329: displayOverview = "none"
2330: }
2331:
1.562 damieng 2332: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2333: ele = document.forms.parmform.elements[i];
2334: if (ele.name == checkName) {
2335: document.forms.parmform.elements[i].checked=value;
2336: }
2337: }
2338: }
1.210 www 2339:
2340: function checkthis(thisvalue, checkName) {
1.562 damieng 2341: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2342: ele = document.forms.parmform.elements[i];
2343: if (ele.name == checkName) {
1.562 damieng 2344: if (ele.value == thisvalue) {
2345: document.forms.parmform.elements[i].checked=true;
2346: }
1.210 www 2347: }
2348: }
2349: }
2350:
2351: function checkdates() {
1.562 damieng 2352: checkthis('duedate','pscat');
2353: checkthis('opendate','pscat');
2354: checkthis('answerdate','pscat');
1.218 www 2355: }
2356:
2357: function checkdisset() {
1.562 damieng 2358: checkthis('discussend','pscat');
2359: checkthis('discusshide','pscat');
2360: checkthis('discussvote','pscat');
1.218 www 2361: }
2362:
2363: function checkcontdates() {
1.562 damieng 2364: checkthis('contentopen','pscat');
2365: checkthis('contentclose','pscat');
1.218 www 2366: }
1.446 bisitz 2367:
1.210 www 2368: function checkvisi() {
1.562 damieng 2369: checkthis('hiddenresource','pscat');
2370: checkthis('encrypturl','pscat');
2371: checkthis('problemstatus','pscat');
2372: checkthis('contentopen','pscat');
2373: checkthis('opendate','pscat');
1.210 www 2374: }
2375:
2376: function checkparts() {
1.562 damieng 2377: checkthis('hiddenparts','pscat');
2378: checkthis('display','pscat');
2379: checkthis('ordered','pscat');
1.210 www 2380: }
2381:
2382: function checkstandard() {
2383: checkall(false,'pscat');
1.562 damieng 2384: checkdates();
2385: checkthis('weight','pscat');
2386: checkthis('maxtries','pscat');
2387: checkthis('type','pscat');
2388: checkthis('problemstatus','pscat');
1.210 www 2389: }
2390:
1.454 bisitz 2391: // ]]>
1.208 www 2392: </script>
2393: ENDSCRIPT
1.453 schualex 2394:
1.491 bisitz 2395: $r->print('<hr />');
1.581 raeburn 2396: &shortCuts($r);
1.491 bisitz 2397: $r->print('<hr />');
1.453 schualex 2398: }
1.562 damieng 2399:
2400: # Returns parameter categories.
2401: #
2402: # @returns {hash} - category name -> title in English
1.465 amueller 2403: sub categories {
2404: return ('time_settings' => 'Time Settings',
2405: 'grading' => 'Grading',
2406: 'tries' => 'Tries',
2407: 'problem_appearance' => 'Problem Appearance',
2408: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2409: 'hiding' => 'Hiding',
2410: 'high_level_randomization' => 'High Level Randomization',
2411: 'slots' => 'Slots',
2412: 'file_submission' => 'File Submission',
2413: 'misc' => 'Miscellaneous' );
2414: }
2415:
1.562 damieng 2416: # Returns the category for each parameter.
2417: #
2418: # @returns {hash} - parameter name -> category name
1.465 amueller 2419: sub lookUpTableParameter {
2420:
2421: return (
2422: 'opendate' => 'time_settings',
2423: 'duedate' => 'time_settings',
2424: 'answerdate' => 'time_settings',
2425: 'interval' => 'time_settings',
2426: 'contentopen' => 'time_settings',
2427: 'contentclose' => 'time_settings',
2428: 'discussend' => 'time_settings',
1.560 damieng 2429: 'printstartdate' => 'time_settings',
2430: 'printenddate' => 'time_settings',
1.465 amueller 2431: 'weight' => 'grading',
2432: 'handgrade' => 'grading',
2433: 'maxtries' => 'tries',
2434: 'hinttries' => 'tries',
1.503 raeburn 2435: 'randomizeontries' => 'tries',
1.465 amueller 2436: 'type' => 'problem_appearance',
2437: 'problemstatus' => 'problem_appearance',
2438: 'display' => 'problem_appearance',
2439: 'ordered' => 'problem_appearance',
2440: 'numbubbles' => 'problem_appearance',
2441: 'tol' => 'behaviour_of_input_fields',
2442: 'sig' => 'behaviour_of_input_fields',
2443: 'turnoffunit' => 'behaviour_of_input_fields',
2444: 'hiddenresource' => 'hiding',
2445: 'hiddenparts' => 'hiding',
2446: 'discusshide' => 'hiding',
2447: 'buttonshide' => 'hiding',
2448: 'turnoffeditor' => 'hiding',
2449: 'encrypturl' => 'hiding',
1.587 raeburn 2450: 'deeplink' => 'hiding',
1.465 amueller 2451: 'randomorder' => 'high_level_randomization',
2452: 'randompick' => 'high_level_randomization',
2453: 'available' => 'slots',
2454: 'useslots' => 'slots',
2455: 'availablestudent' => 'slots',
2456: 'uploadedfiletypes' => 'file_submission',
2457: 'maxfilesize' => 'file_submission',
2458: 'cssfile' => 'misc',
2459: 'mapalias' => 'misc',
2460: 'acc' => 'misc',
2461: 'maxcollaborators' => 'misc',
2462: 'scoreformat' => 'misc',
1.514 raeburn 2463: 'lenient' => 'grading',
1.519 raeburn 2464: 'retrypartial' => 'tries',
1.521 raeburn 2465: 'discussvote' => 'misc',
1.584 raeburn 2466: 'examcode' => 'high_level_randomization',
1.575 raeburn 2467: );
1.465 amueller 2468: }
2469:
1.562 damieng 2470: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2471: #
2472: # @param {string} $name - parameter name
2473: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2474: sub whatIsMyCategory {
2475: my $name = shift;
2476: my $catList = shift;
2477: my @list;
2478: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2479: my $cat = $lookUpList{$name};
2480: if (defined($cat)) {
2481: if (!defined($$catList{$cat})){
2482: push @list, ($name);
2483: $$catList{$cat} = \@list;
2484: } else {
2485: push @{${$catList}{$cat}}, ($name);
2486: }
2487: } else {
2488: if (!defined($$catList{'misc'})){
2489: push @list, ($name);
2490: $$catList{'misc'} = \@list;
2491: } else {
2492: push @{${$catList}{'misc'}}, ($name);
2493: }
2494: }
2495: }
2496:
1.562 damieng 2497: # Sorts parameter names based on appearance order.
2498: #
2499: # @param {array reference} name - array reference of parameter names
2500: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2501: # @returns {Array} - array of parameter names
1.465 amueller 2502: sub keysindisplayorderCategory {
2503: my ($name,$keyorder)=@_;
2504: return sort {
1.473 amueller 2505: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2506: } ( @{$name});
2507: }
2508:
1.562 damieng 2509: # Returns a hash category name -> order, starting at 1 (integer)
2510: #
2511: # @returns {hash}
1.467 amueller 2512: sub category_order {
2513: return (
2514: 'time_settings' => 1,
2515: 'grading' => 2,
2516: 'tries' => 3,
2517: 'problem_appearance' => 4,
2518: 'hiding' => 5,
2519: 'behaviour_of_input_fields' => 6,
2520: 'high_level_randomization' => 7,
2521: 'slots' => 8,
2522: 'file_submission' => 9,
2523: 'misc' => 10
2524: );
2525:
2526: }
1.453 schualex 2527:
1.562 damieng 2528: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2529: #
2530: # @param {Apache2::RequestRec} $r - the Apache request
2531: # @param {hash reference} $allparms - hash parameter name -> parameter title
2532: # @param {array reference} $pscat - list of selected parameter names
2533: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2534: sub parmboxes {
2535: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2536: my %categories = &categories();
1.467 amueller 2537: my %category_order = &category_order();
1.465 amueller 2538: my %categoryList = (
2539: 'time_settings' => [],
2540: 'grading' => [],
2541: 'tries' => [],
2542: 'problem_appearance' => [],
2543: 'behaviour_of_input_fields' => [],
2544: 'hiding' => [],
2545: 'high_level_randomization' => [],
2546: 'slots' => [],
2547: 'file_submission' => [],
2548: 'misc' => [],
1.489 bisitz 2549: );
1.510 www 2550:
1.548 raeburn 2551: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2552: &whatIsMyCategory($tempparameter, \%categoryList);
2553: }
1.453 schualex 2554: #part to print the parm-list
1.536 raeburn 2555: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2556: next if (@{$categoryList{$key}} == 0);
2557: next if ($key eq '');
2558: $r->print('<div class="LC_Box LC_400Box">'
2559: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2560: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2561: next if ($tempkey eq '');
1.536 raeburn 2562: $r->print('<span class="LC_nobreak">'
2563: .'<label><input type="checkbox" name="pscat" '
2564: .'value="'.$tempkey.'" ');
2565: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2566: $r->print( ' checked="checked"');
2567: }
2568: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465 amueller 2569: : $tempkey)
1.536 raeburn 2570: .'</label></span><br />'."\n");
1.465 amueller 2571: }
1.536 raeburn 2572: $r->print('</div>');
1.465 amueller 2573: }
1.536 raeburn 2574: $r->print("\n");
1.453 schualex 2575: }
1.562 damieng 2576:
2577: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2578: #
1.562 damieng 2579: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2580: sub shortCuts {
1.581 raeburn 2581: my ($r)=@_;
1.453 schualex 2582:
1.491 bisitz 2583: # Parameter Selection
2584: $r->print(
2585: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2586: .&Apache::lonhtmlcommon::add_item_funclist(
2587: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2588: .&Apache::lonhtmlcommon::add_item_funclist(
2589: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2590: .&Apache::lonhtmlcommon::add_item_funclist(
2591: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2592: .&Apache::lonhtmlcommon::end_funclist()
2593: );
2594:
2595: # Add Selection for...
2596: $r->print(
2597: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2598: .&Apache::lonhtmlcommon::add_item_funclist(
2599: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2600: .&Apache::lonhtmlcommon::add_item_funclist(
2601: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2602: .&Apache::lonhtmlcommon::add_item_funclist(
2603: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2604: .&Apache::lonhtmlcommon::add_item_funclist(
2605: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2606: .&Apache::lonhtmlcommon::add_item_funclist(
2607: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2608: .&Apache::lonhtmlcommon::end_funclist()
2609: );
1.208 www 2610: }
2611:
1.562 damieng 2612: # Prints HTML to select parts to view (except for the title).
2613: # Used by table and overview modes.
2614: #
2615: # @param {Apache2::RequestRec} $r - the Apache request
2616: # @param {hash reference} $allparts - hash parameter part -> part title
2617: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2618: sub partmenu {
1.446 bisitz 2619: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2620: my $selsize = 1+scalar(keys(%{$allparts}));
2621: if ($selsize > 8) {
2622: $selsize = 8;
2623: }
1.446 bisitz 2624:
1.523 raeburn 2625: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2626: $r->print('<option value="all"');
1.562 damieng 2627: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2628: $r->print('>'.&mt('All Parts').'</option>');
2629: my %temphash=();
2630: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2631: foreach my $tempkey (sort {
1.560 damieng 2632: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2633: } keys(%{$allparts})) {
2634: unless ($tempkey =~ /\./) {
2635: $r->print('<option value="'.$tempkey.'"');
2636: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2637: $r->print(' selected="selected"');
2638: }
2639: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2640: }
1.208 www 2641: }
1.446 bisitz 2642: $r->print('</select>');
1.209 www 2643: }
2644:
1.562 damieng 2645: # Prints HTML to select a user and/or a group.
2646: # Used by table mode.
2647: #
2648: # @param {Apache2::RequestRec} $r - the Apache request
2649: # @param {string} $uname - selected user name
2650: # @param {string} $id - selected Student/Employee ID
2651: # @param {string} $udom - selected user domain
2652: # @param {string} $csec - selected section name
2653: # @param {string} $cgroup - selected group name
2654: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2655: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2656: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2657: sub usermenu {
1.553 raeburn 2658: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2659: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2660: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2661: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2662: function setCourseadv(form,caller) {
2663: if (caller.value == 'st') {
2664: form.courseadv.value = 'none';
2665: } else {
2666: form.courseadv.value = '';
2667: }
2668: return;
2669: }
2670: ENDJS
1.412 bisitz 2671:
1.596 raeburn 2672: my (%chkroles,$stuonly,$courseadv);
2673: if ($env{'form.userroles'} eq 'any') {
2674: $chkroles{'any'} = ' checked="checked"';
2675: } else {
2676: $chkroles{'st'} = ' checked="checked"';
2677: $courseadv = 'none';
2678: }
2679: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2680: if ($crstype eq 'Community') {
2681: $stuonly = &mt('member only');
2682: } else {
2683: $stuonly = &mt('student only');
2684: }
2685: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2686: &mt("User's role").': '.
2687: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2688: $stuonly.'</label> '.
2689: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2690: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2691: my $sections='';
1.300 albertel 2692: my %sectionhash = &Apache::loncommon::get_sections();
2693:
1.269 raeburn 2694: my $groups;
1.553 raeburn 2695: my %grouphash;
2696: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2697: %grouphash = &Apache::longroup::coursegroups();
2698: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2699: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2700: }
1.299 albertel 2701:
1.412 bisitz 2702: my $g_s_header='';
2703: my $g_s_footer='';
1.446 bisitz 2704:
1.552 raeburn 2705: my $currsec = $env{'request.course.sec'};
2706: if ($currsec) {
2707: $sections=&mt('Section:').' '.$currsec;
2708: if (%grouphash) {
2709: $sections .= ';'.(' ' x2);
2710: }
2711: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2712: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2713: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2714: $sections .= qq| onchange="group_or_section('csec')" |;
2715: }
2716: $sections .= '>';
1.548 raeburn 2717: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2718: $sections.='<option value="'.$section.'" '.
2719: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2720: '</option>';
1.209 www 2721: }
2722: $sections.='</select>';
1.269 raeburn 2723: }
1.412 bisitz 2724:
1.552 raeburn 2725: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2726: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2727: $sections .= qq|
2728: <script type="text/javascript">
1.454 bisitz 2729: // <![CDATA[
1.269 raeburn 2730: function group_or_section(caller) {
2731: if (caller == "cgroup") {
2732: if (document.parmform.cgroup.selectedIndex != 0) {
2733: document.parmform.csec.selectedIndex = 0;
2734: }
2735: } else {
2736: if (document.parmform.csec.selectedIndex != 0) {
2737: document.parmform.cgroup.selectedIndex = 0;
2738: }
2739: }
2740: }
1.454 bisitz 2741: // ]]>
1.269 raeburn 2742: </script>
2743: |;
1.554 raeburn 2744: } else {
1.269 raeburn 2745: $sections .= qq|
2746: <script type="text/javascript">
1.454 bisitz 2747: // <![CDATA[
1.269 raeburn 2748: function group_or_section(caller) {
2749: return;
2750: }
1.454 bisitz 2751: // ]]>
1.269 raeburn 2752: </script>
2753: |;
1.446 bisitz 2754: }
1.299 albertel 2755:
2756: if (%grouphash) {
1.597 raeburn 2757: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2758: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2759: $groups .= qq| onchange="group_or_section('cgroup')" |;
2760: }
2761: $groups .= '>';
1.548 raeburn 2762: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2763: $groups.='<option value="'.$grp.'" ';
2764: if ($grp eq $cgroup) {
2765: unless ((defined($uname)) && ($grp eq '')) {
2766: $groups .= 'selected="selected" ';
2767: }
2768: } elsif (!defined($cgroup)) {
2769: if (@{$usersgroups} == 1) {
2770: if ($grp eq $$usersgroups[0]) {
2771: $groups .= 'selected="selected" ';
2772: }
2773: }
2774: }
2775: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2776: }
2777: $groups.='</select>';
2778: }
1.412 bisitz 2779:
1.445 neumanie 2780: if (%sectionhash || %grouphash) {
1.446 bisitz 2781: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2782: $r->print($sections.$groups);
1.448 bisitz 2783: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 2784: } else {
2785: $r->print($sections);
1.445 neumanie 2786: }
1.446 bisitz 2787:
2788: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 2789: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 2790: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
2791: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 2792: ,$chooseopt));
1.209 www 2793: }
2794:
1.562 damieng 2795: # Prints HTML to select parameters from a list of all parameters.
2796: # Uses parmmenu and parmboxes.
2797: # Used by table and overview modes.
1.468 amueller 2798: #
1.562 damieng 2799: # @param {Apache2::RequestRec} $r - the Apache request
2800: # @param {hash reference} $allparms - hash parameter name -> parameter title
2801: # @param {array reference} $pscat - list of selected parameter names
2802: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2803: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 2804: sub displaymenu {
1.581 raeburn 2805: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 2806:
1.445 neumanie 2807: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 2808: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
2809:
1.581 raeburn 2810: &parmmenu($r);
1.536 raeburn 2811: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 2812: &parmboxes($r,$allparms,$pscat,$keyorder);
2813: $r->print(&Apache::loncommon::end_scrollbox());
2814:
2815: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 2816: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 2817:
1.209 www 2818: }
2819:
1.562 damieng 2820: # Prints HTML to select a map.
2821: # Used by table mode and overview mode.
2822: #
2823: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 2824: # @param {hash reference} $allmaps - hash map pc -> map src
2825: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 2826: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 2827: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610 raeburn 2828: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445 neumanie 2829: sub mapmenu {
1.610 raeburn 2830: my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468 amueller 2831: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 2832: my $navmap = Apache::lonnavmaps::navmap->new();
2833: my $tree=[];
2834: my $treeinfo={};
2835: if (defined($navmap)) {
1.499 raeburn 2836: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 2837: my $curRes;
2838: my $depth = 0;
1.468 amueller 2839: my %parent = ();
2840: my $startcount = 5;
2841: my $lastcontainer = $startcount;
2842: # preparing what is to show ...
1.461 neumanie 2843: while ($curRes = $it->next()) {
2844: if ($curRes == $it->BEGIN_MAP()) {
2845: $depth++;
1.468 amueller 2846: $parent{$depth}= $lastcontainer;
1.461 neumanie 2847: }
2848: if ($curRes == $it->END_MAP()) {
2849: $depth--;
1.468 amueller 2850: $lastcontainer = $parent{$depth};
1.461 neumanie 2851: }
2852: if (ref($curRes)) {
1.468 amueller 2853: my $symb = $curRes->symb();
2854: my $ressymb = $symb;
1.461 neumanie 2855: if (($curRes->is_sequence()) || ($curRes->is_page())) {
2856: my $type = 'sequence';
2857: if ($curRes->is_page()) {
2858: $type = 'page';
2859: }
2860: my $id= $curRes->id();
1.468 amueller 2861: my $srcf = $curRes->src();
2862: my $resource_name = &Apache::lonnet::gettitle($srcf);
2863: if(!exists($treeinfo->{$id})) {
2864: push(@$tree,$id);
1.473 amueller 2865: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 2866: $treeinfo->{$id} = {
1.461 neumanie 2867: depth => $depth,
2868: type => $type,
1.468 amueller 2869: name => $resource_name,
2870: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 2871: };
1.462 neumanie 2872: }
1.461 neumanie 2873: }
2874: }
2875: }
1.462 neumanie 2876: }
1.473 amueller 2877: # Show it ...
1.610 raeburn 2878: my $rowattr = ' id="mapmenu"';
2879: if ($parmlev eq 'general') {
2880: $rowattr .= ' style="display:none"';
2881: }
2882: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461 neumanie 2883: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
2884: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 2885: my $whitespace =
2886: '<img src="'
2887: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
2888: .'" alt="" />';
2889:
1.498 bisitz 2890: # Info about selectable folders/maps
2891: $r->print(
2892: '<div class="LC_info">'
1.508 www 2893: .&mt('You can only select maps and folders which have modifiable settings.')
2894: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 2895: .'</div>'
2896: );
2897:
1.536 raeburn 2898: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 2899: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 2900:
1.498 bisitz 2901: # Display row: "All Maps or Folders"
2902: $r->print(
1.523 raeburn 2903: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 2904: .'<td>'
2905: .'<label>'
2906: .'<input type="radio" name="pschp"'
1.497 bisitz 2907: );
2908: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 2909: $r->print(
2910: ' value="all" /> '.$icon.' '
2911: .&mt('All Maps or Folders')
2912: .'</label>'
2913: .'<hr /></td>'
2914: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2915: );
1.497 bisitz 2916:
1.532 raeburn 2917: # Display row: "Main Content"
1.468 amueller 2918: if (exists($$allmaps{1})) {
1.498 bisitz 2919: $r->print(
2920: &Apache::loncommon::start_data_table_row()
2921: .'<td>'
2922: .'<label>'
2923: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 2924: );
1.497 bisitz 2925: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 2926: $r->print(
2927: '/> '.$icon.' '
2928: .$$maptitles{1}
2929: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
2930: .'</label>'
2931: .'</td>'
2932: .&Apache::loncommon::end_data_table_row()
1.468 amueller 2933: );
2934: }
1.497 bisitz 2935:
2936: # Display rows for all course maps and folders
1.468 amueller 2937: foreach my $id (@{$tree}) {
2938: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 2939: # Indentation
1.468 amueller 2940: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 2941: my $indent;
2942: for (my $i = 0; $i < $depth; $i++) {
2943: $indent.= $whitespace;
2944: }
1.461 neumanie 2945: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 2946: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 2947: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
2948: }
1.468 amueller 2949: my $symb_name = $$symbp{$id};
2950: my ($front, $tail) = split (/___${resid}___/, $symb_name);
2951: $symb_name = $tail;
1.498 bisitz 2952: $r->print(
2953: &Apache::loncommon::start_data_table_row()
2954: .'<td>'
2955: .'<label>'
1.463 bisitz 2956: );
1.498 bisitz 2957: # Only offer radio button for folders/maps which can be parameterized
2958: if ($allmaps_inverted{$symb_name}) {
2959: $r->print(
2960: '<input type ="radio" name="pschp"'
2961: .' value="'.$allmaps_inverted{$symb_name}.'"'
2962: );
2963: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
2964: $r->print('/>');
2965: } else {
2966: $r->print($whitespace);
1.461 neumanie 2967: }
1.498 bisitz 2968: $r->print(
2969: $indent.$icon.' '
2970: .$treeinfo->{$id}->{name}
2971: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
2972: .'</label>'
2973: .'</td>'
2974: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2975: );
1.461 neumanie 2976: }
1.497 bisitz 2977:
1.523 raeburn 2978: $r->print(&Apache::loncommon::end_data_table().
2979: '<br style="line-height:2px;" />'.
2980: &Apache::loncommon::end_scrollbox());
1.209 www 2981: }
2982: }
2983:
1.563 damieng 2984: # Prints HTML to select the parameter level (resource, map/folder or course).
2985: # Used by table and overview modes.
2986: #
2987: # @param {Apache2::RequestRec} $r - the Apache request
2988: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
2989: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 2990: sub levelmenu {
1.446 bisitz 2991: my ($r,$alllevs,$parmlev)=@_;
2992:
1.548 raeburn 2993: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
2994: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 2995: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 2996: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
2997: $r->print('<option value="'.$$alllevs{$lev}.'"');
2998: if ($parmlev eq $$alllevs{$lev}) {
2999: $r->print(' selected="selected"');
3000: }
3001: $r->print('>'.&mt($lev).'</option>');
1.208 www 3002: }
1.446 bisitz 3003: $r->print("</select>");
1.208 www 3004: }
3005:
1.211 www 3006:
1.563 damieng 3007: # Returns HTML to select a section (with a select HTML element).
3008: # Used by overview mode.
3009: #
3010: # @param {array reference} $selectedsections - list of selected section ids
3011: # @returns {string}
1.211 www 3012: sub sectionmenu {
1.553 raeburn 3013: my ($selectedsections)=@_;
1.300 albertel 3014: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 3015: return '' if (!%sectionhash);
1.300 albertel 3016:
1.552 raeburn 3017: my (@possibles,$disabled);
3018: if ($env{'request.course.sec'} ne '') {
3019: @possibles = ($env{'request.course.sec'});
3020: $selectedsections = [$env{'request.course.sec'}];
3021: $disabled = ' disabled="disabled"';
3022: } else {
3023: @possibles = ('all',sort(keys(%sectionhash)));
3024: }
1.553 raeburn 3025: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 3026: foreach my $s (@possibles) {
1.553 raeburn 3027: $output .= ' <option value="'.$s.'"';
3028: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
3029: $output .= ' selected="selected"';
1.473 amueller 3030: }
1.553 raeburn 3031: $output .= '>'."$s</option>\n";
1.300 albertel 3032: }
1.553 raeburn 3033: $output .= "</select>\n";
3034: return $output;
1.269 raeburn 3035: }
3036:
1.563 damieng 3037: # Returns HTML to select a group (with a select HTML element).
3038: # Used by overview mode.
3039: #
3040: # @param {array reference} $selectedgroups - list of selected group names
3041: # @returns {string}
1.269 raeburn 3042: sub groupmenu {
1.553 raeburn 3043: my ($selectedgroups)=@_;
3044: my %grouphash;
3045: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3046: %grouphash = &Apache::longroup::coursegroups();
3047: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 3048: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 3049: }
3050: return '' if (!%grouphash);
1.299 albertel 3051:
1.553 raeburn 3052: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 3053: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 3054: $output .= ' <option value="'.$group.'"';
3055: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
3056: $output .= ' selected="selected"';
1.473 amueller 3057: }
1.553 raeburn 3058: $output .= '>'."$group</option>\n";
1.211 www 3059: }
1.553 raeburn 3060: $output .= "</select>\n";
3061: return $output;
1.211 www 3062: }
3063:
1.563 damieng 3064: # Returns an array with the given parameter split by comma.
3065: # Used by assessparms (table mode).
3066: #
3067: # @param {string} $keyp - the string to split
3068: # @returns {Array<string>}
1.210 www 3069: sub keysplit {
3070: my $keyp=shift;
3071: return (split(/\,/,$keyp));
3072: }
3073:
1.563 damieng 3074: # Returns the keys in $name, sorted using $keyorder.
3075: # Parameters are sorted by key, which means they are sorted by part first, then by name.
3076: # Used by assessparms (table mode) for resource level.
3077: #
3078: # @param {hash reference} $name - parameter key -> parameter name
3079: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3080: # @returns {Array<string>}
1.210 www 3081: sub keysinorder {
3082: my ($name,$keyorder)=@_;
3083: return sort {
1.560 damieng 3084: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 3085: } (keys(%{$name}));
1.210 www 3086: }
3087:
1.563 damieng 3088: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3089: # Used by assessparms (table mode) for map and general levels.
3090: #
3091: # @param {hash reference} $name - parameter key -> parameter name
3092: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3093: # @returns {Array<string>}
1.236 albertel 3094: sub keysinorder_bytype {
3095: my ($name,$keyorder)=@_;
3096: return sort {
1.563 damieng 3097: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3098: my $tb=(split('_',$b))[-1];
3099: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3100: return ($a cmp $b);
3101: }
3102: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3103: } (keys(%{$name}));
1.236 albertel 3104: }
3105:
1.563 damieng 3106: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3107: # Used by defaultsetter (parameter settings default actions).
3108: #
3109: # @param {hash reference} $name - hash parameter name -> parameter title
3110: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3111: # @returns {Array<string>}
1.211 www 3112: sub keysindisplayorder {
3113: my ($name,$keyorder)=@_;
3114: return sort {
1.560 damieng 3115: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3116: } (keys(%{$name}));
1.211 www 3117: }
3118:
1.563 damieng 3119: # Prints HTML with a choice to sort results by realm or student first.
3120: # Used by overview mode.
3121: #
3122: # @param {Apache2::RequestRec} $r - the Apache request
3123: # @param {string} $sortorder - realmstudent|studentrealm
1.608 raeburn 3124: # @param {string} $context - newoverview|overview
1.214 www 3125: sub sortmenu {
1.608 raeburn 3126: my ($r,$sortorder,$context)=@_;
3127: my %text;
3128: if ($context eq 'newoverview') {
3129: %text = &Apache::lonlocal::texthash (
3130: realmstudent => 'Sort by location in course first, then student (group/section)',
3131: studentrealm => 'Sort by student (group/section) first, then location in course',
3132: );
3133: } else {
3134: %text = &Apache::lonlocal::texthash (
3135: realmstudent => 'Sort by realm first, then student (group/section)',
3136: studentrealm => 'Sort by student (group/section) first, then realm',
3137: );
1.214 www 3138: }
1.608 raeburn 3139: my %sortchecked = (
3140: realmstudent => ' checked="checked"',
3141: studentrealm => '',
3142: );
1.214 www 3143: if ($sortorder eq 'studentrealm') {
1.608 raeburn 3144: $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
3145: $sortchecked{'realmstudent'} = '';
3146: }
3147: foreach my $sorttype ('realmstudent','studentrealm') {
3148: $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
3149: $text{$sorttype}.'</label>');
1.214 www 3150: }
3151: }
3152:
1.563 damieng 3153: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3154: #
3155: # @returns {hash}
1.211 www 3156: sub standardkeyorder {
3157: return ('parameter_0_opendate' => 1,
1.473 amueller 3158: 'parameter_0_duedate' => 2,
3159: 'parameter_0_answerdate' => 3,
3160: 'parameter_0_interval' => 4,
3161: 'parameter_0_weight' => 5,
3162: 'parameter_0_maxtries' => 6,
3163: 'parameter_0_hinttries' => 7,
3164: 'parameter_0_contentopen' => 8,
3165: 'parameter_0_contentclose' => 9,
3166: 'parameter_0_type' => 10,
3167: 'parameter_0_problemstatus' => 11,
3168: 'parameter_0_hiddenresource' => 12,
3169: 'parameter_0_hiddenparts' => 13,
3170: 'parameter_0_display' => 14,
3171: 'parameter_0_ordered' => 15,
3172: 'parameter_0_tol' => 16,
3173: 'parameter_0_sig' => 17,
3174: 'parameter_0_turnoffunit' => 18,
1.521 raeburn 3175: 'parameter_0_discussend' => 19,
3176: 'parameter_0_discusshide' => 20,
3177: 'parameter_0_discussvote' => 21,
1.560 damieng 3178: 'parameter_0_printstartdate' => 22,
3179: 'parameter_0_printenddate' => 23);
1.211 www 3180: }
3181:
1.59 matthew 3182:
1.560 damieng 3183: # Table mode UI.
1.563 damieng 3184: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3185: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3186: #
3187: # Parameters used from the request:
3188: # action - handler action (see handler), usermenu is checking for value 'settable'
3189: # cgroup - selected group
3190: # command - 'set': direct access to table mode for a resource
3191: # csec - selected section
3192: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3193: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3194: # id - student/employee ID
3195: # parmlev - selected level (full|map|general)
3196: # part - selected part (unused ?)
3197: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3198: # pres_type - &&&-separated parameter types
3199: # pres_value - &&&-separated parameter values
3200: # prevvisit - '1' if the user has submitted the form before
3201: # pscat (multiple values) - selected parameter names
1.566 damieng 3202: # pschp - selected map pc, or 'all'
1.563 damieng 3203: # psprt (multiple values) - list of selected parameter parts
3204: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3205: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3206: # symb - resource symb (when a single resource is selected)
3207: # udom - selected user domain
3208: # uname - selected user name
3209: # url - used only with command 'set', the resource url
3210: #
3211: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3212: # @param $parm_permission - ref to hash of permissions
3213: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3214: sub assessparms {
1.1 www 3215:
1.568 raeburn 3216: my ($r,$parm_permission) = @_;
1.201 www 3217:
1.512 foxr 3218:
3219: # -------------------------------------------------------- Variable declaration
1.566 damieng 3220: my @ids=(); # resource and map ids
3221: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3222: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3223: my %typep=(); # hash resource/map id -> resource type (file extension)
3224: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3225: my %uris=(); # hash resource/map id -> resource src
3226: my %maptitles=(); # hash map pc or src -> map title
3227: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3228: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3229: my %alllevs=(); # hash English level title -> value
3230:
3231: my $uname; # selected user name
3232: my $udom; # selected user domain
3233: my $uhome; # server with the user's files, or 'no_host'
3234: my $csec; # selected section name
3235: my $cgroup; # selected group name
3236: my @usersgroups = (); # list of the user groups
1.582 raeburn 3237: my $numreclinks = 0;
1.446 bisitz 3238:
1.190 albertel 3239: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3240:
1.57 albertel 3241: $alllevs{'Resource Level'}='full';
1.215 www 3242: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3243: $alllevs{'Course Level'}='general';
3244:
1.563 damieng 3245: my %allparms; # hash parameter name -> parameter title
3246: my %allparts; # hash parameter part -> part title
1.512 foxr 3247: # ------------------------------------------------------------------------------
3248:
1.210 www 3249: #
3250: # Order in which these parameters will be displayed
3251: #
1.211 www 3252: my %keyorder=&standardkeyorder();
3253:
1.512 foxr 3254: # @ids=();
3255: # %symbp=(); # These seem defined above already.
3256: # %typep=();
1.43 albertel 3257:
3258: my $message='';
3259:
1.190 albertel 3260: $csec=$env{'form.csec'};
1.552 raeburn 3261: if ($env{'request.course.sec'} ne '') {
3262: $csec = $env{'request.course.sec'};
3263: }
3264:
1.553 raeburn 3265: # Check group privs.
1.269 raeburn 3266: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3267: my $noeditgrp;
3268: if ($cgroup ne '') {
3269: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3270: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3271: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3272: $noeditgrp = 1;
3273: }
3274: }
3275: }
1.188 www 3276:
1.190 albertel 3277: if ($udom=$env{'form.udom'}) {
3278: } elsif ($udom=$env{'request.role.domain'}) {
3279: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3280: } else {
1.473 amueller 3281: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3282: }
1.468 amueller 3283:
1.43 albertel 3284:
1.134 albertel 3285: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3286: my $pschp=$env{'form.pschp'};
1.506 www 3287:
3288:
1.134 albertel 3289: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3290: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3291: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3292:
1.43 albertel 3293: my $pssymb='';
1.57 albertel 3294: my $parmlev='';
1.446 bisitz 3295:
1.190 albertel 3296: unless ($env{'form.parmlev'}) {
1.57 albertel 3297: $parmlev = 'map';
3298: } else {
1.190 albertel 3299: $parmlev = $env{'form.parmlev'};
1.57 albertel 3300: }
1.26 www 3301:
1.29 www 3302: # ----------------------------------------------- Was this started from grades?
3303:
1.560 damieng 3304: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3305: (!$env{'form.dis'})) {
1.473 amueller 3306: my $url=$env{'form.url'};
3307: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3308: $pssymb=&Apache::lonnet::symbread($url);
3309: if (!@pscat) { @pscat=('all'); }
3310: $pschp='';
1.57 albertel 3311: $parmlev = 'full';
1.190 albertel 3312: } elsif ($env{'form.symb'}) {
1.473 amueller 3313: $pssymb=$env{'form.symb'};
3314: if (!@pscat) { @pscat=('all'); }
3315: $pschp='';
1.57 albertel 3316: $parmlev = 'full';
1.43 albertel 3317: } else {
1.473 amueller 3318: $env{'form.url'}='';
1.43 albertel 3319: }
3320:
1.190 albertel 3321: my $id=$env{'form.id'};
1.43 albertel 3322: if (($id) && ($udom)) {
1.555 raeburn 3323: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3324: if ($uname) {
3325: $id='';
3326: } else {
3327: $message=
1.540 bisitz 3328: '<p class="LC_warning">'.
3329: &mt('Unknown ID [_1] at domain [_2]',
3330: "'".$id."'","'".$udom."'").
3331: '</p>';
1.473 amueller 3332: }
1.43 albertel 3333: } else {
1.473 amueller 3334: $uname=$env{'form.uname'};
1.43 albertel 3335: }
3336: unless ($udom) { $uname=''; }
3337: $uhome='';
3338: if ($uname) {
1.473 amueller 3339: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3340: if ($uhome eq 'no_host') {
1.473 amueller 3341: $message=
1.540 bisitz 3342: '<p class="LC_warning">'.
3343: &mt('Unknown user [_1] at domain [_2]',
3344: "'".$uname."'","'".$udom."'").
3345: '</p>';
1.473 amueller 3346: $uname='';
1.12 www 3347: } else {
1.473 amueller 3348: $csec=&Apache::lonnet::getsection($udom,$uname,
3349: $env{'request.course.id'});
3350: if ($csec eq '-1') {
1.596 raeburn 3351: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3352: if ($env{'form.userroles'} eq 'any') {
3353: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3354: $csec = $env{'request.course.sec'};
3355: $message = '<span class="LC_info">';
3356: if ($crstype eq 'Community') {
3357: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3358: $uname,$udom);
3359: } else {
3360: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3361: $uname,$udom);
3362: }
3363: $message .= '</span>';
3364: } else {
3365: my @possroles = ('in','ep','ta','cr');
3366: if ($crstype eq 'Community') {
3367: unshift(@possroles,'co');
3368: } else {
3369: unshift(@possroles,'cc');
3370: }
3371: my %not_student_roles =
3372: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3373: \@possroles,[$udom],1,1);
3374: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3375: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3376: my %sections_by_role;
3377: foreach my $role (keys(%not_student_roles)) {
3378: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3379: my ($rolename,$sec) = ($1,$2);
3380: if ($rolename =~ m{^cr/}) {
3381: $rolename = 'cr';
3382: }
3383: push(@{$sections_by_role{$rolename}},$sec);
3384: }
3385: }
3386: my $numroles = scalar(keys(%sections_by_role));
3387: if ($numroles) {
3388: foreach my $role (@possroles) {
3389: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3390: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3391: $csec = $secs[0];
3392: last;
3393: }
3394: }
3395: }
3396: if ($csec eq '-1') {
3397: $message = '<span class="LC_warning">';
3398: if ($crstype eq 'Community') {
3399: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3400: $uname,$udom);
3401: } else {
3402: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3403: $uname,$udom);
3404: }
3405: $message .= '</span>';
3406: $uname='';
3407: if ($env{'request.course.sec'} ne '') {
3408: $csec=$env{'request.course.sec'};
3409: } else {
3410: $csec=$env{'form.csec'};
3411: }
3412: $cgroup=$env{'form.cgroup'};
3413: } else {
3414: $message = '<span class="LC_info">';
3415: if ($crstype eq 'Community') {
3416: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3417: $uname,$udom);
3418: } else {
3419: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3420: $uname,$udom);
3421: }
3422: $message .= '</span>';
3423: }
3424: }
1.594 raeburn 3425: } else {
1.596 raeburn 3426: $message = '<span class="LC_warning">';
3427: if ($crstype eq 'Community') {
3428: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3429: $uname,$udom);
3430: } else {
3431: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3432: $uname,$udom);
3433: }
3434: $message .= '</span>';
3435: $uname='';
3436: if ($env{'request.course.sec'} ne '') {
3437: $csec=$env{'request.course.sec'};
3438: } else {
3439: $csec=$env{'form.csec'};
3440: }
3441: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3442: }
3443: } elsif ($env{'request.course.sec'} ne '') {
3444: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3445: $message='<span class="LC_warning">'.
1.594 raeburn 3446: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3447: $uname,$udom,$env{'request.course.sec'}).
3448: '</span>';
3449: $uname='';
3450: $csec=$env{'request.course.sec'};
3451: }
1.269 raeburn 3452: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3453: }
3454: if ($uname ne '') {
1.473 amueller 3455: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3456: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3457: $message .= "\n<p>\n".&mt('Full Name').': '
3458: .$name{'firstname'}.' '.$name{'middlename'}.' '
3459: .$name{'lastname'}.' '.$name{'generation'}
3460: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3461: @usersgroups = &Apache::lonnet::get_users_groups(
3462: $udom,$uname,$env{'request.course.id'});
3463: if (@usersgroups > 0) {
3464: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3465: $cgroup = $usersgroups[0];
3466: }
3467: } else {
3468: $cgroup = '';
1.297 raeburn 3469: }
1.269 raeburn 3470: }
1.12 www 3471: }
1.43 albertel 3472: }
1.2 www 3473:
1.43 albertel 3474: unless ($csec) { $csec=''; }
1.269 raeburn 3475: unless ($cgroup) { $cgroup=''; }
1.12 www 3476:
1.14 www 3477: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3478: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3479: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 3480: \%keyorder,undef,$pssymb);
1.63 bowersj2 3481:
1.582 raeburn 3482: %allmaps_inverted = reverse(%allmaps);
3483:
1.57 albertel 3484: $mapp{'0.0'} = '';
3485: $symbp{'0.0'} = '';
1.99 albertel 3486:
1.14 www 3487: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3488: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3489: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3490: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3491: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3492: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3493: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3494: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3495: my ($got_chostname,$chostname,$cmajor,$cminor);
3496: my $totalstored = 0;
1.605 raeburn 3497: my $totalskippeduser = 0;
1.546 raeburn 3498: my $now = time;
1.473 amueller 3499: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3500: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3501: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3502: next if ($csec ne $env{'request.course.sec'});
3503: }
1.556 raeburn 3504: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3505: next if ($noeditgrp);
1.605 raeburn 3506: } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
3507: if ($uname eq '') {
3508: $totalskippeduser ++;
3509: next;
3510: }
1.557 raeburn 3511: }
3512: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3513: $namematch = 'maplevelrecurse';
3514: }
1.556 raeburn 3515: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3516: my (@ok_slots,@fail_slots,@del_slots);
3517: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3518: my ($level,@all) =
3519: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3520: $csec,$cgroup,$courseopt);
3521: foreach my $slot_name (split(/:/,$values[$i])) {
3522: next if ($slot_name eq '');
3523: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3524: push(@ok_slots,$slot_name);
3525:
3526: } else {
3527: push(@fail_slots,$slot_name);
3528: }
3529: }
3530: if (@ok_slots) {
3531: $values[$i] = join(':',@ok_slots);
3532: } else {
3533: $values[$i] = '';
3534: }
3535: if ($all[$level] ne '') {
3536: my @existing = split(/:/,$all[$level]);
3537: foreach my $slot_name (@existing) {
3538: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3539: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3540: push(@del_slots,$slot_name);
3541: }
3542: }
3543: }
3544: }
1.554 raeburn 3545: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3546: $name = $1;
1.533 raeburn 3547: my $val = $values[$i];
1.549 raeburn 3548: my $valmatch = '';
1.533 raeburn 3549: if ($name eq 'examcode') {
1.544 raeburn 3550: if (&Apache::lonnet::validCODE($values[$i])) {
3551: $val = 'valid';
3552: }
1.546 raeburn 3553: } elsif ($name eq 'printstartdate') {
3554: if ($val =~ /^\d+$/) {
3555: if ($val > $now) {
3556: $val = 'future';
3557: }
3558: }
3559: } elsif ($name eq 'printenddate') {
3560: if ($val =~ /^\d+$/) {
3561: if ($val < $now) {
3562: $val = 'past';
3563: }
3564: }
1.549 raeburn 3565: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3566: my $stringtype = &get_stringtype($name);
3567: my $stringmatch = &standard_string_matches($stringtype);
3568: if (ref($stringmatch) eq 'ARRAY') {
3569: foreach my $item (@{$stringmatch}) {
3570: if (ref($item) eq 'ARRAY') {
3571: my ($regexpname,$pattern) = @{$item};
3572: if ($pattern ne '') {
3573: if ($val =~ /$pattern/) {
3574: $valmatch = $regexpname;
3575: $val = '';
3576: last;
3577: }
3578: }
3579: }
3580: }
3581: }
1.554 raeburn 3582: } elsif ($name eq 'interval') {
3583: my $intervaltype = &get_intervaltype($name);
3584: my $intervalmatch = &standard_interval_matches($intervaltype);
3585: if (ref($intervalmatch) eq 'ARRAY') {
3586: foreach my $item (@{$intervalmatch}) {
3587: if (ref($item) eq 'ARRAY') {
3588: my ($regexpname,$pattern) = @{$item};
3589: if ($pattern ne '') {
3590: if ($val =~ /$pattern/) {
3591: $valmatch = $regexpname;
3592: $val = '';
3593: last;
3594: }
3595: }
3596: }
3597: }
3598: }
1.533 raeburn 3599: }
1.504 raeburn 3600: $needsrelease =
1.557 raeburn 3601: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3602: if ($needsrelease) {
1.505 raeburn 3603: unless ($got_chostname) {
1.514 raeburn 3604: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3605: $got_chostname = 1;
1.546 raeburn 3606: }
1.557 raeburn 3607: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3608: $needsrelease,
3609: $cmajor,$cminor);
1.500 raeburn 3610: }
1.437 raeburn 3611: }
1.504 raeburn 3612: if ($needsnewer) {
1.557 raeburn 3613: undef($namematch);
3614: } else {
3615: my $currneeded;
3616: if ($needsrelease) {
3617: $currneeded = $needsrelease;
3618: }
3619: if ($namematch) {
3620: $needsrelease =
3621: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3622: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3623: unless ($got_chostname) {
3624: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3625: $got_chostname = 1;
3626: }
3627: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3628: $needsrelease,
3629: $cmajor,$cminor);
3630: } else {
3631: undef($namematch);
3632: }
3633: }
3634: }
3635: if ($needsnewer) {
3636: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3637: $cminor,$needsrelease);
3638: } else {
3639: $message.=&storeparm(split(/\&/,$markers[$i]),
3640: $values[$i],
3641: $types[$i],
3642: $uname,$udom,$csec,$cgroup);
3643: $totalstored ++;
3644: }
1.473 amueller 3645: }
1.68 www 3646: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3647: if ($totalstored) {
3648: $message.='<p class="LC_warning">'
1.605 raeburn 3649: .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
3650: .'<br />'
1.504 raeburn 3651: .&mt('Changes can take up to 10 minutes before being active for all students.')
3652: .&Apache::loncommon::help_open_topic('Caching')
3653: .'</p>';
1.605 raeburn 3654: } else {
3655: $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
3656: }
3657: if ($totalskippeduser) {
3658: $message .= '<p class="LC_warning">';
3659: if ($uhome eq 'no_host') {
3660: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
3661: $totalskippeduser);
3662: } elsif ($env{'form.userroles'} eq 'any') {
3663: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
3664: $totalskippeduser);
3665: } else {
3666: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
3667: $totalskippeduser);
3668: }
3669: $message .= '</p>';
1.504 raeburn 3670: }
1.68 www 3671: }
1.584 raeburn 3672:
1.57 albertel 3673: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3674: if ($pscat[0] eq "all") {
3675: @pscat = (keys(%allparms));
3676: }
3677: if (!@pscat) {
3678: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3679: };
3680: if ($psprt[0] eq "all" || !@psprt) {
3681: @psprt = (keys(%allparts));
3682: }
1.2 www 3683: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3684:
1.531 raeburn 3685: my $crstype = &Apache::loncommon::course_type();
3686: &startpage($r,$pssymb,$crstype);
1.57 albertel 3687:
1.548 raeburn 3688: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3689: 'date_interval','int','float','string','string_lenient',
3690: 'string_examcode','string_deeplink','string_discussvote',
3691: 'string_useslots','string_problemstatus','string_ip',
3692: 'string_questiontype') {
1.473 amueller 3693: $r->print('<input type="hidden" value="'.
1.563 damieng 3694: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3695: '" name="recent_'.$item.'" />');
1.44 albertel 3696: }
1.446 bisitz 3697:
1.459 bisitz 3698: # ----- Start Parameter Selection
3699:
1.606 raeburn 3700: # Hide parm selection and possibly table?
3701: my ($tablejs,$tabledivsty);
3702: if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
3703: ($env{'form.dis'}) && ($pssymb eq '')) {
3704: $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
3705: $tabledivsty = ' style="display:none"';
3706: }
1.459 bisitz 3707: $r->print(<<ENDPARMSELSCRIPT);
3708: <script type="text/javascript">
3709: // <![CDATA[
3710: function parmsel_show() {
1.562 damieng 3711: document.getElementById('parmsel').style.display = "";
3712: document.getElementById('parmsellink').style.display = "none";
1.606 raeburn 3713: $tablejs
1.459 bisitz 3714: }
3715: // ]]>
3716: </script>
3717: ENDPARMSELSCRIPT
1.474 amueller 3718:
1.445 neumanie 3719: if (!$pssymb) {
1.563 damieng 3720: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3721: my $parmselhiddenstyle=' style="display:none"';
3722: if($env{'form.hideparmsel'} eq 'hidden') {
3723: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3724: } else {
3725: $r->print('<div id="parmsel">');
3726: }
3727:
1.491 bisitz 3728: # Step 1
1.523 raeburn 3729: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3730: $r->print('
1.474 amueller 3731: <script type="text/javascript">
1.523 raeburn 3732: // <![CDATA['.
3733: &showhide_js().'
1.474 amueller 3734: // ]]>
3735: </script>
1.523 raeburn 3736: ');
3737: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3738: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3739: $r->print(&Apache::lonhtmlcommon::row_closure());
1.610 raeburn 3740: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491 bisitz 3741: $r->print(&Apache::lonhtmlcommon::row_closure());
3742: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3743: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3744: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3745: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3746:
3747: # Step 2
1.523 raeburn 3748: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3749: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3750:
3751: # Step 3
1.523 raeburn 3752: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3753: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3754: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3755: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3756: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3757:
3758: # Update Display Button
1.486 www 3759: $r->print('<p>'
3760: .'<input type="submit" name="dis"'
1.511 www 3761: .' value="'.&mt('Update Display').'" />'
1.486 www 3762: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3763: .'</p>');
3764: $r->print('</div>');
1.491 bisitz 3765:
1.486 www 3766: # Offer link to display parameter selection again
3767: $r->print('<p id="parmsellink"');
3768: if ($env{'form.hideparmsel'} ne 'hidden') {
3769: $r->print($parmselhiddenstyle);
3770: }
3771: $r->print('>'
3772: .'<a href="javascript:parmsel_show()">'
3773: .&mt('Change Parameter Selection')
3774: .'</a>'
3775: .'</p>');
1.44 albertel 3776: } else {
1.478 amueller 3777: # parameter screen for a single resource.
1.486 www 3778: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3779: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3780: $r->print(&mt('Specific Resource: [_1] ([_2])',
3781: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3782: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 3783: '<br />');
3784: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
3785: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3786: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3787: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3788: $r->print(&Apache::lonhtmlcommon::end_pick_box());
3789: $r->print('<p>'
1.459 bisitz 3790: .'<input type="submit" name="dis"'
1.511 www 3791: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 3792: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 3793: .'</p>');
1.459 bisitz 3794: }
1.478 amueller 3795:
1.486 www 3796: # ----- End Parameter Selection
1.57 albertel 3797:
1.459 bisitz 3798: # Display Messages
3799: $r->print('<div>'.$message.'</div>');
1.210 www 3800:
1.57 albertel 3801:
3802: my @temp_pscat;
3803: map {
3804: my $cat = $_;
3805: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
3806: } @pscat;
3807:
3808: @pscat = @temp_pscat;
3809:
1.548 raeburn 3810:
1.209 www 3811: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 3812: # ----------------------------------------------------------------- Start Table
1.57 albertel 3813: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 3814: my $csuname=$env{'user.name'};
3815: my $csudom=$env{'user.domain'};
1.568 raeburn 3816: my $readonly = 1;
3817: if ($parm_permission->{'edit'}) {
3818: undef($readonly);
3819: }
1.606 raeburn 3820: $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57 albertel 3821:
1.203 www 3822: if ($parmlev eq 'full') {
1.506 www 3823: #
3824: # This produces the cascading table output of parameters
3825: #
1.578 raeburn 3826: my $coursespan=$csec?8:5;
3827: my $userspan=3;
1.560 damieng 3828: if ($cgroup ne '') {
1.578 raeburn 3829: $coursespan += 3;
1.560 damieng 3830: }
1.473 amueller 3831:
1.560 damieng 3832: $r->print(&Apache::loncommon::start_data_table());
3833: #
3834: # This produces the headers
3835: #
3836: $r->print('<tr><td colspan="5"></td>');
3837: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
3838: if ($uname) {
1.473 amueller 3839: if (@usersgroups > 1) {
1.560 damieng 3840: $userspan ++;
3841: }
3842: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
3843: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
3844: }
3845: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 3846: 'pie' => "Parameter in Effect",
3847: 'csv' => "Current Session Value",
1.472 amueller 3848: 'rl' => "Resource Level",
1.473 amueller 3849: 'ic' => 'in Course',
3850: 'aut' => "Assessment URL and Title",
3851: 'type' => 'Type',
3852: 'emof' => "Enclosing Map or Folder",
3853: 'part' => 'Part',
1.472 amueller 3854: 'pn' => 'Parameter Name',
1.473 amueller 3855: 'def' => 'default',
3856: 'femof' => 'from Enclosing Map or Folder',
3857: 'gen' => 'general',
3858: 'foremf' => 'for Enclosing Map or Folder',
3859: 'fr' => 'for Resource'
3860: );
1.560 damieng 3861: $r->print(<<ENDTABLETWO);
1.419 bisitz 3862: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 3863: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 3864: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 3865: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 3866:
1.10 www 3867: ENDTABLETWO
1.560 damieng 3868: if ($csec) {
1.578 raeburn 3869: $r->print('<th colspan="3">'.
1.560 damieng 3870: &mt("in Section")." $csec</th>");
3871: }
3872: if ($cgroup) {
1.578 raeburn 3873: $r->print('<th colspan="3">'.
1.472 amueller 3874: &mt("in Group")." $cgroup</th>");
1.560 damieng 3875: }
3876: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 3877: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
3878: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 3879: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 3880: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 3881: ENDTABLEHEADFOUR
1.57 albertel 3882:
1.560 damieng 3883: if ($csec) {
1.578 raeburn 3884: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3885: }
1.473 amueller 3886:
1.560 damieng 3887: if ($cgroup) {
1.578 raeburn 3888: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3889: }
3890:
3891: if ($uname) {
3892: if (@usersgroups > 1) {
3893: $r->print('<th>'.&mt('Control by other group?').'</th>');
3894: }
1.578 raeburn 3895: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3896: }
3897:
3898: $r->print('</tr>');
1.506 www 3899: #
3900: # Done with the headers
3901: #
1.560 damieng 3902: my $defbgone='';
3903: my $defbgtwo='';
3904: my $defbgthree = '';
1.57 albertel 3905:
1.560 damieng 3906: foreach my $rid (@ids) {
1.57 albertel 3907:
3908: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 3909: if ((!$pssymb &&
1.560 damieng 3910: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
3911: ||
3912: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 3913: # ------------------------------------------------------ Entry for one resource
1.473 amueller 3914: if ($defbgone eq '#E0E099') {
3915: $defbgone='#E0E0DD';
1.57 albertel 3916: } else {
1.419 bisitz 3917: $defbgone='#E0E099';
1.57 albertel 3918: }
1.419 bisitz 3919: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 3920: $defbgtwo='#FFFFDD';
1.57 albertel 3921: } else {
1.473 amueller 3922: $defbgtwo='#FFFF99';
1.57 albertel 3923: }
1.419 bisitz 3924: if ($defbgthree eq '#FFBB99') {
3925: $defbgthree='#FFBBDD';
1.269 raeburn 3926: } else {
1.419 bisitz 3927: $defbgthree='#FFBB99';
1.269 raeburn 3928: }
3929:
1.57 albertel 3930: my $thistitle='';
3931: my %name= ();
3932: undef %name;
3933: my %part= ();
3934: my %display=();
3935: my %type= ();
3936: my %default=();
1.196 www 3937: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3938: my $toolsymb;
3939: if ($uri =~ /ext\.tool$/) {
3940: $toolsymb = $symbp{$rid};
3941: }
1.57 albertel 3942:
1.506 www 3943: my $filter=$env{'form.filter'};
1.548 raeburn 3944: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 3945: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 3946: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 3947: # We may only want certain parameters listed
3948: if ($filter) {
3949: unless ($filter=~/\Q$parmname\E/) { next; }
3950: }
3951: $name{$tempkeyp}=$parmname;
1.584 raeburn 3952: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 3953:
1.584 raeburn 3954: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 3955: if ($allparms{$name{$tempkeyp}} ne '') {
3956: my $identifier;
3957: if ($parmdis =~ /(\s*\[Part.*)$/) {
3958: $identifier = $1;
3959: }
3960: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3961: } else {
3962: $display{$tempkeyp} = $parmdis;
3963: }
3964: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3965: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 3966: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
3967: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
3968: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 3969: }
3970: }
1.548 raeburn 3971: my $totalparms=scalar(keys(%name));
1.57 albertel 3972: if ($totalparms>0) {
1.560 damieng 3973: my $firstrow=1;
1.473 amueller 3974: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 3975: my $navmap = Apache::lonnavmaps::navmap->new();
3976: my @recurseup;
3977: if (ref($navmap) && $mapp{$rid}) {
3978: @recurseup = $navmap->recurseup_maps($mapp{$rid});
3979: }
1.419 bisitz 3980: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 3981: ' rowspan='.$totalparms.
1.419 bisitz 3982: '><tt><font size="-1">'.
1.57 albertel 3983: join(' / ',split(/\//,$uri)).
3984: '</font></tt><p><b>'.
1.154 albertel 3985: "<a href=\"javascript:openWindow('".
1.473 amueller 3986: &Apache::lonnet::clutter($uri).'?symb='.
3987: &escape($symbp{$rid}).
1.336 albertel 3988: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
3989: " target=\"_self\">$title");
1.57 albertel 3990:
3991: if ($thistitle) {
1.473 amueller 3992: $r->print(' ('.$thistitle.')');
1.57 albertel 3993: }
3994: $r->print('</a></b></td>');
1.419 bisitz 3995: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 3996: ' rowspan='.$totalparms.'>'.$typep{$rid}.
3997: '</td>');
3998:
1.419 bisitz 3999: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 4000: ' rowspan='.$totalparms.
1.238 www 4001: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 4002: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 4003: unless ($firstrow) {
4004: $r->print('<tr>');
4005: } else {
4006: undef $firstrow;
4007: }
1.548 raeburn 4008: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 4009: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 4010: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 4011: $cgroup,\@usersgroups,$noeditgrp,$readonly,
4012: \@recurseup,\%maptitles,\%allmaps_inverted,
4013: \$numreclinks);
1.57 albertel 4014: }
4015: }
4016: }
4017: } # end foreach ids
1.43 albertel 4018: # -------------------------------------------------- End entry for one resource
1.517 www 4019: $r->print(&Apache::loncommon::end_data_table);
1.203 www 4020: } # end of full
1.57 albertel 4021: #--------------------------------------------------- Entry for parm level map
4022: if ($parmlev eq 'map') {
1.419 bisitz 4023: my $defbgone = '#E0E099';
4024: my $defbgtwo = '#FFFF99';
4025: my $defbgthree = '#FFBB99';
1.57 albertel 4026:
4027: my %maplist;
4028:
4029: if ($pschp eq 'all') {
1.446 bisitz 4030: %maplist = %allmaps;
1.57 albertel 4031: } else {
4032: %maplist = ($pschp => $mapp{$pschp});
4033: }
4034:
4035: #-------------------------------------------- for each map, gather information
4036: my $mapid;
1.607 raeburn 4037: foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60 albertel 4038: my $maptitle = $maplist{$mapid};
1.57 albertel 4039:
4040: #----------------------- loop through ids and get all parameter types for map
4041: #----------------------------------------- and associated information
4042: my %name = ();
4043: my %part = ();
4044: my %display = ();
4045: my %type = ();
4046: my %default = ();
4047: my $map = 0;
4048:
1.473 amueller 4049: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 4050:
1.548 raeburn 4051: foreach my $id (@ids) {
4052: ($map)=($id =~ /([\d]*?)\./);
4053: my $rid = $id;
1.446 bisitz 4054:
1.57 albertel 4055: # $r->print("$mapid:$map: $rid <br /> \n");
4056:
1.560 damieng 4057: if ($map eq $mapid) {
1.473 amueller 4058: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4059: my $toolsymb;
4060: if ($uri =~ /ext\.tool$/) {
4061: $toolsymb = $symbp{$rid};
4062: }
1.582 raeburn 4063:
1.57 albertel 4064: # $r->print("Keys: $keyp{$rid} <br />\n");
4065:
4066: #--------------------------------------------------------------------
4067: # @catmarker contains list of all possible parameters including part #s
4068: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4069: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4070: # When storing information, store as part 0
4071: # When requesting information, request from full part
4072: #-------------------------------------------------------------------
1.548 raeburn 4073: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4074: my $tempkeyp = $fullkeyp;
4075: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 4076:
1.548 raeburn 4077: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4078: $part{$tempkeyp}="0";
1.584 raeburn 4079: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4080: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4081: if ($allparms{$name{$tempkeyp}} ne '') {
4082: my $identifier;
4083: if ($parmdis =~ /(\s*\[Part.*)$/) {
4084: $identifier = $1;
4085: }
4086: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4087: } else {
4088: $display{$tempkeyp} = $parmdis;
4089: }
4090: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4091: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4092: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4093: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4094: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 4095: }
4096: } # end loop through keys
1.560 damieng 4097: }
1.57 albertel 4098: } # end loop through ids
1.446 bisitz 4099:
1.57 albertel 4100: #---------------------------------------------------- print header information
1.133 www 4101: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 4102: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 4103: my $tmp="";
1.57 albertel 4104: if ($uname) {
1.473 amueller 4105: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 4106: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
4107: &mt('in')." \n";
1.57 albertel 4108: } else {
1.401 bisitz 4109: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 4110: }
1.269 raeburn 4111: if ($cgroup) {
1.401 bisitz 4112: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
4113: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4114: $csec = '';
4115: } elsif ($csec) {
1.401 bisitz 4116: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
4117: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4118: }
1.401 bisitz 4119: $r->print('<div align="center"><h4>'
4120: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 4121: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 4122: ,$tmp
4123: ,'<font color="red"><i>'.$coursename.'</i></font>'
4124: )
4125: ."<br /></h4>\n"
1.422 bisitz 4126: );
1.57 albertel 4127: #---------------------------------------------------------------- print table
1.419 bisitz 4128: $r->print('<p>'.&Apache::loncommon::start_data_table()
4129: .&Apache::loncommon::start_data_table_header_row()
4130: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 4131: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4132: .'<th>'.&mt('Parameter in Effect').'</th>'
4133: .&Apache::loncommon::end_data_table_header_row()
4134: );
1.57 albertel 4135:
1.582 raeburn 4136: my $navmap = Apache::lonnavmaps::navmap->new();
4137: my @recurseup;
4138: if (ref($navmap)) {
4139: my $mapres = $navmap->getByMapPc($mapid);
4140: if (ref($mapres)) {
4141: @recurseup = $navmap->recurseup_maps($mapres->src());
4142: }
4143: }
4144:
4145:
1.548 raeburn 4146: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4147: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4148: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4149: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4150: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4151: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4152: \$numreclinks);
1.57 albertel 4153: }
1.422 bisitz 4154: $r->print(&Apache::loncommon::end_data_table().'</p>'
4155: .'</div>'
4156: );
1.57 albertel 4157: } # end each map
4158: } # end of $parmlev eq map
4159: #--------------------------------- Entry for parm level general (Course level)
4160: if ($parmlev eq 'general') {
1.473 amueller 4161: my $defbgone = '#E0E099';
1.419 bisitz 4162: my $defbgtwo = '#FFFF99';
4163: my $defbgthree = '#FFBB99';
1.57 albertel 4164:
4165: #-------------------------------------------- for each map, gather information
4166: my $mapid="0.0";
4167: #----------------------- loop through ids and get all parameter types for map
4168: #----------------------------------------- and associated information
4169: my %name = ();
4170: my %part = ();
4171: my %display = ();
4172: my %type = ();
4173: my %default = ();
1.446 bisitz 4174:
1.548 raeburn 4175: foreach $id (@ids) {
4176: my $rid = $id;
1.446 bisitz 4177:
1.196 www 4178: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4179: my $toolsymb;
4180: if ($uri =~ /ext\.tool$/) {
4181: $toolsymb = $symbp{$rid};
4182: }
1.57 albertel 4183:
4184: #--------------------------------------------------------------------
4185: # @catmarker contains list of all possible parameters including part #s
4186: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4187: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4188: # When storing information, store as part 0
4189: # When requesting information, request from full part
4190: #-------------------------------------------------------------------
1.548 raeburn 4191: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4192: my $tempkeyp = $fullkeyp;
4193: $tempkeyp =~ s/_\w+_/_0_/;
4194: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4195: $part{$tempkeyp}="0";
1.584 raeburn 4196: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4197: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4198: if ($allparms{$name{$tempkeyp}} ne '') {
4199: my $identifier;
4200: if ($parmdis =~ /(\s*\[Part.*)$/) {
4201: $identifier = $1;
4202: }
4203: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4204: } else {
4205: $display{$tempkeyp} = $parmdis;
4206: }
4207: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4208: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4209: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4210: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4211: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4212: }
1.57 albertel 4213: } # end loop through keys
4214: } # end loop through ids
1.446 bisitz 4215:
1.57 albertel 4216: #---------------------------------------------------- print header information
1.473 amueller 4217: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4218: $r->print(<<ENDMAPONE);
1.419 bisitz 4219: <center>
4220: <h4>$setdef
1.135 albertel 4221: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4222: ENDMAPONE
4223: if ($uname) {
1.473 amueller 4224: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4225: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4226: } else {
1.135 albertel 4227: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4228: }
1.446 bisitz 4229:
1.135 albertel 4230: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4231: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4232: $r->print("</h4>\n");
1.57 albertel 4233: #---------------------------------------------------------------- print table
1.419 bisitz 4234: $r->print('<p>'.&Apache::loncommon::start_data_table()
4235: .&Apache::loncommon::start_data_table_header_row()
4236: .'<th>'.&mt('Parameter Name').'</th>'
4237: .'<th>'.&mt('Default Value').'</th>'
4238: .'<th>'.&mt('Parameter in Effect').'</th>'
4239: .&Apache::loncommon::end_data_table_header_row()
4240: );
1.57 albertel 4241:
1.548 raeburn 4242: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4243: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4244: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4245: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4246: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4247: $readonly);
1.57 albertel 4248: }
1.419 bisitz 4249: $r->print(&Apache::loncommon::end_data_table()
4250: .'</p>'
4251: .'</center>'
4252: );
1.57 albertel 4253: } # end of $parmlev eq general
1.606 raeburn 4254: $r->print('</div>');
1.43 albertel 4255: }
1.507 www 4256: $r->print('</form>');
1.582 raeburn 4257: if ($numreclinks) {
4258: $r->print(<<"END");
4259: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4260: <input type="hidden" name="pschp" />
4261: <input type="hidden" name="pscat" />
4262: <input type="hidden" name="psprt" />
4263: <input type="hidden" name="hideparmsel" value="hidden" />
4264: </form>
4265: <script type="text/javascript">
4266: function pjumprec(rid,name,part) {
4267: document.forms.recurseform.pschp.value = rid;
4268: document.forms.recurseform.pscat.value = name;
4269: document.forms.recurseform.psprt.value = part;
4270: document.forms.recurseform.submit();
4271: return false;
4272: }
4273: </script>
4274: END
4275: }
1.507 www 4276: &endSettingsScreen($r);
4277: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4278: } # end sub assessparms
1.30 www 4279:
1.560 damieng 4280:
4281:
1.120 www 4282: ##################################################
1.560 damieng 4283: # OVERVIEW MODE
1.207 www 4284: ##################################################
1.124 www 4285:
1.563 damieng 4286: my $tableopen; # boolean, true if HTML table is already opened
4287:
4288: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4289: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4290: # @returns {string}
1.124 www 4291: sub tablestart {
1.576 raeburn 4292: my ($readonly,$is_map) = @_;
1.124 www 4293: if ($tableopen) {
1.552 raeburn 4294: return '';
1.124 www 4295: } else {
1.552 raeburn 4296: $tableopen=1;
4297: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4298: if ($readonly) {
4299: $output .= '<th>'.&mt('Current value').'</th>';
4300: } else {
1.576 raeburn 4301: $output .= '<th>'.&mt('Delete').'</th>'.
4302: '<th>'.&mt('Set to ...').'</th>';
4303: if ($is_map) {
4304: $output .= '<th>'.&mt('Recursive?').'</th>';
4305: }
1.552 raeburn 4306: }
4307: $output .= '</tr>';
4308: return $output;
1.124 www 4309: }
4310: }
4311:
1.563 damieng 4312: # Returns HTML with the HTML table end tag, unless the table is not opened.
4313: # @returns {string}
1.124 www 4314: sub tableend {
4315: if ($tableopen) {
1.560 damieng 4316: $tableopen=0;
4317: return &Apache::loncommon::end_data_table();
1.124 www 4318: } else {
1.560 damieng 4319: return'';
1.124 www 4320: }
4321: }
4322:
1.563 damieng 4323: # Reads course and user information.
4324: # 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).
4325: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4326: # If the context is looking for a list, returns a list with the scalar data and the class list.
4327: # @param {string} $crs - course number
4328: # @param {string} $dom - course domain
4329: # @returns {hash reference|Array}
1.207 www 4330: sub readdata {
4331: my ($crs,$dom)=@_;
4332: # Read coursedata
4333: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4334: # Read userdata
4335:
4336: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4337: foreach my $user (keys(%$classlist)) {
4338: if ($user=~/^($match_username)\:($match_domain)$/) {
4339: my ($tuname,$tudom)=($1,$2);
4340: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4341: foreach my $userkey (keys(%{$useropt})) {
4342: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4343: my $newkey=$userkey;
1.548 raeburn 4344: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4345: $$resourcedata{$newkey}=$$useropt{$userkey};
4346: }
4347: }
1.473 amueller 4348: }
4349: }
1.552 raeburn 4350: if (wantarray) {
4351: return ($resourcedata,$classlist);
4352: } else {
4353: return $resourcedata;
4354: }
1.207 www 4355: }
4356:
4357:
1.563 damieng 4358: # Stores parameter data, using form parameters directly.
4359: #
4360: # 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 4361: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563 damieng 4362: # del_* - remove a parameter
4363: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4364: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4365: # key_* - date values
4366: # days_* - for date intervals
4367: # hours_* - for date intervals
4368: # minutes_* - for date intervals
4369: # seconds_* - for date intervals
4370: # done_* - for date intervals
4371: # typeof_* - parameter type
4372: #
4373: # @param {Apache2::RequestRec} $r - the Apache request
4374: # @param {string} $crs - course number
4375: # @param {string} $dom - course domain
1.208 www 4376: sub storedata {
4377: my ($r,$crs,$dom)=@_;
1.207 www 4378: # Set userlevel immediately
4379: # Do an intermediate store of course level
4380: my $olddata=&readdata($crs,$dom);
1.124 www 4381: my %newdata=();
4382: undef %newdata;
4383: my @deldata=();
1.576 raeburn 4384: my @delrec=();
4385: my @delnonrec=();
1.124 www 4386: undef @deldata;
1.504 raeburn 4387: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4388: my $now = time;
1.560 damieng 4389: foreach my $key (keys(%env)) {
4390: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4391: my $cmd=$1;
4392: my $thiskey=$2;
1.576 raeburn 4393: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588 raeburn 4394: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576 raeburn 4395: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4396: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4397: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4398: $altkey = $thiskey;
4399: $altkey =~ s/\Q___(all)\E/___(rec)/;
4400: if ($env{'form.rec_'.$thiskey}) {
4401: $recursive = 1;
4402: }
4403: }
4404: }
1.560 damieng 4405: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4406: if ($tuname) {
1.576 raeburn 4407: $tkey=$thiskey;
1.560 damieng 4408: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4409: if ($altkey) {
4410: $tkeynonrec = $tkey;
4411: $tkeyrec = $altkey;
4412: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4413: }
1.560 damieng 4414: }
4415: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4416: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4417: if ($cmd eq 'set') {
4418: $data=$env{$key};
4419: $valmatch = '';
4420: $valchk = $data;
4421: $typeof=$env{'form.typeof_'.$thiskey};
4422: $text = &mt('Saved modified parameter for');
4423: if ($typeof eq 'string_questiontype') {
4424: $name = 'type';
1.588 raeburn 4425: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4426: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4427: my $stringmatch = &standard_string_matches($typeof);
4428: if (ref($stringmatch) eq 'ARRAY') {
4429: foreach my $item (@{$stringmatch}) {
4430: if (ref($item) eq 'ARRAY') {
4431: my ($regexpname,$pattern) = @{$item};
4432: if ($pattern ne '') {
4433: if ($data =~ /$pattern/) {
4434: $valmatch = $regexpname;
4435: $valchk = '';
4436: last;
4437: }
1.560 damieng 4438: }
1.549 raeburn 4439: }
4440: }
4441: }
1.563 damieng 4442: } elsif ($typeof eq 'string_discussvote') {
4443: $name = 'discussvote';
4444: } elsif ($typeof eq 'string_examcode') {
4445: $name = 'examcode';
4446: if (&Apache::lonnet::validCODE($data)) {
4447: $valchk = 'valid';
4448: }
4449: } elsif ($typeof eq 'string_yesno') {
4450: if ($thiskey =~ /\.retrypartial$/) {
4451: $name = 'retrypartial';
4452: }
1.549 raeburn 4453: }
1.563 damieng 4454: } elsif ($cmd eq 'datepointer') {
4455: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4456: $typeof=$env{'form.typeof_'.$thiskey};
4457: $text = &mt('Saved modified date for');
4458: if ($typeof eq 'date_start') {
4459: if ($thiskey =~ /\.printstartdate$/) {
4460: $name = 'printstartdate';
4461: if (($data) && ($data > $now)) {
4462: $valchk = 'future';
4463: }
1.560 damieng 4464: }
1.563 damieng 4465: } elsif ($typeof eq 'date_end') {
4466: if ($thiskey =~ /\.printenddate$/) {
4467: $name = 'printenddate';
4468: if (($data) && ($data < $now)) {
4469: $valchk = 'past';
4470: }
1.560 damieng 4471: }
1.504 raeburn 4472: }
1.563 damieng 4473: } elsif ($cmd eq 'dateinterval') {
4474: $data=&get_date_interval_from_form($thiskey);
4475: if ($thiskey =~ /\.interval$/) {
4476: $name = 'interval';
4477: my $intervaltype = &get_intervaltype($name);
4478: my $intervalmatch = &standard_interval_matches($intervaltype);
4479: if (ref($intervalmatch) eq 'ARRAY') {
4480: foreach my $item (@{$intervalmatch}) {
4481: if (ref($item) eq 'ARRAY') {
4482: my ($regexpname,$pattern) = @{$item};
4483: if ($pattern ne '') {
4484: if ($data =~ /$pattern/) {
4485: $valmatch = $regexpname;
4486: $valchk = '';
4487: last;
4488: }
1.560 damieng 4489: }
1.554 raeburn 4490: }
4491: }
4492: }
4493: }
1.563 damieng 4494: $typeof=$env{'form.typeof_'.$thiskey};
4495: $text = &mt('Saved modified date for');
1.554 raeburn 4496: }
1.576 raeburn 4497: if ($recursive) {
1.563 damieng 4498: $namematch = 'maplevelrecurse';
1.560 damieng 4499: }
1.563 damieng 4500: if (($name ne '') || ($namematch ne '')) {
4501: my ($needsrelease,$needsnewer);
4502: if ($name ne '') {
4503: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4504: if ($needsrelease) {
4505: unless ($got_chostname) {
1.563 damieng 4506: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4507: $got_chostname = 1;
4508: }
1.563 damieng 4509: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4510: $needsrelease,
4511: $cmajor,$cminor);
4512: }
4513: }
4514: if ($namematch ne '') {
4515: if ($needsnewer) {
4516: undef($namematch);
1.560 damieng 4517: } else {
1.563 damieng 4518: my $currneeded;
4519: if ($needsrelease) {
4520: $currneeded = $needsrelease;
4521: }
4522: $needsrelease =
4523: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4524: if (($needsrelease) &&
4525: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4526: unless ($got_chostname) {
4527: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4528: $got_chostname = 1;
4529: }
4530: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4531: $namematch, $needsrelease,$cmajor,$cminor);
4532: } else {
4533: undef($namematch);
4534: }
1.560 damieng 4535: }
1.557 raeburn 4536: }
1.563 damieng 4537: if ($needsnewer) {
4538: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4539: $chostname,$cmajor,
4540: $cminor,$needsrelease));
4541: next;
4542: }
1.504 raeburn 4543: }
1.576 raeburn 4544: my ($reconlychg,$haschange,$storekey);
4545: if ($tuname) {
4546: my $ustorekey;
4547: if ($altkey) {
4548: if ($recursive) {
4549: if (exists($$olddata{$thiskey})) {
4550: if ($$olddata{$thiskey} eq $data) {
4551: $reconlychg = 1;
4552: }
4553: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4554: }
4555: if (exists($$olddata{$altkey})) {
4556: if (defined($data) && $$olddata{$altkey} ne $data) {
4557: $haschange = 1;
4558: }
4559: } elsif ((!$reconlychg) && ($data ne '')) {
4560: $haschange = 1;
4561: }
4562: $ustorekey = $tkeyrec;
4563: } else {
4564: if (exists($$olddata{$altkey})) {
4565: if ($$olddata{$altkey} eq $data) {
4566: $reconlychg = 1;
4567: }
4568: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4569: }
4570: if (exists($$olddata{$thiskey})) {
4571: if (defined($data) && $$olddata{$thiskey} ne $data) {
4572: $haschange = 1;
4573: }
4574: } elsif ((!$reconlychg) && ($data ne '')) {
4575: $haschange = 1;
4576: }
4577: $ustorekey = $tkeynonrec;
4578: }
4579: } else {
4580: if (exists($$olddata{$tkey})) {
4581: if (defined($data) && $$olddata{$tkey} ne $data) {
4582: $haschange = 1;
4583: }
4584: $ustorekey = $tkey;
4585: }
4586: }
4587: if ($haschange || $reconlychg) {
4588: unless ($env{'form.del_'.$thiskey}) {
4589: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4590: $ustorekey.'.type' => $typeof},
4591: $tudom,$tuname) eq 'ok') {
4592: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4593: $r->print('<br />'.$text.' '.
4594: &Apache::loncommon::plainname($tuname,$tudom));
4595: } else {
4596: $r->print('<div class="LC_error">'.
4597: &mt('Error saving parameters').'</div>');
4598: }
4599: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4600: }
4601: }
4602: } else {
4603: if ($altkey) {
4604: if ($recursive) {
4605: if (exists($$olddata{$thiskey})) {
4606: if ($$olddata{$thiskey} eq $data) {
4607: $reconlychg = 1;
4608: }
4609: push(@delnonrec,($thiskey,$thiskey.'.type'));
4610: }
4611: if (exists($$olddata{$altkey})) {
4612: if (defined($data) && $$olddata{$altkey} ne $data) {
4613: $haschange = 1;
4614: }
4615: } elsif (($data ne '') && (!$reconlychg)) {
4616: $haschange = 1;
4617: }
4618: $storekey = $altkey;
1.563 damieng 4619: } else {
1.576 raeburn 4620: if (exists($$olddata{$altkey})) {
4621: if ($$olddata{$altkey} eq $data) {
4622: $reconlychg = 1;
4623: }
4624: push(@delrec,($altkey,$altkey.'.type'));
4625: }
4626: if (exists($$olddata{$thiskey})) {
4627: if (defined($data) && $$olddata{$thiskey} ne $data) {
4628: $haschange = 1;
4629: }
4630: } elsif (($data ne '') && (!$reconlychg)) {
4631: $haschange = 1;
4632: }
4633: $storekey = $thiskey;
1.563 damieng 4634: }
1.560 damieng 4635: } else {
1.576 raeburn 4636: if (defined($data) && $$olddata{$thiskey} ne $data) {
4637: $haschange = 1;
4638: $storekey = $thiskey;
4639: }
4640: }
4641: }
4642: if ($reconlychg || $haschange) {
4643: unless ($env{'form.del_'.$thiskey}) {
4644: $newdata{$storekey}=$data;
4645: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4646: }
4647: }
4648: } elsif ($cmd eq 'del') {
4649: if ($tuname) {
1.576 raeburn 4650: my $error;
4651: if ($altkey) {
4652: if (exists($$olddata{$altkey})) {
4653: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4654: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4655: if ($recursive) {
4656: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4657: }
4658: } elsif ($recursive) {
4659: $error = 1;
4660: }
4661: }
4662: if (exists($$olddata{$thiskey})) {
4663: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4664: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4665: unless ($recursive) {
4666: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4667: }
4668: } elsif (!$recursive) {
4669: $error = 1;
4670: }
4671: }
1.560 damieng 4672: } else {
1.576 raeburn 4673: if (exists($$olddata{$thiskey})) {
4674: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4675: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4676: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4677: } else {
4678: $error = 1;
4679: }
4680: }
4681: }
4682: if ($error) {
1.560 damieng 4683: $r->print('<div class="LC_error">'.
4684: &mt('Error deleting parameters').'</div>');
4685: }
4686: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4687: } else {
1.576 raeburn 4688: if ($altkey) {
4689: if (exists($$olddata{$altkey})) {
4690: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4691: push(@deldata,($altkey,$altkey.'.type'));
4692: }
4693: }
4694: if (exists($$olddata{$thiskey})) {
4695: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4696: push(@deldata,($thiskey,$thiskey.'.type'));
4697: }
4698: }
4699: } elsif (exists($$olddata{$thiskey})) {
4700: push(@deldata,($thiskey,$thiskey.'.type'));
4701: }
1.560 damieng 4702: }
1.473 amueller 4703: }
4704: }
4705: }
1.207 www 4706: # Store all course level
1.144 www 4707: my $delentries=$#deldata+1;
1.576 raeburn 4708: my @alldels;
4709: if (@delrec) {
4710: push(@alldels,@delrec);
4711: }
4712: if (@delnonrec) {
4713: push(@alldels,@delnonrec);
4714: }
4715: if (@deldata) {
4716: push(@alldels,@deldata);
4717: }
1.548 raeburn 4718: my @newdatakeys=keys(%newdata);
1.144 www 4719: my $putentries=$#newdatakeys+1;
1.576 raeburn 4720: my ($delresult,$devalidate);
4721: if (@alldels) {
4722: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4723: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4724: &log_parmset(\%loghash,1);
1.576 raeburn 4725: if ($delentries) {
4726: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4727: }
4728: } elsif ($delentries) {
1.560 damieng 4729: $r->print('<div class="LC_error">'.
4730: &mt('Error deleting parameters').'</div>');
4731: }
1.576 raeburn 4732: $devalidate = 1;
1.144 www 4733: }
4734: if ($putentries) {
1.560 damieng 4735: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4736: &log_parmset(\%newdata,0);
4737: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4738: } else {
4739: $r->print('<div class="LC_error">'.
4740: &mt('Error saving parameters').'</div>');
4741: }
1.576 raeburn 4742: $devalidate = 1;
4743: }
4744: if ($devalidate) {
1.560 damieng 4745: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4746: }
1.208 www 4747: }
1.207 www 4748:
1.563 damieng 4749: # Returns the username and domain from a key created in readdata from a resourcedata key.
4750: #
4751: # @param {string} $key - the key
4752: # @returns {Array}
1.208 www 4753: sub extractuser {
4754: my $key=shift;
1.350 albertel 4755: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4756: }
1.206 www 4757:
1.563 damieng 4758: # Parses a parameter key and returns the components.
4759: #
4760: # @param {string} $key -
4761: # @param {hash reference} $listdata -
4762: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4763: sub parse_listdata_key {
4764: my ($key,$listdata) = @_;
4765: # split into student/section affected, and
4766: # the realm (folder/resource part and parameter
1.446 bisitz 4767: my ($student,$realm) =
1.473 amueller 4768: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4769: # if course wide student would be undefined
4770: if (!defined($student)) {
1.560 damieng 4771: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4772: }
4773: # strip off the .type if it's not the Question type parameter
4774: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4775: $realm=~s/\.type//;
1.381 albertel 4776: }
4777: # split into resource+part and parameter name
1.388 albertel 4778: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4779: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4780: return ($student,$res,$part,$parm);
4781: }
4782:
1.563 damieng 4783: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
4784: #
4785: # @param {Apache2::RequestRec} $r - the Apache request
4786: # @param {hash reference} $resourcedata - parameter data returned by readdata
4787: # @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
4788: # @param {string} $sortorder - realmstudent|studentrealm
4789: # @param {string} $caller - name of the calling sub (overview|newoverview)
4790: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 4791: # @param {boolean} $readonly - true if editing not allowed
1.608 raeburn 4792: # @param {string} $parmlev - full|map
4793: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order
4794: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 4795: # @returns{integer} - number of $listdata parameters processed
1.208 www 4796: sub listdata {
1.608 raeburn 4797: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552 raeburn 4798:
1.207 www 4799: # Start list output
1.206 www 4800:
1.122 www 4801: my $oldsection='';
4802: my $oldrealm='';
4803: my $oldpart='';
1.123 www 4804: my $pointer=0;
1.124 www 4805: $tableopen=0;
1.145 www 4806: my $foundkeys=0;
1.248 albertel 4807: my %keyorder=&standardkeyorder();
1.594 raeburn 4808: my $readonlyall = $readonly;
1.381 albertel 4809:
1.552 raeburn 4810: my ($secidx,%grouphash);
4811: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4812: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 4813: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4814: %grouphash = &Apache::longroup::coursegroups();
4815: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 4816: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 4817: }
1.552 raeburn 4818: }
4819:
1.576 raeburn 4820: foreach my $key (sort {
1.560 damieng 4821: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
4822: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608 raeburn 4823: my ($aid,$bid);
4824: if ($caller eq 'newoverview') {
4825: if (ref($hash_for_realm) eq 'HASH') {
4826: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4827: my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4828: my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4829: $aid = $hash_for_realm->{$aurl};
4830: $bid = $hash_for_realm->{$burl};
4831: } elsif ($parmlev eq 'full') {
4832: $aid = $hash_for_realm->{$ares};
4833: $bid = $hash_for_realm->{$bres};
4834: }
4835: }
4836: }
1.381 albertel 4837:
1.560 damieng 4838: # get the numerical order for the param
4839: $aparm=$keyorder{'parameter_0_'.$aparm};
4840: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 4841:
1.560 damieng 4842: my $result=0;
1.381 albertel 4843:
1.560 damieng 4844: if ($sortorder eq 'realmstudent') {
1.381 albertel 4845: if ($ares ne $bres ) {
1.608 raeburn 4846: if ($caller eq 'newoverview') {
4847: if (ref($hash_for_realm) eq 'HASH') {
4848: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4849: $result = ($aid <=> $bid);
4850: } elsif ($parmlev eq 'full') {
4851: $result = ($aid <=> $bid);
4852: } else {
4853: $result = ($ares cmp $bres);
4854: }
4855: } else {
4856: $result = ($ares cmp $bres);
4857: }
4858: } else {
4859: $result = ($ares cmp $bres);
4860: }
1.446 bisitz 4861: } elsif ($astudent ne $bstudent) {
1.560 damieng 4862: $result = ($astudent cmp $bstudent);
4863: } elsif ($apart ne $bpart ) {
4864: $result = ($apart cmp $bpart);
4865: }
4866: } else {
4867: if ($astudent ne $bstudent) {
4868: $result = ($astudent cmp $bstudent);
4869: } elsif ($ares ne $bres ) {
1.608 raeburn 4870: if ($caller eq 'newoverview') {
4871: if (ref($hash_for_realm) eq 'HASH') {
4872: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4873: $result = ($aid <=> $bid);
4874: } elsif ($parmlev eq 'full') {
4875: $result = ($aid <=> $bid);
4876: } else {
4877: $result = ($ares cmp $bres);
4878: }
4879: } else {
4880: $result = ($ares cmp $bres);
4881: }
4882: } else {
4883: $result = ($ares cmp $bres);
4884: }
1.560 damieng 4885: } elsif ($apart ne $bpart ) {
4886: $result = ($apart cmp $bpart);
4887: }
1.473 amueller 4888: }
1.446 bisitz 4889:
1.560 damieng 4890: if (!$result) {
1.381 albertel 4891: if (defined($aparm) && defined($bparm)) {
1.560 damieng 4892: $result = ($aparm <=> $bparm);
1.381 albertel 4893: } elsif (defined($aparm)) {
1.560 damieng 4894: $result = -1;
1.381 albertel 4895: } elsif (defined($bparm)) {
1.560 damieng 4896: $result = 1;
4897: }
1.473 amueller 4898: }
1.381 albertel 4899:
1.560 damieng 4900: $result;
4901:
1.576 raeburn 4902: } keys(%{$listdata})) { # foreach my $key
4903: my $thiskey = $key;
1.560 damieng 4904: if ($$listdata{$thiskey.'.type'}) {
4905: my $thistype=$$listdata{$thiskey.'.type'};
4906: if ($$resourcedata{$thiskey.'.type'}) {
4907: $thistype=$$resourcedata{$thiskey.'.type'};
4908: }
4909: my ($middle,$part,$name)=
1.572 damieng 4910: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 4911: my $section=&mt('All Students');
1.594 raeburn 4912: $readonly = $readonlyall;
1.599 raeburn 4913: my $userscope;
1.576 raeburn 4914: my $showval = $$resourcedata{$thiskey};
1.560 damieng 4915: if ($middle=~/^\[(.*)\]/) {
4916: my $issection=$1;
4917: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
4918: my ($stuname,$studom) = ($1,$2);
4919: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4920: if (ref($classlist) eq 'HASH') {
4921: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
4922: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
4923: }
4924: }
4925: }
4926: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 4927: $userscope = 1;
1.560 damieng 4928: } else {
4929: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4930: if (exists($grouphash{$issection})) {
4931: $section=&mt('Group').': '.$issection;
4932: } elsif ($issection eq $env{'request.course.sec'}) {
4933: $section = &mt('Section').': '.$issection;
4934: } else {
4935: next;
1.552 raeburn 4936: }
1.560 damieng 4937: } else {
4938: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 4939: }
4940: }
1.560 damieng 4941: $middle=~s/^\[(.*)\]//;
4942: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4943: $readonly = 1;
4944: }
4945: $middle=~s/\.+$//;
4946: $middle=~s/^\.+//;
4947: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 4948: my ($is_map,$is_recursive,$mapurl,$maplevel);
4949: if ($caller eq 'overview') {
4950: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
4951: $mapurl = $1;
4952: $maplevel = $2;
4953: $is_map = 1;
4954: }
4955: } elsif ($caller eq 'newoverview') {
4956: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
4957: $mapurl = $1;
4958: $maplevel = $2;
4959: $is_map = 1;
4960: }
4961: }
4962: if ($is_map) {
1.560 damieng 4963: my $leveltitle = &mt('Folder/Map');
1.615 raeburn 4964: my $title = &Apache::lonnet::gettitle($mapurl);
1.608 raeburn 4965: if (ref($hash_for_realm) eq 'HASH') {
4966: if ($hash_for_realm->{$mapurl} eq '1') {
4967: $title = &mt('Main Content');
4968: }
4969: }
1.576 raeburn 4970: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
4971: if ($caller eq 'newoverview') {
4972: my $altkey = $thiskey;
4973: $altkey =~ s/\Q___(all)\E/___(rec)/;
4974: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
4975: $is_recursive = 1;
4976: if ($$resourcedata{$altkey.'.type'}) {
4977: $thistype=$$resourcedata{$altkey.'.type'};
4978: }
4979: $showval = $$resourcedata{$altkey};
4980: }
4981: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
4982: $thiskey =~ s/\Q___(rec)\E/___(all)/;
4983: $is_recursive = 1;
4984: }
1.560 damieng 4985: }
1.608 raeburn 4986: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560 damieng 4987: } elsif ($middle) {
4988: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609 raeburn 4989: next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560 damieng 4990: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
4991: ': '.&Apache::lonnet::gettitle($middle).
4992: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
4993: $id.')</span></span>';
4994: }
4995: if ($sortorder eq 'realmstudent') {
4996: if ($realm ne $oldrealm) {
4997: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
4998: $oldrealm=$realm;
4999: $oldsection='';
5000: }
5001: if ($section ne $oldsection) {
5002: $r->print(&tableend()."\n<h2>$section</h2>");
5003: $oldsection=$section;
5004: $oldpart='';
5005: }
1.552 raeburn 5006: } else {
1.560 damieng 5007: if ($section ne $oldsection) {
5008: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
5009: $oldsection=$section;
5010: $oldrealm='';
5011: }
5012: if ($realm ne $oldrealm) {
5013: $r->print(&tableend()."\n<h2>$realm</h2>");
5014: $oldrealm=$realm;
5015: $oldpart='';
1.552 raeburn 5016: }
5017: }
1.560 damieng 5018: if ($part ne $oldpart) {
5019: $r->print(&tableend().
5020: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
5021: $oldpart=$part;
1.556 raeburn 5022: }
1.560 damieng 5023: #
5024: # Ready to print
5025: #
1.470 raeburn 5026: my $parmitem = &standard_parameter_names($name);
1.576 raeburn 5027: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 5028: &Apache::loncommon::start_data_table_row().
5029: '<td><b>'.&mt($parmitem).
5030: '</b></td>');
5031: unless ($readonly) {
1.599 raeburn 5032: my $disabled;
5033: if (($name eq 'availablestudent') &&
5034: (($showval eq '') || ($userscope))) {
5035: $disabled = ' disabled="disabled"';
5036: }
1.560 damieng 5037: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 5038: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 5039: }
5040: $r->print('<td>');
5041: $foundkeys++;
5042: if (&isdateparm($thistype)) {
5043: my $jskey='key_'.$pointer;
5044: my $state;
5045: $pointer++;
5046: if ($readonly) {
5047: $state = 'disabled';
5048: }
5049: $r->print(
5050: &Apache::lonhtmlcommon::date_setter('parmform',
5051: $jskey,
1.576 raeburn 5052: $showval,
1.560 damieng 5053: '',1,$state));
5054: unless ($readonly) {
5055: $r->print(
5056: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 5057: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 5058: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 5059: &date_sanity_info($showval)
1.560 damieng 5060: );
5061: }
5062: } elsif ($thistype eq 'date_interval') {
5063: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 5064: $showval,$readonly));
1.560 damieng 5065: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 5066: if ($name eq 'availablestudent') {
5067: $readonly = 1;
5068: }
1.560 damieng 5069: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 5070: $showval,$name,$readonly));
1.560 damieng 5071: } else {
1.576 raeburn 5072: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 5073: }
1.560 damieng 5074: unless ($readonly) {
5075: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
5076: $thistype.'" />');
1.552 raeburn 5077: }
1.576 raeburn 5078: $r->print('</td>');
5079: if ($is_map) {
5080: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
5081: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
5082: } else {
5083: my ($disabled,$recon,$recoff);
5084: if ($readonly) {
5085: $disabled = ' disabled="disabled"';
5086: }
5087: if ($is_recursive) {
5088: $recon = ' checked="checked"';
5089: } else {
5090: $recoff = ' checked="checked"';
5091: }
5092: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
5093: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
5094: }
5095: }
5096: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 5097: }
1.121 www 5098: }
1.208 www 5099: return $foundkeys;
5100: }
5101:
1.563 damieng 5102: # Returns a string representing the interval, directly using form data matching the given key.
5103: # The returned string may also include information related to proctored exams.
5104: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
5105: #
5106: # @param {string} $key - suffix for form fields related to the interval
5107: # @returns {string}
1.385 albertel 5108: sub get_date_interval_from_form {
5109: my ($key) = @_;
5110: my $seconds = 0;
1.611 raeburn 5111: my $numnotnull = 0;
1.385 albertel 5112: foreach my $which (['days', 86400],
1.473 amueller 5113: ['hours', 3600],
5114: ['minutes', 60],
5115: ['seconds', 1]) {
1.560 damieng 5116: my ($name, $factor) = @{ $which };
5117: if (defined($env{'form.'.$name.'_'.$key})) {
1.611 raeburn 5118: unless ($env{'form.'.$name.'_'.$key} eq '') {
5119: $numnotnull ++;
5120: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
5121: }
1.560 damieng 5122: }
1.473 amueller 5123: }
1.560 damieng 5124: if (($key =~ /\.interval$/) &&
5125: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 5126: if ($env{'form.done_'.$key.'_buttontext'}) {
5127: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
5128: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
5129: if ($env{'form.done_'.$key} eq '_done_proctor') {
5130: $seconds .= '_proctor';
5131: }
5132: } else {
5133: $seconds .= $env{'form.done_'.$key};
5134: }
5135: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 5136: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 5137: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
5138: }
1.554 raeburn 5139: }
1.611 raeburn 5140: return if (!$numnotnull);
1.385 albertel 5141: return $seconds;
5142: }
5143:
5144:
1.563 damieng 5145: # Returns HTML to enter a text value for a parameter.
5146: #
5147: # @param {string} $thiskey - parameter key
5148: # @param {string} $showval - the current value
5149: # @param {boolean} $readonly - true if the field should not be made editable
5150: # @returns {string}
1.383 albertel 5151: sub default_selector {
1.552 raeburn 5152: my ($thiskey, $showval, $readonly) = @_;
5153: my $disabled;
5154: if ($readonly) {
5155: $disabled = ' disabled="disabled"';
5156: }
5157: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 5158: }
5159:
1.563 damieng 5160: # Returns HTML to enter allow/deny rules related to IP addresses.
5161: #
5162: # @param {string} $thiskey - parameter key
5163: # @param {string} $showval - the current value
5164: # @param {boolean} $readonly - true if the fields should not be made editable
5165: # @returns {string}
1.549 raeburn 5166: sub string_ip_selector {
1.552 raeburn 5167: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 5168: my %access = (
5169: allow => [],
5170: deny => [],
5171: );
5172: if ($showval ne '') {
5173: my @current;
5174: if ($showval =~ /,/) {
5175: @current = split(/,/,$showval);
5176: } else {
5177: @current = ($showval);
5178: }
5179: foreach my $item (@current) {
5180: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
5181: push(@{$access{'deny'}},$1);
5182: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
5183: push(@{$access{'allow'}},$item);
5184: }
5185: }
5186: }
5187: if (!@{$access{'allow'}}) {
5188: @{$access{'allow'}} = ('');
5189: }
5190: if (!@{$access{'deny'}}) {
5191: @{$access{'deny'}} = ('');
5192: }
1.552 raeburn 5193: my ($disabled,$addmore);
1.567 raeburn 5194: if ($readonly) {
1.552 raeburn 5195: $disabled=' disabled="disabled"';
5196: } else {
5197: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5198: }
1.549 raeburn 5199: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5200: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5201: foreach my $acctype ('allow','deny') {
5202: $output .= '
5203: <td valign="top">
5204: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5205: <div class="LC_string_ipacc_inner">'."\n";
5206: my $num = 0;
5207: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5208: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5209: if ($num > 0) {
5210: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5211: }
5212: $output .= '</div>'."\n";
5213: $num ++;
5214: }
5215: $output .= '
1.552 raeburn 5216: </div>'.$addmore.'
1.549 raeburn 5217: </div>
5218: </td>';
5219: }
5220: $output .= '
5221: </tr>
5222: </table>'."\n";
5223: return $output;
5224: }
5225:
1.588 raeburn 5226: sub string_deeplink_selector {
5227: my ($thiskey, $showval, $readonly) = @_;
1.616 ! raeburn 5228: my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
! 5229: %selectnull,%domlti,%crslti,@possmenus,%components);
! 5230: @tables = ('upper','lower');
! 5231: %components = (
! 5232: upper => ['state','others','listing','scope'],
! 5233: lower => ['protect','menus','target','exit'],
! 5234: );
1.588 raeburn 5235: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5236: state => 'Access status',
5237: others => 'Hide other resources',
1.588 raeburn 5238: listing => 'In Contents and/or Gradebook',
5239: scope => 'Access scope for link',
1.601 raeburn 5240: protect => 'Link protection',
1.597 raeburn 5241: menus => 'Menu Items Displayed',
1.613 raeburn 5242: target => 'Embedded?',
1.616 ! raeburn 5243: exit => 'Exit Tool Button?',
1.588 raeburn 5244: );
5245: %options = (
1.601 raeburn 5246: state => ['only','off','both'],
5247: others => ['hide','unhide'],
1.588 raeburn 5248: listing => ['full','absent','grades','details','datestatus'],
5249: scope => ['res','map','rec'],
1.601 raeburn 5250: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5251: menus => ['std','colls'],
1.613 raeburn 5252: target => ['_self','_top'],
1.616 ! raeburn 5253: exit => ['no','yes','url'],
1.588 raeburn 5254: );
5255: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5256: only => 'deep only',
5257: off => 'deeplink off',
5258: both => 'regular + deep',
5259: hide => 'Hidden',
5260: unhide => 'Unhidden',
1.588 raeburn 5261: full => 'Listed (linked) in both',
5262: absent => 'Not listed',
5263: grades => 'Listed in grades only',
5264: details => 'Listed (unlinked) in both',
5265: datestatus => 'Listed (unlinked) inc. status in both',
5266: res => 'resource only',
5267: map => 'enclosing map/folder',
5268: rec => 'recursive map/folder',
1.601 raeburn 5269: none => 'not in use',
5270: key => 'key access',
5271: ltic => 'LTI access (course)',
5272: ltid => 'LTI access (domain)' ,
1.597 raeburn 5273: std => 'Standard (all menus)',
5274: colls => 'Numbered collection',
1.614 raeburn 5275: _self => 'Embedded',
1.613 raeburn 5276: _top => 'Not embedded',
1.616 ! raeburn 5277: no => 'Not in use',
! 5278: yes => 'In use, no URL redirect',
! 5279: url => 'In use, redirect to URL',
1.597 raeburn 5280: );
5281: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5282: ltic => 'Select Launcher',
5283: ltid => 'Select Launcher',
1.597 raeburn 5284: colls => 'Select',
1.588 raeburn 5285: );
5286: if ($showval =~ /,/) {
1.597 raeburn 5287: %values=();
1.588 raeburn 5288: @current = split(/,/,$showval);
1.601 raeburn 5289: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5290: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5291: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5292: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5293: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5294: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613 raeburn 5295: ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616 ! raeburn 5296: ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588 raeburn 5297: } else {
1.601 raeburn 5298: $defaults{'state'} = 'off',
5299: $defaults{'others'} = 'unhide',
1.588 raeburn 5300: $defaults{'listing'} = 'full';
5301: $defaults{'scope'} = 'res';
1.601 raeburn 5302: $defaults{'protect'} = 'none';
1.597 raeburn 5303: $defaults{'menus'} = '0';
1.613 raeburn 5304: $defaults{'target'} = '_top';
1.616 ! raeburn 5305: $defaults{'exit'} = 'yes';
1.588 raeburn 5306: }
5307: my $disabled;
5308: if ($readonly) {
5309: $disabled=' disabled="disabled"';
5310: }
1.601 raeburn 5311: my %courselti =
5312: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
5313: $env{'course.'.$env{'request.course.id'}.'.domain'});
5314: foreach my $item (keys(%courselti)) {
5315: if (ref($courselti{$item}) eq 'HASH') {
5316: $crslti{$item} = $courselti{$item}{'name'};
5317: }
5318: }
5319: my %lti =
1.588 raeburn 5320: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 5321: 'linkprot');
1.588 raeburn 5322: foreach my $item (keys(%lti)) {
1.604 raeburn 5323: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
5324: $domlti{$item} = $lti{$item}{'name'};
1.588 raeburn 5325: }
5326: }
1.597 raeburn 5327: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5328: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5329: my ($num,$value) = split(/\%/,$item);
5330: if ($num =~ /^\d+$/) {
5331: push(@possmenus,$num);
5332: }
5333: }
5334: }
5335:
1.616 ! raeburn 5336: my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
! 5337: foreach my $table ('upper','lower') {
! 5338: next unless (ref($components{$table}) eq 'ARRAY');
! 5339: $output .= '<table width="100%"><tr>';
! 5340: foreach my $item (@{$components{$table}}) {
! 5341: $output .= '<th>'.$titles{$item}.'</th>';
! 5342: }
! 5343: $output .= '</tr><tr>';
! 5344: foreach my $item (@{$components{$table}}) {
! 5345: $output .= '<td>';
! 5346: if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
! 5347: my $selected = $values{$item};
! 5348: foreach my $option (@{$options{$item}}) {
! 5349: if ($item eq 'protect') {
! 5350: if ($option eq 'ltid') {
! 5351: next unless (keys(%domlti));
! 5352: } elsif ($option eq 'ltic') {
! 5353: next unless (keys(%crslti));
! 5354: }
! 5355: } elsif (($item eq 'menus') && ($option eq 'colls')) {
! 5356: next unless (@possmenus);
! 5357: }
! 5358: my $checked;
! 5359: if ($item eq 'menus') {
! 5360: if (($selected =~ /^\d+$/) && (@possmenus) &&
! 5361: (grep(/^\Q$selected\E$/,@possmenus))) {
! 5362: if ($option eq 'colls') {
! 5363: $checked = ' checked="checked"';
! 5364: }
! 5365: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597 raeburn 5366: $checked = ' checked="checked"';
5367: }
1.616 ! raeburn 5368: } elsif ($selected =~ /^\Q$option\E/) {
1.597 raeburn 5369: $checked = ' checked="checked"';
5370: }
1.616 ! raeburn 5371: my $onclick;
! 5372: unless ($readonly) {
! 5373: my $esc_key = &js_escape($thiskey);
! 5374: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
! 5375: }
! 5376: $output .= '<span class="LC_nobreak"><label>'.
! 5377: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
! 5378: $optiontext{$option}.'</label>';
! 5379: if (($item eq 'protect') && ($option eq 'key')) {
! 5380: my $visibility="hidden";
! 5381: my $currkey;
! 5382: if ($checked) {
! 5383: $visibility = "text";
! 5384: $currkey = (split(/\:/,$values{$item}))[1];
! 5385: }
! 5386: $output .= ' '.
! 5387: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
! 5388: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
! 5389: my $display="none";
! 5390: my ($current,$blankcheck,@possibles);
! 5391: if ($checked) {
! 5392: $display = 'inline-block';
! 5393: if (($option eq 'ltic') || ($option eq 'ltid')) {
! 5394: $current = (split(/\:/,$selected))[1];
! 5395: } else {
! 5396: $current = $selected;
! 5397: }
1.597 raeburn 5398: } else {
1.616 ! raeburn 5399: $blankcheck = ' selected="selected"';
1.597 raeburn 5400: }
1.601 raeburn 5401: if ($option eq 'ltid') {
1.616 ! raeburn 5402: @possibles = keys(%domlti);
1.601 raeburn 5403: } elsif ($option eq 'ltic') {
1.616 ! raeburn 5404: @possibles = keys(%crslti);
! 5405: } else {
! 5406: @possibles = @possmenus;
! 5407: }
! 5408: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
! 5409: ' style="display: '.$display.'"> <select name="'.
! 5410: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
! 5411: if (@possibles > 1) {
! 5412: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
! 5413: '</option>'."\n";
! 5414: }
! 5415: foreach my $poss (sort { $a <=> $b } @possibles) {
! 5416: my $selected;
! 5417: if (($poss == $current) || (scalar(@possibles) ==1)) {
! 5418: $selected = ' selected="selected"';
! 5419: }
! 5420: my $shown = $poss;
! 5421: if ($option eq 'ltid') {
! 5422: $shown = $domlti{$poss};
! 5423: } elsif ($option eq 'ltic') {
! 5424: $shown = $crslti{$poss};
! 5425: }
! 5426: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
! 5427: }
! 5428: $output .= '</select></div>';
! 5429: }
! 5430: $output .= '</span> ';
! 5431: }
! 5432: if ($item eq 'exit') {
! 5433: my $exitsty = 'none';
! 5434: my $displayval;
! 5435: if ($values{$item} =~ /^(yes|url)/) {
! 5436: $exitsty = 'inline-block';
! 5437: my $currval = (split(/\:/,$values{$item}))[1];
! 5438: if ($currval eq '') {
! 5439: $displayval = 'Exit Tool';
! 5440: } else {
! 5441: $displayval = $currval;
1.597 raeburn 5442: }
1.588 raeburn 5443: }
1.616 ! raeburn 5444: $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
! 5445: ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
! 5446: '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
! 5447: ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
! 5448: ' size="10"'.$disabled.' /></div>';
1.588 raeburn 5449: }
1.616 ! raeburn 5450: } else {
! 5451: my $selected = $values{$item};
! 5452: my $defsel;
! 5453: if ($selected eq '') {
! 5454: $defsel = ' selected="selected"';
! 5455: }
! 5456: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
! 5457: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
! 5458: foreach my $option (@{$options{$item}}) {
! 5459: $output .= '<option value="'.$option.'"';
! 5460: if ($option eq $selected) {
! 5461: $output .= ' selected="selected"';
! 5462: }
! 5463: $output .= '>'.$optiontext{$option}.'</option>';
1.588 raeburn 5464: }
1.616 ! raeburn 5465: $output .= '</select>';
1.588 raeburn 5466: }
1.616 ! raeburn 5467: $output .= '</td>';
! 5468: }
! 5469: $output .= '</tr></table>'."\n";
! 5470: if ($table eq 'upper') {
! 5471: $output .= '<br />';
1.588 raeburn 5472: }
5473: }
5474: return $output;
5475: }
5476:
1.560 damieng 5477:
5478: { # block using some constants related to parameter types (overview mode)
5479:
1.446 bisitz 5480: my %strings =
1.383 albertel 5481: (
5482: 'string_yesno'
5483: => [[ 'yes', 'Yes' ],
1.560 damieng 5484: [ 'no', 'No' ]],
1.383 albertel 5485: 'string_problemstatus'
5486: => [[ 'yes', 'Yes' ],
1.473 amueller 5487: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5488: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5489: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5490: 'string_questiontype'
5491: => [[ 'problem', 'Standard Problem'],
5492: [ 'survey', 'Survey'],
5493: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5494: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5495: [ 'anonsurvey', 'Anonymous Survey'],
5496: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5497: [ 'practice', 'Practice'],
5498: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5499: 'string_lenient'
5500: => [['yes', 'Yes' ],
5501: [ 'no', 'No' ],
1.549 raeburn 5502: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5503: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5504: 'string_discussvote'
5505: => [['yes','Yes'],
5506: ['notended','Yes, unless discussion ended'],
5507: ['no','No']],
1.549 raeburn 5508: 'string_ip'
5509: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5510: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5511: 'string_deeplink'
1.616 ! raeburn 5512: => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.587 raeburn 5513: );
5514:
1.383 albertel 5515:
1.549 raeburn 5516: my %stringmatches = (
5517: 'string_lenient'
5518: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5519: 'string_ip'
5520: => [['_allowfrom_','[^\!]+'],
5521: ['_denyfrom_','\!']],
1.588 raeburn 5522: 'string_deeplink'
1.616 ! raeburn 5523: => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],
1.549 raeburn 5524: );
5525:
5526: my %stringtypes = (
5527: type => 'string_questiontype',
5528: lenient => 'string_lenient',
5529: retrypartial => 'string_yesno',
5530: discussvote => 'string_discussvote',
5531: examcode => 'string_examcode',
5532: acc => 'string_ip',
1.587 raeburn 5533: deeplink => 'string_deeplink',
1.549 raeburn 5534: );
5535:
1.563 damieng 5536: # Returns the possible values and titles for a given string type, or undef if there are none.
5537: # Used by courseprefs.
5538: #
5539: # @param {string} $string_type - a parameter type for strings
5540: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5541: sub standard_string_options {
5542: my ($string_type) = @_;
5543: if (ref($strings{$string_type}) eq 'ARRAY') {
5544: return $strings{$string_type};
5545: }
5546: return;
5547: }
1.383 albertel 5548:
1.563 damieng 5549: # Returns regular expressions to match kinds of string types, or undef if there are none.
5550: #
5551: # @param {string} $string_type - a parameter type for strings
5552: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5553: sub standard_string_matches {
5554: my ($string_type) = @_;
5555: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5556: return $stringmatches{$string_type};
5557: }
5558: return;
5559: }
5560:
1.563 damieng 5561: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5562: #
5563: # @param {string} $name - parameter name
5564: # @returns {string}
1.549 raeburn 5565: sub get_stringtype {
5566: my ($name) = @_;
5567: if (exists($stringtypes{$name})) {
5568: return $stringtypes{$name};
5569: }
5570: return;
5571: }
5572:
1.563 damieng 5573: # Returns HTML to edit a string parameter.
5574: #
5575: # @param {string} $thistype - parameter type
5576: # @param {string} $thiskey - parameter key
5577: # @param {string} $showval - parameter current value
5578: # @param {string} $name - parameter name
5579: # @param {boolean} $readonly - true if the values should not be made editable
5580: # @returns {string}
1.383 albertel 5581: sub string_selector {
1.552 raeburn 5582: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5583:
1.383 albertel 5584: if (!exists($strings{$thistype})) {
1.552 raeburn 5585: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5586: }
5587:
1.504 raeburn 5588: my %skiptype;
1.514 raeburn 5589: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5590: ($thistype eq 'string_lenient') ||
5591: ($thistype eq 'string_discussvote') ||
5592: ($thistype eq 'string_ip') ||
1.588 raeburn 5593: ($thistype eq 'string_deeplink') ||
1.560 damieng 5594: ($name eq 'retrypartial')) {
1.504 raeburn 5595: my ($got_chostname,$chostname,$cmajor,$cminor);
5596: foreach my $possibilities (@{ $strings{$thistype} }) {
5597: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5598: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5599: my $parmmatch;
5600: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5601: foreach my $item (@{$stringmatches{$thistype}}) {
5602: if (ref($item) eq 'ARRAY') {
5603: if ($parmval eq $item->[0]) {
5604: $parmmatch = $parmval;
5605: $parmval = '';
5606: last;
5607: }
5608: }
5609: }
5610: }
5611: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5612: if ($needsrelease) {
5613: unless ($got_chostname) {
1.514 raeburn 5614: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5615: $got_chostname = 1;
5616: }
1.557 raeburn 5617: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5618: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5619: if ($needsnewer) {
1.549 raeburn 5620: if ($parmmatch ne '') {
5621: $skiptype{$parmmatch} = 1;
5622: } elsif ($parmval ne '') {
5623: $skiptype{$parmval} = 1;
5624: }
1.504 raeburn 5625: }
5626: }
5627: }
5628: }
1.549 raeburn 5629:
5630: if ($thistype eq 'string_ip') {
1.552 raeburn 5631: return &string_ip_selector($thiskey,$showval,$readonly);
1.588 raeburn 5632: } elsif ($thistype eq 'string_deeplink') {
5633: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5634: }
1.504 raeburn 5635:
1.552 raeburn 5636: my ($result,$disabled);
5637:
5638: if ($readonly) {
5639: $disabled = ' disabled="disabled"';
5640: }
1.504 raeburn 5641: my $numinrow = 3;
5642: if ($thistype eq 'string_problemstatus') {
5643: $numinrow = 2;
5644: } elsif ($thistype eq 'string_questiontype') {
5645: if (keys(%skiptype) > 0) {
5646: $numinrow = 4;
5647: }
5648: }
5649: my $rem;
5650: if (ref($strings{$thistype}) eq 'ARRAY') {
5651: my $i=0;
5652: foreach my $possibilities (@{ $strings{$thistype} }) {
5653: next unless (ref($possibilities) eq 'ARRAY');
5654: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5655: next if ($skiptype{$name});
1.504 raeburn 5656: $rem = $i%($numinrow);
5657: if ($rem == 0) {
5658: if ($i > 0) {
5659: $result .= '</tr>';
5660: }
5661: $result .= '<tr>';
5662: }
1.549 raeburn 5663: my $colspan;
5664: if ($i == @{ $strings{$thistype} }-1) {
5665: $rem = @{ $strings{$thistype} }%($numinrow);
5666: if ($rem) {
5667: my $colsleft = $numinrow - $rem;
5668: if ($colsleft) {
5669: $colspan = $colsleft+1;
5670: $colspan = ' colspan="'.$colspan.'"';
5671: }
5672: }
5673: }
5674: my ($add,$onchange,$css_class);
5675: if ($thistype eq 'string_lenient') {
5676: if ($name eq 'weighted') {
5677: my $display;
5678: my %relatives = &Apache::lonlocal::texthash(
5679: corrchkd => 'Correct (checked)',
5680: corrunchkd => 'Correct (unchecked)',
5681: incorrchkd => 'Incorrect (checked)',
5682: incorrunchkd => 'Incorrect (unchecked)',
5683: );
5684: my %textval = (
5685: corrchkd => '1.0',
5686: corrunchkd => '1.0',
5687: incorrchkd => '0.0',
5688: incorrunchkd => '0.0',
5689: );
5690: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
5691: $textval{'corrchkd'} = $1;
5692: $textval{'corrunchkd'} = $2;
5693: $textval{'incorrchkd'} = $3;
5694: $textval{'incorrunchkd'} = $4;
5695: $display = 'inline';
5696: $showval = $name;
5697: } else {
5698: $display = 'none';
5699: }
5700: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
5701: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
5702: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
5703: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
5704: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 5705: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 5706: '</td></tr>';
5707: }
5708: $add .= '</table></div>'."\n";
5709: }
5710: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
5711: $css_class = ' class="LC_lenient_radio"';
5712: }
5713: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 5714: '<span class="LC_nobreak"><label>'.
5715: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 5716: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 5717: if ($showval eq $name) {
5718: $result .= ' checked="checked"';
5719: }
1.549 raeburn 5720: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 5721: $i++;
5722: }
5723: $result .= '</tr>';
1.473 amueller 5724: }
1.504 raeburn 5725: if ($result) {
5726: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 5727: }
5728: return $result;
5729: }
5730:
1.554 raeburn 5731: my %intervals =
5732: (
5733: 'date_interval'
5734: => [[ 'done', 'Yes' ],
1.558 raeburn 5735: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 5736: [ '', 'No' ]],
5737: );
5738:
5739: my %intervalmatches = (
5740: 'date_interval'
1.559 raeburn 5741: => [['done','\d+_done(|\:[^\:]+\:)$'],
5742: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 5743: );
5744:
5745: my %intervaltypes = (
5746: interval => 'date_interval',
5747: );
5748:
1.563 damieng 5749: # Returns regular expressions to match kinds of interval type, or undef if there are none.
5750: #
5751: # @param {string} $interval_type - a parameter type for intervals
5752: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 5753: sub standard_interval_matches {
5754: my ($interval_type) = @_;
5755: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
5756: return $intervalmatches{$interval_type};
5757: }
5758: return;
5759: }
5760:
1.563 damieng 5761: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
5762: #
5763: # @param {string} $name - parameter name
5764: # @returns {string}
1.554 raeburn 5765: sub get_intervaltype {
5766: my ($name) = @_;
5767: if (exists($intervaltypes{$name})) {
5768: return $intervaltypes{$name};
5769: }
5770: return;
5771: }
5772:
1.563 damieng 5773: # Returns the possible values and titles for a given interval type, or undef if there are none.
5774: # Used by courseprefs.
5775: #
5776: # @param {string} $interval_type - a parameter type for intervals
5777: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 5778: sub standard_interval_options {
5779: my ($interval_type) = @_;
5780: if (ref($intervals{$interval_type}) eq 'ARRAY') {
5781: return $intervals{$interval_type};
5782: }
5783: return;
5784: }
5785:
1.563 damieng 5786: # Returns HTML to edit a date interval parameter.
5787: #
5788: # @param {string} $thiskey - parameter key
5789: # @param {string} $name - parameter name
5790: # @param {string} $showval - parameter current value
5791: # @param {boolean} $readonly - true if the values should not be made editable
5792: # @returns {string}
1.554 raeburn 5793: sub date_interval_selector {
5794: my ($thiskey, $name, $showval, $readonly) = @_;
5795: my ($result,%skipval);
5796: if ($name eq 'interval') {
5797: my $intervaltype = &get_intervaltype($name);
5798: my ($got_chostname,$chostname,$cmajor,$cminor);
5799: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
5800: next unless (ref($possibilities) eq 'ARRAY');
5801: my ($parmval, $description) = @{ $possibilities };
5802: my $parmmatch;
5803: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
5804: foreach my $item (@{$intervalmatches{$intervaltype}}) {
5805: if (ref($item) eq 'ARRAY') {
5806: if ($parmval eq $item->[0]) {
5807: $parmmatch = $parmval;
5808: $parmval = '';
5809: last;
5810: }
5811: }
5812: }
5813: }
5814: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
5815: if ($needsrelease) {
5816: unless ($got_chostname) {
5817: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
5818: $got_chostname = 1;
5819: }
1.557 raeburn 5820: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 5821: $needsrelease,$cmajor,$cminor);
5822: if ($needsnewer) {
5823: if ($parmmatch ne '') {
5824: $skipval{$parmmatch} = 1;
5825: } elsif ($parmval ne '') {
5826: $skipval{$parmval} = 1;
5827: }
5828: }
5829: }
5830: }
5831: }
5832:
5833: my $currval = $showval;
5834: foreach my $which (['days', 86400, 31],
5835: ['hours', 3600, 23],
5836: ['minutes', 60, 59],
5837: ['seconds', 1, 59]) {
1.560 damieng 5838: my ($name, $factor, $max) = @{ $which };
5839: my $amount = int($showval/$factor);
5840: $showval %= $factor;
5841: my %select = ((map {$_ => $_} (0..$max)),
5842: 'select_form_order' => [0..$max]);
1.611 raeburn 5843: if ($currval eq '') {
5844: unshift(@{$select{'select_form_order'}},'');
5845: $select{''} = '';
5846: $amount = '';
5847: }
1.560 damieng 5848: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
5849: \%select,'',$readonly);
5850: $result .= ' '.&mt($name);
1.554 raeburn 5851: }
5852: if ($name eq 'interval') {
5853: unless ($skipval{'done'}) {
5854: my $checkedon = '';
1.611 raeburn 5855: my $checkedoff = '';
1.558 raeburn 5856: my $checkedproc = '';
5857: my $currproctorkey = '';
5858: my $currprocdisplay = 'hidden';
1.559 raeburn 5859: my $currdonetext = &mt('Done');
5860: if ($currval =~ /^(?:\d+)_done$/) {
5861: $checkedon = ' checked="checked"';
5862: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
5863: $currdonetext = $1;
1.554 raeburn 5864: $checkedon = ' checked="checked"';
1.558 raeburn 5865: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
5866: $currproctorkey = $1;
5867: $checkedproc = ' checked="checked"';
5868: $currprocdisplay = 'text';
1.559 raeburn 5869: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
5870: $currdonetext = $1;
5871: $currproctorkey = $2;
5872: $checkedproc = ' checked="checked"';
5873: $currprocdisplay = 'text';
1.611 raeburn 5874: } elsif ($currval ne '') {
5875: $checkedoff = ' checked="checked"';
5876: } else {
5877: $currdonetext = '';
1.554 raeburn 5878: }
1.558 raeburn 5879: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 5880: my $disabled;
5881: if ($readonly) {
5882: $disabled = ' disabled="disabled"';
5883: }
1.558 raeburn 5884: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 5885: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 5886: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 5887: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 5888: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 5889: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 5890: &mt('Yes, with proctor key').'</label>'.
5891: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 5892: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 5893: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611 raeburn 5894: '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
5895: &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 5896: }
5897: }
5898: unless ($readonly) {
5899: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
5900: }
5901: return $result;
5902: }
5903:
1.563 damieng 5904: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
5905: #
5906: # @param {string} $name - parameter name
5907: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
5908: # @param {string} $value - parameter value
5909: # @param {string} $chostname - course server name
5910: # @param {integer} $cmajor - major version number
5911: # @param {integer} $cminor - minor version number
5912: # @param {string} $needsrelease - release version needed (major.minor)
5913: # @returns {string}
1.549 raeburn 5914: sub oldversion_warning {
1.557 raeburn 5915: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
5916: my $standard_name = &standard_parameter_names($name);
5917: if ($namematch) {
5918: my $level = &standard_parameter_levels($namematch);
5919: my $msg = '';
5920: if ($level) {
5921: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
5922: $standard_name,'<b>','</b>','"'.$level.'"');
5923: } else {
5924: $msg = &mt('[_1] was [_2]not[_3] set.',
5925: $standard_name,'<b>','</b>');
5926: }
5927: return '<p class="LC_warning">'.$msg.'<br />'.
5928: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5929: $cmajor.'.'.$cminor,$chostname,
5930: $needsrelease).
5931: '</p>';
5932: }
1.549 raeburn 5933: my $desc;
5934: my $stringtype = &get_stringtype($name);
5935: if ($stringtype ne '') {
5936: if ($name eq 'examcode') {
5937: $desc = $value;
5938: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
5939: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
5940: next unless (ref($possibilities) eq 'ARRAY');
5941: my ($parmval, $description) = @{ $possibilities };
5942: my $parmmatch;
5943: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
5944: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
5945: if (ref($item) eq 'ARRAY') {
5946: my ($regexpname,$pattern) = @{$item};
5947: if ($parmval eq $regexpname) {
5948: if ($value =~ /$pattern/) {
5949: $desc = $description;
5950: $parmmatch = 1;
5951: last;
5952: }
5953: }
5954: }
5955: }
5956: last if ($parmmatch);
5957: } elsif ($parmval eq $value) {
5958: $desc = $description;
5959: last;
5960: }
5961: }
5962: }
5963: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
5964: my $now = time;
5965: if ($value =~ /^\d+$/) {
5966: if ($name eq 'printstartdate') {
5967: if ($value > $now) {
5968: $desc = &Apache::lonlocal::locallocaltime($value);
5969: }
5970: } elsif ($name eq 'printenddate') {
5971: if ($value < $now) {
5972: $desc = &Apache::lonlocal::locallocaltime($value);
5973: }
5974: }
5975: }
5976: }
5977: return '<p class="LC_warning">'.
1.557 raeburn 5978: &mt('[_1] was [_2]not[_3] set to [_4].',
5979: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
5980: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5981: $cmajor.'.'.$cminor,$chostname,
5982: $needsrelease).
5983: '</p>';
1.549 raeburn 5984: }
5985:
1.560 damieng 5986: } # end of block using some constants related to parameter types
5987:
1.549 raeburn 5988:
1.563 damieng 5989:
5990: # Shifts all start and end dates in the current course by $shift.
1.389 www 5991: #
1.563 damieng 5992: # @param {integer} $shift - time to shift, in seconds
5993: # @returns {string} - error name or 'ok'
1.389 www 5994: sub dateshift {
1.594 raeburn 5995: my ($shift,$numchanges)=@_;
1.389 www 5996: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5997: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 5998: my $sec = $env{'request.course.sec'};
1.595 raeburn 5999: my $secgrpregex;
6000: if ($sec ne '') {
6001: my @groups;
6002: if ($env{'request.course.groups'} ne '') {
6003: @groups = split(/:/,$env{'request.course.groups'});
6004: }
6005: if (@groups) {
6006: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
6007: } else {
6008: $secgrpregex = $sec;
6009: }
6010: }
1.389 www 6011: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
6012: # ugly retro fix for broken version of types
1.548 raeburn 6013: foreach my $key (keys(%data)) {
1.389 www 6014: if ($key=~/\wtype$/) {
6015: my $newkey=$key;
6016: $newkey=~s/type$/\.type/;
6017: $data{$newkey}=$data{$key};
6018: delete $data{$key};
6019: }
6020: }
1.391 www 6021: my %storecontent=();
1.389 www 6022: # go through all parameters and look for dates
1.548 raeburn 6023: foreach my $key (keys(%data)) {
1.389 www 6024: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 6025: if ($sec ne '') {
1.595 raeburn 6026: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 6027: }
1.389 www 6028: my $newdate=$data{$key}+$shift;
1.594 raeburn 6029: $$numchanges ++;
1.391 www 6030: $storecontent{$key}=$newdate;
1.389 www 6031: }
6032: }
1.391 www 6033: my $reply=&Apache::lonnet::cput
6034: ('resourcedata',\%storecontent,$dom,$crs);
6035: if ($reply eq 'ok') {
6036: &log_parmset(\%storecontent);
6037: }
6038: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
6039: return $reply;
1.389 www 6040: }
6041:
1.563 damieng 6042: # Overview mode UI to edit course parameters.
6043: #
6044: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6045: sub newoverview {
1.568 raeburn 6046: my ($r,$parm_permission) = @_;
1.280 albertel 6047:
1.208 www 6048: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6049: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6050: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6051: my $readonly = 1;
6052: if ($parm_permission->{'edit'}) {
6053: undef($readonly);
6054: }
1.414 droeschl 6055: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6056: text=>"Overview Mode"});
1.523 raeburn 6057:
6058: my %loaditems = (
1.549 raeburn 6059: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 6060: );
6061: my $js = '
6062: <script type="text/javascript">
6063: // <![CDATA[
6064: '.
6065: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
6066: &showhide_js()."\n".
1.549 raeburn 6067: &toggleparmtextbox_js()."\n".
6068: &validateparms_js()."\n".
6069: &ipacc_boxes_js()."\n".
1.558 raeburn 6070: &done_proctor_js()."\n".
1.588 raeburn 6071: &deeplink_js()."\n".
1.523 raeburn 6072: '// ]]>
6073: </script>
6074: ';
1.549 raeburn 6075:
1.523 raeburn 6076: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
6077: {'add_entries' => \%loaditems,});
1.298 albertel 6078: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6079: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6080: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 6081: $r->print(<<ENDOVER);
1.549 raeburn 6082: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208 www 6083: ENDOVER
1.211 www 6084: my @ids=();
6085: my %typep=();
6086: my %keyp=();
6087: my %allparms=();
6088: my %allparts=();
6089: my %allmaps=();
6090: my %mapp=();
6091: my %symbp=();
6092: my %maptitles=();
6093: my %uris=();
6094: my %keyorder=&standardkeyorder();
6095: my %defkeytype=();
6096:
6097: my %alllevs=();
6098: $alllevs{'Resource Level'}='full';
1.215 www 6099: $alllevs{'Map/Folder Level'}='map';
1.211 www 6100: $alllevs{'Course Level'}='general';
6101:
6102: my $csec=$env{'form.csec'};
1.269 raeburn 6103: my $cgroup=$env{'form.cgroup'};
1.211 www 6104:
6105: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
6106: my $pschp=$env{'form.pschp'};
1.506 www 6107:
1.211 www 6108: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 6109: if (!@psprt) { $psprt[0]='all'; }
1.211 www 6110:
1.446 bisitz 6111: my @selected_sections =
1.473 amueller 6112: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 6113: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 6114: foreach my $sec (@selected_sections) {
6115: if ($sec eq 'all') {
1.211 www 6116: @selected_sections = ('all');
6117: }
6118: }
1.552 raeburn 6119: if ($env{'request.course.sec'} ne '') {
6120: @selected_sections = ($env{'request.course.sec'});
6121: }
1.269 raeburn 6122: my @selected_groups =
6123: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 6124:
6125: my $pssymb='';
6126: my $parmlev='';
1.446 bisitz 6127:
1.211 www 6128: unless ($env{'form.parmlev'}) {
6129: $parmlev = 'map';
6130: } else {
6131: $parmlev = $env{'form.parmlev'};
6132: }
6133:
1.446 bisitz 6134: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 6135: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 6136: \%keyorder,\%defkeytype,$pssymb);
1.211 www 6137:
1.374 albertel 6138: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 6139: @psprt = keys(%allparts);
1.374 albertel 6140: }
1.211 www 6141: # Menu to select levels, etc
6142:
1.456 bisitz 6143: $r->print('<div class="LC_Box">');
1.445 neumanie 6144: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 6145: $r->print('<div>');
1.523 raeburn 6146: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 6147: &levelmenu($r,\%alllevs,$parmlev);
1.610 raeburn 6148: $r->print(&Apache::lonhtmlcommon::row_closure());
6149: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447 bisitz 6150: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6151: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6152: $r->print('</div></div>');
1.446 bisitz 6153:
1.456 bisitz 6154: $r->print('<div class="LC_Box">');
1.452 bisitz 6155: $r->print('<div>');
1.581 raeburn 6156: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 6157: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 6158: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 6159: my $sectionselector = §ionmenu(\@selected_sections);
6160: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 6161: $r->print('<table>'.
1.553 raeburn 6162: '<tr><th>'.&mt('Parts').'</th>');
6163: if ($sectionselector) {
6164: $r->print('<th>'.&mt('Section(s)').'</th>');
6165: }
6166: if ($groupselector) {
6167: $r->print('<th>'.&mt('Group(s)').'</th>');
6168: }
6169: $r->print('</tr><tr><td>');
1.211 www 6170: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 6171: $r->print('</td>');
6172: if ($sectionselector) {
6173: $r->print('<td>'.$sectionselector.'</td>');
6174: }
6175: if ($groupselector) {
6176: $r->print('<td>'.$groupselector.'</td>');
6177: }
6178: $r->print('</tr></table>');
1.447 bisitz 6179: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6180: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6181: $r->print('</div></div>');
6182:
1.456 bisitz 6183: $r->print('<div class="LC_Box">');
1.452 bisitz 6184: $r->print('<div>');
1.214 www 6185: my $sortorder=$env{'form.sortorder'};
6186: unless ($sortorder) { $sortorder='realmstudent'; }
1.612 raeburn 6187: &sortmenu($r,$sortorder,'newoverview');
1.445 neumanie 6188: $r->print('</div></div>');
1.446 bisitz 6189:
1.214 www 6190: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446 bisitz 6191:
1.211 www 6192: # Build the list data hash from the specified parms
6193:
6194: my $listdata;
6195: %{$listdata}=();
6196:
6197: foreach my $cat (@pscat) {
1.269 raeburn 6198: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
6199: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 6200: }
6201:
1.212 www 6202: if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211 www 6203:
1.481 amueller 6204: if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211 www 6205:
6206: # Read modified data
6207:
1.481 amueller 6208: my $resourcedata=&readdata($crs,$dom);
1.211 www 6209:
6210: # List data
6211:
1.608 raeburn 6212: my $hash_for_realm;
6213: if (($parmlev eq 'map') && (keys(%allmaps))) {
6214: %{$hash_for_realm} = reverse(%allmaps);
6215: } elsif (($parmlev eq 'full') && (keys(%symbp))) {
6216: for (my $i=0; $i<@ids; $i++) {
6217: $hash_for_realm->{$symbp{$ids[$i]}} = $i;
6218: }
6219: }
6220: &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568 raeburn 6221: }
6222: $r->print(&tableend());
6223: unless ($readonly) {
6224: $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211 www 6225: }
1.568 raeburn 6226: $r->print('</form>');
1.507 www 6227: &endSettingsScreen($r);
6228: $r->print(&Apache::loncommon::end_page());
1.208 www 6229: }
6230:
1.563 damieng 6231: # Fills $listdata with parameter information.
6232: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
6233: # The non-type value is always 1.
6234: #
6235: # @param {string} $cat - parameter name
1.566 damieng 6236: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 6237: # @param {string} $parmlev - selected level value (full|map|general), or ''
6238: # @param {hash reference} $listdata - the parameter data that will be modified
6239: # @param {array reference} $psprt - selected parts
6240: # @param {array reference} $selections - selected sections
6241: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6242: # @param {hash reference} $allmaps - hash map pc -> map src
6243: # @param {array reference} $ids - resource and map ids
6244: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6245: sub secgroup_lister {
6246: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6247: foreach my $item (@{$selections}) {
6248: foreach my $part (@{$psprt}) {
6249: my $rootparmkey=$env{'request.course.id'};
6250: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6251: $rootparmkey.='.['.$item.']';
6252: }
6253: if ($parmlev eq 'general') {
6254: # course-level parameter
6255: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6256: $$listdata{$newparmkey}=1;
6257: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6258: } elsif ($parmlev eq 'map') {
6259: # map-level parameter
1.548 raeburn 6260: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6261: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6262: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6263: $$listdata{$newparmkey}=1;
6264: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6265: }
6266: } else {
6267: # resource-level parameter
6268: foreach my $rid (@{$ids}) {
6269: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6270: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6271: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6272: $$listdata{$newparmkey}=1;
6273: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6274: }
6275: }
6276: }
6277: }
6278: }
6279:
1.563 damieng 6280: # UI to edit parameter settings starting with a list of all existing parameters.
6281: # (called by setoverview action)
6282: #
6283: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6284: sub overview {
1.568 raeburn 6285: my ($r,$parm_permission) = @_;
1.208 www 6286: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6287: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6288: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6289: my $readonly = 1;
6290: if ($parm_permission->{'edit'}) {
6291: undef($readonly);
6292: }
1.549 raeburn 6293: my $js = '<script type="text/javascript">'."\n".
6294: '// <![CDATA['."\n".
6295: &toggleparmtextbox_js()."\n".
6296: &validateparms_js()."\n".
6297: &ipacc_boxes_js()."\n".
1.558 raeburn 6298: &done_proctor_js()."\n".
1.588 raeburn 6299: &deeplink_js()."\n".
1.549 raeburn 6300: '// ]]>'."\n".
6301: '</script>'."\n";
1.414 droeschl 6302: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6303: text=>"Overview Mode"});
1.549 raeburn 6304: my %loaditems = (
6305: 'onload' => "showHideLenient();",
6306: );
6307:
6308: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6309: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6310: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6311: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6312: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6313:
1.208 www 6314: # Store modified
6315:
1.568 raeburn 6316: unless ($readonly) {
6317: &storedata($r,$crs,$dom);
6318: }
1.208 www 6319:
6320: # Read modified data
6321:
1.552 raeburn 6322: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6323:
1.214 www 6324:
6325: my $sortorder=$env{'form.sortorder'};
6326: unless ($sortorder) { $sortorder='realmstudent'; }
1.608 raeburn 6327: &sortmenu($r,$sortorder,'overview');
1.214 www 6328:
1.568 raeburn 6329: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6330:
6331: if ($readonly) {
6332: $r->print('<p>'.$submitbutton.'</p>');
6333: }
6334:
1.208 www 6335: # List data
6336:
1.568 raeburn 6337: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6338: $r->print(&tableend().'<p>');
6339: if ($foundkeys) {
6340: unless ($readonly) {
6341: $r->print('<p>'.$submitbutton.'</p>');
6342: }
6343: } else {
6344: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6345: }
6346: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6347: }
1.121 www 6348:
1.560 damieng 6349: # Unused sub.
1.563 damieng 6350: #
6351: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6352: sub clean_parameters {
6353: my ($r) = @_;
6354: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6355: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6356:
1.414 droeschl 6357: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6358: text=>"Clean Parameters"});
1.333 albertel 6359: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6360: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6361: $r->print(<<ENDOVER);
6362: $start_page
6363: $breadcrumbs
6364: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6365: ENDOVER
6366: # Store modified
6367:
6368: &storedata($r,$crs,$dom);
6369:
6370: # Read modified data
6371:
6372: my $resourcedata=&readdata($crs,$dom);
6373:
6374: # List data
6375:
6376: $r->print('<h3>'.
1.473 amueller 6377: &mt('These parameters refer to resources that do not exist.').
6378: '</h3>'.
6379: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6380: '<br />');
1.333 albertel 6381: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6382: '<tr>'.
6383: '<th>'.&mt('Delete').'</th>'.
6384: '<th>'.&mt('Parameter').'</th>'.
6385: '</tr>');
1.333 albertel 6386: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6387: next if (!exists($resourcedata->{$thiskey.'.type'})
6388: && $thiskey=~/\.type$/);
6389: my %data = &parse_key($thiskey);
6390: if (1) { #exists($data{'realm_exists'})
6391: #&& !$data{'realm_exists'}) {
6392: $r->print(&Apache::loncommon::start_data_table_row().
6393: '<tr>'.
6394: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6395:
6396: $r->print('<td>');
6397: my $display_value = $resourcedata->{$thiskey};
6398: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6399: $display_value =
6400: &Apache::lonlocal::locallocaltime($display_value);
6401: }
1.470 raeburn 6402: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6403: $parmitem = &mt($parmitem);
1.560 damieng 6404: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6405: $parmitem,$resourcedata->{$thiskey}));
6406: $r->print('<br />');
6407: if ($data{'scope_type'} eq 'all') {
6408: $r->print(&mt('All users'));
6409: } elsif ($data{'scope_type'} eq 'user') {
6410: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6411: } elsif ($data{'scope_type'} eq 'secgroup') {
6412: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6413: }
6414: $r->print('<br />');
6415: if ($data{'realm_type'} eq 'all') {
6416: $r->print(&mt('All Resources'));
6417: } elsif ($data{'realm_type'} eq 'folder') {
6418: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6419: } elsif ($data{'realm_type'} eq 'symb') {
6420: my ($map,$resid,$url) =
6421: &Apache::lonnet::decode_symb($data{'realm'});
6422: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6423: $url.' <br /> ',
6424: $resid.' <br /> ',$map));
6425: }
6426: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6427: $r->print('</td></tr>');
6428:
1.473 amueller 6429: }
1.333 albertel 6430: }
6431: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6432: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6433: '</p></form>');
6434: &endSettingsScreen($r);
6435: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6436: }
6437:
1.563 damieng 6438: # UI to shift all dates (called by dateshift1 action).
6439: # Used by overview mode.
6440: #
6441: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6442: sub date_shift_one {
6443: my ($r) = @_;
6444: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6445: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6446: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6447: my $sec = $env{'request.course.sec'};
1.414 droeschl 6448: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6449: text=>"Shifting Dates"});
1.594 raeburn 6450: my $submit_text = &mt('Shift all dates accordingly');
6451: if ($sec ne '') {
1.595 raeburn 6452: my @groups;
6453: if ($env{'request.course.groups'} ne '') {
6454: @groups = split(/:/,$env{'request.course.groups'});
6455: }
6456: if (@groups) {
6457: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6458: } else {
6459: $submit_text = &mt("Shift dates set just for your section, accordingly");
6460: }
1.594 raeburn 6461: }
1.390 www 6462: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6463: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6464: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6465: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6466: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6467: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6468: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6469: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6470: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6471: 'timeshifted',
6472: $env{'form.timebase'},,
6473: '').
6474: '</td></tr></table>'.
6475: '<input type="hidden" name="action" value="dateshift2" />'.
6476: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6477: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6478: &endSettingsScreen($r);
1.390 www 6479: $r->print(&Apache::loncommon::end_page());
6480: }
6481:
1.563 damieng 6482: # UI to shift all dates (second form).
6483: #
6484: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6485: sub date_shift_two {
6486: my ($r) = @_;
6487: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6488: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6489: my $sec = $env{'request.course.sec'};
1.531 raeburn 6490: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6491: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6492: text=>"Shifting Dates"});
1.390 www 6493: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6494: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6495: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6496: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6497: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6498: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6499: if ($sec ne '') {
1.595 raeburn 6500: my @groups;
6501: if ($env{'request.course.groups'} ne '') {
6502: @groups = split(/:/,$env{'request.course.groups'});
6503: }
6504: if (@groups) {
6505: $r->print('<p>'.
6506: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6507: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6508: &Apache::lonlocal::locallocaltime($timeshifted)).
6509: '</p>');
6510: } else {
6511: $r->print('<p>'.
6512: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6513: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6514: &Apache::lonlocal::locallocaltime($timeshifted)).
6515: '</p>');
6516: }
1.594 raeburn 6517: } else {
6518: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6519: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6520: &Apache::lonlocal::locallocaltime($timeshifted)).
6521: '</p>');
6522: }
1.390 www 6523: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6524: my $numchanges = 0;
6525: my $result = &dateshift($delta,\$numchanges);
6526: if ($result eq 'ok') {
6527: $r->print(
6528: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6529: $numchanges)));
6530: } elsif ($result eq 'con_delayed') {
6531: $r->print(
6532: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6533: $numchanges)));
6534: } else {
6535: $r->print(
6536: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6537: }
1.543 bisitz 6538: $r->print(
6539: '<br /><br />'.
6540: &Apache::lonhtmlcommon::actionbox(
6541: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6542: &endSettingsScreen($r);
1.390 www 6543: $r->print(&Apache::loncommon::end_page());
6544: }
6545:
1.563 damieng 6546: # Returns the different components of a resourcedata key.
6547: # Keys: scope_type, scope, realm_type, realm, realm_title,
6548: # realm_exists, parameter_part, parameter_name.
6549: # Was used by clean_parameters (which is unused).
6550: #
6551: # @param {string} $key - the parameter key
6552: # @returns {hash}
1.333 albertel 6553: sub parse_key {
6554: my ($key) = @_;
6555: my %data;
6556: my ($middle,$part,$name)=
1.572 damieng 6557: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6558: $data{'scope_type'} = 'all';
6559: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6560: $data{'scope'} = $1;
6561: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6562: $data{'scope_type'} = 'user';
6563: $data{'scope'} = [$1,$2];
6564: } else {
1.581 raeburn 6565: $data{'scope_type'} = 'secgroup';
1.560 damieng 6566: }
6567: $middle=~s/^\[(.*)\]//;
1.333 albertel 6568: }
6569: $middle=~s/\.+$//;
6570: $middle=~s/^\.+//;
6571: $data{'realm_type'}='all';
6572: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6573: $data{'realm'} = $1;
6574: $data{'realm_type'} = 'folder';
6575: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6576: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6577: } elsif ($middle) {
1.560 damieng 6578: $data{'realm'} = $middle;
6579: $data{'realm_type'} = 'symb';
6580: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6581: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6582: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6583: }
1.446 bisitz 6584:
1.333 albertel 6585: $data{'parameter_part'} = $part;
6586: $data{'parameter_name'} = $name;
6587:
6588: return %data;
6589: }
6590:
1.239 raeburn 6591:
1.563 damieng 6592: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6593: sub header {
1.507 www 6594: return &Apache::loncommon::start_page('Settings');
1.416 jms 6595: }
1.193 albertel 6596:
6597:
6598:
1.560 damieng 6599: ##################################################
6600: # MAIN MENU
6601: ##################################################
6602:
1.563 damieng 6603: # Content and problem settings main menu.
6604: #
6605: # @param {Apache2::RequestRec} $r - the Apache request
6606: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 6607: sub print_main_menu {
6608: my ($r,$parm_permission)=@_;
6609: #
1.414 droeschl 6610: $r->print(&header());
1.507 www 6611: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 6612: my $crstype = &Apache::loncommon::course_type();
6613: my $lc_crstype = lc($crstype);
6614:
6615: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 6616: $r->print(<<ENDMAINFORMHEAD);
6617: <form method="post" enctype="multipart/form-data"
6618: action="/adm/parmset" name="studentform">
6619: ENDMAINFORMHEAD
6620: #
1.195 albertel 6621: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6622: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 6623: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 6624: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 6625: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 6626: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
6627: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 6628: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
6629: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
6630: '/'.$env{'request.course.sec'});
6631: }
1.568 raeburn 6632: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
6633: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
6634: '/'.$env{'request.course.sec'});
6635: }
6636: my (%linktext,%linktitle,%url);
6637: if ($parm_permission->{'edit'}) {
6638: %linktext = (
6639: newoverview => 'Edit Resource Parameters - Overview Mode',
6640: settable => 'Edit Resource Parameters - Table Mode',
6641: setoverview => 'Modify Resource Parameters - Overview Mode',
6642: );
6643: %linktitle = (
6644: newoverview => 'Set/Modify resource parameters in overview mode.',
6645: settable => 'Set/Modify resource parameters in table mode.',
6646: setoverview => 'Set/Modify existing resource parameters in overview mode.',
6647: );
6648: } else {
6649: %linktext = (
6650: newoverview => 'View Resource Parameters - Overview Mode',
6651: settable => 'View Resource Parameters - Table Mode',
6652: setoverview => 'View Resource Parameters - Overview Mode',
6653: );
6654: %linktitle = (
6655: newoverview => 'Display resource parameters in overview mode.',
6656: settable => 'Display resource parameters in table mode.',
6657: setoverview => 'Display existing resource parameters in overview mode.',
6658: );
6659: }
6660: if ($mgr) {
6661: $linktext{'resettimes'} = 'Reset Student Access Times';
6662: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
6663: $url{'resettimes'} = '/adm/helper/resettimes.helper';
6664: } elsif ($vgr) {
6665: $linktext{'resettimes'} = 'Display Student Access Times',
6666: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
6667: $url{'resettimes'} = '/adm/accesstimes';
6668: }
1.193 albertel 6669: my @menu =
1.507 www 6670: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 6671: items => [
6672: { linktext => 'Portfolio Metadata',
6673: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 6674: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 6675: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 6676: icon =>'contact-new.png' ,
6677: },
1.568 raeburn 6678: { linktext => $linktext{'resettimes'},
6679: url => $url{'resettimes'},
6680: permission => ($vgr || $mgr),
6681: linktitle => $linktitle{'resettimes'},
6682: icon => 'start-here.png',
1.473 amueller 6683: },
1.520 raeburn 6684: { linktext => 'Blocking Communication/Resource Access',
6685: url => '/adm/setblock',
1.568 raeburn 6686: permission => ($vcb || $dcm),
1.520 raeburn 6687: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
6688: icon => 'comblock.png',
6689: },
1.473 amueller 6690: { linktext => 'Set Parameter Setting Default Actions',
6691: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 6692: permission => $parm_permission->{'setdefaults'},
1.473 amueller 6693: linktitle =>'Set default actions for parameters.' ,
6694: icon => 'folder-new.png' ,
6695: }]},
6696: { categorytitle => 'New and Existing Parameter Settings for Resources',
6697: items => [
6698: { linktext => 'Edit Resource Parameters - Helper Mode',
6699: url => '/adm/helper/parameter.helper',
1.568 raeburn 6700: permission => $parm_permission->{'helper'},
1.473 amueller 6701: linktitle =>'Set/Modify resource parameters in helper mode.' ,
6702: icon => 'dialog-information.png' ,
6703: #help => 'Parameter_Helper',
6704: },
1.568 raeburn 6705: { linktext => $linktext{'newoverview'},
1.473 amueller 6706: url => '/adm/parmset?action=newoverview',
1.568 raeburn 6707: permission => $parm_permission->{'newoverview'},
6708: linktitle => $linktitle{'newoverview'},
6709: icon => 'edit-find.png',
1.473 amueller 6710: #help => 'Parameter_Overview',
6711: },
1.568 raeburn 6712: { linktext => $linktext{'settable'},
1.473 amueller 6713: url => '/adm/parmset?action=settable',
1.568 raeburn 6714: permission => $parm_permission->{'settable'},
6715: linktitle => $linktitle{'settable'},
6716: icon => 'edit-copy.png',
1.473 amueller 6717: #help => 'Table_Mode',
6718: }]},
1.417 droeschl 6719: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 6720: items => [
1.570 raeburn 6721: { linktext => $linktext{'setoverview'},
1.473 amueller 6722: url => '/adm/parmset?action=setoverview',
1.568 raeburn 6723: permission => $parm_permission->{'setoverview'},
6724: linktitle => $linktitle{'setoverview'},
6725: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 6726: #help => 'Parameter_Overview',
6727: },
6728: { linktext => 'Change Log',
6729: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 6730: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 6731: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 6732: icon => 'document-properties.png',
1.473 amueller 6733: }]}
1.193 albertel 6734: );
1.414 droeschl 6735: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 6736: $r->print('</form>');
1.507 www 6737: &endSettingsScreen($r);
1.539 raeburn 6738: $r->print(&Apache::loncommon::end_page());
1.193 albertel 6739: return;
6740: }
1.414 droeschl 6741:
1.416 jms 6742:
6743:
1.560 damieng 6744: ##################################################
6745: # PORTFOLIO METADATA
6746: ##################################################
6747:
1.563 damieng 6748: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
6749: # It looks like field titles are not localized.
6750: #
6751: # @param {Apache2::RequestRec} $r - the Apache request
6752: # @param {string} $field_name - metadata field name
6753: # @param {string} $field_text - metadata field title, in English unless manually added
6754: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 6755: sub output_row {
1.347 banghart 6756: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 6757: my $output;
1.263 banghart 6758: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
6759: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 6760: if (!defined($options)) {
1.254 banghart 6761: $options = 'active,stuadd';
1.261 banghart 6762: $values = '';
1.252 banghart 6763: }
1.337 banghart 6764: if (!($options =~ /deleted/)) {
6765: my @options= ( ['active', 'Show to student'],
1.418 schafran 6766: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 6767: ['choices','Provide choices for students to select from']);
1.473 amueller 6768: # ['onlyone','Student may select only one choice']);
1.337 banghart 6769: if ($added_flag) {
6770: push @options,['deleted', 'Delete Metadata Field'];
6771: }
1.351 banghart 6772: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 6773: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 6774: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 6775: foreach my $opt (@options) {
1.560 damieng 6776: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
6777: $output .= &Apache::loncommon::continue_data_table_row();
6778: $output .= '<td>'.(' ' x 5).'<label>
6779: <input type="checkbox" name="'.
6780: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
6781: &mt($opt->[1]).'</label></td>';
6782: $output .= &Apache::loncommon::end_data_table_row();
6783: }
1.351 banghart 6784: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 6785: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 6786: $output .= &Apache::loncommon::end_data_table_row();
6787: my $multiple_checked;
6788: my $single_checked;
6789: if ($options =~ m/onlyone/) {
1.422 bisitz 6790: $multiple_checked = '';
1.423 bisitz 6791: $single_checked = ' checked="checked"';
1.351 banghart 6792: } else {
1.423 bisitz 6793: $multiple_checked = ' checked="checked"';
1.422 bisitz 6794: $single_checked = '';
1.351 banghart 6795: }
1.560 damieng 6796: $output .= &Apache::loncommon::continue_data_table_row();
6797: $output .= '<td>'.(' ' x 10).'
6798: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
6799: '.&mt('Student may select multiple choices from list').'</td>';
6800: $output .= &Apache::loncommon::end_data_table_row();
6801: $output .= &Apache::loncommon::continue_data_table_row();
6802: $output .= '<td>'.(' ' x 10).'
6803: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
6804: '.&mt('Student may select only one choice from list').'</td>';
6805: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 6806: }
6807: return ($output);
6808: }
1.416 jms 6809:
6810:
1.560 damieng 6811: # UI to order portfolio metadata fields.
1.563 damieng 6812: # Currently useless because addmetafield does not work.
6813: #
6814: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 6815: sub order_meta_fields {
6816: my ($r)=@_;
6817: my $idx = 1;
6818: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6819: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6820: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 6821: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 6822: &Apache::lonhtmlcommon::add_breadcrumb(
6823: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6824: text=>"Add Metadata Field"});
1.560 damieng 6825: &Apache::lonhtmlcommon::add_breadcrumb(
6826: {href=>"/adm/parmset?action=setrestrictmeta",
6827: text=>"Restrict Metadata"},
6828: {text=>"Order Metadata"});
1.345 banghart 6829: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 6830: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 6831: if ($env{'form.storeorder'}) {
6832: my $newpos = $env{'form.newpos'} - 1;
6833: my $currentpos = $env{'form.currentpos'} - 1;
6834: my @neworder = ();
1.548 raeburn 6835: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6836: my $i;
1.341 banghart 6837: if ($newpos > $currentpos) {
1.340 banghart 6838: # moving stuff up
6839: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 6840: $neworder[$i]=$oldorder[$i];
1.340 banghart 6841: }
6842: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 6843: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 6844: }
6845: $neworder[$newpos]=$oldorder[$currentpos];
6846: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 6847: $neworder[$i]=$oldorder[$i];
1.340 banghart 6848: }
6849: } else {
6850: # moving stuff down
1.473 amueller 6851: for ($i=0;$i<$newpos;$i++) {
6852: $neworder[$i]=$oldorder[$i];
6853: }
6854: $neworder[$newpos]=$oldorder[$currentpos];
6855: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
6856: $neworder[$i]=$oldorder[$i-1];
6857: }
6858: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
6859: $neworder[$i]=$oldorder[$i];
6860: }
1.340 banghart 6861: }
1.560 damieng 6862: my $ordered_fields = join ",", @neworder;
1.343 banghart 6863: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 6864: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6865: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 6866: }
1.357 raeburn 6867: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 6868: my $ordered_fields;
1.548 raeburn 6869: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6870: if (!@fields_in_order) {
6871: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 6872: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 6873: push @fields_in_order, $key;
1.341 banghart 6874: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 6875: }
1.341 banghart 6876: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 6877: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6878: }
1.340 banghart 6879: $r->print('<table>');
6880: my $num_fields = scalar(@fields_in_order);
6881: foreach my $key (@fields_in_order) {
6882: $r->print('<tr><td>');
6883: $r->print('<form method="post" action="">');
1.537 bisitz 6884: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 6885: for (my $i = 1;$i le $num_fields;$i ++) {
6886: if ($i eq $idx) {
6887: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
6888: } else {
6889: $r->print('<option value="'.$i.'">'.$i.'</option>');
6890: }
6891: }
6892: $r->print('</select></td><td>');
6893: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
6894: $r->print('<input type="hidden" name="storeorder" value="true" />');
6895: $r->print('</form>');
6896: $r->print($$fields{$key}.'</td></tr>');
6897: $idx ++;
6898: }
6899: $r->print('</table>');
1.507 www 6900: &endSettingsScreen($r);
1.340 banghart 6901: return 'ok';
6902: }
1.416 jms 6903:
6904:
1.563 damieng 6905: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
6906: # @returns {string}
1.359 banghart 6907: sub continue {
6908: my $output;
6909: $output .= '<form action="" method="post">';
6910: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 6911: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 6912: return ($output);
6913: }
1.416 jms 6914:
6915:
1.563 damieng 6916: # UI to add a metadata field.
6917: # Currenly does not work because of an HTML error (the field is not visible).
6918: #
6919: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 6920: sub addmetafield {
6921: my ($r)=@_;
1.414 droeschl 6922: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6923: text=>"Add Metadata Field"});
1.334 banghart 6924: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
6925: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 6926: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6927: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6928: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6929: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 6930: if (exists($env{'form.undelete'})) {
1.358 banghart 6931: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 6932: foreach my $meta_field(@meta_fields) {
6933: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
6934: $options =~ s/deleted//;
6935: $options =~ s/,,/,/;
6936: my $put_result = &Apache::lonnet::put('environment',
6937: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 6938:
1.586 raeburn 6939: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
6940: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
6941: '</strong>',$put_result).
6942: '<br />');
1.339 banghart 6943: }
1.359 banghart 6944: $r->print(&continue());
1.339 banghart 6945: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 6946: my $meta_field = $env{'form.fieldname'};
6947: my $display_field = $env{'form.fieldname'};
6948: $meta_field =~ s/\W/_/g;
1.338 banghart 6949: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 6950: my $put_result = &Apache::lonnet::put('environment',
6951: {'metadata.'.$meta_field.'.values'=>"",
6952: 'metadata.'.$meta_field.'.added'=>"$display_field",
6953: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 6954: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
6955: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
6956: '<br />');
1.359 banghart 6957: $r->print(&continue());
1.335 banghart 6958: } else {
1.357 raeburn 6959: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 6960: if ($fields) {
1.586 raeburn 6961: $r->print(&mt('You may undelete previously deleted fields.').
6962: '<br />'.
6963: &mt('Check those you wish to undelete and click Undelete.').
6964: '<br />');
1.339 banghart 6965: $r->print('<form method="post" action="">');
6966: foreach my $key(keys(%$fields)) {
1.581 raeburn 6967: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 6968: }
1.586 raeburn 6969: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 6970: $r->print('</form>');
6971: }
1.586 raeburn 6972: $r->print('<hr />'.
6973: &mt('[_1]Or[_2] you may enter a new metadata field name.',
6974: '<strong>','</strong>').
1.581 raeburn 6975: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 6976: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 6977: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 6978: $r->print('</form>');
1.334 banghart 6979: }
1.507 www 6980: &endSettingsScreen($r);
1.334 banghart 6981: }
1.416 jms 6982:
6983:
6984:
1.560 damieng 6985: # Display or save portfolio metadata.
1.563 damieng 6986: #
6987: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 6988: sub setrestrictmeta {
1.240 banghart 6989: my ($r)=@_;
1.242 banghart 6990: my $next_meta;
1.244 banghart 6991: my $output;
1.245 banghart 6992: my $item_num;
1.246 banghart 6993: my $put_result;
1.414 droeschl 6994: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 6995: text=>"Restrict Metadata"});
1.280 albertel 6996: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 6997: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 6998: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6999: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7000: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
7001: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 7002: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 7003: my $save_field = '';
1.586 raeburn 7004: my %lt = &Apache::lonlocal::texthash(
7005: addm => 'Add Metadata Field',
7006: ordm => 'Order Metadata Fields',
7007: save => 'Save',
7008: );
1.259 banghart 7009: if ($env{'form.restrictmeta'}) {
1.254 banghart 7010: foreach my $field (sort(keys(%env))) {
1.252 banghart 7011: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 7012: my $options;
1.252 banghart 7013: my $meta_field = $1;
7014: my $meta_key = $2;
1.253 banghart 7015: if ($save_field ne $meta_field) {
1.252 banghart 7016: $save_field = $meta_field;
1.473 amueller 7017: if ($env{'form.'.$meta_field.'_stuadd'}) {
7018: $options.='stuadd,';
7019: }
7020: if ($env{'form.'.$meta_field.'_choices'}) {
7021: $options.='choices,';
7022: }
7023: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
7024: $options.='onlyone,';
7025: }
7026: if ($env{'form.'.$meta_field.'_active'}) {
7027: $options.='active,';
7028: }
7029: if ($env{'form.'.$meta_field.'_deleted'}) {
7030: $options.='deleted,';
7031: }
1.259 banghart 7032: my $name = $save_field;
1.560 damieng 7033: $put_result = &Apache::lonnet::put('environment',
7034: {'metadata.'.$meta_field.'.options'=>$options,
7035: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
7036: },$dom,$crs);
1.252 banghart 7037: }
7038: }
7039: }
7040: }
1.296 albertel 7041: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 7042: {'freshen_cache' => 1});
1.335 banghart 7043: # Get the default metadata fields
1.258 albertel 7044: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 7045: # Now get possible added metadata fields
1.357 raeburn 7046: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 7047: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 7048: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 7049: if ($field ne 'courserestricted') {
1.586 raeburn 7050: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 7051: }
1.255 banghart 7052: }
1.351 banghart 7053: my $buttons = (<<ENDButtons);
1.586 raeburn 7054: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 7055: </form><br />
7056: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 7057: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 7058: </form>
7059: <br />
7060: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 7061: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 7062: ENDButtons
1.337 banghart 7063: my $added_flag = 1;
1.335 banghart 7064: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 7065: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 7066: }
1.347 banghart 7067: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 7068: $r->print(<<ENDenv);
1.259 banghart 7069: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 7070: $output
1.351 banghart 7071: $buttons
1.340 banghart 7072: </form>
1.244 banghart 7073: ENDenv
1.507 www 7074: &endSettingsScreen($r);
1.280 albertel 7075: $r->print(&Apache::loncommon::end_page());
1.240 banghart 7076: return 'ok';
7077: }
1.416 jms 7078:
7079:
1.563 damieng 7080: # Returns metadata fields that have been manually added.
7081: #
7082: # @param {string} $cid - course id
7083: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 7084: sub get_added_meta_fieldnames {
1.357 raeburn 7085: my ($cid) = @_;
1.335 banghart 7086: my %fields;
7087: foreach my $key(%env) {
1.357 raeburn 7088: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 7089: my $field_name = $1;
7090: my ($display_field_name) = $env{$key};
7091: $fields{$field_name} = $display_field_name;
7092: }
7093: }
7094: return \%fields;
7095: }
1.416 jms 7096:
7097:
1.563 damieng 7098: # Returns metadata fields that have been manually added and deleted.
7099: #
7100: # @param {string} $cid - course id
7101: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 7102: sub get_deleted_meta_fieldnames {
1.357 raeburn 7103: my ($cid) = @_;
1.339 banghart 7104: my %fields;
7105: foreach my $key(%env) {
1.357 raeburn 7106: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 7107: my $field_name = $1;
7108: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
7109: my ($display_field_name) = $env{$key};
7110: $fields{$field_name} = $display_field_name;
7111: }
7112: }
7113: }
7114: return \%fields;
7115: }
1.560 damieng 7116:
7117:
7118: ##################################################
7119: # PARAMETER SETTINGS DEFAULT ACTIONS
7120: ##################################################
7121:
7122: # UI to change parameter setting default actions
1.563 damieng 7123: #
7124: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 7125: sub defaultsetter {
1.280 albertel 7126: my ($r) = @_;
7127:
1.414 droeschl 7128: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 7129: text=>"Set Defaults"});
1.531 raeburn 7130: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7131: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
7132: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 7133: my $start_page =
1.531 raeburn 7134: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 7135: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 7136: $r->print($start_page.$breadcrumbs);
1.531 raeburn 7137: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 7138: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 7139:
1.221 www 7140: my @ids=();
7141: my %typep=();
7142: my %keyp=();
7143: my %allparms=();
7144: my %allparts=();
7145: my %allmaps=();
7146: my %mapp=();
7147: my %symbp=();
7148: my %maptitles=();
7149: my %uris=();
7150: my %keyorder=&standardkeyorder();
7151: my %defkeytype=();
7152:
1.446 bisitz 7153: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 7154: \%mapp, \%symbp,\%maptitles,\%uris,
7155: \%keyorder,\%defkeytype);
1.224 www 7156: if ($env{'form.storerules'}) {
1.560 damieng 7157: my %newrules=();
7158: my @delrules=();
7159: my %triggers=();
7160: foreach my $key (keys(%env)) {
1.225 albertel 7161: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 7162: my $tempkey=$1;
7163: my $action=$env{$key};
1.226 www 7164: if ($action) {
1.560 damieng 7165: $newrules{$tempkey.'_action'}=$action;
7166: if ($action ne 'default') {
7167: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
7168: $triggers{$whichparm}.=$tempkey.':';
7169: }
7170: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
7171: if (&isdateparm($defkeytype{$tempkey})) {
7172: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
7173: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
7174: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
7175: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
7176: } else {
7177: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
7178: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
7179: }
7180: } else {
7181: push(@delrules,$tempkey.'_action');
7182: push(@delrules,$tempkey.'_type');
7183: push(@delrules,$tempkey.'_hours');
7184: push(@delrules,$tempkey.'_min');
7185: push(@delrules,$tempkey.'_sec');
7186: push(@delrules,$tempkey.'_value');
7187: }
1.473 amueller 7188: }
7189: }
1.560 damieng 7190: foreach my $key (keys(%allparms)) {
7191: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 7192: }
1.560 damieng 7193: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
7194: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
7195: &resetrulescache();
1.224 www 7196: }
1.227 www 7197: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 7198: 'hours' => 'Hours',
7199: 'min' => 'Minutes',
7200: 'sec' => 'Seconds',
7201: 'yes' => 'Yes',
7202: 'no' => 'No');
1.222 www 7203: my @standardoptions=('','default');
7204: my @standarddisplay=('',&mt('Default value when manually setting'));
7205: my @dateoptions=('','default');
7206: my @datedisplay=('',&mt('Default value when manually setting'));
7207: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7208: unless ($tempkey) { next; }
7209: push @standardoptions,'when_setting_'.$tempkey;
7210: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
7211: if (&isdateparm($defkeytype{$tempkey})) {
7212: push @dateoptions,'later_than_'.$tempkey;
7213: push @datedisplay,&mt('Automatically set later than ').$tempkey;
7214: push @dateoptions,'earlier_than_'.$tempkey;
7215: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
7216: }
1.222 www 7217: }
1.563 damieng 7218: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
7219: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 7220: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 7221: &Apache::loncommon::start_data_table_header_row().
7222: "<th>".&mt('Rule for parameter').'</th><th>'.
7223: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
7224: &Apache::loncommon::end_data_table_header_row());
1.221 www 7225: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7226: unless ($tempkey) { next; }
7227: $r->print("\n".&Apache::loncommon::start_data_table_row().
7228: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
7229: my $action=&rulescache($tempkey.'_action');
7230: $r->print('<select name="'.$tempkey.'_action">');
7231: if (&isdateparm($defkeytype{$tempkey})) {
7232: for (my $i=0;$i<=$#dateoptions;$i++) {
7233: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
7234: $r->print("\n<option value='$dateoptions[$i]'".
7235: ($dateoptions[$i] eq $action?' selected="selected"':'').
7236: ">$datedisplay[$i]</option>");
7237: }
7238: } else {
7239: for (my $i=0;$i<=$#standardoptions;$i++) {
7240: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
7241: $r->print("\n<option value='$standardoptions[$i]'".
7242: ($standardoptions[$i] eq $action?' selected="selected"':'').
7243: ">$standarddisplay[$i]</option>");
7244: }
1.473 amueller 7245: }
1.560 damieng 7246: $r->print('</select>');
7247: unless (&isdateparm($defkeytype{$tempkey})) {
7248: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7249: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7250: }
1.560 damieng 7251: $r->print("\n</td><td>\n");
1.222 www 7252:
1.221 www 7253: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7254: my $days=&rulescache($tempkey.'_days');
7255: my $hours=&rulescache($tempkey.'_hours');
7256: my $min=&rulescache($tempkey.'_min');
7257: my $sec=&rulescache($tempkey.'_sec');
7258: $r->print(<<ENDINPUTDATE);
7259: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7260: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7261: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7262: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7263: ENDINPUTDATE
1.560 damieng 7264: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7265: my $yeschecked='';
7266: my $nochecked='';
7267: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7268: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7269:
7270: $r->print(<<ENDYESNO);
7271: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7272: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7273: ENDYESNO
1.221 www 7274: } else {
1.560 damieng 7275: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7276: }
1.318 albertel 7277: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7278: }
1.318 albertel 7279: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7280: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7281: &mt('Save').'" /></form>'."\n");
7282: &endSettingsScreen($r);
7283: $r->print(&Apache::loncommon::end_page());
1.220 www 7284: return;
7285: }
1.193 albertel 7286:
1.560 damieng 7287: ##################################################
7288: # PARAMETER CHANGES LOG
7289: ##################################################
7290:
1.563 damieng 7291: # Returns some info for a parameter log entry.
7292: # Returned entries:
7293: # $realm - HTML title for the parameter level and resource
7294: # $section - parameter section
7295: # $name - parameter name
7296: # $part - parameter part
7297: # $what - $part.'.'.$name
7298: # $middle - resource symb ?
7299: # $uname - user name (same as given)
7300: # $udom - user domain (same as given)
7301: # $issection - section or group name
7302: # $realmdescription - title for the parameter level and resource (without using HTML)
7303: #
7304: # @param {string} $key - parameter log key
7305: # @param {string} $uname - user name
7306: # @param {string} $udom - user domain
7307: # @param {boolean} $typeflag - .type log entry
7308: # @returns {Array}
1.290 www 7309: sub components {
1.581 raeburn 7310: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7311:
7312: if ($typeflag) {
1.560 damieng 7313: $key=~s/\.type$//;
1.290 www 7314: }
1.330 albertel 7315:
7316: my ($middle,$part,$name)=
1.572 damieng 7317: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7318: my $issection;
1.330 albertel 7319:
1.290 www 7320: my $section=&mt('All Students');
7321: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7322: $issection=$1;
7323: $section=&mt('Group/Section').': '.$issection;
7324: $middle=~s/^\[(.*)\]//;
1.290 www 7325: }
7326: $middle=~s/\.+$//;
7327: $middle=~s/^\.+//;
1.291 www 7328: if ($uname) {
1.560 damieng 7329: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7330: $issection='';
1.291 www 7331: }
1.316 albertel 7332: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7333: my $realmdescription=&mt('all resources');
1.556 raeburn 7334: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7335: my $mapurl = $1;
7336: my $maplevel = $2;
7337: my $leveltitle = &mt('Folder/Map');
7338: if ($maplevel eq 'rec') {
7339: $leveltitle = &mt('Recursive');
7340: }
1.560 damieng 7341: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7342: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7343: $mapurl.')</span></span>';
7344: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7345: } elsif ($middle) {
7346: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7347: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7348: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7349: ' in '.$map.' id: '.$id.')</span></span>';
7350: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7351: }
1.291 www 7352: my $what=$part.'.'.$name;
1.330 albertel 7353: return ($realm,$section,$name,$part,
1.473 amueller 7354: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7355: }
1.293 www 7356:
1.563 damieng 7357: my %standard_parms; # hash parameter name -> parameter title (not localized)
7358: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7359:
1.563 damieng 7360: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7361: sub load_parameter_names {
1.583 raeburn 7362: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7363: while (my $configline=<$config>) {
1.560 damieng 7364: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7365: chomp($configline);
7366: my ($short,$plain)=split(/:/,$configline);
7367: my (undef,$name,$type)=split(/\&/,$short,3);
7368: if ($type eq 'display') {
7369: $standard_parms{$name} = $plain;
1.469 raeburn 7370: } elsif ($type eq 'type') {
1.560 damieng 7371: $standard_parms_types{$name} = $plain;
1.469 raeburn 7372: }
1.328 albertel 7373: }
7374: close($config);
7375: $standard_parms{'int_pos'} = 'Positive Integer';
7376: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7377: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7378: }
7379:
1.563 damieng 7380: # Returns a parameter title for standard parameters, the name for others.
7381: #
7382: # @param {string} $name - parameter name
7383: # @returns {string}
1.292 www 7384: sub standard_parameter_names {
7385: my ($name)=@_;
1.328 albertel 7386: if (!%standard_parms) {
1.560 damieng 7387: &load_parameter_names();
1.328 albertel 7388: }
1.292 www 7389: if ($standard_parms{$name}) {
1.560 damieng 7390: return $standard_parms{$name};
1.446 bisitz 7391: } else {
1.560 damieng 7392: return $name;
1.292 www 7393: }
7394: }
1.290 www 7395:
1.563 damieng 7396: # Returns a parameter type for standard parameters, undef for others.
7397: #
7398: # @param {string} $name - parameter name
7399: # @returns {string}
1.469 raeburn 7400: sub standard_parameter_types {
7401: my ($name)=@_;
7402: if (!%standard_parms_types) {
7403: &load_parameter_names();
7404: }
7405: if ($standard_parms_types{$name}) {
7406: return $standard_parms_types{$name};
7407: }
7408: return;
7409: }
1.309 www 7410:
1.563 damieng 7411: # Returns a parameter level title (not localized) from the parameter level name.
7412: #
7413: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7414: # @returns {string}
1.557 raeburn 7415: sub standard_parameter_levels {
7416: my ($name)=@_;
7417: my %levels = (
7418: 'resourcelevel' => 'a single resource',
7419: 'maplevel' => 'the enclosing map/folder',
7420: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7421: 'courselevel' => 'the general (course) level',
7422: );
7423: if ($levels{$name}) {
7424: return $levels{$name};
7425: }
7426: return;
7427: }
7428:
1.560 damieng 7429: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7430: #
7431: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7432: sub parm_change_log {
1.568 raeburn 7433: my ($r,$parm_permission)=@_;
1.531 raeburn 7434: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7435: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7436: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7437: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7438: text=>"Parameter Change Log"});
1.522 raeburn 7439: my $js = '<script type="text/javascript">'."\n".
7440: '// <![CDATA['."\n".
7441: &Apache::loncommon::display_filter_js('parmslog')."\n".
7442: '// ]]>'."\n".
7443: '</script>'."\n";
7444: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7445: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7446: &startSettingsScreen($r,'parmset',$crstype);
7447: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7448:
1.301 www 7449: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7450:
1.522 raeburn 7451: $r->print('<div class="LC_left_float">'.
7452: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7453: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7454: method="post" name="parameterlog">');
1.446 bisitz 7455:
1.311 albertel 7456: my %saveable_parameters = ('show' => 'scalar',);
7457: &Apache::loncommon::store_course_settings('parameter_log',
7458: \%saveable_parameters);
7459: &Apache::loncommon::restore_course_settings('parameter_log',
7460: \%saveable_parameters);
1.522 raeburn 7461: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7462: '<input type="submit" value="'.&mt('Display').'" />'.
7463: '</form></fieldset></div><br clear="all" />');
1.301 www 7464:
1.568 raeburn 7465: my $readonly = 1;
7466: if ($parm_permission->{'edit'}) {
7467: undef($readonly);
7468: }
1.531 raeburn 7469: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7470: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7471: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7472: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7473: unless ($readonly) {
7474: $r->print('<th>'.&mt('Announce').'</th>');
7475: }
7476: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7477: my $shown=0;
1.349 www 7478: my $folder='';
7479: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7480: my $last='';
7481: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7482: &GDBM_READER(),0640)) {
7483: $last=$hash{'last_known'};
7484: untie(%hash);
7485: }
7486: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7487: }
1.595 raeburn 7488: my $numgroups = 0;
7489: my @groups;
7490: if ($env{'request.course.groups'} ne '') {
7491: @groups = split(/:/,$env{'request.course.groups'});
7492: $numgroups = scalar(@groups);
7493: }
1.560 damieng 7494: foreach my $id (sort {
7495: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7496: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7497: }
7498: my $aid = (split('00000',$a))[-1];
7499: my $bid = (split('00000',$b))[-1];
7500: return $bid<=>$aid;
1.473 amueller 7501: } (keys(%parmlog))) {
1.294 www 7502: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7503: my $count = 0;
7504: my $time =
7505: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7506: my $plainname =
7507: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7508: $parmlog{$id}{'exe_udom'});
7509: my $about_me_link =
7510: &Apache::loncommon::aboutmewrapper($plainname,
7511: $parmlog{$id}{'exe_uname'},
7512: $parmlog{$id}{'exe_udom'});
7513: my $send_msg_link='';
1.568 raeburn 7514: if ((!$readonly) &&
7515: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7516: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7517: $send_msg_link ='<br />'.
7518: &Apache::loncommon::messagewrapper(&mt('Send message'),
7519: $parmlog{$id}{'exe_uname'},
7520: $parmlog{$id}{'exe_udom'});
7521: }
7522: my $row_start=&Apache::loncommon::start_data_table_row();
7523: my $makenewrow=0;
7524: my %istype=();
7525: my $output;
7526: foreach my $changed (reverse(sort(@changes))) {
7527: my $value=$parmlog{$id}{'logentry'}{$changed};
7528: my $typeflag = ($changed =~/\.type$/ &&
7529: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7530: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7531: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7532: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7533: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7534: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7535: if ($uname ne '') {
7536: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7537: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7538: }
7539: }
7540: if ($env{'form.displayfilter'} eq 'currentfolder') {
7541: if ($folder) {
7542: if ($middle!~/^\Q$folder\E/) { next; }
7543: }
7544: }
7545: if ($typeflag) {
7546: $istype{$parmname}=$value;
7547: if (!$env{'form.includetypes'}) { next; }
7548: }
7549: $count++;
7550: if ($makenewrow) {
7551: $output .= $row_start;
7552: } else {
7553: $makenewrow=1;
7554: }
1.470 raeburn 7555: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7556: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7557: &mt($parmitem).'</td><td>'.
7558: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7559: my $stillactive=0;
7560: if ($parmlog{$id}{'delflag'}) {
7561: $output .= &mt('Deleted');
7562: } else {
7563: if ($typeflag) {
1.470 raeburn 7564: my $parmitem = &standard_parameter_names($value);
7565: $parmitem = &mt($parmitem);
1.560 damieng 7566: $output .= &mt('Type: [_1]',$parmitem);
7567: } else {
1.584 raeburn 7568: my $toolsymb;
7569: if ($middle =~ /ext\.tool$/) {
7570: $toolsymb = $middle;
7571: }
1.560 damieng 7572: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7573: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7574: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7575: my $showvalue = $value;
7576: if ($istype{$parmname} eq '') {
7577: my $type = &standard_parameter_types($parmname);
7578: if ($type ne '') {
7579: if (&isdateparm($type)) {
7580: $showvalue =
7581: &Apache::lonlocal::locallocaltime($value);
7582: }
7583: }
7584: } else {
1.560 damieng 7585: if (&isdateparm($istype{$parmname})) {
7586: $showvalue = &Apache::lonlocal::locallocaltime($value);
7587: }
1.469 raeburn 7588: }
7589: $output .= $showvalue;
1.560 damieng 7590: if ($value ne $all[$level]) {
7591: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7592: } else {
7593: $stillactive=1;
7594: }
7595: }
1.473 amueller 7596: }
1.568 raeburn 7597: $output .= '</td>';
7598:
7599: unless ($readonly) {
7600: $output .= '<td>';
7601: if ($stillactive) {
7602: my $parmitem = &standard_parameter_names($parmname);
7603: $parmitem = &mt($parmitem);
7604: my $title=&mt('Changed [_1]',$parmitem);
7605: my $description=&mt('Changed [_1] for [_2] to [_3]',
7606: $parmitem,$realmdescription,
7607: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
7608: if (($uname) && ($udom)) {
7609: $output .=
7610: &Apache::loncommon::messagewrapper('Notify User',
7611: $uname,$udom,$title,
7612: $description);
7613: } else {
7614: $output .=
7615: &Apache::lonrss::course_blog_link($id,$title,
7616: $description);
7617: }
1.560 damieng 7618: }
1.568 raeburn 7619: $output .= '</td>';
1.560 damieng 7620: }
1.568 raeburn 7621: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 7622: }
1.560 damieng 7623: if ($env{'form.displayfilter'} eq 'containing') {
7624: my $wholeentry=$about_me_link.':'.
7625: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
7626: $output;
7627: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 7628: }
1.349 www 7629: if ($count) {
1.560 damieng 7630: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
7631: <td rowspan="'.$count.'">'.$about_me_link.
7632: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
7633: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
7634: $send_msg_link.'</td>'.$output);
7635: $shown++;
7636: }
7637: if (!($env{'form.show'} eq &mt('all')
7638: || $shown<=$env{'form.show'})) { last; }
1.286 www 7639: }
1.301 www 7640: $r->print(&Apache::loncommon::end_data_table());
1.507 www 7641: &endSettingsScreen($r);
1.284 www 7642: $r->print(&Apache::loncommon::end_page());
7643: }
7644:
1.560 damieng 7645: ##################################################
7646: # MISC !
7647: ##################################################
7648:
1.563 damieng 7649: # Stores slot information.
1.560 damieng 7650: # Used by table UI
1.563 damieng 7651: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7652: #
7653: # @param {string} $slot_name - slot name
7654: # @param {string} $cdom - course domain
7655: # @param {string} $cnum - course number
7656: # @param {string} $symb - resource symb
7657: # @param {string} $uname - user name
7658: # @param {string} $udom - user domain
7659: # @returns {string} - 'ok' or error name
1.437 raeburn 7660: sub update_slots {
7661: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
7662: my %slot=&Apache::lonnet::get_slot($slot_name);
7663: if (!keys(%slot)) {
7664: return 'error: slot does not exist';
7665: }
7666: my $max=$slot{'maxspace'};
7667: if (!defined($max)) { $max=99999; }
7668:
7669: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
7670: "^$slot_name\0");
7671: my ($tmp)=%consumed;
7672: if ($tmp=~/^error: 2 / ) {
7673: return 'error: unable to determine current slot status';
7674: }
7675: my $last=0;
7676: foreach my $key (keys(%consumed)) {
7677: my $num=(split('\0',$key))[1];
7678: if ($num > $last) { $last=$num; }
7679: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7680: return 'ok';
7681: }
7682: }
7683:
7684: if (scalar(keys(%consumed)) >= $max) {
7685: return 'error: no space left in slot';
7686: }
7687: my $wanted=$last+1;
7688:
7689: my %reservation=('name' => $uname.':'.$udom,
7690: 'timestamp' => time,
7691: 'symb' => $symb);
7692:
7693: my $success=&Apache::lonnet::newput('slot_reservations',
7694: {"$slot_name\0$wanted" =>
7695: \%reservation},
7696: $cdom, $cnum);
1.438 raeburn 7697: if ($success eq 'ok') {
7698: my %storehash = (
7699: symb => $symb,
7700: slot => $slot_name,
7701: action => 'reserve',
7702: context => 'parameter',
7703: );
1.526 raeburn 7704: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7705: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 7706:
1.526 raeburn 7707: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7708: '',$uname,$udom,$uname,$udom);
1.438 raeburn 7709: }
1.437 raeburn 7710: return $success;
7711: }
7712:
1.563 damieng 7713: # Deletes a slot reservation.
1.560 damieng 7714: # Used by table UI
1.563 damieng 7715: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7716: #
7717: # @param {string} $slot_name - slot name
7718: # @param {string} $cdom - course domain
7719: # @param {string} $cnum - course number
7720: # @param {string} $uname - user name
7721: # @param {string} $udom - user domain
7722: # @param {string} $symb - resource symb
7723: # @returns {string} - 'ok' or error name
1.437 raeburn 7724: sub delete_slots {
7725: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
7726: my $delresult;
7727: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
7728: $cnum, "^$slot_name\0");
7729: if (&Apache::lonnet::error(%consumed)) {
7730: return 'error: unable to determine current slot status';
7731: }
7732: my ($tmp)=%consumed;
7733: if ($tmp=~/^error: 2 /) {
7734: return 'error: unable to determine current slot status';
7735: }
7736: foreach my $key (keys(%consumed)) {
7737: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7738: my $num=(split('\0',$key))[1];
7739: my $entry = $slot_name.'\0'.$num;
7740: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
7741: $cdom,$cnum);
7742: if ($delresult eq 'ok') {
7743: my %storehash = (
7744: symb => $symb,
7745: slot => $slot_name,
7746: action => 'release',
7747: context => 'parameter',
7748: );
1.526 raeburn 7749: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7750: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 7751: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7752: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 7753: }
7754: }
7755: }
7756: return $delresult;
7757: }
7758:
1.563 damieng 7759: # Returns true if there is a current course.
1.560 damieng 7760: # Used by handler
1.563 damieng 7761: #
7762: # @returns {boolean}
1.355 albertel 7763: sub check_for_course_info {
7764: my $navmap = Apache::lonnavmaps::navmap->new();
7765: return 1 if ($navmap);
7766: return 0;
7767: }
7768:
1.563 damieng 7769: # Returns the current course host and host LON-CAPA version.
7770: #
7771: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 7772: sub parameter_release_vars {
1.504 raeburn 7773: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7774: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
7775: my $chostname = &Apache::lonnet::hostname($chome);
7776: my ($cmajor,$cminor) =
7777: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
7778: return ($chostname,$cmajor,$cminor);
7779: }
7780:
1.563 damieng 7781: # Checks if the course host version can handle a parameter required version,
7782: # and if it does, stores the release needed for the course.
7783: #
7784: # @param {string} $name - parameter name
7785: # @param {string} $value - parameter value
7786: # @param {string} $valmatch - name of the test used for checking the value
7787: # @param {string} $namematch - name of the test used for checking the name
7788: # @param {string} $needsrelease - version needed by the parameter, major.minor
7789: # @param {integer} $cmajor - course major version number
7790: # @param {integer} $cminor - course minor version number
7791: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 7792: sub parameter_releasecheck {
1.557 raeburn 7793: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 7794: my $needsnewer;
7795: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
7796: if (($cmajor < $needsmajor) ||
7797: ($cmajor == $needsmajor && $cminor < $needsminor)) {
7798: $needsnewer = 1;
1.557 raeburn 7799: } elsif ($name) {
7800: if ($valmatch) {
7801: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
7802: } elsif ($value) {
7803: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
7804: }
7805: } elsif ($namematch) {
7806: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 7807: }
7808: return $needsnewer;
7809: }
7810:
1.568 raeburn 7811: sub get_permission {
7812: my %permission;
7813: my $allowed = 0;
7814: return (\%permission,$allowed) unless ($env{'request.course.id'});
7815: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
7816: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
7817: $env{'request.course.sec'}))) {
7818: %permission= (
7819: 'edit' => 1,
7820: 'set' => 1,
7821: 'setoverview' => 1,
7822: 'addmetadata' => 1,
7823: 'ordermetadata' => 1,
7824: 'setrestrictmeta' => 1,
7825: 'newoverview' => 1,
7826: 'setdefaults' => 1,
7827: 'settable' => 1,
7828: 'parameterchangelog' => 1,
7829: 'cleanparameters' => 1,
7830: 'dateshift1' => 1,
7831: 'dateshift2' => 1,
7832: 'helper' => 1,
7833: );
7834: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
7835: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
7836: $env{'request.course.sec'}))) {
7837: %permission = (
7838: 'set' => 1,
7839: 'settable' => 1,
7840: 'newoverview' => 1,
7841: 'setoverview' => 1,
7842: 'parameterchangelog' => 1,
7843: );
7844: }
7845: foreach my $perm (values(%permission)) {
7846: if ($perm) { $allowed=1; last; }
7847: }
7848: return (\%permission,$allowed);
7849: }
7850:
1.560 damieng 7851: ##################################################
7852: # HANDLER
7853: ##################################################
7854:
7855: # Main handler for lonparmset.
7856: # Sub called based on request parameters action and command:
7857: # no command or action: print_main_menu
7858: # command 'set': assessparms (direct access to table mode for a resource)
7859: # (this can also be accessed simply with the symb parameter)
7860: # action 'setoverview': overview (display all existing parameter settings)
7861: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
7862: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
7863: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
7864: # action 'newoverview': newoverview (overview mode)
7865: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
7866: # action 'settable': assessparms (table mode)
7867: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
7868: # blog postings, user notification changes)
7869: # action 'cleanparameters': clean_parameters (unused)
7870: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
7871: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 7872: sub handler {
1.43 albertel 7873: my $r=shift;
1.30 www 7874:
1.376 albertel 7875: &reset_caches();
7876:
1.414 droeschl 7877: &Apache::loncommon::content_type($r,'text/html');
7878: $r->send_http_header;
7879: return OK if $r->header_only;
7880:
1.193 albertel 7881: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 7882: ['action','state',
1.205 www 7883: 'pres_marker',
7884: 'pres_value',
1.206 www 7885: 'pres_type',
1.506 www 7886: 'filter','part',
1.390 www 7887: 'udom','uname','symb','serial','timebase']);
1.131 www 7888:
1.83 bowersj2 7889:
1.193 albertel 7890: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 7891: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 7892: text=>"Content and Problem Settings",
1.473 amueller 7893: faq=>10,
7894: bug=>'Instructor Interface',
1.442 droeschl 7895: help =>
7896: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 7897:
1.30 www 7898: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 7899: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 7900: my $exists = &check_for_course_info();
7901:
1.568 raeburn 7902: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 7903: #
7904: # Main switch on form.action and form.state, as appropriate
7905: #
7906: # Check first if coming from someone else headed directly for
7907: # the table mode
1.568 raeburn 7908: if (($parm_permission->{'set'}) &&
7909: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
7910: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
7911: &assessparms($r,$parm_permission);
1.193 albertel 7912: } elsif (! exists($env{'form.action'})) {
7913: &print_main_menu($r,$parm_permission);
1.568 raeburn 7914: } elsif (!$parm_permission->{$env{'form.action'}}) {
7915: &print_main_menu($r,$parm_permission);
1.414 droeschl 7916: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 7917: &overview($r,$parm_permission);
1.560 damieng 7918: } elsif ($env{'form.action'} eq 'addmetadata') {
7919: &addmetafield($r);
7920: } elsif ($env{'form.action'} eq 'ordermetadata') {
7921: &order_meta_fields($r);
1.414 droeschl 7922: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 7923: &setrestrictmeta($r);
1.414 droeschl 7924: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 7925: &newoverview($r,$parm_permission);
1.414 droeschl 7926: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 7927: &defaultsetter($r);
7928: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 7929: &assessparms($r,$parm_permission);
1.414 droeschl 7930: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 7931: &parm_change_log($r,$parm_permission);
1.414 droeschl 7932: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 7933: &clean_parameters($r);
1.414 droeschl 7934: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 7935: &date_shift_one($r);
1.414 droeschl 7936: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 7937: &date_shift_two($r);
1.446 bisitz 7938: }
1.43 albertel 7939: } else {
1.1 www 7940: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 7941: if ($exists) {
7942: $env{'user.error.msg'}=
7943: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
7944: } else {
7945: $env{'user.error.msg'}=
7946: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
7947: }
7948: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 7949: }
1.376 albertel 7950: &reset_caches();
7951:
1.43 albertel 7952: return OK;
1.1 www 7953: }
7954:
7955: 1;
7956: __END__
7957:
7958:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>