Annotation of loncom/interface/lonparmset.pm, revision 1.608
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.608 ! raeburn 4: # $Id: lonparmset.pm,v 1.607 2022/04/28 15:30:34 raeburn Exp $
1.40 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.59 matthew 28: ###################################################################
29: ###################################################################
30:
31: =pod
32:
33: =head1 NAME
34:
35: lonparmset - Handler to set parameters for assessments and course
36:
37: =head1 SYNOPSIS
38:
1.579 raeburn 39: lonparmset provides an interface to setting content parameters in a
40: course.
1.560 damieng 41:
42: It contains all the code for the "Content and Problem Settings" UI, except
43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
44: and lonblockingmenu.pm.
1.59 matthew 45:
46: =head1 DESCRIPTION
47:
48: This module sets coursewide and assessment parameters.
49:
50: =head1 INTERNAL SUBROUTINES
51:
1.416 jms 52: =over
1.59 matthew 53:
1.416 jms 54: =item parmval()
1.59 matthew 55:
56: Figure out a cascading parameter.
57:
1.71 albertel 58: Inputs: $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162 albertel 59: $id - a bighash Id number
1.71 albertel 60: $def - the resource's default value 'stupid emacs
61:
1.556 raeburn 62: Returns: A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71 albertel 63:
1.556 raeburn 64: 18 - General Course
65: 17 - Map or Folder level in course (recursive)
66: 16 - Map or Folder level in course (non-recursive)
67: 15 - resource default
68: 14 - map default
69: 13 - resource level in course
70: 12 - General for section
71: 11 - Map or Folder level for section (recursive)
72: 10 - Map or Folder level for section (non-recursive)
73: 9 - resource level in section
74: 8 - General for group
75: 7 - Map or Folder level for group (recursive)
76: 6 - Map or Folder level for group (non-recursive)
77: 5 - resource level in group
78: 4 - General for specific student
79: 3 - Map or Folder level for specific student (recursive)
80: 2 - Map or Folder level for specific student (non-recursive)
1.71 albertel 81: 1 - resource level for specific student
1.2 www 82:
1.416 jms 83: =item parmval_by_symb()
84:
85: =item reset_caches()
86:
87: =item cacheparmhash()
88:
89: =item parmhash()
90:
91: =item symbcache()
92:
93: =item preset_defaults()
94:
95: =item date_sanity_info()
96:
97: =item storeparm()
98:
99: Store a parameter by symb
100:
101: Takes
102: - symb
103: - name of parameter
104: - level
105: - new value
106: - new type
107: - username
108: - userdomain
109:
110: =item log_parmset()
111:
112: =item storeparm_by_symb_inner()
113:
114: =item valout()
115:
116: Format a value for output.
117:
118: Inputs: $value, $type, $editable
119:
120: Returns: $value, formatted for output. If $type indicates it is a date,
121: localtime($value) is returned.
122: $editable will return an icon to click on
123:
124: =item plink()
125:
126: Produces a link anchor.
127:
128: Inputs: $type,$dis,$value,$marker,$return,$call
129:
130: Returns: scalar with html code for a link which will envoke the
131: javascript function 'pjump'.
132:
133: =item page_js()
134:
135: =item startpage()
136:
137: =item print_row()
138:
139: =item print_td()
140:
1.580 raeburn 141: =item check_other_groups()
1.416 jms 142:
143: =item parm_control_group()
144:
145: =item extractResourceInformation() :
146:
1.512 foxr 147: extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416 jms 148:
1.542 raeburn 149: Input: See list below
150:
151: =over 4
1.416 jms 152:
1.512 foxr 153: =item * B<env{'user.name'}> : Current username
1.416 jms 154:
1.512 foxr 155: =item * B<env{'user.domain'}> : Domain of current user.
1.416 jms 156:
1.542 raeburn 157: =item * B<env{"request.course.fn"}> : Course
158:
159: =back
1.416 jms 160:
1.512 foxr 161: Outputs: See list below:
1.416 jms 162:
1.542 raeburn 163: =over 4
164:
1.512 foxr 165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416 jms 166:
1.512 foxr 167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416 jms 168:
1.512 foxr 169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416 jms 170:
1.512 foxr 171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416 jms 172:
1.512 foxr 173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
174:
175: =item * B<allmaps> (out) : hash, ???
1.416 jms 176:
177: =item * B<mapp> : ??
178:
179: =item * B<symbp> : hash, id->full sym?
180:
1.512 foxr 181: =item * B<maptitles>
182:
183: =item * B<uris>
1.416 jms 184:
1.512 foxr 185: =item * B<keyorder>
186:
187: =item * B<defkeytype>
1.416 jms 188:
1.542 raeburn 189: =back
190:
1.416 jms 191: =item isdateparm()
192:
193: =item parmmenu()
194:
195: =item partmenu()
196:
197: =item usermenu()
198:
199: =item displaymenu()
200:
201: =item mapmenu()
202:
203: =item levelmenu()
204:
205: =item sectionmenu()
206:
207: =item keysplit()
208:
209: =item keysinorder()
210:
211: =item keysinorder_bytype()
212:
213: =item keysindisplayorder()
214:
215: =item standardkeyorder()
216:
217: =item assessparms() :
218:
219: Show assessment data and parameters. This is a large routine that should
220: be simplified and shortened... someday.
221:
1.513 foxr 222: Inputs: $r - the Apache request object.
223:
1.416 jms 224: Returns: nothing
225:
226: Variables used (guessed by Jeremy):
227:
1.542 raeburn 228: =over
229:
1.416 jms 230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
231:
232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
233:
234: =item * B<@catmarker> contains list of all possible parameters including part #s
235:
236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
237:
238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
239: When storing information, store as part 0
240: When requesting information, request from full part
241:
1.542 raeburn 242: =back
243:
1.416 jms 244: =item tablestart()
245:
246: =item tableend()
247:
248: =item extractuser()
249:
250: =item parse_listdata_key()
251:
252: =item listdata()
253:
254: =item date_interval_selector()
255:
256: =item get_date_interval_from_form()
257:
258: =item default_selector()
259:
260: =item string_selector()
261:
262: =item dateshift()
263:
264: =item newoverview()
265:
266: =item secgroup_lister()
267:
268: =item overview()
269:
270: =item clean_parameters()
271:
272: =item date_shift_one()
273:
274: =item date_shift_two()
275:
276: =item parse_key()
277:
278: =item header()
279:
280: Output html header for page
281:
282: =item print_main_menu()
283:
284: =item output_row()
285:
286: Set portfolio metadata
287:
288: =item order_meta_fields()
289:
290: =item addmetafield()
291:
292: =item setrestrictmeta()
293:
294: =item get_added_meta_fieldnames()
295:
296: =item get_deleted_meta_fieldnames()
297:
298: =item defaultsetter()
299:
300: =item components()
301:
302: =item load_parameter_names()
303:
304: =item parm_change_log()
305:
306: =item handler() :
307:
1.450 raeburn 308: Main handler. Calls &assessparms subroutine.
1.416 jms 309:
310: =back
311:
1.59 matthew 312: =cut
313:
1.416 jms 314: ###################################################################
315: ###################################################################
316:
317: package Apache::lonparmset;
318:
319: use strict;
320: use Apache::lonnet;
321: use Apache::Constants qw(:common :http REDIRECT);
322: use Apache::lonhtmlcommon();
323: use Apache::loncommon;
324: use GDBM_File;
325: use Apache::lonhomework;
326: use Apache::lonxml;
327: use Apache::lonlocal;
328: use Apache::lonnavmaps;
329: use Apache::longroup;
330: use Apache::lonrss;
1.506 www 331: use HTML::Entities;
1.416 jms 332: use LONCAPA qw(:DEFAULT :match);
333:
334:
1.560 damieng 335: ##################################################
336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
337: ##################################################
338:
339: # Page header
1.561 damieng 340: #
341: # @param {Apache2::RequestRec} $r - Apache request object
342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
343: # @param {string} $crstype - course type ('Community' for community settings)
1.507 www 344: sub startSettingsScreen {
1.531 raeburn 345: my ($r,$mode,$crstype)=@_;
1.507 www 346:
1.531 raeburn 347: my $tabtext = &mt('Course Settings');
348: if ($crstype eq 'Community') {
349: $tabtext = &mt('Community Settings');
350: }
1.507 www 351: $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
352: $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b> '.
1.531 raeburn 353: $tabtext.
1.507 www 354: ' </b></a></li>');
355:
1.523 raeburn 356: $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507 www 357: &mt('Content and Problem Settings').'</b></a></li>');
358: $r->print("\n".'</ul>'."\n");
1.523 raeburn 359: $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507 www 360: }
361:
1.560 damieng 362: # Page footer
1.507 www 363: sub endSettingsScreen {
364: my ($r)=@_;
365: $r->print('</div></div></div>');
366: }
367:
368:
369:
1.560 damieng 370: ##################################################
1.563 damieng 371: # (mostly) TABLE MODE
1.560 damieng 372: # (parmval is also used for the log of parameter changes)
373: ##################################################
374:
1.566 damieng 375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561 damieng 376: #
377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 378: # @param {string} $id - resource id or map pc
1.561 damieng 379: # @param {string} $def - the resource's default value for this parameter
380: # @param {string} $uname - user name
381: # @param {string} $udom - user domain
382: # @param {string} $csec - section name
383: # @param {string} $cgroup - group name
384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
385: # @returns {Array}
1.2 www 386: sub parmval {
1.275 raeburn 387: my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
388: return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
389: $cgroup,$courseopt);
1.201 www 390: }
391:
1.561 damieng 392: # Returns an array containing
393: # - the most specific level that is defined for that parameter (integer)
394: # - an array with the level as index and the parameter value as value (when defined)
395: # (level 1 is the most specific and will have precedence)
396: #
397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 398: # @param {string} $symb - resource symb or map src
1.561 damieng 399: # @param {string} $def - the resource's default value for this parameter
400: # @param {string} $uname - user name
401: # @param {string} $udom - user domain
402: # @param {string} $csec - section name
403: # @param {string} $cgroup - group name
404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
405: # @returns {Array}
1.201 www 406: sub parmval_by_symb {
1.275 raeburn 407: my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200 www 408:
1.352 albertel 409: my $useropt;
410: if ($uname ne '' && $udom ne '') {
1.561 damieng 411: $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352 albertel 412: }
1.200 www 413:
1.8 www 414: my $result='';
1.44 albertel 415: my @outpar=();
1.2 www 416: # ----------------------------------------------------- Cascading lookup scheme
1.446 bisitz 417: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 418: $map = &Apache::lonnet::deversion($map);
1.561 damieng 419:
420: # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
421: # any change should be reflected there.
422:
1.201 www 423: my $symbparm=$symb.'.'.$what;
1.556 raeburn 424: my $recurseparm=$map.'___(rec).'.$what;
1.201 www 425: my $mapparm=$map.'___(all).'.$what;
1.10 www 426:
1.269 raeburn 427: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
428: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 429: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 430: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
431:
1.190 albertel 432: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
433: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 434: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 435: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
436:
437: my $courselevel=$env{'request.course.id'}.'.'.$what;
438: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 439: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 440: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2 www 441:
1.11 www 442:
1.182 albertel 443: # --------------------------------------------------------- first, check course
1.11 www 444:
1.561 damieng 445: # 18 - General Course
1.200 www 446: if (defined($$courseopt{$courselevel})) {
1.556 raeburn 447: $outpar[18]=$$courseopt{$courselevel};
448: $result=18;
449: }
450:
1.561 damieng 451: # 17 - Map or Folder level in course (recursive)
1.556 raeburn 452: if (defined($$courseopt{$courseleveli})) {
453: $outpar[17]=$$courseopt{$courseleveli};
454: $result=17;
1.43 albertel 455: }
1.11 www 456:
1.561 damieng 457: # 16 - Map or Folder level in course (non-recursive)
1.200 www 458: if (defined($$courseopt{$courselevelm})) {
1.556 raeburn 459: $outpar[16]=$$courseopt{$courselevelm};
460: $result=16;
1.43 albertel 461: }
1.11 www 462:
1.182 albertel 463: # ------------------------------------------------------- second, check default
464:
1.561 damieng 465: # 15 - resource default
1.556 raeburn 466: if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182 albertel 467:
468: # ------------------------------------------------------ third, check map parms
469:
1.556 raeburn 470:
1.561 damieng 471: # 14 - map default
1.376 albertel 472: my $thisparm=&parmhash($symbparm);
1.556 raeburn 473: if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182 albertel 474:
1.561 damieng 475: # 13 - resource level in course
1.200 www 476: if (defined($$courseopt{$courselevelr})) {
1.556 raeburn 477: $outpar[13]=$$courseopt{$courselevelr};
478: $result=13;
1.43 albertel 479: }
1.11 www 480:
1.182 albertel 481: # ------------------------------------------------------ fourth, back to course
1.352 albertel 482: if ($csec ne '') {
1.561 damieng 483: # 12 - General for section
1.200 www 484: if (defined($$courseopt{$seclevel})) {
1.556 raeburn 485: $outpar[12]=$$courseopt{$seclevel};
486: $result=12;
487: }
1.561 damieng 488: # 11 - Map or Folder level for section (recursive)
1.556 raeburn 489: if (defined($$courseopt{$secleveli})) {
490: $outpar[11]=$$courseopt{$secleveli};
491: $result=11;
492: }
1.561 damieng 493: # 10 - Map or Folder level for section (non-recursive)
1.200 www 494: if (defined($$courseopt{$seclevelm})) {
1.556 raeburn 495: $outpar[10]=$$courseopt{$seclevelm};
496: $result=10;
497: }
1.561 damieng 498: # 9 - resource level in section
1.200 www 499: if (defined($$courseopt{$seclevelr})) {
1.556 raeburn 500: $outpar[9]=$$courseopt{$seclevelr};
501: $result=9;
502: }
1.43 albertel 503: }
1.275 raeburn 504: # ------------------------------------------------------ fifth, check course group
1.352 albertel 505: if ($cgroup ne '') {
1.561 damieng 506: # 8 - General for group
1.269 raeburn 507: if (defined($$courseopt{$grplevel})) {
1.556 raeburn 508: $outpar[8]=$$courseopt{$grplevel};
509: $result=8;
510: }
1.561 damieng 511: # 7 - Map or Folder level for group (recursive)
1.556 raeburn 512: if (defined($$courseopt{$grpleveli})) {
513: $outpar[7]=$$courseopt{$grpleveli};
514: $result=7;
1.269 raeburn 515: }
1.561 damieng 516: # 6 - Map or Folder level for group (non-recursive)
1.269 raeburn 517: if (defined($$courseopt{$grplevelm})) {
1.556 raeburn 518: $outpar[6]=$$courseopt{$grplevelm};
519: $result=6;
1.269 raeburn 520: }
1.561 damieng 521: # 5 - resource level in group
1.269 raeburn 522: if (defined($$courseopt{$grplevelr})) {
1.556 raeburn 523: $outpar[5]=$$courseopt{$grplevelr};
524: $result=5;
1.269 raeburn 525: }
526: }
1.11 www 527:
1.556 raeburn 528: # ---------------------------------------------------------- sixth, check user
1.11 www 529:
1.352 albertel 530: if ($uname ne '') {
1.561 damieng 531: # 4 - General for specific student
532: if (defined($$useropt{$courselevel})) {
533: $outpar[4]=$$useropt{$courselevel};
534: $result=4;
535: }
1.556 raeburn 536:
1.561 damieng 537: # 3 - Map or Folder level for specific student (recursive)
538: if (defined($$useropt{$courseleveli})) {
539: $outpar[3]=$$useropt{$courseleveli};
540: $result=3;
541: }
1.473 amueller 542:
1.561 damieng 543: # 2 - Map or Folder level for specific student (non-recursive)
544: if (defined($$useropt{$courselevelm})) {
545: $outpar[2]=$$useropt{$courselevelm};
546: $result=2;
547: }
1.473 amueller 548:
1.561 damieng 549: # 1 - resource level for specific student
550: if (defined($$useropt{$courselevelr})) {
551: $outpar[1]=$$useropt{$courselevelr};
552: $result=1;
553: }
1.43 albertel 554: }
1.44 albertel 555: return ($result,@outpar);
1.2 www 556: }
557:
1.198 www 558:
559:
1.376 albertel 560: # --- Caches local to lonparmset
561:
1.446 bisitz 562:
1.561 damieng 563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376 albertel 564: sub reset_caches {
565: &resetparmhash();
566: &resetsymbcache();
567: &resetrulescache();
1.203 www 568: }
569:
1.561 damieng 570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376 albertel 572: {
1.561 damieng 573: my $parmhashid; # course identifier, to initialize the cache only once for a course
574: my %parmhash; # the parameter cache
575: # reset map parameter hash
1.376 albertel 576: sub resetparmhash {
1.560 damieng 577: undef($parmhashid);
578: undef(%parmhash);
1.376 albertel 579: }
1.446 bisitz 580:
1.561 damieng 581: # dump the _parms.db database into %parmhash
1.376 albertel 582: sub cacheparmhash {
1.560 damieng 583: if ($parmhashid eq $env{'request.course.fn'}) { return; }
584: my %parmhashfile;
585: if (tie(%parmhashfile,'GDBM_File',
586: $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
587: %parmhash=%parmhashfile;
588: untie(%parmhashfile);
589: $parmhashid=$env{'request.course.fn'};
590: }
1.201 www 591: }
1.446 bisitz 592:
1.561 damieng 593: # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376 albertel 594: sub parmhash {
1.560 damieng 595: my ($id) = @_;
596: &cacheparmhash();
597: return $parmhash{$id};
1.376 albertel 598: }
1.560 damieng 599: }
1.376 albertel 600:
1.566 damieng 601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446 bisitz 602: {
1.561 damieng 603: my $symbsid; # course identifier, to initialize the cache only once for a course
604: my %symbs; # hash id->symb
605: # reset the id->symb cache
1.376 albertel 606: sub resetsymbcache {
1.560 damieng 607: undef($symbsid);
608: undef(%symbs);
1.376 albertel 609: }
1.446 bisitz 610:
1.566 damieng 611: # returns the resource symb or map src corresponding to a resource id or map pc
612: # (using lonnavmaps and a cache)
1.376 albertel 613: sub symbcache {
1.560 damieng 614: my $id=shift;
615: if ($symbsid ne $env{'request.course.id'}) {
616: undef(%symbs);
617: }
618: if (!$symbs{$id}) {
619: my $navmap = Apache::lonnavmaps::navmap->new();
620: if ($id=~/\./) {
621: my $resource=$navmap->getById($id);
622: $symbs{$id}=$resource->symb();
623: } else {
624: my $resource=$navmap->getByMapPc($id);
625: $symbs{$id}=&Apache::lonnet::declutter($resource->src());
626: }
627: $symbsid=$env{'request.course.id'};
1.473 amueller 628: }
1.560 damieng 629: return $symbs{$id};
1.473 amueller 630: }
1.560 damieng 631: }
1.201 www 632:
1.561 damieng 633: # cache for parameter default actions (stored in parmdefactions.db)
1.446 bisitz 634: {
1.561 damieng 635: my $rulesid; # course identifier, to initialize the cache only once for a course
636: my %rules; # parameter default actions hash
1.376 albertel 637: sub resetrulescache {
1.560 damieng 638: undef($rulesid);
639: undef(%rules);
1.376 albertel 640: }
1.446 bisitz 641:
1.561 damieng 642: # returns the value for a given key in the parameter default action hash
1.376 albertel 643: sub rulescache {
1.560 damieng 644: my $id=shift;
645: if ($rulesid ne $env{'request.course.id'}
646: && !defined($rules{$id})) {
647: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
648: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
649: %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
650: $rulesid=$env{'request.course.id'};
651: }
652: return $rules{$id};
1.221 www 653: }
654: }
655:
1.416 jms 656:
1.561 damieng 657: # Returns the values of the parameter type default action
658: # "default value when manually setting".
659: # If none is defined, ('','','','','') is returned.
660: #
661: # @param {string} $type - parameter type
662: # @returns {Array<string>} - (hours, min, sec, value)
1.229 www 663: sub preset_defaults {
664: my $type=shift;
665: if (&rulescache($type.'_action') eq 'default') {
1.560 damieng 666: # yes, there is something
667: return (&rulescache($type.'_hours'),
668: &rulescache($type.'_min'),
669: &rulescache($type.'_sec'),
670: &rulescache($type.'_value'));
1.229 www 671: } else {
1.560 damieng 672: # nothing there or something else
673: return ('','','','','');
1.229 www 674: }
675: }
676:
1.416 jms 677:
1.561 damieng 678: # Checks that a date is after enrollment start date and before
679: # enrollment end date.
680: # Returns HTML with a warning if it is not, or the empty string otherwise.
681: # This is used by both overview and table modes.
682: #
683: # @param {integer} $checkdate - the date to check.
684: # @returns {string} - HTML possibly containing a localized warning message.
1.277 www 685: sub date_sanity_info {
686: my $checkdate=shift;
687: unless ($checkdate) { return ''; }
688: my $result='';
689: my $crsprefix='course.'.$env{'request.course.id'}.'.';
690: if ($env{$crsprefix.'default_enrollment_end_date'}) {
691: if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413 bisitz 692: $result.='<div class="LC_warning">'
693: .&mt('After course enrollment end!')
694: .'</div>';
1.277 www 695: }
696: }
697: if ($env{$crsprefix.'default_enrollment_start_date'}) {
698: if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413 bisitz 699: $result.='<div class="LC_warning">'
700: .&mt('Before course enrollment start!')
701: .'</div>';
1.277 www 702: }
703: }
1.413 bisitz 704: # Preparation for additional warnings about dates in the past/future.
705: # An improved, more context sensitive version is recommended,
706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
707: # if ($checkdate<time) {
708: # $result.='<div class="LC_info">'
709: # .'('.&mt('in the past').')'
710: # .'</div>';
711: # }
712: # if ($checkdate>time) {
713: # $result.='<div class="LC_info">'
714: # .'('.&mt('in the future').')'
715: # .'</div>';
716: # }
1.277 www 717: return $result;
718: }
1.561 damieng 719:
720:
721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186 www 722: #
1.566 damieng 723: # @param {string} $sresid - resource id or map pc
1.565 damieng 724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 725: # @param {integer} $snum - level
726: # @param {string} $nval - new value
727: # @param {string} $ntype - new type
728: # @param {string} $uname - username
729: # @param {string} $udom - userdomain
730: # @param {string} $csec - section name
731: # @param {string} $cgroup - group name
1.186 www 732: sub storeparm {
1.269 raeburn 733: my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275 raeburn 734: &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197 www 735: }
736:
1.561 damieng 737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
738:
739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
741: #
1.566 damieng 742: # @param {string} $symb - resource symb or map src
1.565 damieng 743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 744: # @param {integer} $snum - level
745: # @param {string} $nval - new value
746: # @param {string} $ntype - new type
747: # @param {string} $uname - username
748: # @param {string} $udom - userdomain
749: # @param {string} $csec - section name
750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
751: # @param {string} $cgroup - group name
1.197 www 752: sub storeparm_by_symb {
1.275 raeburn 753: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226 www 754: unless ($recflag) {
1.560 damieng 755: # first time call
756: %recstack=();
757: $recflag=1;
1.226 www 758: }
1.560 damieng 759: # store parameter
1.226 www 760: &storeparm_by_symb_inner
1.473 amueller 761: ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560 damieng 762: # don't do anything if parameter was reset
1.266 www 763: unless ($nval) { return; }
1.226 www 764: my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560 damieng 765: # remember that this was set
1.226 www 766: $recstack{$parm}=1;
1.560 damieng 767: # what does this trigger?
1.226 www 768: foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560 damieng 769: # don't backfire
770: unless ((!$triggered) || ($recstack{$triggered})) {
771: my $action=&rulescache($triggered.'_action');
772: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
773: # set triggered parameter on same level
774: my $newspnam=$prefix.$triggered;
775: my $newvalue='';
776: my $active=1;
777: if ($action=~/^when\_setting/) {
778: # are there restrictions?
779: if (&rulescache($triggered.'_triggervalue')=~/\w/) {
780: $active=0;
1.565 damieng 781: foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560 damieng 782: if (lc($possiblevalue) eq lc($nval)) { $active=1; }
783: }
784: }
785: $newvalue=&rulescache($triggered.'_value');
786: } else {
787: my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
788: if ($action=~/^later\_than/) {
789: $newvalue=$nval+$totalsecs;
790: } else {
791: $newvalue=$nval-$totalsecs;
792: }
793: }
794: if ($active) {
795: &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
796: $uname,$udom,$csec,$recflag,$cgroup);
797: }
798: }
1.226 www 799: }
800: return '';
801: }
802:
1.561 damieng 803: # Adds all given arguments to the course parameter log.
804: # @returns {string} - the answer to the lonnet query.
1.293 www 805: sub log_parmset {
1.525 raeburn 806: return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284 www 807: }
808:
1.561 damieng 809: # Store a parameter value and type by symb, without using the parameter default actions.
810: # Expire related sheets.
811: #
1.566 damieng 812: # @param {string} $symb - resource symb or map src
1.561 damieng 813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
814: # @param {integer} $snum - level
815: # @param {string} $nval - new value
816: # @param {string} $ntype - new type
817: # @param {string} $uname - username
818: # @param {string} $udom - userdomain
819: # @param {string} $csec - section name
820: # @param {string} $cgroup - group name
821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226 www 822: sub storeparm_by_symb_inner {
1.197 www 823: # ---------------------------------------------------------- Get symb, map, etc
1.269 raeburn 824: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197 www 825: # ---------------------------------------------------------- Construct prefixes
1.186 www 826: $spnam=~s/\_([^\_]+)$/\.$1/;
1.446 bisitz 827: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 828: $map = &Apache::lonnet::deversion($map);
829:
1.197 www 830: my $symbparm=$symb.'.'.$spnam;
1.556 raeburn 831: my $recurseparm=$map.'___(rec).'.$spnam;
1.197 www 832: my $mapparm=$map.'___(all).'.$spnam;
833:
1.269 raeburn 834: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
835: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 836: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 837: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
838:
1.190 albertel 839: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
840: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 841: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 842: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446 bisitz 843:
1.190 albertel 844: my $courselevel=$env{'request.course.id'}.'.'.$spnam;
845: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 846: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 847: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446 bisitz 848:
1.186 www 849: my $storeunder='';
1.578 raeburn 850: my $possreplace='';
1.556 raeburn 851: if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578 raeburn 852: if (($snum==17) || ($snum==3)) {
853: $storeunder=$courseleveli;
854: $possreplace=$courselevelm;
855: }
856: if (($snum==16) || ($snum==2)) {
857: $storeunder=$courselevelm;
858: $possreplace=$courseleveli;
859: }
1.556 raeburn 860: if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
861: if ($snum==12) { $storeunder=$seclevel; }
1.578 raeburn 862: if ($snum==11) {
863: $storeunder=$secleveli;
864: $possreplace=$seclevelm;
865: }
866: if ($snum==10) {
867: $storeunder=$seclevelm;
868: $possreplace=$secleveli;
869: }
1.556 raeburn 870: if ($snum==9) { $storeunder=$seclevelr; }
871: if ($snum==8) { $storeunder=$grplevel; }
1.578 raeburn 872: if ($snum==7) {
873: $storeunder=$grpleveli;
874: $possreplace=$grplevelm;
875: }
876: if ($snum==6) {
877: $storeunder=$grplevelm;
878: $possreplace=$grpleveli;
879: }
1.556 raeburn 880: if ($snum==5) { $storeunder=$grplevelr; }
1.269 raeburn 881:
1.446 bisitz 882:
1.186 www 883: my $delete;
884: if ($nval eq '') { $delete=1;}
885: my %storecontent = ($storeunder => $nval,
1.473 amueller 886: $storeunder.'.type' => $ntype);
1.186 www 887: my $reply='';
1.560 damieng 888:
1.556 raeburn 889: if ($snum>4) {
1.186 www 890: # ---------------------------------------------------------------- Store Course
891: #
1.560 damieng 892: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
893: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
894: # Expire sheets
895: &Apache::lonnet::expirespread('','','studentcalc');
896: if (($snum==13) || ($snum==9) || ($snum==5)) {
897: &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578 raeburn 898: } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560 damieng 899: &Apache::lonnet::expirespread('','','assesscalc',$map);
900: } else {
901: &Apache::lonnet::expirespread('','','assesscalc');
902: }
903: # Store parameter
904: if ($delete) {
905: $reply=&Apache::lonnet::del
906: ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
907: &log_parmset(\%storecontent,1);
908: } else {
909: $reply=&Apache::lonnet::cput
910: ('resourcedata',\%storecontent,$cdom,$cnum);
911: &log_parmset(\%storecontent);
1.578 raeburn 912: if ($possreplace) {
913: my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
914: if (ref($resdata) eq 'HASH') {
915: if (exists($resdata->{$possreplace})) {
916: if (&Apache::lonnet::del
917: ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
918: &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);
919: }
920: }
921: }
922: }
1.560 damieng 923: }
924: &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186 www 925: } else {
926: # ------------------------------------------------------------------ Store User
927: #
1.560 damieng 928: # Expire sheets
929: &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
930: if ($snum==1) {
931: &Apache::lonnet::expirespread
932: ($uname,$udom,'assesscalc',$symb);
1.578 raeburn 933: } elsif (($snum==2) || ($snum==3)) {
1.560 damieng 934: &Apache::lonnet::expirespread
935: ($uname,$udom,'assesscalc',$map);
936: } else {
937: &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
938: }
939: # Store parameter
940: if ($delete) {
941: $reply=&Apache::lonnet::del
942: ('resourcedata',[keys(%storecontent)],$udom,$uname);
943: &log_parmset(\%storecontent,1,$uname,$udom);
944: } else {
945: $reply=&Apache::lonnet::cput
946: ('resourcedata',\%storecontent,$udom,$uname);
947: &log_parmset(\%storecontent,0,$uname,$udom);
1.578 raeburn 948: if ($possreplace) {
949: my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
950: if (ref($resdata) eq 'HASH') {
951: if (exists($resdata->{$possreplace})) {
952: if (&Apache::lonnet::del
953: ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
954: &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
955: $uname,$udom);
956: }
957: }
958: }
959: }
1.560 damieng 960: }
961: &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186 www 962: }
1.446 bisitz 963:
1.186 www 964: if ($reply=~/^error\:(.*)/) {
1.560 damieng 965: return "<span class=\"LC_error\">Write Error: $1</span>";
1.186 www 966: }
967: return '';
968: }
969:
1.9 www 970:
1.561 damieng 971: # Returns HTML with the value of the given parameter,
972: # using a readable format for dates, and
973: # a warning if there is a problem with a date.
974: # Used by table mode.
975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
976: #
977: # @param {string} $value - the parameter value
978: # @param {string} $type - the parameter type
979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9 www 980: sub valout {
1.600 raeburn 981: my ($value,$type,$editable)=@_;
1.59 matthew 982: my $result = '';
983: # Values of zero are valid.
984: if (! $value && $value ne '0') {
1.528 bisitz 985: if ($editable) {
986: $result =
987: '<img src="/res/adm/pages/editmap.png"'
988: .' alt="'.&mt('Change').'"'
1.539 raeburn 989: .' title="'.&mt('Change').'" style="border:0;" />';
1.528 bisitz 990: } else {
991: $result=' ';
992: }
1.59 matthew 993: } else {
1.66 www 994: if ($type eq 'date_interval') {
1.559 raeburn 995: my ($totalsecs,$donesuffix) = split(/_/,$value,2);
996: my ($usesdone,$donebuttontext,$proctor,$secretkey);
997: if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
998: $donebuttontext = $1;
999: (undef,$proctor,$secretkey) = split(/_/,$2);
1000: $usesdone = 'done';
1001: } elsif ($donesuffix =~ /^done(|_.+)$/) {
1002: $donebuttontext = &mt('Done');
1003: ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
1004: }
1.554 raeburn 1005: my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413 bisitz 1006: my @timer;
1.66 www 1007: $year=$year-70;
1008: $mday--;
1009: if ($year) {
1.413 bisitz 1010: # $result.=&mt('[quant,_1,yr]',$year).' ';
1011: push(@timer,&mt('[quant,_1,yr]',$year));
1.66 www 1012: }
1013: if ($mon) {
1.413 bisitz 1014: # $result.=&mt('[quant,_1,mth]',$mon).' ';
1015: push(@timer,&mt('[quant,_1,mth]',$mon));
1.66 www 1016: }
1017: if ($mday) {
1.413 bisitz 1018: # $result.=&mt('[quant,_1,day]',$mday).' ';
1019: push(@timer,&mt('[quant,_1,day]',$mday));
1.66 www 1020: }
1021: if ($hour) {
1.413 bisitz 1022: # $result.=&mt('[quant,_1,hr]',$hour).' ';
1023: push(@timer,&mt('[quant,_1,hr]',$hour));
1.66 www 1024: }
1025: if ($min) {
1.413 bisitz 1026: # $result.=&mt('[quant,_1,min]',$min).' ';
1027: push(@timer,&mt('[quant,_1,min]',$min));
1.66 www 1028: }
1029: if ($sec) {
1.413 bisitz 1030: # $result.=&mt('[quant,_1,sec]',$sec).' ';
1031: push(@timer,&mt('[quant,_1,sec]',$sec));
1.66 www 1032: }
1.413 bisitz 1033: # $result=~s/\s+$//;
1034: if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
1035: push(@timer,&mt('[quant,_1,sec]',0));
1036: }
1037: $result.=join(", ",@timer);
1.559 raeburn 1038: if ($usesdone eq 'done') {
1.558 raeburn 1039: if ($secretkey) {
1.559 raeburn 1040: $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
1.558 raeburn 1041: } else {
1.559 raeburn 1042: $result .= ' + "'.$donebuttontext.'"';
1043: }
1.554 raeburn 1044: }
1.213 www 1045: } elsif (&isdateparm($type)) {
1.361 albertel 1046: $result = &Apache::lonlocal::locallocaltime($value).
1.560 damieng 1047: &date_sanity_info($value);
1.59 matthew 1048: } else {
1049: $result = $value;
1.517 www 1050: $result=~s/\,/\, /gs;
1.560 damieng 1051: $result = &HTML::Entities::encode($result,'"<>&');
1.59 matthew 1052: }
1053: }
1054: return $result;
1.9 www 1055: }
1056:
1.59 matthew 1057:
1.561 damieng 1058: # Returns HTML containing a link on a parameter value, for table mode.
1059: # The link uses the javascript function 'pjump'.
1060: #
1061: # @param {string} $type - parameter type
1062: # @param {string} $dis - dialog title for editing the parameter value and type
1063: # @param {string} $value - parameter value
1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588 raeburn 1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5 www 1069: sub plink {
1.588 raeburn 1070: my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23 www 1071: my $winvalue=$value;
1072: unless ($winvalue) {
1.592 raeburn 1073: if (&isdateparm($type) || (&is_specialstring($type))) {
1.190 albertel 1074: $winvalue=$env{'form.recent_'.$type};
1.591 raeburn 1075: } elsif ($type eq 'string_yesno') {
1076: if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
1077: $winvalue=$env{'form.recent_string'};
1078: }
1.23 www 1079: } else {
1.190 albertel 1080: $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23 www 1081: }
1082: }
1.229 www 1083: my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
1084: my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
1085: unless (defined($winvalue)) { $winvalue=$val; }
1.593 raeburn 1086: my $valout = &valout($value,$type,1);
1.429 raeburn 1087: my $unencmarker = $marker;
1.378 albertel 1088: foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588 raeburn 1089: \$hour, \$min, \$sec, \$extra) {
1.560 damieng 1090: $$item = &HTML::Entities::encode($$item,'"<>&');
1091: $$item =~ s/\'/\\\'/g;
1.378 albertel 1092: }
1.429 raeburn 1093: return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473 amueller 1094: '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588 raeburn 1095: .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578 raeburn 1096: $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
1097: &mt('recursive').'</td></tr>' : '').'</table>';
1098:
1.5 www 1099: }
1100:
1.561 damieng 1101: # Javascript for table mode.
1.280 albertel 1102: sub page_js {
1103:
1.81 www 1104: my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88 matthew 1105: my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280 albertel 1106:
1107: return(<<ENDJS);
1108: <script type="text/javascript">
1.454 bisitz 1109: // <![CDATA[
1.44 albertel 1110:
1.88 matthew 1111: $pjump_def
1.44 albertel 1112:
1113: function psub() {
1.591 raeburn 1114: var specstring = /^string_!(yesno|any)/i;
1.44 albertel 1115: if (document.parmform.pres_marker.value!='') {
1116: document.parmform.action+='#'+document.parmform.pres_marker.value;
1117: var typedef=new Array();
1118: typedef=document.parmform.pres_type.value.split('_');
1.562 damieng 1119: if (document.parmform.pres_type.value!='') {
1.589 raeburn 1120: if ((typedef[0]=='date') ||
1.591 raeburn 1121: (specstring.test(document.parmform.pres_type.value))) {
1.562 damieng 1122: eval('document.parmform.recent_'+
1123: document.parmform.pres_type.value+
1124: '.value=document.parmform.pres_value.value;');
1125: } else {
1126: eval('document.parmform.recent_'+typedef[0]+
1127: '.value=document.parmform.pres_value.value;');
1128: }
1.44 albertel 1129: }
1130: document.parmform.submit();
1131: } else {
1132: document.parmform.pres_value.value='';
1133: document.parmform.pres_marker.value='';
1134: }
1135: }
1136:
1.57 albertel 1137: function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
1138: var options = "width=" + w + ",height=" + h + ",";
1139: options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
1140: options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
1141: var newWin = window.open(url, wdwName, options);
1142: newWin.focus();
1143: }
1.523 raeburn 1144:
1.454 bisitz 1145: // ]]>
1.523 raeburn 1146:
1.44 albertel 1147: </script>
1.81 www 1148: $selscript
1.280 albertel 1149: ENDJS
1150:
1151: }
1.507 www 1152:
1.561 damieng 1153: # Javascript to show or hide the map selection (function showHide_courseContent),
1154: # for table and overview modes.
1.523 raeburn 1155: sub showhide_js {
1156: return <<"COURSECONTENTSCRIPT";
1157:
1158: function showHide_courseContent() {
1159: var parmlevValue=document.getElementById("parmlev").value;
1160: if (parmlevValue == 'general') {
1161: document.getElementById('mapmenu').style.display="none";
1162: } else {
1163: if ((parmlevValue == "full") || (parmlevValue == "map")) {
1164: document.getElementById('mapmenu').style.display ="";
1165: } else {
1166: document.getElementById('mapmenu').style.display="none";
1167: }
1168: }
1169: return;
1170: }
1171:
1172: COURSECONTENTSCRIPT
1173: }
1174:
1.561 damieng 1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549 raeburn 1176: sub toggleparmtextbox_js {
1177: return <<"ENDSCRIPT";
1178:
1179: if (!document.getElementsByClassName) {
1180: function getElementsByClassName(node, classname) {
1181: var a = [];
1182: var re = new RegExp('(^| )'+classname+'( |$)');
1183: var els = node.getElementsByTagName("*");
1184: for(var i=0,j=els.length; i<j; i++)
1185: if(re.test(els[i].className))a.push(els[i]);
1186: return a;
1187: }
1188: }
1189:
1190: function showHideLenient() {
1191: var lenients;
1192: var setRegExp = /^set_/;
1193: if (document.getElementsByClassName) {
1194: lenients = document.getElementsByClassName('LC_lenient_radio');
1195: } else {
1196: lenients = getElementsByClassName(document.body,'LC_lenient_radio');
1197: }
1198: if (lenients != 'undefined') {
1199: for (var i=0; i<lenients.length; i++) {
1200: if (lenients[i].checked) {
1201: if (lenients[i].value == 'weighted') {
1202: if (setRegExp.test(lenients[i].name)) {
1203: var identifier = lenients[i].name.replace(setRegExp,'');
1204: toggleParmTextbox(document.parmform,identifier);
1205: }
1206: }
1207: }
1208: }
1209: }
1210: return;
1211: }
1212:
1213: function toggleParmTextbox(form,key) {
1214: var divfortext = document.getElementById('LC_parmtext_'+key);
1215: if (divfortext) {
1216: var caller = form.elements['set_'+key];
1217: if (caller.length) {
1218: for (i=0; i<caller.length; i++) {
1219: if (caller[i].checked) {
1220: if (caller[i].value == 'weighted') {
1221: divfortext.style.display = 'inline';
1222: } else {
1223: divfortext.style.display = 'none';
1224: }
1225: }
1226: }
1227: }
1228: }
1229: return;
1230: }
1231:
1232: ENDSCRIPT
1233: }
1234:
1.561 damieng 1235: # Javascript function validateParms, for overview mode
1.549 raeburn 1236: sub validateparms_js {
1237: return <<'ENDSCRIPT';
1238:
1239: function validateParms() {
1240: var textRegExp = /^settext_/;
1241: var tailLenient = /\.lenient$/;
1242: var patternRelWeight = /^\-?[\d.]+$/;
1243: var patternLenientStd = /^(yes|no|default)$/;
1.597 raeburn 1244: var ipRegExp = /^setip/;
1.549 raeburn 1245: var ipallowRegExp = /^setipallow_/;
1246: var ipdenyRegExp = /^setipdeny_/;
1.597 raeburn 1247: var deeplinkRegExp = /^deeplink_/;
1.601 raeburn 1248: var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;
1249: var dlLinkProtectRegExp = /^deeplink_protect_/;
1250: var dlLtidRegExp = /^deeplink_ltid_/;
1251: var dlLticRegExp = /^deeplink_ltic_/;
1.597 raeburn 1252: var dlKeyRegExp = /^deeplink_key_/;
1253: var dlMenusRegExp = /^deeplink_menus_/;
1254: var dlCollsRegExp = /^deeplink_colls_/;
1.549 raeburn 1255: var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1256: if ((document.parmform.elements.length != 'undefined') && (document.parmform.elements.length) != 'null') {
1257: if (document.parmform.elements.length) {
1258: for (i=0; i<document.parmform.elements.length; i++) {
1259: var name=document.parmform.elements[i].name;
1.588 raeburn 1260: if (textRegExp.test(name)) {
1.549 raeburn 1261: var identifier = name.replace(textRegExp,'');
1262: if (tailLenient.test(identifier)) {
1263: if (document.parmform.elements['set_'+identifier].length) {
1264: for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
1265: if (document.parmform.elements['set_'+identifier][j].checked) {
1266: if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
1267: var relweight = document.parmform.elements[i].value;
1268: relweight = relweight.replace(/^\s+|\s+$/g,'');
1269: if (!patternRelWeight.test(relweight)) {
1270: relweight = '0.0';
1271: }
1272: if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
1273: document.parmform.elements['set_'+identifier][j].value = relweight;
1274: } else {
1275: document.parmform.elements['set_'+identifier][j].value += ','+relweight;
1276: }
1277: }
1278: break;
1279: }
1280: }
1281: }
1282: }
1.597 raeburn 1283: } else if (ipRegExp.test(name)) {
1284: if (ipallowRegExp.test(name)) {
1285: var identifier = name.replace(ipallowRegExp,'');
1286: var possallow = document.parmform.elements[i].value;
1287: possallow = possallow.replace(/^\s+|\s+$/g,'');
1288: if (patternIP.test(possallow)) {
1289: if (document.parmform.elements['set_'+identifier].value) {
1290: possallow = ','+possallow;
1291: }
1292: document.parmform.elements['set_'+identifier].value += possallow;
1293: }
1294: } else if (ipdenyRegExp.test(name)) {
1295: var identifier = name.replace(ipdenyRegExp,'');
1296: var possdeny = document.parmform.elements[i].value;
1297: possdeny = possdeny.replace(/^\s+|\s+$/g,'');
1298: if (patternIP.test(possdeny)) {
1299: possdeny = '!'+possdeny;
1300: if (document.parmform.elements['set_'+identifier].value) {
1301: possdeny = ','+possdeny;
1302: }
1303: document.parmform.elements['set_'+identifier].value += possdeny;
1.588 raeburn 1304: }
1305: }
1306: } else if (deeplinkRegExp.test(name)) {
1.597 raeburn 1307: if (dlListScopeRegExp.test(name)) {
1308: var identifier = name.replace(dlListScopeRegExp,'');
1309: var idx = document.parmform.elements[i].selectedIndex;
1310: if (idx > 0) {
1311: var possdeeplink = document.parmform.elements[i].options[idx].value
1312: possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
1313: if (document.parmform.elements['set_'+identifier].value) {
1314: possdeeplink = ','+possdeeplink;
1315: }
1316: document.parmform.elements['set_'+identifier].value += possdeeplink;
1317: }
1.601 raeburn 1318: } else if (dlLinkProtectRegExp.test(name)) {
1.597 raeburn 1319: if (document.parmform.elements[i].checked) {
1.601 raeburn 1320: var identifier = name.replace(dlLinkProtectRegExp,'');
1.597 raeburn 1321: var posslinkurl = document.parmform.elements[i].value;
1322: posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
1323: if (document.parmform.elements['set_'+identifier].value) {
1324: posslinkurl = ','+posslinkurl;
1325: }
1326: document.parmform.elements['set_'+identifier].value += posslinkurl;
1327: }
1.601 raeburn 1328: } else if (dlLtidRegExp.test(name)) {
1329: var identifier = name.replace(dlLtidRegExp,'');
1330: if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
1331: var possltid = document.parmform.elements[i].value;
1332: possltid = possltid.replace(/\D+/g,'');
1333: if (possltid.length) {
1.597 raeburn 1334: if (document.parmform.elements['set_'+identifier].value) {
1.601 raeburn 1335: possltid = ':'+possltid;
1.597 raeburn 1336: }
1.601 raeburn 1337: document.parmform.elements['set_'+identifier].value += possltid;
1.597 raeburn 1338: } else {
1339: document.parmform.elements['set_'+identifier].value = '';
1.601 raeburn 1340: alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597 raeburn 1341: return false;
1342: }
1343: }
1.601 raeburn 1344: } else if (dlLticRegExp.test(name)) {
1345: var identifier = name.replace(dlLticRegExp,'');
1346: if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
1347: var possltic = document.parmform.elements[i].value;
1348: possltic = possltic.replace(/\D+/g,'');
1349: if (possltic.length) {
1350: if (document.parmform.elements['set_'+identifier].value) {
1351: possltic = ':'+possltic;
1352: }
1353: document.parmform.elements['set_'+identifier].value += possltic;
1354: } else {
1355: document.parmform.elements['set_'+identifier].value = '';
1356: alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1357: return false;
1358: }
1359: }
1.597 raeburn 1360: } else if (dlKeyRegExp.test(name)) {
1361: var identifier = name.replace(dlKeyRegExp,'');
1.601 raeburn 1362: if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597 raeburn 1363: var posskey = document.parmform.elements[i].value;
1364: posskey = posskey.replace(/^\s+|\s+$/g,'');
1365: var origlength = posskey.length;
1366: posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
1367: var newlength = posskey.length;
1368: if (newlength > 0) {
1369: var change = origlength - newlength;
1370: if (change) {
1371: alert(change+' disallowed character(s) removed from deeplink key');
1372: }
1373: if (document.parmform.elements['set_'+identifier].value) {
1374: posskey = ':'+posskey;
1375: }
1376: document.parmform.elements['set_'+identifier].value += posskey;
1377: } else {
1378: document.parmform.elements['set_'+identifier].value = '';
1379: if (newlength < origlength) {
1380: alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
1381: } else {
1382: alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
1383: }
1384: return false;
1385: }
1386: }
1387: } else if (dlMenusRegExp.test(name)) {
1388: if (document.parmform.elements[i].checked) {
1389: var identifier = name.replace(dlMenusRegExp,'');
1390: var posslinkmenu = document.parmform.elements[i].value;
1391: posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
1392: if (posslinkmenu == 'std') {
1393: posslinkmenu = '0';
1394: if (document.parmform.elements['set_'+identifier].value) {
1395: posslinkmenu = ','+posslinkmenu;
1396: }
1397: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1398: }
1399: }
1400: } else if (dlCollsRegExp.test(name)) {
1401: var identifier = name.replace(dlCollsRegExp,'');
1402: if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
1403: var posslinkmenu = document.parmform.elements[i].value;
1404: if (document.parmform.elements['set_'+identifier].value) {
1405: posslinkmenu = ','+posslinkmenu;
1406: }
1407: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1408: }
1.549 raeburn 1409: }
1410: }
1411: }
1412: }
1413: }
1414: return true;
1415: }
1416:
1.597 raeburn 1417: function isRadioSet(name,expected) {
1418: var menuitems = document.getElementsByName(name);
1419: var radioLength = menuitems.length;
1420: result = false;
1421: if (radioLength > 1) {
1422: for (var j=0; j<radioLength; j++) {
1423: if (menuitems[j].checked) {
1424: if (menuitems[j].value == expected) {
1425: result = true;
1426: break;
1427: }
1428: }
1429: }
1430: }
1431: return result;
1432: }
1433:
1.549 raeburn 1434: ENDSCRIPT
1435: }
1436:
1.561 damieng 1437: # Javascript initialization, for overview mode
1.549 raeburn 1438: sub ipacc_boxes_js {
1439: my $remove = &mt('Remove');
1440: return <<"END";
1441: \$(document).ready(function() {
1442: var wrapper = \$(".LC_string_ipacc_wrap");
1443: var add_button = \$(".LC_add_ipacc_button");
1444: var ipaccRegExp = /^LC_string_ipacc_/;
1445:
1446: \$(add_button).click(function(e){
1447: e.preventDefault();
1448: var identifier = \$(this).closest("div").attr("id");
1449: identifier = identifier.replace(ipaccRegExp,'');
1.551 raeburn 1450: \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');
1.549 raeburn 1451: });
1452:
1453: \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
1454: e.preventDefault(); \$(this).closest("div").remove();
1455: })
1456: });
1457:
1458:
1459: END
1460: }
1461:
1.561 damieng 1462: # Javascript function toggleSecret, for overview mode.
1.558 raeburn 1463: sub done_proctor_js {
1464: return <<"END";
1465: function toggleSecret(form,radio,key) {
1466: var radios = form[radio+key];
1467: if (radios.length) {
1468: for (var i=0; i<radios.length; i++) {
1469: if (radios[i].checked) {
1470: if (radios[i].value == '_done_proctor') {
1471: if (document.getElementById('done_'+key+'_proctorkey')) {
1472: document.getElementById('done_'+key+'_proctorkey').type='text';
1473: }
1474: } else {
1475: if (document.getElementById('done_'+key+'_proctorkey')) {
1476: document.getElementById('done_'+key+'_proctorkey').type='hidden';
1477: document.getElementById('done_'+key+'_proctorkey').value='';
1478: }
1479: }
1480: }
1481: }
1482: }
1483: }
1484: END
1485:
1486: }
1487:
1.588 raeburn 1488: # Javascript function toggle
1489: sub deeplink_js {
1490: return <<"END";
1491: function toggleDeepLink(form,item,key) {
1492: var radios = form['deeplink_'+item+'_'+key];
1493: if (radios.length) {
1494: var keybox;
1495: if (document.getElementById('deeplink_key_'+item+'_'+key)) {
1496: keybox = document.getElementById('deeplink_key_'+item+'_'+key);
1497: }
1.601 raeburn 1498: var divoptions = new Array();
1499: if (item == 'protect') {
1500: divoptions = ['ltic','ltid'];
1.597 raeburn 1501: } else {
1502: if (item == 'menus') {
1.601 raeburn 1503: divoptions = ['colls'];
1.597 raeburn 1504: }
1505: }
1.601 raeburn 1506: var seldivs = new Array();
1507: if ((item == 'protect') || (item == 'menus')) {
1508: for (var i=0; i<divoptions.length; i++) {
1509: if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
1510: seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
1511: } else {
1512: seldivs[i] = '';
1513: }
1514: }
1.588 raeburn 1515: }
1516: for (var i=0; i<radios.length; i++) {
1517: if (radios[i].checked) {
1.601 raeburn 1518: if ((item == 'protect') || (item == 'menus')) {
1519: for (var j=0; j<seldivs.length; j++) {
1520: if (radios[i].value == divoptions[j]) {
1521: if (seldivs[j] != '') {
1522: seldivs[j].style.display = 'inline-block';
1523: }
1524: if (item == 'protect') {
1525: keybox.type = 'hidden';
1526: keybox.value = '';
1527: }
1528: } else {
1529: if (seldivs[j] != '') {
1530: seldivs[j].style.display = 'none';
1531: form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
1532: }
1533: }
1.597 raeburn 1534: }
1.601 raeburn 1535: if (item == 'protect') {
1.597 raeburn 1536: if (radios[i].value == 'key') {
1537: keybox.type = 'text';
1538: } else {
1539: keybox.type = 'hidden';
1540: }
1.588 raeburn 1541: }
1542: }
1543: }
1544: }
1545: }
1546: }
1547: END
1548:
1549: }
1550:
1.561 damieng 1551: # Prints HTML page start for table mode.
1552: # @param {Apache2::RequestRec} $r - the Apache request
1553: # @param {string} $psymb - resource symb
1554: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280 albertel 1555: sub startpage {
1.531 raeburn 1556: my ($r,$psymb,$crstype) = @_;
1.281 albertel 1557:
1.515 raeburn 1558: my %loaditems = (
1559: 'onload' => "group_or_section('cgroup')",
1560: );
1561: if (!$psymb) {
1.523 raeburn 1562: $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515 raeburn 1563: }
1.280 albertel 1564:
1.560 damieng 1565: if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
1566: (!$env{'form.dis'})) || ($env{'form.symb'})) {
1567: &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
1568: text=>"Problem Parameters"});
1.414 droeschl 1569: } else {
1.560 damieng 1570: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1571: text=>"Table Mode",
1572: help => 'Course_Setting_Parameters'});
1.414 droeschl 1573: }
1.523 raeburn 1574: my $js = &page_js().'
1575: <script type="text/javascript">
1576: // <![CDATA[
1577: '.
1578: &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
1579: // ]]>
1580: </script>
1581: ';
1.446 bisitz 1582: my $start_page =
1.523 raeburn 1583: &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
1584: {'add_entries' => \%loaditems,});
1.446 bisitz 1585: my $breadcrumbs =
1.473 amueller 1586: &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506 www 1587: my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
1588: my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507 www 1589: $r->print($start_page.$breadcrumbs);
1.531 raeburn 1590: &startSettingsScreen($r,'parmset',$crstype);
1.280 albertel 1591: $r->print(<<ENDHEAD);
1.193 albertel 1592: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419 bisitz 1593: <input type="hidden" value="" name="pres_value" />
1594: <input type="hidden" value="" name="pres_type" />
1595: <input type="hidden" value="" name="pres_marker" />
1596: <input type="hidden" value="1" name="prevvisit" />
1.506 www 1597: <input type="hidden" value="$escfilter" name="filter" />
1598: <input type="hidden" value="$escpart" name="part" />
1.44 albertel 1599: ENDHEAD
1600: }
1601:
1.209 www 1602:
1.561 damieng 1603: # Prints a row for table mode (except for the tr start).
1604: # Every time a hash reference is passed, a single entry is used, so print_row
1605: # could just use these values, but why make it simple when it can be complicated ?
1606: #
1607: # @param {Apache2::RequestRec} $r - the Apache request
1608: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
1609: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
1610: # @param {hash reference} $name - parameter key -> parameter name
1.566 damieng 1611: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561 damieng 1612: # @param {string} $rid - resource id
1613: # @param {hash reference} $default - parameter key -> resource parameter default value
1614: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
1615: # @param {hash reference} $display - parameter key -> full title for the parameter
1616: # @param {string} $defbgone - user level and other levels background color
1617: # @param {string} $defbgtwo - section level background color, also used for part number
1618: # @param {string} $defbgthree - group level background color
1619: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1620: # @param {string} $uname - user name
1621: # @param {string} $udom - user domain
1622: # @param {string} $csec - section name
1623: # @param {string} $cgroup - group name
1624: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1625: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582 raeburn 1626: # @param {boolean} $readonly - true if no editing allowed.
1627: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
1628: # @param {hash reference} - $maptitles - - hash map id or src -> map title
1629: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
1630: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set
1.44 albertel 1631: sub print_row {
1.201 www 1632: my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568 raeburn 1633: $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582 raeburn 1634: $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275 raeburn 1635: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1636: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1637: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582 raeburn 1638: my $numlinks = 0;
1.553 raeburn 1639:
1.560 damieng 1640: # get the values for the parameter in cascading order
1641: # empty levels will remain empty
1.44 albertel 1642: my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473 amueller 1643: $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1644: # get the type for the parameters
1645: # problem: these may not be set for all levels
1.66 www 1646: my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275 raeburn 1647: $$name{$which}.'.type',$rid,
1.473 amueller 1648: $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1649: # cascade down manually
1.182 albertel 1650: my $cascadetype=$$defaulttype{$which};
1.556 raeburn 1651: for (my $i=18;$i>0;$i--) {
1.560 damieng 1652: if ($typeoutpar[$i]) {
1.66 www 1653: $cascadetype=$typeoutpar[$i];
1.560 damieng 1654: } else {
1.66 www 1655: $typeoutpar[$i]=$cascadetype;
1656: }
1657: }
1.57 albertel 1658: my $parm=$$display{$which};
1659:
1.203 www 1660: if ($parmlev eq 'full') {
1.419 bisitz 1661: $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506 www 1662: .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433 raeburn 1663: } else {
1.57 albertel 1664: $parm=~s|\[.*\]\s||g;
1665: }
1.231 www 1666: my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
1667: if ($automatic) {
1.560 damieng 1668: $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231 www 1669: }
1.427 bisitz 1670: $r->print('<td>'.$parm.'</td>');
1.446 bisitz 1671:
1.44 albertel 1672: my $thismarker=$which;
1673: $thismarker=~s/^parameter\_//;
1674: my $mprefix=$rid.'&'.$thismarker.'&';
1.582 raeburn 1675: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1676: my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588 raeburn 1677: $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582 raeburn 1678: if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
1679: if ($result eq '') {
1680: $recurse_check = 1;
1681: } elsif (($uname ne '') && ($result > 3)) {
1682: $recurse_check = 1;
1683: } elsif (($cgroup ne '') && ($result > 7)) {
1684: $recurse_check = 1;
1685: } elsif (($csec ne '') && ($result > 11)) {
1686: $recurse_check = 1;
1687: } elsif ($result > 17) {
1688: $recurse_check = 1;
1689: }
1690: if ($recurse_check) {
1691: my $what = $$part{$which}.'.'.$$name{$which};
1692: my $prefix;
1693: if (($uname ne '') && ($udom ne '')) {
1694: my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1695: $prefix = $env{'request.course.id'};
1696: $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
1697: if (ref($recursinfo) eq 'ARRAY') {
1698: $effparm_rec = 1;
1699: $effparm_level = &mt('user: [_1]',$uname);
1700: }
1701: }
1702: if (($cgroup ne '') && (!$effparm_rec)) {
1703: $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
1704: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1705: if (ref($recursinfo) eq 'ARRAY') {
1706: $effparm_rec = 1;
1707: $effparm_level = &mt('group: [_1]',$cgroup);
1708: }
1709: }
1710: if (($csec ne '') && (!$effparm_rec)) {
1711: $prefix = $env{'request.course.id'}.'.['.$csec.']';
1712: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1713: if (ref($recursinfo) eq 'ARRAY') {
1714: $effparm_rec = 1;
1715: $effparm_level = &mt('section: [_1]',$csec);
1716: }
1717: }
1718: if (!$effparm_rec) {
1719: $prefix = $env{'request.course.id'};
1720: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1721: if (ref($recursinfo) eq 'ARRAY') {
1722: $effparm_rec = 1;
1723: }
1724: }
1725: }
1726: }
1727: if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
1728: $effparm_rec = 1;
1729: }
1730: if ((!$effparm_rec) &&
1731: (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) &&
1732: ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578 raeburn 1733: $effparm_rec = 1;
1734: }
1.588 raeburn 1735: if ($parmname eq 'deeplink') {
1.601 raeburn 1736: my ($domltistr,$crsltistr);
1.588 raeburn 1737: my %lti =
1738: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 1739: 'linkprot');
1.601 raeburn 1740: if (keys(%lti)) {
1741: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1.604 raeburn 1742: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
1743: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588 raeburn 1744: }
1745: }
1.601 raeburn 1746: $domltistr =~ s/,$//;
1747: if ($domltistr) {
1748: $extra = 'ltid_'.$domltistr;
1749: }
1.588 raeburn 1750: }
1.601 raeburn 1751: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
1752: if (keys(%courselti)) {
1753: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
1754: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
1755: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
1756: }
1757: }
1758: $crsltistr =~ s/,$//;
1759: if ($crsltistr) {
1760: if ($extra) {
1761: $extra .= '&';
1762: }
1763: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 1764: }
1765: }
1.597 raeburn 1766: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
1767: my @colls;
1768: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
1769: my ($num,$value) = split(/\%/,$item);
1770: if ($num =~ /^\d+$/) {
1771: push(@colls,$num);
1772: }
1773: }
1774: if (@colls) {
1775: if ($extra) {
1776: $extra .= '&';
1777: }
1778: $extra .= 'menus_'.join(',',@colls);
1779: }
1780: }
1.588 raeburn 1781: }
1.57 albertel 1782: if ($parmlev eq 'general') {
1783: if ($uname) {
1.588 raeburn 1784: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 1785: } elsif ($cgroup) {
1.588 raeburn 1786: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 1787: } elsif ($csec) {
1.588 raeburn 1788: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1789: } else {
1.588 raeburn 1790: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1791: }
1792: } elsif ($parmlev eq 'map') {
1793: if ($uname) {
1.588 raeburn 1794: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 1795: } elsif ($cgroup) {
1.588 raeburn 1796: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 1797: } elsif ($csec) {
1.588 raeburn 1798: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1799: } else {
1.588 raeburn 1800: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1801: }
1802: } else {
1.275 raeburn 1803: if ($uname) {
1804: if (@{$usersgroups} > 1) {
1.582 raeburn 1805: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 1806: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 1807: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 1808: if (($coursereply) && ($result > 4)) {
1.275 raeburn 1809: if (defined($controlgrp)) {
1810: if ($cgroup ne $controlgrp) {
1.582 raeburn 1811: $eff_groupparm = $grp_parm;
1812: undef($result);
1813: undef($effparm_rec);
1814: if ($grp_is_rec) {
1815: $effparm_rec = 1;
1816: }
1.275 raeburn 1817: }
1818: }
1819: }
1820: }
1821: }
1.57 albertel 1822:
1.588 raeburn 1823: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1824: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1825: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1826: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1827: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1828:
1829: if ($csec) {
1.588 raeburn 1830: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1831: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1832: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1833: }
1.269 raeburn 1834:
1835: if ($cgroup) {
1.588 raeburn 1836: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1837: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1838: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 1839: }
1.446 bisitz 1840:
1.548 raeburn 1841: if ($uname) {
1.275 raeburn 1842: if ($othergrp) {
1843: $r->print($othergrp);
1844: }
1.588 raeburn 1845: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1846: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1847: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1848: }
1.57 albertel 1849: } # end of $parmlev if/else
1.582 raeburn 1850: if (ref($recursinfo) eq 'ARRAY') {
1851: my $rectitle = &mt('recursive');
1852: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
1853: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
1854: $rectitle = &mt('set in: [_1]','"'.
1855: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
1856: "'$parmname','$$part{$which}'".');">'.
1857: $maptitles->{$recursinfo->[2]}.'</a>"');
1858:
1859: $numlinks ++;
1860: }
1861: }
1862: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 1863: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 1864: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1865: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
1866: $effparm_level.'</span></td>');
1867: } else {
1868: if ($result) {
1.593 raeburn 1869: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 1870: }
1871: if ($eff_groupparm) {
1872: $effective_parm = $eff_groupparm;
1873: }
1874: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1875: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
1876: '</span>':'').'</td>');
1877: }
1.203 www 1878: if ($parmlev eq 'full') {
1.136 albertel 1879: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 1880: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 1881: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 1882: if (!defined($sessionvaltype)) {
1883: $sessionvaltype=$$defaulttype{$which};
1884: }
1.419 bisitz 1885: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 1886: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 1887: '</font></td>');
1.136 albertel 1888: }
1.44 albertel 1889: $r->print('</tr>');
1.57 albertel 1890: $r->print("\n");
1.582 raeburn 1891: if (($numlinks) && (ref($reclinks))) {
1892: $$reclinks = $numlinks;
1893: }
1.44 albertel 1894: }
1.59 matthew 1895:
1.561 damieng 1896: # Prints a cell for table mode.
1897: #
1898: # FIXME: some of these parameter names are uninspired ($which and $value)
1899: # Also, it would make more sense to pass the display for this cell rather
1900: # than the full display hash and the key to use.
1901: #
1902: # @param {Apache2::RequestRec} $r - the Apache request
1903: # @param {integer} $which - level
1904: # @param {string} $defbg - cell background color
1905: # @param {integer} $result - the most specific level that is defined for that parameter
1906: # @param {array reference} $outpar - array level -> parameter value (when defined)
1907: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
1908: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
1909: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
1910: # @param {hash reference} $display - parameter key -> full title for the parameter
1911: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 1912: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 1913: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 1914: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 1915: sub print_td {
1.578 raeburn 1916: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 1917: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 1918: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
1919: $ineffect = 0;
1920: $currval = $$outpar[$which];
1921: $currtype = $$typeoutpar[$which];
1922: $currlevel = $which;
1923: if (($result) && ($result == $which)) {
1924: $ineffect = 1;
1925: }
1926: if ($ismaplevel) {
1927: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
1928: if (($result) && ($result == $which)) {
1929: $recursive = 1;
1930: }
1931: } elsif ($$outpar[$which+1] ne '') {
1932: $recursive = 1;
1933: $currlevel = $which+1;
1934: $currval = $$outpar[$currlevel];
1935: $currtype = $$typeoutpar[$currlevel];
1936: if (($result) && ($result == $currlevel)) {
1937: $ineffect = 1;
1938: }
1939: }
1940: }
1941: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 1942: ';" align="center">');
1.437 raeburn 1943: my $nolink = 0;
1.568 raeburn 1944: if ($readonly) {
1.552 raeburn 1945: $nolink = 1;
1.568 raeburn 1946: } else {
1.578 raeburn 1947: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 1948: $nolink = 1;
1.568 raeburn 1949: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 1950: $nolink = 1;
1.568 raeburn 1951: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
1952: if ($noeditgrp) {
1953: $nolink = 1;
1954: }
1955: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 1956: $nolink = 1;
1.568 raeburn 1957: } elsif ($mprefix =~ /examcode\&$/) {
1958: unless ($which == 2) {
1959: $nolink = 1;
1960: }
1.533 raeburn 1961: }
1.437 raeburn 1962: }
1963: if ($nolink) {
1.577 raeburn 1964: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 1965: $r->print(&valout($currval,$currtype));
1.114 www 1966: } else {
1.578 raeburn 1967: $r->print(&plink($currtype,
1968: $$display{$value},$currval,
1.588 raeburn 1969: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
1970: $extra));
1.114 www 1971: }
1972: $r->print('</td>'."\n");
1.57 albertel 1973: }
1974:
1.561 damieng 1975: # Returns HTML and other info for the cell added when a user is selected
1976: # and that user is in several groups. This is the cell with the title "Control by other group".
1977: #
1978: # @param {string} $what - parameter part.'.'.parameter name
1979: # @param {string} $rid - resource id
1980: # @param {string} $cgroup - group name
1981: # @param {string} $defbg - cell background color
1982: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1983: # @param {integer} $result - level
1984: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 1985: # @returns {Array} - array (parameter value for the other group, HTML for the cell, HTML with the value, name of the other group, true if recursive)
1.580 raeburn 1986: sub check_other_groups {
1987: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 1988: my $courseid = $env{'request.course.id'};
1989: my $output;
1990: my $symb = &symbcache($rid);
1991: my $symbparm=$symb.'.'.$what;
1992: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 1993: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 1994: my $mapparm=$map.'___(all).'.$what;
1995: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 1996: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
1997: $recurseparm,$what,$courseopt);
1.275 raeburn 1998: my $bgcolor = $defbg;
1.582 raeburn 1999: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2000: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2001: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2002: if ($result > 3) {
1.419 bisitz 2003: $bgcolor = '#AAFFAA';
1.275 raeburn 2004: }
1.593 raeburn 2005: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2006: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2007: if ($resultgroup && $resultlevel) {
1.582 raeburn 2008: if ($resultlevel eq 'recursive') {
2009: $resultlevel = 'map/folder';
2010: $grp_is_rec = 1;
2011: }
2012: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2013: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2014:
1.275 raeburn 2015: } else {
2016: $output .= ' ';
2017: }
2018: $output .= '</td>';
2019: } else {
1.419 bisitz 2020: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2021: }
1.582 raeburn 2022: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2023: }
2024:
1.561 damieng 2025: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2026: # Used by check_other_groups.
1.561 damieng 2027: #
2028: # @param {string} $courseid - the course id
2029: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2030: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2031: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2032: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2033: # @param {string} $what - parameter part.'.'.parameter name
2034: # @param {hash reference} $courseopt - course parameters hash
2035: # @returns {Array} - (parameter value for the group, course parameter hash key for the parameter, name of the group, level name, parameter type)
1.275 raeburn 2036: sub parm_control_group {
1.556 raeburn 2037: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2038: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2039: my $grpfound = 0;
1.556 raeburn 2040: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2041: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2042: foreach my $group (@{$usersgroups}) {
2043: if ($grpfound) { last; }
2044: for (my $i=0; $i<@levels; $i++) {
2045: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2046: if (defined($$courseopt{$item})) {
2047: $coursereply = $$courseopt{$item};
2048: $resultitem = $item;
2049: $resultgroup = $group;
2050: $resultlevel = $levelnames[$i];
2051: $resulttype = $$courseopt{$item.'.type'};
2052: $grpfound = 1;
2053: last;
2054: }
2055: }
2056: }
2057: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2058: }
1.201 www 2059:
1.63 bowersj2 2060:
2061:
1.562 damieng 2062: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2063: # All the parameters are references and are filled by the sub.
2064: #
1.566 damieng 2065: # @param {array reference} $ids - resource and map ids
2066: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2067: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2068: # @param {hash reference} $allparms - hash parameter name -> parameter title
2069: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2070: # @param {hash reference} $allmaps - hash map pc -> map src
2071: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2072: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2073: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2074: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2075: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2076: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608 ! raeburn 2077: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63 bowersj2 2078: sub extractResourceInformation {
2079: my $ids = shift;
2080: my $typep = shift;
2081: my $keyp = shift;
2082: my $allparms = shift;
2083: my $allparts = shift;
2084: my $allmaps = shift;
2085: my $mapp = shift;
2086: my $symbp = shift;
1.82 www 2087: my $maptitles=shift;
1.196 www 2088: my $uris=shift;
1.210 www 2089: my $keyorder=shift;
1.211 www 2090: my $defkeytype=shift;
1.603 raeburn 2091: my $pssymb=shift;
1.196 www 2092:
1.210 www 2093: my $keyordercnt=100;
1.63 bowersj2 2094:
1.196 www 2095: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 raeburn 2096: return unless(ref($navmap));
2097: my @allres;
2098: if ($pssymb ne '') {
2099: my $res = $navmap->getBySymb($pssymb);
2100: if (ref($res)) {
2101: @allres = ($res);
2102: }
2103: }
2104: if (!@allres) {
2105: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
2106: }
1.196 www 2107: foreach my $resource (@allres) {
1.480 amueller 2108: my $id=$resource->id();
1.196 www 2109: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2110: if ($mapid eq '0') { next; }
2111: $$ids[$#$ids+1]=$id;
2112: my $srcf=$resource->src();
2113: $srcf=~/\.(\w+)$/;
2114: $$typep{$id}=$1;
1.584 raeburn 2115: my $toolsymb;
2116: if ($srcf =~ /ext\.tool$/) {
2117: $toolsymb = $resource->symb();
2118: }
1.480 amueller 2119: $$keyp{$id}='';
1.196 www 2120: $$uris{$id}=$srcf;
1.512 foxr 2121:
1.584 raeburn 2122: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2123: next if ($key!~/^parameter_/);
1.363 albertel 2124:
1.209 www 2125: # Hidden parameters
1.584 raeburn 2126: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2127: #
2128: # allparms is a hash of parameter names
2129: #
1.584 raeburn 2130: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2131: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2132: my ($display,$parmdis);
2133: $display = &standard_parameter_names($name);
2134: if ($display eq '') {
1.584 raeburn 2135: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2136: $parmdis = $display;
2137: $parmdis =~ s/\s*\[Part.*$//g;
2138: } else {
2139: $parmdis = &mt($display);
2140: }
2141: $$allparms{$name}=$parmdis;
2142: if (ref($defkeytype)) {
2143: $$defkeytype{$name}=
1.584 raeburn 2144: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2145: }
2146: }
1.363 albertel 2147:
1.209 www 2148: #
2149: # allparts is a hash of all parts
2150: #
1.584 raeburn 2151: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2152: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2153: #
2154: # Remember all keys going with this resource
2155: #
1.480 amueller 2156: if ($$keyp{$id}) {
2157: $$keyp{$id}.=','.$key;
2158: } else {
2159: $$keyp{$id}=$key;
2160: }
1.210 www 2161: #
2162: # Put in order
1.446 bisitz 2163: #
1.480 amueller 2164: unless ($$keyorder{$key}) {
2165: $$keyorder{$key}=$keyordercnt;
2166: $keyordercnt++;
2167: }
1.473 amueller 2168: }
2169:
2170:
1.480 amueller 2171: if (!exists($$mapp{$mapid})) {
2172: $$mapp{$id}=
2173: &Apache::lonnet::declutter($resource->enclosing_map_src());
2174: $$mapp{$mapid}=$$mapp{$id};
2175: $$allmaps{$mapid}=$$mapp{$id};
2176: if ($mapid eq '1') {
1.532 raeburn 2177: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2178: } else {
2179: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2180: }
2181: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2182: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2183: # Lines 1038 and 1114 which use $symbp{$mapid}
2184: # are commented out in rev. 1.57
1.473 amueller 2185: } else {
1.480 amueller 2186: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2187: }
1.480 amueller 2188: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2189: }
2190: }
2191:
1.582 raeburn 2192: sub get_recursive {
2193: my ($recurseup,$resdata,$what,$prefix) = @_;
2194: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2195: foreach my $item (@{$recurseup}) {
2196: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2197: if (defined($resdata->{$norecursechk})) {
2198: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2199: my $type = $resdata->{$norecursechk.'.type'};
2200: return [$resdata->{$norecursechk},$type,$item];
2201: } else {
2202: last;
2203: }
2204: }
2205: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2206: if (defined($resdata->{$recursechk})) {
2207: my $type = $resdata->{$recursechk.'.type'};
2208: return [$resdata->{$recursechk},$type,$item];
2209: }
2210: }
2211: }
2212: return;
2213: }
2214:
1.208 www 2215:
1.562 damieng 2216: # Tells if a parameter type is a date.
2217: #
2218: # @param {string} type - parameter type
2219: # @returns{boolean} - true if it is a date
1.213 www 2220: sub isdateparm {
2221: my $type=shift;
2222: return (($type=~/^date/) && (!($type eq 'date_interval')));
2223: }
2224:
1.589 raeburn 2225: # Determine if parameter type is specialized string type (i.e.,
2226: # not just string or string_yesno.
2227:
2228: sub is_specialstring {
2229: my $type=shift;
1.603 raeburn 2230: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2231: }
2232:
1.562 damieng 2233: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2234: #
1.581 raeburn 2235: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2236: sub parmmenu {
1.581 raeburn 2237: my ($r)=@_;
1.208 www 2238: $r->print(<<ENDSCRIPT);
2239: <script type="text/javascript">
1.454 bisitz 2240: // <![CDATA[
1.208 www 2241: function checkall(value, checkName) {
1.453 schualex 2242:
2243: var li = "_li";
2244: var displayOverview = "";
2245:
2246: if (value == false) {
2247: displayOverview = "none"
2248: }
2249:
1.562 damieng 2250: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2251: ele = document.forms.parmform.elements[i];
2252: if (ele.name == checkName) {
2253: document.forms.parmform.elements[i].checked=value;
2254: }
2255: }
2256: }
1.210 www 2257:
2258: function checkthis(thisvalue, checkName) {
1.562 damieng 2259: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2260: ele = document.forms.parmform.elements[i];
2261: if (ele.name == checkName) {
1.562 damieng 2262: if (ele.value == thisvalue) {
2263: document.forms.parmform.elements[i].checked=true;
2264: }
1.210 www 2265: }
2266: }
2267: }
2268:
2269: function checkdates() {
1.562 damieng 2270: checkthis('duedate','pscat');
2271: checkthis('opendate','pscat');
2272: checkthis('answerdate','pscat');
1.218 www 2273: }
2274:
2275: function checkdisset() {
1.562 damieng 2276: checkthis('discussend','pscat');
2277: checkthis('discusshide','pscat');
2278: checkthis('discussvote','pscat');
1.218 www 2279: }
2280:
2281: function checkcontdates() {
1.562 damieng 2282: checkthis('contentopen','pscat');
2283: checkthis('contentclose','pscat');
1.218 www 2284: }
1.446 bisitz 2285:
1.210 www 2286: function checkvisi() {
1.562 damieng 2287: checkthis('hiddenresource','pscat');
2288: checkthis('encrypturl','pscat');
2289: checkthis('problemstatus','pscat');
2290: checkthis('contentopen','pscat');
2291: checkthis('opendate','pscat');
1.210 www 2292: }
2293:
2294: function checkparts() {
1.562 damieng 2295: checkthis('hiddenparts','pscat');
2296: checkthis('display','pscat');
2297: checkthis('ordered','pscat');
1.210 www 2298: }
2299:
2300: function checkstandard() {
2301: checkall(false,'pscat');
1.562 damieng 2302: checkdates();
2303: checkthis('weight','pscat');
2304: checkthis('maxtries','pscat');
2305: checkthis('type','pscat');
2306: checkthis('problemstatus','pscat');
1.210 www 2307: }
2308:
1.454 bisitz 2309: // ]]>
1.208 www 2310: </script>
2311: ENDSCRIPT
1.453 schualex 2312:
1.491 bisitz 2313: $r->print('<hr />');
1.581 raeburn 2314: &shortCuts($r);
1.491 bisitz 2315: $r->print('<hr />');
1.453 schualex 2316: }
1.562 damieng 2317:
2318: # Returns parameter categories.
2319: #
2320: # @returns {hash} - category name -> title in English
1.465 amueller 2321: sub categories {
2322: return ('time_settings' => 'Time Settings',
2323: 'grading' => 'Grading',
2324: 'tries' => 'Tries',
2325: 'problem_appearance' => 'Problem Appearance',
2326: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2327: 'hiding' => 'Hiding',
2328: 'high_level_randomization' => 'High Level Randomization',
2329: 'slots' => 'Slots',
2330: 'file_submission' => 'File Submission',
2331: 'misc' => 'Miscellaneous' );
2332: }
2333:
1.562 damieng 2334: # Returns the category for each parameter.
2335: #
2336: # @returns {hash} - parameter name -> category name
1.465 amueller 2337: sub lookUpTableParameter {
2338:
2339: return (
2340: 'opendate' => 'time_settings',
2341: 'duedate' => 'time_settings',
2342: 'answerdate' => 'time_settings',
2343: 'interval' => 'time_settings',
2344: 'contentopen' => 'time_settings',
2345: 'contentclose' => 'time_settings',
2346: 'discussend' => 'time_settings',
1.560 damieng 2347: 'printstartdate' => 'time_settings',
2348: 'printenddate' => 'time_settings',
1.465 amueller 2349: 'weight' => 'grading',
2350: 'handgrade' => 'grading',
2351: 'maxtries' => 'tries',
2352: 'hinttries' => 'tries',
1.503 raeburn 2353: 'randomizeontries' => 'tries',
1.465 amueller 2354: 'type' => 'problem_appearance',
2355: 'problemstatus' => 'problem_appearance',
2356: 'display' => 'problem_appearance',
2357: 'ordered' => 'problem_appearance',
2358: 'numbubbles' => 'problem_appearance',
2359: 'tol' => 'behaviour_of_input_fields',
2360: 'sig' => 'behaviour_of_input_fields',
2361: 'turnoffunit' => 'behaviour_of_input_fields',
2362: 'hiddenresource' => 'hiding',
2363: 'hiddenparts' => 'hiding',
2364: 'discusshide' => 'hiding',
2365: 'buttonshide' => 'hiding',
2366: 'turnoffeditor' => 'hiding',
2367: 'encrypturl' => 'hiding',
1.587 raeburn 2368: 'deeplink' => 'hiding',
1.465 amueller 2369: 'randomorder' => 'high_level_randomization',
2370: 'randompick' => 'high_level_randomization',
2371: 'available' => 'slots',
2372: 'useslots' => 'slots',
2373: 'availablestudent' => 'slots',
2374: 'uploadedfiletypes' => 'file_submission',
2375: 'maxfilesize' => 'file_submission',
2376: 'cssfile' => 'misc',
2377: 'mapalias' => 'misc',
2378: 'acc' => 'misc',
2379: 'maxcollaborators' => 'misc',
2380: 'scoreformat' => 'misc',
1.514 raeburn 2381: 'lenient' => 'grading',
1.519 raeburn 2382: 'retrypartial' => 'tries',
1.521 raeburn 2383: 'discussvote' => 'misc',
1.584 raeburn 2384: 'examcode' => 'high_level_randomization',
1.575 raeburn 2385: );
1.465 amueller 2386: }
2387:
1.562 damieng 2388: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2389: #
2390: # @param {string} $name - parameter name
2391: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2392: sub whatIsMyCategory {
2393: my $name = shift;
2394: my $catList = shift;
2395: my @list;
2396: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2397: my $cat = $lookUpList{$name};
2398: if (defined($cat)) {
2399: if (!defined($$catList{$cat})){
2400: push @list, ($name);
2401: $$catList{$cat} = \@list;
2402: } else {
2403: push @{${$catList}{$cat}}, ($name);
2404: }
2405: } else {
2406: if (!defined($$catList{'misc'})){
2407: push @list, ($name);
2408: $$catList{'misc'} = \@list;
2409: } else {
2410: push @{${$catList}{'misc'}}, ($name);
2411: }
2412: }
2413: }
2414:
1.562 damieng 2415: # Sorts parameter names based on appearance order.
2416: #
2417: # @param {array reference} name - array reference of parameter names
2418: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2419: # @returns {Array} - array of parameter names
1.465 amueller 2420: sub keysindisplayorderCategory {
2421: my ($name,$keyorder)=@_;
2422: return sort {
1.473 amueller 2423: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2424: } ( @{$name});
2425: }
2426:
1.562 damieng 2427: # Returns a hash category name -> order, starting at 1 (integer)
2428: #
2429: # @returns {hash}
1.467 amueller 2430: sub category_order {
2431: return (
2432: 'time_settings' => 1,
2433: 'grading' => 2,
2434: 'tries' => 3,
2435: 'problem_appearance' => 4,
2436: 'hiding' => 5,
2437: 'behaviour_of_input_fields' => 6,
2438: 'high_level_randomization' => 7,
2439: 'slots' => 8,
2440: 'file_submission' => 9,
2441: 'misc' => 10
2442: );
2443:
2444: }
1.453 schualex 2445:
1.562 damieng 2446: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2447: #
2448: # @param {Apache2::RequestRec} $r - the Apache request
2449: # @param {hash reference} $allparms - hash parameter name -> parameter title
2450: # @param {array reference} $pscat - list of selected parameter names
2451: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2452: sub parmboxes {
2453: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2454: my %categories = &categories();
1.467 amueller 2455: my %category_order = &category_order();
1.465 amueller 2456: my %categoryList = (
2457: 'time_settings' => [],
2458: 'grading' => [],
2459: 'tries' => [],
2460: 'problem_appearance' => [],
2461: 'behaviour_of_input_fields' => [],
2462: 'hiding' => [],
2463: 'high_level_randomization' => [],
2464: 'slots' => [],
2465: 'file_submission' => [],
2466: 'misc' => [],
1.489 bisitz 2467: );
1.510 www 2468:
1.548 raeburn 2469: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2470: &whatIsMyCategory($tempparameter, \%categoryList);
2471: }
1.453 schualex 2472: #part to print the parm-list
1.536 raeburn 2473: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2474: next if (@{$categoryList{$key}} == 0);
2475: next if ($key eq '');
2476: $r->print('<div class="LC_Box LC_400Box">'
2477: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2478: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2479: next if ($tempkey eq '');
1.536 raeburn 2480: $r->print('<span class="LC_nobreak">'
2481: .'<label><input type="checkbox" name="pscat" '
2482: .'value="'.$tempkey.'" ');
2483: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2484: $r->print( ' checked="checked"');
2485: }
2486: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465 amueller 2487: : $tempkey)
1.536 raeburn 2488: .'</label></span><br />'."\n");
1.465 amueller 2489: }
1.536 raeburn 2490: $r->print('</div>');
1.465 amueller 2491: }
1.536 raeburn 2492: $r->print("\n");
1.453 schualex 2493: }
1.562 damieng 2494:
2495: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2496: #
1.562 damieng 2497: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2498: sub shortCuts {
1.581 raeburn 2499: my ($r)=@_;
1.453 schualex 2500:
1.491 bisitz 2501: # Parameter Selection
2502: $r->print(
2503: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2504: .&Apache::lonhtmlcommon::add_item_funclist(
2505: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2506: .&Apache::lonhtmlcommon::add_item_funclist(
2507: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2508: .&Apache::lonhtmlcommon::add_item_funclist(
2509: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2510: .&Apache::lonhtmlcommon::end_funclist()
2511: );
2512:
2513: # Add Selection for...
2514: $r->print(
2515: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2516: .&Apache::lonhtmlcommon::add_item_funclist(
2517: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2518: .&Apache::lonhtmlcommon::add_item_funclist(
2519: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2520: .&Apache::lonhtmlcommon::add_item_funclist(
2521: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2522: .&Apache::lonhtmlcommon::add_item_funclist(
2523: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2524: .&Apache::lonhtmlcommon::add_item_funclist(
2525: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2526: .&Apache::lonhtmlcommon::end_funclist()
2527: );
1.208 www 2528: }
2529:
1.562 damieng 2530: # Prints HTML to select parts to view (except for the title).
2531: # Used by table and overview modes.
2532: #
2533: # @param {Apache2::RequestRec} $r - the Apache request
2534: # @param {hash reference} $allparts - hash parameter part -> part title
2535: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2536: sub partmenu {
1.446 bisitz 2537: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2538: my $selsize = 1+scalar(keys(%{$allparts}));
2539: if ($selsize > 8) {
2540: $selsize = 8;
2541: }
1.446 bisitz 2542:
1.523 raeburn 2543: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2544: $r->print('<option value="all"');
1.562 damieng 2545: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2546: $r->print('>'.&mt('All Parts').'</option>');
2547: my %temphash=();
2548: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2549: foreach my $tempkey (sort {
1.560 damieng 2550: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2551: } keys(%{$allparts})) {
2552: unless ($tempkey =~ /\./) {
2553: $r->print('<option value="'.$tempkey.'"');
2554: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2555: $r->print(' selected="selected"');
2556: }
2557: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2558: }
1.208 www 2559: }
1.446 bisitz 2560: $r->print('</select>');
1.209 www 2561: }
2562:
1.562 damieng 2563: # Prints HTML to select a user and/or a group.
2564: # Used by table mode.
2565: #
2566: # @param {Apache2::RequestRec} $r - the Apache request
2567: # @param {string} $uname - selected user name
2568: # @param {string} $id - selected Student/Employee ID
2569: # @param {string} $udom - selected user domain
2570: # @param {string} $csec - selected section name
2571: # @param {string} $cgroup - selected group name
2572: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2573: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2574: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2575: sub usermenu {
1.553 raeburn 2576: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2577: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2578: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2579: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2580: function setCourseadv(form,caller) {
2581: if (caller.value == 'st') {
2582: form.courseadv.value = 'none';
2583: } else {
2584: form.courseadv.value = '';
2585: }
2586: return;
2587: }
2588: ENDJS
1.412 bisitz 2589:
1.596 raeburn 2590: my (%chkroles,$stuonly,$courseadv);
2591: if ($env{'form.userroles'} eq 'any') {
2592: $chkroles{'any'} = ' checked="checked"';
2593: } else {
2594: $chkroles{'st'} = ' checked="checked"';
2595: $courseadv = 'none';
2596: }
2597: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2598: if ($crstype eq 'Community') {
2599: $stuonly = &mt('member only');
2600: } else {
2601: $stuonly = &mt('student only');
2602: }
2603: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2604: &mt("User's role").': '.
2605: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2606: $stuonly.'</label> '.
2607: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2608: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2609: my $sections='';
1.300 albertel 2610: my %sectionhash = &Apache::loncommon::get_sections();
2611:
1.269 raeburn 2612: my $groups;
1.553 raeburn 2613: my %grouphash;
2614: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2615: %grouphash = &Apache::longroup::coursegroups();
2616: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2617: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2618: }
1.299 albertel 2619:
1.412 bisitz 2620: my $g_s_header='';
2621: my $g_s_footer='';
1.446 bisitz 2622:
1.552 raeburn 2623: my $currsec = $env{'request.course.sec'};
2624: if ($currsec) {
2625: $sections=&mt('Section:').' '.$currsec;
2626: if (%grouphash) {
2627: $sections .= ';'.(' ' x2);
2628: }
2629: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2630: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2631: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2632: $sections .= qq| onchange="group_or_section('csec')" |;
2633: }
2634: $sections .= '>';
1.548 raeburn 2635: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2636: $sections.='<option value="'.$section.'" '.
2637: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2638: '</option>';
1.209 www 2639: }
2640: $sections.='</select>';
1.269 raeburn 2641: }
1.412 bisitz 2642:
1.552 raeburn 2643: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2644: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2645: $sections .= qq|
2646: <script type="text/javascript">
1.454 bisitz 2647: // <![CDATA[
1.269 raeburn 2648: function group_or_section(caller) {
2649: if (caller == "cgroup") {
2650: if (document.parmform.cgroup.selectedIndex != 0) {
2651: document.parmform.csec.selectedIndex = 0;
2652: }
2653: } else {
2654: if (document.parmform.csec.selectedIndex != 0) {
2655: document.parmform.cgroup.selectedIndex = 0;
2656: }
2657: }
2658: }
1.454 bisitz 2659: // ]]>
1.269 raeburn 2660: </script>
2661: |;
1.554 raeburn 2662: } else {
1.269 raeburn 2663: $sections .= qq|
2664: <script type="text/javascript">
1.454 bisitz 2665: // <![CDATA[
1.269 raeburn 2666: function group_or_section(caller) {
2667: return;
2668: }
1.454 bisitz 2669: // ]]>
1.269 raeburn 2670: </script>
2671: |;
1.446 bisitz 2672: }
1.299 albertel 2673:
2674: if (%grouphash) {
1.597 raeburn 2675: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2676: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2677: $groups .= qq| onchange="group_or_section('cgroup')" |;
2678: }
2679: $groups .= '>';
1.548 raeburn 2680: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2681: $groups.='<option value="'.$grp.'" ';
2682: if ($grp eq $cgroup) {
2683: unless ((defined($uname)) && ($grp eq '')) {
2684: $groups .= 'selected="selected" ';
2685: }
2686: } elsif (!defined($cgroup)) {
2687: if (@{$usersgroups} == 1) {
2688: if ($grp eq $$usersgroups[0]) {
2689: $groups .= 'selected="selected" ';
2690: }
2691: }
2692: }
2693: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2694: }
2695: $groups.='</select>';
2696: }
1.412 bisitz 2697:
1.445 neumanie 2698: if (%sectionhash || %grouphash) {
1.446 bisitz 2699: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2700: $r->print($sections.$groups);
1.448 bisitz 2701: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 2702: } else {
2703: $r->print($sections);
1.445 neumanie 2704: }
1.446 bisitz 2705:
2706: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 2707: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 2708: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
2709: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 2710: ,$chooseopt));
1.209 www 2711: }
2712:
1.562 damieng 2713: # Prints HTML to select parameters from a list of all parameters.
2714: # Uses parmmenu and parmboxes.
2715: # Used by table and overview modes.
1.468 amueller 2716: #
1.562 damieng 2717: # @param {Apache2::RequestRec} $r - the Apache request
2718: # @param {hash reference} $allparms - hash parameter name -> parameter title
2719: # @param {array reference} $pscat - list of selected parameter names
2720: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2721: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 2722: sub displaymenu {
1.581 raeburn 2723: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 2724:
1.445 neumanie 2725: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 2726: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
2727:
1.581 raeburn 2728: &parmmenu($r);
1.536 raeburn 2729: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 2730: &parmboxes($r,$allparms,$pscat,$keyorder);
2731: $r->print(&Apache::loncommon::end_scrollbox());
2732:
2733: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 2734: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 2735:
1.209 www 2736: }
2737:
1.562 damieng 2738: # Prints HTML to select a map.
2739: # Used by table mode and overview mode.
2740: #
2741: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 2742: # @param {hash reference} $allmaps - hash map pc -> map src
2743: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 2744: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 2745: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445 neumanie 2746: sub mapmenu {
1.499 raeburn 2747: my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468 amueller 2748: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 2749: my $navmap = Apache::lonnavmaps::navmap->new();
2750: my $tree=[];
2751: my $treeinfo={};
2752: if (defined($navmap)) {
1.499 raeburn 2753: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 2754: my $curRes;
2755: my $depth = 0;
1.468 amueller 2756: my %parent = ();
2757: my $startcount = 5;
2758: my $lastcontainer = $startcount;
2759: # preparing what is to show ...
1.461 neumanie 2760: while ($curRes = $it->next()) {
2761: if ($curRes == $it->BEGIN_MAP()) {
2762: $depth++;
1.468 amueller 2763: $parent{$depth}= $lastcontainer;
1.461 neumanie 2764: }
2765: if ($curRes == $it->END_MAP()) {
2766: $depth--;
1.468 amueller 2767: $lastcontainer = $parent{$depth};
1.461 neumanie 2768: }
2769: if (ref($curRes)) {
1.468 amueller 2770: my $symb = $curRes->symb();
2771: my $ressymb = $symb;
1.461 neumanie 2772: if (($curRes->is_sequence()) || ($curRes->is_page())) {
2773: my $type = 'sequence';
2774: if ($curRes->is_page()) {
2775: $type = 'page';
2776: }
2777: my $id= $curRes->id();
1.468 amueller 2778: my $srcf = $curRes->src();
2779: my $resource_name = &Apache::lonnet::gettitle($srcf);
2780: if(!exists($treeinfo->{$id})) {
2781: push(@$tree,$id);
1.473 amueller 2782: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 2783: $treeinfo->{$id} = {
1.461 neumanie 2784: depth => $depth,
2785: type => $type,
1.468 amueller 2786: name => $resource_name,
2787: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 2788: };
1.462 neumanie 2789: }
1.461 neumanie 2790: }
2791: }
2792: }
1.462 neumanie 2793: }
1.473 amueller 2794: # Show it ...
1.484 amueller 2795: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461 neumanie 2796: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
2797: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 2798: my $whitespace =
2799: '<img src="'
2800: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
2801: .'" alt="" />';
2802:
1.498 bisitz 2803: # Info about selectable folders/maps
2804: $r->print(
2805: '<div class="LC_info">'
1.508 www 2806: .&mt('You can only select maps and folders which have modifiable settings.')
2807: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 2808: .'</div>'
2809: );
2810:
1.536 raeburn 2811: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 2812: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 2813:
1.498 bisitz 2814: # Display row: "All Maps or Folders"
2815: $r->print(
1.523 raeburn 2816: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 2817: .'<td>'
2818: .'<label>'
2819: .'<input type="radio" name="pschp"'
1.497 bisitz 2820: );
2821: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 2822: $r->print(
2823: ' value="all" /> '.$icon.' '
2824: .&mt('All Maps or Folders')
2825: .'</label>'
2826: .'<hr /></td>'
2827: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2828: );
1.497 bisitz 2829:
1.532 raeburn 2830: # Display row: "Main Content"
1.468 amueller 2831: if (exists($$allmaps{1})) {
1.498 bisitz 2832: $r->print(
2833: &Apache::loncommon::start_data_table_row()
2834: .'<td>'
2835: .'<label>'
2836: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 2837: );
1.497 bisitz 2838: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 2839: $r->print(
2840: '/> '.$icon.' '
2841: .$$maptitles{1}
2842: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
2843: .'</label>'
2844: .'</td>'
2845: .&Apache::loncommon::end_data_table_row()
1.468 amueller 2846: );
2847: }
1.497 bisitz 2848:
2849: # Display rows for all course maps and folders
1.468 amueller 2850: foreach my $id (@{$tree}) {
2851: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 2852: # Indentation
1.468 amueller 2853: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 2854: my $indent;
2855: for (my $i = 0; $i < $depth; $i++) {
2856: $indent.= $whitespace;
2857: }
1.461 neumanie 2858: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 2859: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 2860: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
2861: }
1.468 amueller 2862: my $symb_name = $$symbp{$id};
2863: my ($front, $tail) = split (/___${resid}___/, $symb_name);
2864: $symb_name = $tail;
1.498 bisitz 2865: $r->print(
2866: &Apache::loncommon::start_data_table_row()
2867: .'<td>'
2868: .'<label>'
1.463 bisitz 2869: );
1.498 bisitz 2870: # Only offer radio button for folders/maps which can be parameterized
2871: if ($allmaps_inverted{$symb_name}) {
2872: $r->print(
2873: '<input type ="radio" name="pschp"'
2874: .' value="'.$allmaps_inverted{$symb_name}.'"'
2875: );
2876: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
2877: $r->print('/>');
2878: } else {
2879: $r->print($whitespace);
1.461 neumanie 2880: }
1.498 bisitz 2881: $r->print(
2882: $indent.$icon.' '
2883: .$treeinfo->{$id}->{name}
2884: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
2885: .'</label>'
2886: .'</td>'
2887: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2888: );
1.461 neumanie 2889: }
1.497 bisitz 2890:
1.523 raeburn 2891: $r->print(&Apache::loncommon::end_data_table().
2892: '<br style="line-height:2px;" />'.
2893: &Apache::loncommon::end_scrollbox());
1.209 www 2894: }
2895: }
2896:
1.563 damieng 2897: # Prints HTML to select the parameter level (resource, map/folder or course).
2898: # Used by table and overview modes.
2899: #
2900: # @param {Apache2::RequestRec} $r - the Apache request
2901: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
2902: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 2903: sub levelmenu {
1.446 bisitz 2904: my ($r,$alllevs,$parmlev)=@_;
2905:
1.548 raeburn 2906: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
2907: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 2908: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 2909: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
2910: $r->print('<option value="'.$$alllevs{$lev}.'"');
2911: if ($parmlev eq $$alllevs{$lev}) {
2912: $r->print(' selected="selected"');
2913: }
2914: $r->print('>'.&mt($lev).'</option>');
1.208 www 2915: }
1.446 bisitz 2916: $r->print("</select>");
1.208 www 2917: }
2918:
1.211 www 2919:
1.563 damieng 2920: # Returns HTML to select a section (with a select HTML element).
2921: # Used by overview mode.
2922: #
2923: # @param {array reference} $selectedsections - list of selected section ids
2924: # @returns {string}
1.211 www 2925: sub sectionmenu {
1.553 raeburn 2926: my ($selectedsections)=@_;
1.300 albertel 2927: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 2928: return '' if (!%sectionhash);
1.300 albertel 2929:
1.552 raeburn 2930: my (@possibles,$disabled);
2931: if ($env{'request.course.sec'} ne '') {
2932: @possibles = ($env{'request.course.sec'});
2933: $selectedsections = [$env{'request.course.sec'}];
2934: $disabled = ' disabled="disabled"';
2935: } else {
2936: @possibles = ('all',sort(keys(%sectionhash)));
2937: }
1.553 raeburn 2938: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 2939: foreach my $s (@possibles) {
1.553 raeburn 2940: $output .= ' <option value="'.$s.'"';
2941: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
2942: $output .= ' selected="selected"';
1.473 amueller 2943: }
1.553 raeburn 2944: $output .= '>'."$s</option>\n";
1.300 albertel 2945: }
1.553 raeburn 2946: $output .= "</select>\n";
2947: return $output;
1.269 raeburn 2948: }
2949:
1.563 damieng 2950: # Returns HTML to select a group (with a select HTML element).
2951: # Used by overview mode.
2952: #
2953: # @param {array reference} $selectedgroups - list of selected group names
2954: # @returns {string}
1.269 raeburn 2955: sub groupmenu {
1.553 raeburn 2956: my ($selectedgroups)=@_;
2957: my %grouphash;
2958: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2959: %grouphash = &Apache::longroup::coursegroups();
2960: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2961: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2962: }
2963: return '' if (!%grouphash);
1.299 albertel 2964:
1.553 raeburn 2965: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 2966: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 2967: $output .= ' <option value="'.$group.'"';
2968: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
2969: $output .= ' selected="selected"';
1.473 amueller 2970: }
1.553 raeburn 2971: $output .= '>'."$group</option>\n";
1.211 www 2972: }
1.553 raeburn 2973: $output .= "</select>\n";
2974: return $output;
1.211 www 2975: }
2976:
1.563 damieng 2977: # Returns an array with the given parameter split by comma.
2978: # Used by assessparms (table mode).
2979: #
2980: # @param {string} $keyp - the string to split
2981: # @returns {Array<string>}
1.210 www 2982: sub keysplit {
2983: my $keyp=shift;
2984: return (split(/\,/,$keyp));
2985: }
2986:
1.563 damieng 2987: # Returns the keys in $name, sorted using $keyorder.
2988: # Parameters are sorted by key, which means they are sorted by part first, then by name.
2989: # Used by assessparms (table mode) for resource level.
2990: #
2991: # @param {hash reference} $name - parameter key -> parameter name
2992: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2993: # @returns {Array<string>}
1.210 www 2994: sub keysinorder {
2995: my ($name,$keyorder)=@_;
2996: return sort {
1.560 damieng 2997: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 2998: } (keys(%{$name}));
1.210 www 2999: }
3000:
1.563 damieng 3001: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3002: # Used by assessparms (table mode) for map and general levels.
3003: #
3004: # @param {hash reference} $name - parameter key -> parameter name
3005: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3006: # @returns {Array<string>}
1.236 albertel 3007: sub keysinorder_bytype {
3008: my ($name,$keyorder)=@_;
3009: return sort {
1.563 damieng 3010: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3011: my $tb=(split('_',$b))[-1];
3012: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3013: return ($a cmp $b);
3014: }
3015: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3016: } (keys(%{$name}));
1.236 albertel 3017: }
3018:
1.563 damieng 3019: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3020: # Used by defaultsetter (parameter settings default actions).
3021: #
3022: # @param {hash reference} $name - hash parameter name -> parameter title
3023: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3024: # @returns {Array<string>}
1.211 www 3025: sub keysindisplayorder {
3026: my ($name,$keyorder)=@_;
3027: return sort {
1.560 damieng 3028: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3029: } (keys(%{$name}));
1.211 www 3030: }
3031:
1.563 damieng 3032: # Prints HTML with a choice to sort results by realm or student first.
3033: # Used by overview mode.
3034: #
3035: # @param {Apache2::RequestRec} $r - the Apache request
3036: # @param {string} $sortorder - realmstudent|studentrealm
1.608 ! raeburn 3037: # @param {string} $context - newoverview|overview
1.214 www 3038: sub sortmenu {
1.608 ! raeburn 3039: my ($r,$sortorder,$context)=@_;
! 3040: my %text;
! 3041: if ($context eq 'newoverview') {
! 3042: %text = &Apache::lonlocal::texthash (
! 3043: realmstudent => 'Sort by location in course first, then student (group/section)',
! 3044: studentrealm => 'Sort by student (group/section) first, then location in course',
! 3045: );
! 3046: } else {
! 3047: %text = &Apache::lonlocal::texthash (
! 3048: realmstudent => 'Sort by realm first, then student (group/section)',
! 3049: studentrealm => 'Sort by student (group/section) first, then realm',
! 3050: );
1.214 www 3051: }
1.608 ! raeburn 3052: my %sortchecked = (
! 3053: realmstudent => ' checked="checked"',
! 3054: studentrealm => '',
! 3055: );
1.214 www 3056: if ($sortorder eq 'studentrealm') {
1.608 ! raeburn 3057: $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
! 3058: $sortchecked{'realmstudent'} = '';
! 3059: }
! 3060: foreach my $sorttype ('realmstudent','studentrealm') {
! 3061: $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
! 3062: $text{$sorttype}.'</label>');
1.214 www 3063: }
3064: }
3065:
1.563 damieng 3066: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3067: #
3068: # @returns {hash}
1.211 www 3069: sub standardkeyorder {
3070: return ('parameter_0_opendate' => 1,
1.473 amueller 3071: 'parameter_0_duedate' => 2,
3072: 'parameter_0_answerdate' => 3,
3073: 'parameter_0_interval' => 4,
3074: 'parameter_0_weight' => 5,
3075: 'parameter_0_maxtries' => 6,
3076: 'parameter_0_hinttries' => 7,
3077: 'parameter_0_contentopen' => 8,
3078: 'parameter_0_contentclose' => 9,
3079: 'parameter_0_type' => 10,
3080: 'parameter_0_problemstatus' => 11,
3081: 'parameter_0_hiddenresource' => 12,
3082: 'parameter_0_hiddenparts' => 13,
3083: 'parameter_0_display' => 14,
3084: 'parameter_0_ordered' => 15,
3085: 'parameter_0_tol' => 16,
3086: 'parameter_0_sig' => 17,
3087: 'parameter_0_turnoffunit' => 18,
1.521 raeburn 3088: 'parameter_0_discussend' => 19,
3089: 'parameter_0_discusshide' => 20,
3090: 'parameter_0_discussvote' => 21,
1.560 damieng 3091: 'parameter_0_printstartdate' => 22,
3092: 'parameter_0_printenddate' => 23);
1.211 www 3093: }
3094:
1.59 matthew 3095:
1.560 damieng 3096: # Table mode UI.
1.563 damieng 3097: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3098: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3099: #
3100: # Parameters used from the request:
3101: # action - handler action (see handler), usermenu is checking for value 'settable'
3102: # cgroup - selected group
3103: # command - 'set': direct access to table mode for a resource
3104: # csec - selected section
3105: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3106: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3107: # id - student/employee ID
3108: # parmlev - selected level (full|map|general)
3109: # part - selected part (unused ?)
3110: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3111: # pres_type - &&&-separated parameter types
3112: # pres_value - &&&-separated parameter values
3113: # prevvisit - '1' if the user has submitted the form before
3114: # pscat (multiple values) - selected parameter names
1.566 damieng 3115: # pschp - selected map pc, or 'all'
1.563 damieng 3116: # psprt (multiple values) - list of selected parameter parts
3117: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3118: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3119: # symb - resource symb (when a single resource is selected)
3120: # udom - selected user domain
3121: # uname - selected user name
3122: # url - used only with command 'set', the resource url
3123: #
3124: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3125: # @param $parm_permission - ref to hash of permissions
3126: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3127: sub assessparms {
1.1 www 3128:
1.568 raeburn 3129: my ($r,$parm_permission) = @_;
1.201 www 3130:
1.512 foxr 3131:
3132: # -------------------------------------------------------- Variable declaration
1.566 damieng 3133: my @ids=(); # resource and map ids
3134: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3135: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3136: my %typep=(); # hash resource/map id -> resource type (file extension)
3137: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3138: my %uris=(); # hash resource/map id -> resource src
3139: my %maptitles=(); # hash map pc or src -> map title
3140: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3141: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3142: my %alllevs=(); # hash English level title -> value
3143:
3144: my $uname; # selected user name
3145: my $udom; # selected user domain
3146: my $uhome; # server with the user's files, or 'no_host'
3147: my $csec; # selected section name
3148: my $cgroup; # selected group name
3149: my @usersgroups = (); # list of the user groups
1.582 raeburn 3150: my $numreclinks = 0;
1.446 bisitz 3151:
1.190 albertel 3152: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3153:
1.57 albertel 3154: $alllevs{'Resource Level'}='full';
1.215 www 3155: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3156: $alllevs{'Course Level'}='general';
3157:
1.563 damieng 3158: my %allparms; # hash parameter name -> parameter title
3159: my %allparts; # hash parameter part -> part title
1.512 foxr 3160: # ------------------------------------------------------------------------------
3161:
1.210 www 3162: #
3163: # Order in which these parameters will be displayed
3164: #
1.211 www 3165: my %keyorder=&standardkeyorder();
3166:
1.512 foxr 3167: # @ids=();
3168: # %symbp=(); # These seem defined above already.
3169: # %typep=();
1.43 albertel 3170:
3171: my $message='';
3172:
1.190 albertel 3173: $csec=$env{'form.csec'};
1.552 raeburn 3174: if ($env{'request.course.sec'} ne '') {
3175: $csec = $env{'request.course.sec'};
3176: }
3177:
1.553 raeburn 3178: # Check group privs.
1.269 raeburn 3179: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3180: my $noeditgrp;
3181: if ($cgroup ne '') {
3182: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3183: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3184: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3185: $noeditgrp = 1;
3186: }
3187: }
3188: }
1.188 www 3189:
1.190 albertel 3190: if ($udom=$env{'form.udom'}) {
3191: } elsif ($udom=$env{'request.role.domain'}) {
3192: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3193: } else {
1.473 amueller 3194: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3195: }
1.468 amueller 3196:
1.43 albertel 3197:
1.134 albertel 3198: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3199: my $pschp=$env{'form.pschp'};
1.506 www 3200:
3201:
1.134 albertel 3202: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3203: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3204: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3205:
1.43 albertel 3206: my $pssymb='';
1.57 albertel 3207: my $parmlev='';
1.446 bisitz 3208:
1.190 albertel 3209: unless ($env{'form.parmlev'}) {
1.57 albertel 3210: $parmlev = 'map';
3211: } else {
1.190 albertel 3212: $parmlev = $env{'form.parmlev'};
1.57 albertel 3213: }
1.26 www 3214:
1.29 www 3215: # ----------------------------------------------- Was this started from grades?
3216:
1.560 damieng 3217: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3218: (!$env{'form.dis'})) {
1.473 amueller 3219: my $url=$env{'form.url'};
3220: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3221: $pssymb=&Apache::lonnet::symbread($url);
3222: if (!@pscat) { @pscat=('all'); }
3223: $pschp='';
1.57 albertel 3224: $parmlev = 'full';
1.190 albertel 3225: } elsif ($env{'form.symb'}) {
1.473 amueller 3226: $pssymb=$env{'form.symb'};
3227: if (!@pscat) { @pscat=('all'); }
3228: $pschp='';
1.57 albertel 3229: $parmlev = 'full';
1.43 albertel 3230: } else {
1.473 amueller 3231: $env{'form.url'}='';
1.43 albertel 3232: }
3233:
1.190 albertel 3234: my $id=$env{'form.id'};
1.43 albertel 3235: if (($id) && ($udom)) {
1.555 raeburn 3236: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3237: if ($uname) {
3238: $id='';
3239: } else {
3240: $message=
1.540 bisitz 3241: '<p class="LC_warning">'.
3242: &mt('Unknown ID [_1] at domain [_2]',
3243: "'".$id."'","'".$udom."'").
3244: '</p>';
1.473 amueller 3245: }
1.43 albertel 3246: } else {
1.473 amueller 3247: $uname=$env{'form.uname'};
1.43 albertel 3248: }
3249: unless ($udom) { $uname=''; }
3250: $uhome='';
3251: if ($uname) {
1.473 amueller 3252: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3253: if ($uhome eq 'no_host') {
1.473 amueller 3254: $message=
1.540 bisitz 3255: '<p class="LC_warning">'.
3256: &mt('Unknown user [_1] at domain [_2]',
3257: "'".$uname."'","'".$udom."'").
3258: '</p>';
1.473 amueller 3259: $uname='';
1.12 www 3260: } else {
1.473 amueller 3261: $csec=&Apache::lonnet::getsection($udom,$uname,
3262: $env{'request.course.id'});
3263: if ($csec eq '-1') {
1.596 raeburn 3264: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3265: if ($env{'form.userroles'} eq 'any') {
3266: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3267: $csec = $env{'request.course.sec'};
3268: $message = '<span class="LC_info">';
3269: if ($crstype eq 'Community') {
3270: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3271: $uname,$udom);
3272: } else {
3273: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3274: $uname,$udom);
3275: }
3276: $message .= '</span>';
3277: } else {
3278: my @possroles = ('in','ep','ta','cr');
3279: if ($crstype eq 'Community') {
3280: unshift(@possroles,'co');
3281: } else {
3282: unshift(@possroles,'cc');
3283: }
3284: my %not_student_roles =
3285: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3286: \@possroles,[$udom],1,1);
3287: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3288: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3289: my %sections_by_role;
3290: foreach my $role (keys(%not_student_roles)) {
3291: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3292: my ($rolename,$sec) = ($1,$2);
3293: if ($rolename =~ m{^cr/}) {
3294: $rolename = 'cr';
3295: }
3296: push(@{$sections_by_role{$rolename}},$sec);
3297: }
3298: }
3299: my $numroles = scalar(keys(%sections_by_role));
3300: if ($numroles) {
3301: foreach my $role (@possroles) {
3302: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3303: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3304: $csec = $secs[0];
3305: last;
3306: }
3307: }
3308: }
3309: if ($csec eq '-1') {
3310: $message = '<span class="LC_warning">';
3311: if ($crstype eq 'Community') {
3312: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3313: $uname,$udom);
3314: } else {
3315: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3316: $uname,$udom);
3317: }
3318: $message .= '</span>';
3319: $uname='';
3320: if ($env{'request.course.sec'} ne '') {
3321: $csec=$env{'request.course.sec'};
3322: } else {
3323: $csec=$env{'form.csec'};
3324: }
3325: $cgroup=$env{'form.cgroup'};
3326: } else {
3327: $message = '<span class="LC_info">';
3328: if ($crstype eq 'Community') {
3329: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3330: $uname,$udom);
3331: } else {
3332: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3333: $uname,$udom);
3334: }
3335: $message .= '</span>';
3336: }
3337: }
1.594 raeburn 3338: } else {
1.596 raeburn 3339: $message = '<span class="LC_warning">';
3340: if ($crstype eq 'Community') {
3341: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3342: $uname,$udom);
3343: } else {
3344: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3345: $uname,$udom);
3346: }
3347: $message .= '</span>';
3348: $uname='';
3349: if ($env{'request.course.sec'} ne '') {
3350: $csec=$env{'request.course.sec'};
3351: } else {
3352: $csec=$env{'form.csec'};
3353: }
3354: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3355: }
3356: } elsif ($env{'request.course.sec'} ne '') {
3357: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3358: $message='<span class="LC_warning">'.
1.594 raeburn 3359: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3360: $uname,$udom,$env{'request.course.sec'}).
3361: '</span>';
3362: $uname='';
3363: $csec=$env{'request.course.sec'};
3364: }
1.269 raeburn 3365: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3366: }
3367: if ($uname ne '') {
1.473 amueller 3368: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3369: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3370: $message .= "\n<p>\n".&mt('Full Name').': '
3371: .$name{'firstname'}.' '.$name{'middlename'}.' '
3372: .$name{'lastname'}.' '.$name{'generation'}
3373: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3374: @usersgroups = &Apache::lonnet::get_users_groups(
3375: $udom,$uname,$env{'request.course.id'});
3376: if (@usersgroups > 0) {
3377: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3378: $cgroup = $usersgroups[0];
3379: }
3380: } else {
3381: $cgroup = '';
1.297 raeburn 3382: }
1.269 raeburn 3383: }
1.12 www 3384: }
1.43 albertel 3385: }
1.2 www 3386:
1.43 albertel 3387: unless ($csec) { $csec=''; }
1.269 raeburn 3388: unless ($cgroup) { $cgroup=''; }
1.12 www 3389:
1.14 www 3390: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3391: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3392: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 3393: \%keyorder,undef,$pssymb);
1.63 bowersj2 3394:
1.582 raeburn 3395: %allmaps_inverted = reverse(%allmaps);
3396:
1.57 albertel 3397: $mapp{'0.0'} = '';
3398: $symbp{'0.0'} = '';
1.99 albertel 3399:
1.14 www 3400: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3401: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3402: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3403: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3404: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3405: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3406: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3407: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3408: my ($got_chostname,$chostname,$cmajor,$cminor);
3409: my $totalstored = 0;
1.605 raeburn 3410: my $totalskippeduser = 0;
1.546 raeburn 3411: my $now = time;
1.473 amueller 3412: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3413: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3414: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3415: next if ($csec ne $env{'request.course.sec'});
3416: }
1.556 raeburn 3417: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3418: next if ($noeditgrp);
1.605 raeburn 3419: } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
3420: if ($uname eq '') {
3421: $totalskippeduser ++;
3422: next;
3423: }
1.557 raeburn 3424: }
3425: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3426: $namematch = 'maplevelrecurse';
3427: }
1.556 raeburn 3428: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3429: my (@ok_slots,@fail_slots,@del_slots);
3430: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3431: my ($level,@all) =
3432: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3433: $csec,$cgroup,$courseopt);
3434: foreach my $slot_name (split(/:/,$values[$i])) {
3435: next if ($slot_name eq '');
3436: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3437: push(@ok_slots,$slot_name);
3438:
3439: } else {
3440: push(@fail_slots,$slot_name);
3441: }
3442: }
3443: if (@ok_slots) {
3444: $values[$i] = join(':',@ok_slots);
3445: } else {
3446: $values[$i] = '';
3447: }
3448: if ($all[$level] ne '') {
3449: my @existing = split(/:/,$all[$level]);
3450: foreach my $slot_name (@existing) {
3451: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3452: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3453: push(@del_slots,$slot_name);
3454: }
3455: }
3456: }
3457: }
1.554 raeburn 3458: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3459: $name = $1;
1.533 raeburn 3460: my $val = $values[$i];
1.549 raeburn 3461: my $valmatch = '';
1.533 raeburn 3462: if ($name eq 'examcode') {
1.544 raeburn 3463: if (&Apache::lonnet::validCODE($values[$i])) {
3464: $val = 'valid';
3465: }
1.546 raeburn 3466: } elsif ($name eq 'printstartdate') {
3467: if ($val =~ /^\d+$/) {
3468: if ($val > $now) {
3469: $val = 'future';
3470: }
3471: }
3472: } elsif ($name eq 'printenddate') {
3473: if ($val =~ /^\d+$/) {
3474: if ($val < $now) {
3475: $val = 'past';
3476: }
3477: }
1.549 raeburn 3478: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3479: my $stringtype = &get_stringtype($name);
3480: my $stringmatch = &standard_string_matches($stringtype);
3481: if (ref($stringmatch) eq 'ARRAY') {
3482: foreach my $item (@{$stringmatch}) {
3483: if (ref($item) eq 'ARRAY') {
3484: my ($regexpname,$pattern) = @{$item};
3485: if ($pattern ne '') {
3486: if ($val =~ /$pattern/) {
3487: $valmatch = $regexpname;
3488: $val = '';
3489: last;
3490: }
3491: }
3492: }
3493: }
3494: }
1.554 raeburn 3495: } elsif ($name eq 'interval') {
3496: my $intervaltype = &get_intervaltype($name);
3497: my $intervalmatch = &standard_interval_matches($intervaltype);
3498: if (ref($intervalmatch) eq 'ARRAY') {
3499: foreach my $item (@{$intervalmatch}) {
3500: if (ref($item) eq 'ARRAY') {
3501: my ($regexpname,$pattern) = @{$item};
3502: if ($pattern ne '') {
3503: if ($val =~ /$pattern/) {
3504: $valmatch = $regexpname;
3505: $val = '';
3506: last;
3507: }
3508: }
3509: }
3510: }
3511: }
1.533 raeburn 3512: }
1.504 raeburn 3513: $needsrelease =
1.557 raeburn 3514: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3515: if ($needsrelease) {
1.505 raeburn 3516: unless ($got_chostname) {
1.514 raeburn 3517: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3518: $got_chostname = 1;
1.546 raeburn 3519: }
1.557 raeburn 3520: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3521: $needsrelease,
3522: $cmajor,$cminor);
1.500 raeburn 3523: }
1.437 raeburn 3524: }
1.504 raeburn 3525: if ($needsnewer) {
1.557 raeburn 3526: undef($namematch);
3527: } else {
3528: my $currneeded;
3529: if ($needsrelease) {
3530: $currneeded = $needsrelease;
3531: }
3532: if ($namematch) {
3533: $needsrelease =
3534: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3535: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3536: unless ($got_chostname) {
3537: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3538: $got_chostname = 1;
3539: }
3540: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3541: $needsrelease,
3542: $cmajor,$cminor);
3543: } else {
3544: undef($namematch);
3545: }
3546: }
3547: }
3548: if ($needsnewer) {
3549: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3550: $cminor,$needsrelease);
3551: } else {
3552: $message.=&storeparm(split(/\&/,$markers[$i]),
3553: $values[$i],
3554: $types[$i],
3555: $uname,$udom,$csec,$cgroup);
3556: $totalstored ++;
3557: }
1.473 amueller 3558: }
1.68 www 3559: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3560: if ($totalstored) {
3561: $message.='<p class="LC_warning">'
1.605 raeburn 3562: .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
3563: .'<br />'
1.504 raeburn 3564: .&mt('Changes can take up to 10 minutes before being active for all students.')
3565: .&Apache::loncommon::help_open_topic('Caching')
3566: .'</p>';
1.605 raeburn 3567: } else {
3568: $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
3569: }
3570: if ($totalskippeduser) {
3571: $message .= '<p class="LC_warning">';
3572: if ($uhome eq 'no_host') {
3573: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
3574: $totalskippeduser);
3575: } elsif ($env{'form.userroles'} eq 'any') {
3576: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
3577: $totalskippeduser);
3578: } else {
3579: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
3580: $totalskippeduser);
3581: }
3582: $message .= '</p>';
1.504 raeburn 3583: }
1.68 www 3584: }
1.584 raeburn 3585:
1.57 albertel 3586: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3587: if ($pscat[0] eq "all") {
3588: @pscat = (keys(%allparms));
3589: }
3590: if (!@pscat) {
3591: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3592: };
3593: if ($psprt[0] eq "all" || !@psprt) {
3594: @psprt = (keys(%allparts));
3595: }
1.2 www 3596: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3597:
1.531 raeburn 3598: my $crstype = &Apache::loncommon::course_type();
3599: &startpage($r,$pssymb,$crstype);
1.57 albertel 3600:
1.548 raeburn 3601: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3602: 'date_interval','int','float','string','string_lenient',
3603: 'string_examcode','string_deeplink','string_discussvote',
3604: 'string_useslots','string_problemstatus','string_ip',
3605: 'string_questiontype') {
1.473 amueller 3606: $r->print('<input type="hidden" value="'.
1.563 damieng 3607: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3608: '" name="recent_'.$item.'" />');
1.44 albertel 3609: }
1.446 bisitz 3610:
1.459 bisitz 3611: # ----- Start Parameter Selection
3612:
1.606 raeburn 3613: # Hide parm selection and possibly table?
3614: my ($tablejs,$tabledivsty);
3615: if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
3616: ($env{'form.dis'}) && ($pssymb eq '')) {
3617: $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
3618: $tabledivsty = ' style="display:none"';
3619: }
1.459 bisitz 3620: $r->print(<<ENDPARMSELSCRIPT);
3621: <script type="text/javascript">
3622: // <![CDATA[
3623: function parmsel_show() {
1.562 damieng 3624: document.getElementById('parmsel').style.display = "";
3625: document.getElementById('parmsellink').style.display = "none";
1.606 raeburn 3626: $tablejs
1.459 bisitz 3627: }
3628: // ]]>
3629: </script>
3630: ENDPARMSELSCRIPT
1.474 amueller 3631:
1.445 neumanie 3632: if (!$pssymb) {
1.563 damieng 3633: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3634: my $parmselhiddenstyle=' style="display:none"';
3635: if($env{'form.hideparmsel'} eq 'hidden') {
3636: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3637: } else {
3638: $r->print('<div id="parmsel">');
3639: }
3640:
1.491 bisitz 3641: # Step 1
1.523 raeburn 3642: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3643: $r->print('
1.474 amueller 3644: <script type="text/javascript">
1.523 raeburn 3645: // <![CDATA['.
3646: &showhide_js().'
1.474 amueller 3647: // ]]>
3648: </script>
1.523 raeburn 3649: ');
3650: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3651: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3652: $r->print(&Apache::lonhtmlcommon::row_closure());
1.474 amueller 3653: &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491 bisitz 3654: $r->print(&Apache::lonhtmlcommon::row_closure());
3655: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3656: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3657: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3658: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3659:
3660: # Step 2
1.523 raeburn 3661: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3662: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3663:
3664: # Step 3
1.523 raeburn 3665: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3666: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3667: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3668: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3669: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3670:
3671: # Update Display Button
1.486 www 3672: $r->print('<p>'
3673: .'<input type="submit" name="dis"'
1.511 www 3674: .' value="'.&mt('Update Display').'" />'
1.486 www 3675: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3676: .'</p>');
3677: $r->print('</div>');
1.491 bisitz 3678:
1.486 www 3679: # Offer link to display parameter selection again
3680: $r->print('<p id="parmsellink"');
3681: if ($env{'form.hideparmsel'} ne 'hidden') {
3682: $r->print($parmselhiddenstyle);
3683: }
3684: $r->print('>'
3685: .'<a href="javascript:parmsel_show()">'
3686: .&mt('Change Parameter Selection')
3687: .'</a>'
3688: .'</p>');
1.44 albertel 3689: } else {
1.478 amueller 3690: # parameter screen for a single resource.
1.486 www 3691: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3692: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3693: $r->print(&mt('Specific Resource: [_1] ([_2])',
3694: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3695: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 3696: '<br />');
3697: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
3698: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3699: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3700: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3701: $r->print(&Apache::lonhtmlcommon::end_pick_box());
3702: $r->print('<p>'
1.459 bisitz 3703: .'<input type="submit" name="dis"'
1.511 www 3704: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 3705: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 3706: .'</p>');
1.459 bisitz 3707: }
1.478 amueller 3708:
1.486 www 3709: # ----- End Parameter Selection
1.57 albertel 3710:
1.459 bisitz 3711: # Display Messages
3712: $r->print('<div>'.$message.'</div>');
1.210 www 3713:
1.57 albertel 3714:
3715: my @temp_pscat;
3716: map {
3717: my $cat = $_;
3718: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
3719: } @pscat;
3720:
3721: @pscat = @temp_pscat;
3722:
1.548 raeburn 3723:
1.209 www 3724: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 3725: # ----------------------------------------------------------------- Start Table
1.57 albertel 3726: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 3727: my $csuname=$env{'user.name'};
3728: my $csudom=$env{'user.domain'};
1.568 raeburn 3729: my $readonly = 1;
3730: if ($parm_permission->{'edit'}) {
3731: undef($readonly);
3732: }
1.606 raeburn 3733: $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57 albertel 3734:
1.203 www 3735: if ($parmlev eq 'full') {
1.506 www 3736: #
3737: # This produces the cascading table output of parameters
3738: #
1.578 raeburn 3739: my $coursespan=$csec?8:5;
3740: my $userspan=3;
1.560 damieng 3741: if ($cgroup ne '') {
1.578 raeburn 3742: $coursespan += 3;
1.560 damieng 3743: }
1.473 amueller 3744:
1.560 damieng 3745: $r->print(&Apache::loncommon::start_data_table());
3746: #
3747: # This produces the headers
3748: #
3749: $r->print('<tr><td colspan="5"></td>');
3750: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
3751: if ($uname) {
1.473 amueller 3752: if (@usersgroups > 1) {
1.560 damieng 3753: $userspan ++;
3754: }
3755: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
3756: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
3757: }
3758: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 3759: 'pie' => "Parameter in Effect",
3760: 'csv' => "Current Session Value",
1.472 amueller 3761: 'rl' => "Resource Level",
1.473 amueller 3762: 'ic' => 'in Course',
3763: 'aut' => "Assessment URL and Title",
3764: 'type' => 'Type',
3765: 'emof' => "Enclosing Map or Folder",
3766: 'part' => 'Part',
1.472 amueller 3767: 'pn' => 'Parameter Name',
1.473 amueller 3768: 'def' => 'default',
3769: 'femof' => 'from Enclosing Map or Folder',
3770: 'gen' => 'general',
3771: 'foremf' => 'for Enclosing Map or Folder',
3772: 'fr' => 'for Resource'
3773: );
1.560 damieng 3774: $r->print(<<ENDTABLETWO);
1.419 bisitz 3775: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 3776: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 3777: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 3778: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 3779:
1.10 www 3780: ENDTABLETWO
1.560 damieng 3781: if ($csec) {
1.578 raeburn 3782: $r->print('<th colspan="3">'.
1.560 damieng 3783: &mt("in Section")." $csec</th>");
3784: }
3785: if ($cgroup) {
1.578 raeburn 3786: $r->print('<th colspan="3">'.
1.472 amueller 3787: &mt("in Group")." $cgroup</th>");
1.560 damieng 3788: }
3789: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 3790: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
3791: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 3792: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 3793: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 3794: ENDTABLEHEADFOUR
1.57 albertel 3795:
1.560 damieng 3796: if ($csec) {
1.578 raeburn 3797: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3798: }
1.473 amueller 3799:
1.560 damieng 3800: if ($cgroup) {
1.578 raeburn 3801: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3802: }
3803:
3804: if ($uname) {
3805: if (@usersgroups > 1) {
3806: $r->print('<th>'.&mt('Control by other group?').'</th>');
3807: }
1.578 raeburn 3808: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3809: }
3810:
3811: $r->print('</tr>');
1.506 www 3812: #
3813: # Done with the headers
3814: #
1.560 damieng 3815: my $defbgone='';
3816: my $defbgtwo='';
3817: my $defbgthree = '';
1.57 albertel 3818:
1.560 damieng 3819: foreach my $rid (@ids) {
1.57 albertel 3820:
3821: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 3822: if ((!$pssymb &&
1.560 damieng 3823: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
3824: ||
3825: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 3826: # ------------------------------------------------------ Entry for one resource
1.473 amueller 3827: if ($defbgone eq '#E0E099') {
3828: $defbgone='#E0E0DD';
1.57 albertel 3829: } else {
1.419 bisitz 3830: $defbgone='#E0E099';
1.57 albertel 3831: }
1.419 bisitz 3832: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 3833: $defbgtwo='#FFFFDD';
1.57 albertel 3834: } else {
1.473 amueller 3835: $defbgtwo='#FFFF99';
1.57 albertel 3836: }
1.419 bisitz 3837: if ($defbgthree eq '#FFBB99') {
3838: $defbgthree='#FFBBDD';
1.269 raeburn 3839: } else {
1.419 bisitz 3840: $defbgthree='#FFBB99';
1.269 raeburn 3841: }
3842:
1.57 albertel 3843: my $thistitle='';
3844: my %name= ();
3845: undef %name;
3846: my %part= ();
3847: my %display=();
3848: my %type= ();
3849: my %default=();
1.196 www 3850: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3851: my $toolsymb;
3852: if ($uri =~ /ext\.tool$/) {
3853: $toolsymb = $symbp{$rid};
3854: }
1.57 albertel 3855:
1.506 www 3856: my $filter=$env{'form.filter'};
1.548 raeburn 3857: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 3858: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 3859: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 3860: # We may only want certain parameters listed
3861: if ($filter) {
3862: unless ($filter=~/\Q$parmname\E/) { next; }
3863: }
3864: $name{$tempkeyp}=$parmname;
1.584 raeburn 3865: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 3866:
1.584 raeburn 3867: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 3868: if ($allparms{$name{$tempkeyp}} ne '') {
3869: my $identifier;
3870: if ($parmdis =~ /(\s*\[Part.*)$/) {
3871: $identifier = $1;
3872: }
3873: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3874: } else {
3875: $display{$tempkeyp} = $parmdis;
3876: }
3877: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3878: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 3879: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
3880: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
3881: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 3882: }
3883: }
1.548 raeburn 3884: my $totalparms=scalar(keys(%name));
1.57 albertel 3885: if ($totalparms>0) {
1.560 damieng 3886: my $firstrow=1;
1.473 amueller 3887: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 3888: my $navmap = Apache::lonnavmaps::navmap->new();
3889: my @recurseup;
3890: if (ref($navmap) && $mapp{$rid}) {
3891: @recurseup = $navmap->recurseup_maps($mapp{$rid});
3892: }
1.419 bisitz 3893: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 3894: ' rowspan='.$totalparms.
1.419 bisitz 3895: '><tt><font size="-1">'.
1.57 albertel 3896: join(' / ',split(/\//,$uri)).
3897: '</font></tt><p><b>'.
1.154 albertel 3898: "<a href=\"javascript:openWindow('".
1.473 amueller 3899: &Apache::lonnet::clutter($uri).'?symb='.
3900: &escape($symbp{$rid}).
1.336 albertel 3901: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
3902: " target=\"_self\">$title");
1.57 albertel 3903:
3904: if ($thistitle) {
1.473 amueller 3905: $r->print(' ('.$thistitle.')');
1.57 albertel 3906: }
3907: $r->print('</a></b></td>');
1.419 bisitz 3908: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 3909: ' rowspan='.$totalparms.'>'.$typep{$rid}.
3910: '</td>');
3911:
1.419 bisitz 3912: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 3913: ' rowspan='.$totalparms.
1.238 www 3914: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 3915: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 3916: unless ($firstrow) {
3917: $r->print('<tr>');
3918: } else {
3919: undef $firstrow;
3920: }
1.548 raeburn 3921: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 3922: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 3923: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 3924: $cgroup,\@usersgroups,$noeditgrp,$readonly,
3925: \@recurseup,\%maptitles,\%allmaps_inverted,
3926: \$numreclinks);
1.57 albertel 3927: }
3928: }
3929: }
3930: } # end foreach ids
1.43 albertel 3931: # -------------------------------------------------- End entry for one resource
1.517 www 3932: $r->print(&Apache::loncommon::end_data_table);
1.203 www 3933: } # end of full
1.57 albertel 3934: #--------------------------------------------------- Entry for parm level map
3935: if ($parmlev eq 'map') {
1.419 bisitz 3936: my $defbgone = '#E0E099';
3937: my $defbgtwo = '#FFFF99';
3938: my $defbgthree = '#FFBB99';
1.57 albertel 3939:
3940: my %maplist;
3941:
3942: if ($pschp eq 'all') {
1.446 bisitz 3943: %maplist = %allmaps;
1.57 albertel 3944: } else {
3945: %maplist = ($pschp => $mapp{$pschp});
3946: }
3947:
3948: #-------------------------------------------- for each map, gather information
3949: my $mapid;
1.607 raeburn 3950: foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60 albertel 3951: my $maptitle = $maplist{$mapid};
1.57 albertel 3952:
3953: #----------------------- loop through ids and get all parameter types for map
3954: #----------------------------------------- and associated information
3955: my %name = ();
3956: my %part = ();
3957: my %display = ();
3958: my %type = ();
3959: my %default = ();
3960: my $map = 0;
3961:
1.473 amueller 3962: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 3963:
1.548 raeburn 3964: foreach my $id (@ids) {
3965: ($map)=($id =~ /([\d]*?)\./);
3966: my $rid = $id;
1.446 bisitz 3967:
1.57 albertel 3968: # $r->print("$mapid:$map: $rid <br /> \n");
3969:
1.560 damieng 3970: if ($map eq $mapid) {
1.473 amueller 3971: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3972: my $toolsymb;
3973: if ($uri =~ /ext\.tool$/) {
3974: $toolsymb = $symbp{$rid};
3975: }
1.582 raeburn 3976:
1.57 albertel 3977: # $r->print("Keys: $keyp{$rid} <br />\n");
3978:
3979: #--------------------------------------------------------------------
3980: # @catmarker contains list of all possible parameters including part #s
3981: # $fullkeyp contains the full part/id # for the extraction of proper parameters
3982: # $tempkeyp contains part 0 only (no ids - ie, subparts)
3983: # When storing information, store as part 0
3984: # When requesting information, request from full part
3985: #-------------------------------------------------------------------
1.548 raeburn 3986: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
3987: my $tempkeyp = $fullkeyp;
3988: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 3989:
1.548 raeburn 3990: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 3991: $part{$tempkeyp}="0";
1.584 raeburn 3992: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
3993: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 3994: if ($allparms{$name{$tempkeyp}} ne '') {
3995: my $identifier;
3996: if ($parmdis =~ /(\s*\[Part.*)$/) {
3997: $identifier = $1;
3998: }
3999: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4000: } else {
4001: $display{$tempkeyp} = $parmdis;
4002: }
4003: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4004: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4005: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4006: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4007: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 4008: }
4009: } # end loop through keys
1.560 damieng 4010: }
1.57 albertel 4011: } # end loop through ids
1.446 bisitz 4012:
1.57 albertel 4013: #---------------------------------------------------- print header information
1.133 www 4014: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 4015: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 4016: my $tmp="";
1.57 albertel 4017: if ($uname) {
1.473 amueller 4018: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 4019: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
4020: &mt('in')." \n";
1.57 albertel 4021: } else {
1.401 bisitz 4022: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 4023: }
1.269 raeburn 4024: if ($cgroup) {
1.401 bisitz 4025: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
4026: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4027: $csec = '';
4028: } elsif ($csec) {
1.401 bisitz 4029: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
4030: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4031: }
1.401 bisitz 4032: $r->print('<div align="center"><h4>'
4033: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 4034: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 4035: ,$tmp
4036: ,'<font color="red"><i>'.$coursename.'</i></font>'
4037: )
4038: ."<br /></h4>\n"
1.422 bisitz 4039: );
1.57 albertel 4040: #---------------------------------------------------------------- print table
1.419 bisitz 4041: $r->print('<p>'.&Apache::loncommon::start_data_table()
4042: .&Apache::loncommon::start_data_table_header_row()
4043: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 4044: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4045: .'<th>'.&mt('Parameter in Effect').'</th>'
4046: .&Apache::loncommon::end_data_table_header_row()
4047: );
1.57 albertel 4048:
1.582 raeburn 4049: my $navmap = Apache::lonnavmaps::navmap->new();
4050: my @recurseup;
4051: if (ref($navmap)) {
4052: my $mapres = $navmap->getByMapPc($mapid);
4053: if (ref($mapres)) {
4054: @recurseup = $navmap->recurseup_maps($mapres->src());
4055: }
4056: }
4057:
4058:
1.548 raeburn 4059: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4060: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4061: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4062: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4063: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4064: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4065: \$numreclinks);
1.57 albertel 4066: }
1.422 bisitz 4067: $r->print(&Apache::loncommon::end_data_table().'</p>'
4068: .'</div>'
4069: );
1.57 albertel 4070: } # end each map
4071: } # end of $parmlev eq map
4072: #--------------------------------- Entry for parm level general (Course level)
4073: if ($parmlev eq 'general') {
1.473 amueller 4074: my $defbgone = '#E0E099';
1.419 bisitz 4075: my $defbgtwo = '#FFFF99';
4076: my $defbgthree = '#FFBB99';
1.57 albertel 4077:
4078: #-------------------------------------------- for each map, gather information
4079: my $mapid="0.0";
4080: #----------------------- loop through ids and get all parameter types for map
4081: #----------------------------------------- and associated information
4082: my %name = ();
4083: my %part = ();
4084: my %display = ();
4085: my %type = ();
4086: my %default = ();
1.446 bisitz 4087:
1.548 raeburn 4088: foreach $id (@ids) {
4089: my $rid = $id;
1.446 bisitz 4090:
1.196 www 4091: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4092: my $toolsymb;
4093: if ($uri =~ /ext\.tool$/) {
4094: $toolsymb = $symbp{$rid};
4095: }
1.57 albertel 4096:
4097: #--------------------------------------------------------------------
4098: # @catmarker contains list of all possible parameters including part #s
4099: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4100: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4101: # When storing information, store as part 0
4102: # When requesting information, request from full part
4103: #-------------------------------------------------------------------
1.548 raeburn 4104: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4105: my $tempkeyp = $fullkeyp;
4106: $tempkeyp =~ s/_\w+_/_0_/;
4107: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4108: $part{$tempkeyp}="0";
1.584 raeburn 4109: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4110: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4111: if ($allparms{$name{$tempkeyp}} ne '') {
4112: my $identifier;
4113: if ($parmdis =~ /(\s*\[Part.*)$/) {
4114: $identifier = $1;
4115: }
4116: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4117: } else {
4118: $display{$tempkeyp} = $parmdis;
4119: }
4120: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4121: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4122: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4123: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4124: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4125: }
1.57 albertel 4126: } # end loop through keys
4127: } # end loop through ids
1.446 bisitz 4128:
1.57 albertel 4129: #---------------------------------------------------- print header information
1.473 amueller 4130: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4131: $r->print(<<ENDMAPONE);
1.419 bisitz 4132: <center>
4133: <h4>$setdef
1.135 albertel 4134: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4135: ENDMAPONE
4136: if ($uname) {
1.473 amueller 4137: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4138: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4139: } else {
1.135 albertel 4140: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4141: }
1.446 bisitz 4142:
1.135 albertel 4143: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4144: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4145: $r->print("</h4>\n");
1.57 albertel 4146: #---------------------------------------------------------------- print table
1.419 bisitz 4147: $r->print('<p>'.&Apache::loncommon::start_data_table()
4148: .&Apache::loncommon::start_data_table_header_row()
4149: .'<th>'.&mt('Parameter Name').'</th>'
4150: .'<th>'.&mt('Default Value').'</th>'
4151: .'<th>'.&mt('Parameter in Effect').'</th>'
4152: .&Apache::loncommon::end_data_table_header_row()
4153: );
1.57 albertel 4154:
1.548 raeburn 4155: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4156: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4157: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4158: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4159: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4160: $readonly);
1.57 albertel 4161: }
1.419 bisitz 4162: $r->print(&Apache::loncommon::end_data_table()
4163: .'</p>'
4164: .'</center>'
4165: );
1.57 albertel 4166: } # end of $parmlev eq general
1.606 raeburn 4167: $r->print('</div>');
1.43 albertel 4168: }
1.507 www 4169: $r->print('</form>');
1.582 raeburn 4170: if ($numreclinks) {
4171: $r->print(<<"END");
4172: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4173: <input type="hidden" name="pschp" />
4174: <input type="hidden" name="pscat" />
4175: <input type="hidden" name="psprt" />
4176: <input type="hidden" name="hideparmsel" value="hidden" />
4177: </form>
4178: <script type="text/javascript">
4179: function pjumprec(rid,name,part) {
4180: document.forms.recurseform.pschp.value = rid;
4181: document.forms.recurseform.pscat.value = name;
4182: document.forms.recurseform.psprt.value = part;
4183: document.forms.recurseform.submit();
4184: return false;
4185: }
4186: </script>
4187: END
4188: }
1.507 www 4189: &endSettingsScreen($r);
4190: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4191: } # end sub assessparms
1.30 www 4192:
1.560 damieng 4193:
4194:
1.120 www 4195: ##################################################
1.560 damieng 4196: # OVERVIEW MODE
1.207 www 4197: ##################################################
1.124 www 4198:
1.563 damieng 4199: my $tableopen; # boolean, true if HTML table is already opened
4200:
4201: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4202: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4203: # @returns {string}
1.124 www 4204: sub tablestart {
1.576 raeburn 4205: my ($readonly,$is_map) = @_;
1.124 www 4206: if ($tableopen) {
1.552 raeburn 4207: return '';
1.124 www 4208: } else {
1.552 raeburn 4209: $tableopen=1;
4210: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4211: if ($readonly) {
4212: $output .= '<th>'.&mt('Current value').'</th>';
4213: } else {
1.576 raeburn 4214: $output .= '<th>'.&mt('Delete').'</th>'.
4215: '<th>'.&mt('Set to ...').'</th>';
4216: if ($is_map) {
4217: $output .= '<th>'.&mt('Recursive?').'</th>';
4218: }
1.552 raeburn 4219: }
4220: $output .= '</tr>';
4221: return $output;
1.124 www 4222: }
4223: }
4224:
1.563 damieng 4225: # Returns HTML with the HTML table end tag, unless the table is not opened.
4226: # @returns {string}
1.124 www 4227: sub tableend {
4228: if ($tableopen) {
1.560 damieng 4229: $tableopen=0;
4230: return &Apache::loncommon::end_data_table();
1.124 www 4231: } else {
1.560 damieng 4232: return'';
1.124 www 4233: }
4234: }
4235:
1.563 damieng 4236: # Reads course and user information.
4237: # 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).
4238: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4239: # If the context is looking for a list, returns a list with the scalar data and the class list.
4240: # @param {string} $crs - course number
4241: # @param {string} $dom - course domain
4242: # @returns {hash reference|Array}
1.207 www 4243: sub readdata {
4244: my ($crs,$dom)=@_;
4245: # Read coursedata
4246: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4247: # Read userdata
4248:
4249: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4250: foreach my $user (keys(%$classlist)) {
4251: if ($user=~/^($match_username)\:($match_domain)$/) {
4252: my ($tuname,$tudom)=($1,$2);
4253: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4254: foreach my $userkey (keys(%{$useropt})) {
4255: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4256: my $newkey=$userkey;
1.548 raeburn 4257: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4258: $$resourcedata{$newkey}=$$useropt{$userkey};
4259: }
4260: }
1.473 amueller 4261: }
4262: }
1.552 raeburn 4263: if (wantarray) {
4264: return ($resourcedata,$classlist);
4265: } else {
4266: return $resourcedata;
4267: }
1.207 www 4268: }
4269:
4270:
1.563 damieng 4271: # Stores parameter data, using form parameters directly.
4272: #
4273: # 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 4274: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563 damieng 4275: # del_* - remove a parameter
4276: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4277: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4278: # key_* - date values
4279: # days_* - for date intervals
4280: # hours_* - for date intervals
4281: # minutes_* - for date intervals
4282: # seconds_* - for date intervals
4283: # done_* - for date intervals
4284: # typeof_* - parameter type
4285: #
4286: # @param {Apache2::RequestRec} $r - the Apache request
4287: # @param {string} $crs - course number
4288: # @param {string} $dom - course domain
1.208 www 4289: sub storedata {
4290: my ($r,$crs,$dom)=@_;
1.207 www 4291: # Set userlevel immediately
4292: # Do an intermediate store of course level
4293: my $olddata=&readdata($crs,$dom);
1.124 www 4294: my %newdata=();
4295: undef %newdata;
4296: my @deldata=();
1.576 raeburn 4297: my @delrec=();
4298: my @delnonrec=();
1.124 www 4299: undef @deldata;
1.504 raeburn 4300: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4301: my $now = time;
1.560 damieng 4302: foreach my $key (keys(%env)) {
4303: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4304: my $cmd=$1;
4305: my $thiskey=$2;
1.576 raeburn 4306: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588 raeburn 4307: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576 raeburn 4308: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4309: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4310: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4311: $altkey = $thiskey;
4312: $altkey =~ s/\Q___(all)\E/___(rec)/;
4313: if ($env{'form.rec_'.$thiskey}) {
4314: $recursive = 1;
4315: }
4316: }
4317: }
1.560 damieng 4318: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4319: if ($tuname) {
1.576 raeburn 4320: $tkey=$thiskey;
1.560 damieng 4321: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4322: if ($altkey) {
4323: $tkeynonrec = $tkey;
4324: $tkeyrec = $altkey;
4325: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4326: }
1.560 damieng 4327: }
4328: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4329: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4330: if ($cmd eq 'set') {
4331: $data=$env{$key};
4332: $valmatch = '';
4333: $valchk = $data;
4334: $typeof=$env{'form.typeof_'.$thiskey};
4335: $text = &mt('Saved modified parameter for');
4336: if ($typeof eq 'string_questiontype') {
4337: $name = 'type';
1.588 raeburn 4338: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4339: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4340: my $stringmatch = &standard_string_matches($typeof);
4341: if (ref($stringmatch) eq 'ARRAY') {
4342: foreach my $item (@{$stringmatch}) {
4343: if (ref($item) eq 'ARRAY') {
4344: my ($regexpname,$pattern) = @{$item};
4345: if ($pattern ne '') {
4346: if ($data =~ /$pattern/) {
4347: $valmatch = $regexpname;
4348: $valchk = '';
4349: last;
4350: }
1.560 damieng 4351: }
1.549 raeburn 4352: }
4353: }
4354: }
1.563 damieng 4355: } elsif ($typeof eq 'string_discussvote') {
4356: $name = 'discussvote';
4357: } elsif ($typeof eq 'string_examcode') {
4358: $name = 'examcode';
4359: if (&Apache::lonnet::validCODE($data)) {
4360: $valchk = 'valid';
4361: }
4362: } elsif ($typeof eq 'string_yesno') {
4363: if ($thiskey =~ /\.retrypartial$/) {
4364: $name = 'retrypartial';
4365: }
1.549 raeburn 4366: }
1.563 damieng 4367: } elsif ($cmd eq 'datepointer') {
4368: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4369: $typeof=$env{'form.typeof_'.$thiskey};
4370: $text = &mt('Saved modified date for');
4371: if ($typeof eq 'date_start') {
4372: if ($thiskey =~ /\.printstartdate$/) {
4373: $name = 'printstartdate';
4374: if (($data) && ($data > $now)) {
4375: $valchk = 'future';
4376: }
1.560 damieng 4377: }
1.563 damieng 4378: } elsif ($typeof eq 'date_end') {
4379: if ($thiskey =~ /\.printenddate$/) {
4380: $name = 'printenddate';
4381: if (($data) && ($data < $now)) {
4382: $valchk = 'past';
4383: }
1.560 damieng 4384: }
1.504 raeburn 4385: }
1.563 damieng 4386: } elsif ($cmd eq 'dateinterval') {
4387: $data=&get_date_interval_from_form($thiskey);
4388: if ($thiskey =~ /\.interval$/) {
4389: $name = 'interval';
4390: my $intervaltype = &get_intervaltype($name);
4391: my $intervalmatch = &standard_interval_matches($intervaltype);
4392: if (ref($intervalmatch) eq 'ARRAY') {
4393: foreach my $item (@{$intervalmatch}) {
4394: if (ref($item) eq 'ARRAY') {
4395: my ($regexpname,$pattern) = @{$item};
4396: if ($pattern ne '') {
4397: if ($data =~ /$pattern/) {
4398: $valmatch = $regexpname;
4399: $valchk = '';
4400: last;
4401: }
1.560 damieng 4402: }
1.554 raeburn 4403: }
4404: }
4405: }
4406: }
1.563 damieng 4407: $typeof=$env{'form.typeof_'.$thiskey};
4408: $text = &mt('Saved modified date for');
1.554 raeburn 4409: }
1.576 raeburn 4410: if ($recursive) {
1.563 damieng 4411: $namematch = 'maplevelrecurse';
1.560 damieng 4412: }
1.563 damieng 4413: if (($name ne '') || ($namematch ne '')) {
4414: my ($needsrelease,$needsnewer);
4415: if ($name ne '') {
4416: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4417: if ($needsrelease) {
4418: unless ($got_chostname) {
1.563 damieng 4419: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4420: $got_chostname = 1;
4421: }
1.563 damieng 4422: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4423: $needsrelease,
4424: $cmajor,$cminor);
4425: }
4426: }
4427: if ($namematch ne '') {
4428: if ($needsnewer) {
4429: undef($namematch);
1.560 damieng 4430: } else {
1.563 damieng 4431: my $currneeded;
4432: if ($needsrelease) {
4433: $currneeded = $needsrelease;
4434: }
4435: $needsrelease =
4436: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4437: if (($needsrelease) &&
4438: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4439: unless ($got_chostname) {
4440: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4441: $got_chostname = 1;
4442: }
4443: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4444: $namematch, $needsrelease,$cmajor,$cminor);
4445: } else {
4446: undef($namematch);
4447: }
1.560 damieng 4448: }
1.557 raeburn 4449: }
1.563 damieng 4450: if ($needsnewer) {
4451: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4452: $chostname,$cmajor,
4453: $cminor,$needsrelease));
4454: next;
4455: }
1.504 raeburn 4456: }
1.576 raeburn 4457: my ($reconlychg,$haschange,$storekey);
4458: if ($tuname) {
4459: my $ustorekey;
4460: if ($altkey) {
4461: if ($recursive) {
4462: if (exists($$olddata{$thiskey})) {
4463: if ($$olddata{$thiskey} eq $data) {
4464: $reconlychg = 1;
4465: }
4466: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4467: }
4468: if (exists($$olddata{$altkey})) {
4469: if (defined($data) && $$olddata{$altkey} ne $data) {
4470: $haschange = 1;
4471: }
4472: } elsif ((!$reconlychg) && ($data ne '')) {
4473: $haschange = 1;
4474: }
4475: $ustorekey = $tkeyrec;
4476: } else {
4477: if (exists($$olddata{$altkey})) {
4478: if ($$olddata{$altkey} eq $data) {
4479: $reconlychg = 1;
4480: }
4481: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4482: }
4483: if (exists($$olddata{$thiskey})) {
4484: if (defined($data) && $$olddata{$thiskey} ne $data) {
4485: $haschange = 1;
4486: }
4487: } elsif ((!$reconlychg) && ($data ne '')) {
4488: $haschange = 1;
4489: }
4490: $ustorekey = $tkeynonrec;
4491: }
4492: } else {
4493: if (exists($$olddata{$tkey})) {
4494: if (defined($data) && $$olddata{$tkey} ne $data) {
4495: $haschange = 1;
4496: }
4497: $ustorekey = $tkey;
4498: }
4499: }
4500: if ($haschange || $reconlychg) {
4501: unless ($env{'form.del_'.$thiskey}) {
4502: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4503: $ustorekey.'.type' => $typeof},
4504: $tudom,$tuname) eq 'ok') {
4505: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4506: $r->print('<br />'.$text.' '.
4507: &Apache::loncommon::plainname($tuname,$tudom));
4508: } else {
4509: $r->print('<div class="LC_error">'.
4510: &mt('Error saving parameters').'</div>');
4511: }
4512: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4513: }
4514: }
4515: } else {
4516: if ($altkey) {
4517: if ($recursive) {
4518: if (exists($$olddata{$thiskey})) {
4519: if ($$olddata{$thiskey} eq $data) {
4520: $reconlychg = 1;
4521: }
4522: push(@delnonrec,($thiskey,$thiskey.'.type'));
4523: }
4524: if (exists($$olddata{$altkey})) {
4525: if (defined($data) && $$olddata{$altkey} ne $data) {
4526: $haschange = 1;
4527: }
4528: } elsif (($data ne '') && (!$reconlychg)) {
4529: $haschange = 1;
4530: }
4531: $storekey = $altkey;
1.563 damieng 4532: } else {
1.576 raeburn 4533: if (exists($$olddata{$altkey})) {
4534: if ($$olddata{$altkey} eq $data) {
4535: $reconlychg = 1;
4536: }
4537: push(@delrec,($altkey,$altkey.'.type'));
4538: }
4539: if (exists($$olddata{$thiskey})) {
4540: if (defined($data) && $$olddata{$thiskey} ne $data) {
4541: $haschange = 1;
4542: }
4543: } elsif (($data ne '') && (!$reconlychg)) {
4544: $haschange = 1;
4545: }
4546: $storekey = $thiskey;
1.563 damieng 4547: }
1.560 damieng 4548: } else {
1.576 raeburn 4549: if (defined($data) && $$olddata{$thiskey} ne $data) {
4550: $haschange = 1;
4551: $storekey = $thiskey;
4552: }
4553: }
4554: }
4555: if ($reconlychg || $haschange) {
4556: unless ($env{'form.del_'.$thiskey}) {
4557: $newdata{$storekey}=$data;
4558: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4559: }
4560: }
4561: } elsif ($cmd eq 'del') {
4562: if ($tuname) {
1.576 raeburn 4563: my $error;
4564: if ($altkey) {
4565: if (exists($$olddata{$altkey})) {
4566: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4567: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4568: if ($recursive) {
4569: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4570: }
4571: } elsif ($recursive) {
4572: $error = 1;
4573: }
4574: }
4575: if (exists($$olddata{$thiskey})) {
4576: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4577: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4578: unless ($recursive) {
4579: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4580: }
4581: } elsif (!$recursive) {
4582: $error = 1;
4583: }
4584: }
1.560 damieng 4585: } else {
1.576 raeburn 4586: if (exists($$olddata{$thiskey})) {
4587: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4588: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4589: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4590: } else {
4591: $error = 1;
4592: }
4593: }
4594: }
4595: if ($error) {
1.560 damieng 4596: $r->print('<div class="LC_error">'.
4597: &mt('Error deleting parameters').'</div>');
4598: }
4599: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4600: } else {
1.576 raeburn 4601: if ($altkey) {
4602: if (exists($$olddata{$altkey})) {
4603: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4604: push(@deldata,($altkey,$altkey.'.type'));
4605: }
4606: }
4607: if (exists($$olddata{$thiskey})) {
4608: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4609: push(@deldata,($thiskey,$thiskey.'.type'));
4610: }
4611: }
4612: } elsif (exists($$olddata{$thiskey})) {
4613: push(@deldata,($thiskey,$thiskey.'.type'));
4614: }
1.560 damieng 4615: }
1.473 amueller 4616: }
4617: }
4618: }
1.207 www 4619: # Store all course level
1.144 www 4620: my $delentries=$#deldata+1;
1.576 raeburn 4621: my @alldels;
4622: if (@delrec) {
4623: push(@alldels,@delrec);
4624: }
4625: if (@delnonrec) {
4626: push(@alldels,@delnonrec);
4627: }
4628: if (@deldata) {
4629: push(@alldels,@deldata);
4630: }
1.548 raeburn 4631: my @newdatakeys=keys(%newdata);
1.144 www 4632: my $putentries=$#newdatakeys+1;
1.576 raeburn 4633: my ($delresult,$devalidate);
4634: if (@alldels) {
4635: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4636: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4637: &log_parmset(\%loghash,1);
1.576 raeburn 4638: if ($delentries) {
4639: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4640: }
4641: } elsif ($delentries) {
1.560 damieng 4642: $r->print('<div class="LC_error">'.
4643: &mt('Error deleting parameters').'</div>');
4644: }
1.576 raeburn 4645: $devalidate = 1;
1.144 www 4646: }
4647: if ($putentries) {
1.560 damieng 4648: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4649: &log_parmset(\%newdata,0);
4650: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4651: } else {
4652: $r->print('<div class="LC_error">'.
4653: &mt('Error saving parameters').'</div>');
4654: }
1.576 raeburn 4655: $devalidate = 1;
4656: }
4657: if ($devalidate) {
1.560 damieng 4658: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4659: }
1.208 www 4660: }
1.207 www 4661:
1.563 damieng 4662: # Returns the username and domain from a key created in readdata from a resourcedata key.
4663: #
4664: # @param {string} $key - the key
4665: # @returns {Array}
1.208 www 4666: sub extractuser {
4667: my $key=shift;
1.350 albertel 4668: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4669: }
1.206 www 4670:
1.563 damieng 4671: # Parses a parameter key and returns the components.
4672: #
4673: # @param {string} $key -
4674: # @param {hash reference} $listdata -
4675: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4676: sub parse_listdata_key {
4677: my ($key,$listdata) = @_;
4678: # split into student/section affected, and
4679: # the realm (folder/resource part and parameter
1.446 bisitz 4680: my ($student,$realm) =
1.473 amueller 4681: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4682: # if course wide student would be undefined
4683: if (!defined($student)) {
1.560 damieng 4684: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4685: }
4686: # strip off the .type if it's not the Question type parameter
4687: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4688: $realm=~s/\.type//;
1.381 albertel 4689: }
4690: # split into resource+part and parameter name
1.388 albertel 4691: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4692: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4693: return ($student,$res,$part,$parm);
4694: }
4695:
1.563 damieng 4696: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
4697: #
4698: # @param {Apache2::RequestRec} $r - the Apache request
4699: # @param {hash reference} $resourcedata - parameter data returned by readdata
4700: # @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
4701: # @param {string} $sortorder - realmstudent|studentrealm
4702: # @param {string} $caller - name of the calling sub (overview|newoverview)
4703: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 4704: # @param {boolean} $readonly - true if editing not allowed
1.608 ! raeburn 4705: # @param {string} $parmlev - full|map
! 4706: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order
! 4707: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 4708: # @returns{integer} - number of $listdata parameters processed
1.208 www 4709: sub listdata {
1.608 ! raeburn 4710: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552 raeburn 4711:
1.207 www 4712: # Start list output
1.206 www 4713:
1.122 www 4714: my $oldsection='';
4715: my $oldrealm='';
4716: my $oldpart='';
1.123 www 4717: my $pointer=0;
1.124 www 4718: $tableopen=0;
1.145 www 4719: my $foundkeys=0;
1.248 albertel 4720: my %keyorder=&standardkeyorder();
1.594 raeburn 4721: my $readonlyall = $readonly;
1.381 albertel 4722:
1.552 raeburn 4723: my ($secidx,%grouphash);
4724: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4725: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 4726: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4727: %grouphash = &Apache::longroup::coursegroups();
4728: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 4729: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 4730: }
1.552 raeburn 4731: }
4732:
1.576 raeburn 4733: foreach my $key (sort {
1.560 damieng 4734: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
4735: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608 ! raeburn 4736: my ($aid,$bid);
! 4737: if ($caller eq 'newoverview') {
! 4738: if (ref($hash_for_realm) eq 'HASH') {
! 4739: if (($parmlev eq 'map') && ($pschp eq 'all')) {
! 4740: my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
! 4741: my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
! 4742: $aid = $hash_for_realm->{$aurl};
! 4743: $bid = $hash_for_realm->{$burl};
! 4744: } elsif ($parmlev eq 'full') {
! 4745: $aid = $hash_for_realm->{$ares};
! 4746: $bid = $hash_for_realm->{$bres};
! 4747: }
! 4748: }
! 4749: }
1.381 albertel 4750:
1.560 damieng 4751: # get the numerical order for the param
4752: $aparm=$keyorder{'parameter_0_'.$aparm};
4753: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 4754:
1.560 damieng 4755: my $result=0;
1.381 albertel 4756:
1.560 damieng 4757: if ($sortorder eq 'realmstudent') {
1.381 albertel 4758: if ($ares ne $bres ) {
1.608 ! raeburn 4759: if ($caller eq 'newoverview') {
! 4760: if (ref($hash_for_realm) eq 'HASH') {
! 4761: if (($parmlev eq 'map') && ($pschp eq 'all')) {
! 4762: $result = ($aid <=> $bid);
! 4763: } elsif ($parmlev eq 'full') {
! 4764: $result = ($aid <=> $bid);
! 4765: } else {
! 4766: $result = ($ares cmp $bres);
! 4767: }
! 4768: } else {
! 4769: $result = ($ares cmp $bres);
! 4770: }
! 4771: } else {
! 4772: $result = ($ares cmp $bres);
! 4773: }
1.446 bisitz 4774: } elsif ($astudent ne $bstudent) {
1.560 damieng 4775: $result = ($astudent cmp $bstudent);
4776: } elsif ($apart ne $bpart ) {
4777: $result = ($apart cmp $bpart);
4778: }
4779: } else {
4780: if ($astudent ne $bstudent) {
4781: $result = ($astudent cmp $bstudent);
4782: } elsif ($ares ne $bres ) {
1.608 ! raeburn 4783: if ($caller eq 'newoverview') {
! 4784: if (ref($hash_for_realm) eq 'HASH') {
! 4785: if (($parmlev eq 'map') && ($pschp eq 'all')) {
! 4786: $result = ($aid <=> $bid);
! 4787: } elsif ($parmlev eq 'full') {
! 4788: $result = ($aid <=> $bid);
! 4789: } else {
! 4790: $result = ($ares cmp $bres);
! 4791: }
! 4792: } else {
! 4793: $result = ($ares cmp $bres);
! 4794: }
! 4795: } else {
! 4796: $result = ($ares cmp $bres);
! 4797: }
1.560 damieng 4798: } elsif ($apart ne $bpart ) {
4799: $result = ($apart cmp $bpart);
4800: }
1.473 amueller 4801: }
1.446 bisitz 4802:
1.560 damieng 4803: if (!$result) {
1.381 albertel 4804: if (defined($aparm) && defined($bparm)) {
1.560 damieng 4805: $result = ($aparm <=> $bparm);
1.381 albertel 4806: } elsif (defined($aparm)) {
1.560 damieng 4807: $result = -1;
1.381 albertel 4808: } elsif (defined($bparm)) {
1.560 damieng 4809: $result = 1;
4810: }
1.473 amueller 4811: }
1.381 albertel 4812:
1.560 damieng 4813: $result;
4814:
1.576 raeburn 4815: } keys(%{$listdata})) { # foreach my $key
4816: my $thiskey = $key;
1.560 damieng 4817: if ($$listdata{$thiskey.'.type'}) {
4818: my $thistype=$$listdata{$thiskey.'.type'};
4819: if ($$resourcedata{$thiskey.'.type'}) {
4820: $thistype=$$resourcedata{$thiskey.'.type'};
4821: }
4822: my ($middle,$part,$name)=
1.572 damieng 4823: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 4824: my $section=&mt('All Students');
1.594 raeburn 4825: $readonly = $readonlyall;
1.599 raeburn 4826: my $userscope;
1.576 raeburn 4827: my $showval = $$resourcedata{$thiskey};
1.560 damieng 4828: if ($middle=~/^\[(.*)\]/) {
4829: my $issection=$1;
4830: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
4831: my ($stuname,$studom) = ($1,$2);
4832: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4833: if (ref($classlist) eq 'HASH') {
4834: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
4835: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
4836: }
4837: }
4838: }
4839: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 4840: $userscope = 1;
1.560 damieng 4841: } else {
4842: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4843: if (exists($grouphash{$issection})) {
4844: $section=&mt('Group').': '.$issection;
4845: } elsif ($issection eq $env{'request.course.sec'}) {
4846: $section = &mt('Section').': '.$issection;
4847: } else {
4848: next;
1.552 raeburn 4849: }
1.560 damieng 4850: } else {
4851: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 4852: }
4853: }
1.560 damieng 4854: $middle=~s/^\[(.*)\]//;
4855: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4856: $readonly = 1;
4857: }
4858: $middle=~s/\.+$//;
4859: $middle=~s/^\.+//;
4860: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 4861: my ($is_map,$is_recursive,$mapurl,$maplevel);
4862: if ($caller eq 'overview') {
4863: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
4864: $mapurl = $1;
4865: $maplevel = $2;
4866: $is_map = 1;
4867: }
4868: } elsif ($caller eq 'newoverview') {
4869: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
4870: $mapurl = $1;
4871: $maplevel = $2;
4872: $is_map = 1;
4873: }
4874: }
4875: if ($is_map) {
1.560 damieng 4876: my $leveltitle = &mt('Folder/Map');
1.608 ! raeburn 4877: my $title = &Apache::lonnet::gettitle($1);
! 4878: if (ref($hash_for_realm) eq 'HASH') {
! 4879: if ($hash_for_realm->{$mapurl} eq '1') {
! 4880: $title = &mt('Main Content');
! 4881: }
! 4882: }
1.576 raeburn 4883: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
4884: if ($caller eq 'newoverview') {
4885: my $altkey = $thiskey;
4886: $altkey =~ s/\Q___(all)\E/___(rec)/;
4887: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
4888: $is_recursive = 1;
4889: if ($$resourcedata{$altkey.'.type'}) {
4890: $thistype=$$resourcedata{$altkey.'.type'};
4891: }
4892: $showval = $$resourcedata{$altkey};
4893: }
4894: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
4895: $thiskey =~ s/\Q___(rec)\E/___(all)/;
4896: $is_recursive = 1;
4897: }
1.560 damieng 4898: }
1.608 ! raeburn 4899: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560 damieng 4900: } elsif ($middle) {
4901: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
4902: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
4903: ': '.&Apache::lonnet::gettitle($middle).
4904: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
4905: $id.')</span></span>';
4906: }
4907: if ($sortorder eq 'realmstudent') {
4908: if ($realm ne $oldrealm) {
4909: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
4910: $oldrealm=$realm;
4911: $oldsection='';
4912: }
4913: if ($section ne $oldsection) {
4914: $r->print(&tableend()."\n<h2>$section</h2>");
4915: $oldsection=$section;
4916: $oldpart='';
4917: }
1.552 raeburn 4918: } else {
1.560 damieng 4919: if ($section ne $oldsection) {
4920: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
4921: $oldsection=$section;
4922: $oldrealm='';
4923: }
4924: if ($realm ne $oldrealm) {
4925: $r->print(&tableend()."\n<h2>$realm</h2>");
4926: $oldrealm=$realm;
4927: $oldpart='';
1.552 raeburn 4928: }
4929: }
1.560 damieng 4930: if ($part ne $oldpart) {
4931: $r->print(&tableend().
4932: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
4933: $oldpart=$part;
1.556 raeburn 4934: }
1.560 damieng 4935: #
4936: # Ready to print
4937: #
1.470 raeburn 4938: my $parmitem = &standard_parameter_names($name);
1.576 raeburn 4939: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 4940: &Apache::loncommon::start_data_table_row().
4941: '<td><b>'.&mt($parmitem).
4942: '</b></td>');
4943: unless ($readonly) {
1.599 raeburn 4944: my $disabled;
4945: if (($name eq 'availablestudent') &&
4946: (($showval eq '') || ($userscope))) {
4947: $disabled = ' disabled="disabled"';
4948: }
1.560 damieng 4949: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 4950: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 4951: }
4952: $r->print('<td>');
4953: $foundkeys++;
4954: if (&isdateparm($thistype)) {
4955: my $jskey='key_'.$pointer;
4956: my $state;
4957: $pointer++;
4958: if ($readonly) {
4959: $state = 'disabled';
4960: }
4961: $r->print(
4962: &Apache::lonhtmlcommon::date_setter('parmform',
4963: $jskey,
1.576 raeburn 4964: $showval,
1.560 damieng 4965: '',1,$state));
4966: unless ($readonly) {
4967: $r->print(
4968: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 4969: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 4970: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 4971: &date_sanity_info($showval)
1.560 damieng 4972: );
4973: }
4974: } elsif ($thistype eq 'date_interval') {
4975: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 4976: $showval,$readonly));
1.560 damieng 4977: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 4978: if ($name eq 'availablestudent') {
4979: $readonly = 1;
4980: }
1.560 damieng 4981: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 4982: $showval,$name,$readonly));
1.560 damieng 4983: } else {
1.576 raeburn 4984: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 4985: }
1.560 damieng 4986: unless ($readonly) {
4987: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
4988: $thistype.'" />');
1.552 raeburn 4989: }
1.576 raeburn 4990: $r->print('</td>');
4991: if ($is_map) {
4992: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
4993: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
4994: } else {
4995: my ($disabled,$recon,$recoff);
4996: if ($readonly) {
4997: $disabled = ' disabled="disabled"';
4998: }
4999: if ($is_recursive) {
5000: $recon = ' checked="checked"';
5001: } else {
5002: $recoff = ' checked="checked"';
5003: }
5004: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
5005: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
5006: }
5007: }
5008: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 5009: }
1.121 www 5010: }
1.208 www 5011: return $foundkeys;
5012: }
5013:
1.563 damieng 5014: # Returns a string representing the interval, directly using form data matching the given key.
5015: # The returned string may also include information related to proctored exams.
5016: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
5017: #
5018: # @param {string} $key - suffix for form fields related to the interval
5019: # @returns {string}
1.385 albertel 5020: sub get_date_interval_from_form {
5021: my ($key) = @_;
5022: my $seconds = 0;
5023: foreach my $which (['days', 86400],
1.473 amueller 5024: ['hours', 3600],
5025: ['minutes', 60],
5026: ['seconds', 1]) {
1.560 damieng 5027: my ($name, $factor) = @{ $which };
5028: if (defined($env{'form.'.$name.'_'.$key})) {
5029: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
5030: }
1.473 amueller 5031: }
1.560 damieng 5032: if (($key =~ /\.interval$/) &&
5033: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 5034: if ($env{'form.done_'.$key.'_buttontext'}) {
5035: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
5036: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
5037: if ($env{'form.done_'.$key} eq '_done_proctor') {
5038: $seconds .= '_proctor';
5039: }
5040: } else {
5041: $seconds .= $env{'form.done_'.$key};
5042: }
5043: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 5044: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 5045: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
5046: }
1.554 raeburn 5047: }
1.385 albertel 5048: return $seconds;
5049: }
5050:
5051:
1.563 damieng 5052: # Returns HTML to enter a text value for a parameter.
5053: #
5054: # @param {string} $thiskey - parameter key
5055: # @param {string} $showval - the current value
5056: # @param {boolean} $readonly - true if the field should not be made editable
5057: # @returns {string}
1.383 albertel 5058: sub default_selector {
1.552 raeburn 5059: my ($thiskey, $showval, $readonly) = @_;
5060: my $disabled;
5061: if ($readonly) {
5062: $disabled = ' disabled="disabled"';
5063: }
5064: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 5065: }
5066:
1.563 damieng 5067: # Returns HTML to enter allow/deny rules related to IP addresses.
5068: #
5069: # @param {string} $thiskey - parameter key
5070: # @param {string} $showval - the current value
5071: # @param {boolean} $readonly - true if the fields should not be made editable
5072: # @returns {string}
1.549 raeburn 5073: sub string_ip_selector {
1.552 raeburn 5074: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 5075: my %access = (
5076: allow => [],
5077: deny => [],
5078: );
5079: if ($showval ne '') {
5080: my @current;
5081: if ($showval =~ /,/) {
5082: @current = split(/,/,$showval);
5083: } else {
5084: @current = ($showval);
5085: }
5086: foreach my $item (@current) {
5087: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
5088: push(@{$access{'deny'}},$1);
5089: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
5090: push(@{$access{'allow'}},$item);
5091: }
5092: }
5093: }
5094: if (!@{$access{'allow'}}) {
5095: @{$access{'allow'}} = ('');
5096: }
5097: if (!@{$access{'deny'}}) {
5098: @{$access{'deny'}} = ('');
5099: }
1.552 raeburn 5100: my ($disabled,$addmore);
1.567 raeburn 5101: if ($readonly) {
1.552 raeburn 5102: $disabled=' disabled="disabled"';
5103: } else {
5104: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5105: }
1.549 raeburn 5106: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5107: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5108: foreach my $acctype ('allow','deny') {
5109: $output .= '
5110: <td valign="top">
5111: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5112: <div class="LC_string_ipacc_inner">'."\n";
5113: my $num = 0;
5114: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5115: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5116: if ($num > 0) {
5117: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5118: }
5119: $output .= '</div>'."\n";
5120: $num ++;
5121: }
5122: $output .= '
1.552 raeburn 5123: </div>'.$addmore.'
1.549 raeburn 5124: </div>
5125: </td>';
5126: }
5127: $output .= '
5128: </tr>
5129: </table>'."\n";
5130: return $output;
5131: }
5132:
1.588 raeburn 5133: sub string_deeplink_selector {
5134: my ($thiskey, $showval, $readonly) = @_;
1.597 raeburn 5135: my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601 raeburn 5136: %selectnull,%domlti,%crslti,@possmenus);
5137: @components = ('state','others','listing','scope','protect','menus');
1.588 raeburn 5138: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5139: state => 'Access status',
5140: others => 'Hide other resources',
1.588 raeburn 5141: listing => 'In Contents and/or Gradebook',
5142: scope => 'Access scope for link',
1.601 raeburn 5143: protect => 'Link protection',
1.597 raeburn 5144: menus => 'Menu Items Displayed',
1.588 raeburn 5145: );
5146: %options = (
1.601 raeburn 5147: state => ['only','off','both'],
5148: others => ['hide','unhide'],
1.588 raeburn 5149: listing => ['full','absent','grades','details','datestatus'],
5150: scope => ['res','map','rec'],
1.601 raeburn 5151: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5152: menus => ['std','colls'],
1.588 raeburn 5153: );
5154: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5155: only => 'deep only',
5156: off => 'deeplink off',
5157: both => 'regular + deep',
5158: hide => 'Hidden',
5159: unhide => 'Unhidden',
1.588 raeburn 5160: full => 'Listed (linked) in both',
5161: absent => 'Not listed',
5162: grades => 'Listed in grades only',
5163: details => 'Listed (unlinked) in both',
5164: datestatus => 'Listed (unlinked) inc. status in both',
5165: res => 'resource only',
5166: map => 'enclosing map/folder',
5167: rec => 'recursive map/folder',
1.601 raeburn 5168: none => 'not in use',
5169: key => 'key access',
5170: ltic => 'LTI access (course)',
5171: ltid => 'LTI access (domain)' ,
1.597 raeburn 5172: std => 'Standard (all menus)',
5173: colls => 'Numbered collection',
5174: );
5175: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5176: ltic => 'Select Launcher',
5177: ltid => 'Select Launcher',
1.597 raeburn 5178: colls => 'Select',
1.588 raeburn 5179: );
5180: if ($showval =~ /,/) {
1.597 raeburn 5181: %values=();
1.588 raeburn 5182: @current = split(/,/,$showval);
1.601 raeburn 5183: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5184: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5185: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5186: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5187: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5188: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.588 raeburn 5189: } else {
1.601 raeburn 5190: $defaults{'state'} = 'off',
5191: $defaults{'others'} = 'unhide',
1.588 raeburn 5192: $defaults{'listing'} = 'full';
5193: $defaults{'scope'} = 'res';
1.601 raeburn 5194: $defaults{'protect'} = 'none';
1.597 raeburn 5195: $defaults{'menus'} = '0';
1.588 raeburn 5196: }
5197: my $disabled;
5198: if ($readonly) {
5199: $disabled=' disabled="disabled"';
5200: }
1.601 raeburn 5201: my %courselti =
5202: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
5203: $env{'course.'.$env{'request.course.id'}.'.domain'});
5204: foreach my $item (keys(%courselti)) {
5205: if (ref($courselti{$item}) eq 'HASH') {
5206: $crslti{$item} = $courselti{$item}{'name'};
5207: }
5208: }
5209: my %lti =
1.588 raeburn 5210: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 5211: 'linkprot');
1.588 raeburn 5212: foreach my $item (keys(%lti)) {
1.604 raeburn 5213: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
5214: $domlti{$item} = $lti{$item}{'name'};
1.588 raeburn 5215: }
5216: }
1.597 raeburn 5217: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5218: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5219: my ($num,$value) = split(/\%/,$item);
5220: if ($num =~ /^\d+$/) {
5221: push(@possmenus,$num);
5222: }
5223: }
5224: }
5225:
1.588 raeburn 5226: my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597 raeburn 5227: foreach my $item (@components) {
1.588 raeburn 5228: $output .= '<th>'.$titles{$item}.'</th>';
5229: }
5230: $output .= '</tr><tr>';
5231: foreach my $item (@components) {
5232: $output .= '<td>';
1.601 raeburn 5233: if (($item eq 'protect') || ($item eq 'menus')) {
1.588 raeburn 5234: my $selected = $values{$item};
5235: foreach my $option (@{$options{$item}}) {
1.601 raeburn 5236: if ($item eq 'protect') {
5237: if ($option eq 'ltid') {
5238: next unless (keys(%domlti));
5239: } elsif ($option eq 'ltic') {
5240: next unless (keys(%crslti));
5241: }
1.597 raeburn 5242: } elsif (($item eq 'menus') && ($option eq 'colls')) {
5243: next unless (@possmenus);
1.588 raeburn 5244: }
5245: my $checked;
1.597 raeburn 5246: if ($item eq 'menus') {
5247: if (($selected =~ /^\d+$/) && (@possmenus) &&
5248: (grep(/^\Q$selected\E$/,@possmenus))) {
5249: if ($option eq 'colls') {
5250: $checked = ' checked="checked"';
5251: }
5252: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
5253: $checked = ' checked="checked"';
5254: }
5255: } elsif ($selected =~ /^\Q$option\E/) {
1.588 raeburn 5256: $checked = ' checked="checked"';
5257: }
5258: my $onclick;
5259: unless ($readonly) {
5260: my $esc_key = &js_escape($thiskey);
5261: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
5262: }
5263: $output .= '<span class="LC_nobreak"><label>'.
5264: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
5265: $optiontext{$option}.'</label>';
1.601 raeburn 5266: if (($item eq 'protect') && ($option eq 'key')) {
1.588 raeburn 5267: my $visibility="hidden";
5268: my $currkey;
5269: if ($checked) {
5270: $visibility = "text";
5271: $currkey = (split(/\:/,$values{$item}))[1];
5272: }
5273: $output .= ' '.
1.597 raeburn 5274: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601 raeburn 5275: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588 raeburn 5276: my $display="none";
1.597 raeburn 5277: my ($current,$blankcheck,@possibles);
1.588 raeburn 5278: if ($checked) {
5279: $display = 'inline-block';
1.601 raeburn 5280: if (($option eq 'ltic') || ($option eq 'ltid')) {
1.597 raeburn 5281: $current = (split(/\:/,$selected))[1];
5282: } else {
5283: $current = $selected;
5284: }
1.588 raeburn 5285: } else {
5286: $blankcheck = ' selected="selected"';
5287: }
1.601 raeburn 5288: if ($option eq 'ltid') {
5289: @possibles = keys(%domlti);
5290: } elsif ($option eq 'ltic') {
5291: @possibles = keys(%crslti);
1.597 raeburn 5292: } else {
5293: @possibles = @possmenus;
5294: }
1.588 raeburn 5295: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
5296: ' style="display: '.$display.'"> <select name="'.
1.597 raeburn 5297: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
5298: if (@possibles > 1) {
5299: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
5300: '</option>'."\n";
5301: }
5302: foreach my $poss (sort { $a <=> $b } @possibles) {
1.588 raeburn 5303: my $selected;
1.597 raeburn 5304: if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588 raeburn 5305: $selected = ' selected="selected"';
5306: }
1.597 raeburn 5307: my $shown = $poss;
1.601 raeburn 5308: if ($option eq 'ltid') {
5309: $shown = $domlti{$poss};
5310: } elsif ($option eq 'ltic') {
5311: $shown = $crslti{$poss};
1.597 raeburn 5312: }
5313: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588 raeburn 5314: }
5315: $output .= '</select></div>';
5316: }
5317: $output .= '</span> ';
5318: }
5319: } else {
5320: my $selected = $values{$item};
5321: my $defsel;
5322: if ($selected eq '') {
5323: $defsel = ' selected="selected"';
5324: }
5325: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
5326: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
5327: foreach my $option (@{$options{$item}}) {
5328: $output .= '<option value="'.$option.'"';
5329: if ($option eq $selected) {
5330: $output .= ' selected="selected"';
5331: }
5332: $output .= '>'.$optiontext{$option}.'</option>';
5333: }
5334: $output .= '</select>';
5335: }
5336: $output .= '</td>';
5337: }
5338: $output .= '</tr></table>'."\n";
5339: return $output;
5340: }
5341:
1.560 damieng 5342:
5343: { # block using some constants related to parameter types (overview mode)
5344:
1.446 bisitz 5345: my %strings =
1.383 albertel 5346: (
5347: 'string_yesno'
5348: => [[ 'yes', 'Yes' ],
1.560 damieng 5349: [ 'no', 'No' ]],
1.383 albertel 5350: 'string_problemstatus'
5351: => [[ 'yes', 'Yes' ],
1.473 amueller 5352: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5353: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5354: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5355: 'string_questiontype'
5356: => [[ 'problem', 'Standard Problem'],
5357: [ 'survey', 'Survey'],
5358: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5359: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5360: [ 'anonsurvey', 'Anonymous Survey'],
5361: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5362: [ 'practice', 'Practice'],
5363: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5364: 'string_lenient'
5365: => [['yes', 'Yes' ],
5366: [ 'no', 'No' ],
1.549 raeburn 5367: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5368: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5369: 'string_discussvote'
5370: => [['yes','Yes'],
5371: ['notended','Yes, unless discussion ended'],
5372: ['no','No']],
1.549 raeburn 5373: 'string_ip'
5374: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5375: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5376: 'string_deeplink'
1.597 raeburn 5377: => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
1.587 raeburn 5378: );
5379:
1.383 albertel 5380:
1.549 raeburn 5381: my %stringmatches = (
5382: 'string_lenient'
5383: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5384: 'string_ip'
5385: => [['_allowfrom_','[^\!]+'],
5386: ['_denyfrom_','\!']],
1.588 raeburn 5387: 'string_deeplink'
1.602 raeburn 5388: => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)$']],
1.549 raeburn 5389: );
5390:
5391: my %stringtypes = (
5392: type => 'string_questiontype',
5393: lenient => 'string_lenient',
5394: retrypartial => 'string_yesno',
5395: discussvote => 'string_discussvote',
5396: examcode => 'string_examcode',
5397: acc => 'string_ip',
1.587 raeburn 5398: deeplink => 'string_deeplink',
1.549 raeburn 5399: );
5400:
1.563 damieng 5401: # Returns the possible values and titles for a given string type, or undef if there are none.
5402: # Used by courseprefs.
5403: #
5404: # @param {string} $string_type - a parameter type for strings
5405: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5406: sub standard_string_options {
5407: my ($string_type) = @_;
5408: if (ref($strings{$string_type}) eq 'ARRAY') {
5409: return $strings{$string_type};
5410: }
5411: return;
5412: }
1.383 albertel 5413:
1.563 damieng 5414: # Returns regular expressions to match kinds of string types, or undef if there are none.
5415: #
5416: # @param {string} $string_type - a parameter type for strings
5417: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5418: sub standard_string_matches {
5419: my ($string_type) = @_;
5420: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5421: return $stringmatches{$string_type};
5422: }
5423: return;
5424: }
5425:
1.563 damieng 5426: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5427: #
5428: # @param {string} $name - parameter name
5429: # @returns {string}
1.549 raeburn 5430: sub get_stringtype {
5431: my ($name) = @_;
5432: if (exists($stringtypes{$name})) {
5433: return $stringtypes{$name};
5434: }
5435: return;
5436: }
5437:
1.563 damieng 5438: # Returns HTML to edit a string parameter.
5439: #
5440: # @param {string} $thistype - parameter type
5441: # @param {string} $thiskey - parameter key
5442: # @param {string} $showval - parameter current value
5443: # @param {string} $name - parameter name
5444: # @param {boolean} $readonly - true if the values should not be made editable
5445: # @returns {string}
1.383 albertel 5446: sub string_selector {
1.552 raeburn 5447: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5448:
1.383 albertel 5449: if (!exists($strings{$thistype})) {
1.552 raeburn 5450: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5451: }
5452:
1.504 raeburn 5453: my %skiptype;
1.514 raeburn 5454: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5455: ($thistype eq 'string_lenient') ||
5456: ($thistype eq 'string_discussvote') ||
5457: ($thistype eq 'string_ip') ||
1.588 raeburn 5458: ($thistype eq 'string_deeplink') ||
1.560 damieng 5459: ($name eq 'retrypartial')) {
1.504 raeburn 5460: my ($got_chostname,$chostname,$cmajor,$cminor);
5461: foreach my $possibilities (@{ $strings{$thistype} }) {
5462: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5463: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5464: my $parmmatch;
5465: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5466: foreach my $item (@{$stringmatches{$thistype}}) {
5467: if (ref($item) eq 'ARRAY') {
5468: if ($parmval eq $item->[0]) {
5469: $parmmatch = $parmval;
5470: $parmval = '';
5471: last;
5472: }
5473: }
5474: }
5475: }
5476: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5477: if ($needsrelease) {
5478: unless ($got_chostname) {
1.514 raeburn 5479: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5480: $got_chostname = 1;
5481: }
1.557 raeburn 5482: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5483: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5484: if ($needsnewer) {
1.549 raeburn 5485: if ($parmmatch ne '') {
5486: $skiptype{$parmmatch} = 1;
5487: } elsif ($parmval ne '') {
5488: $skiptype{$parmval} = 1;
5489: }
1.504 raeburn 5490: }
5491: }
5492: }
5493: }
1.549 raeburn 5494:
5495: if ($thistype eq 'string_ip') {
1.552 raeburn 5496: return &string_ip_selector($thiskey,$showval,$readonly);
1.588 raeburn 5497: } elsif ($thistype eq 'string_deeplink') {
5498: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5499: }
1.504 raeburn 5500:
1.552 raeburn 5501: my ($result,$disabled);
5502:
5503: if ($readonly) {
5504: $disabled = ' disabled="disabled"';
5505: }
1.504 raeburn 5506: my $numinrow = 3;
5507: if ($thistype eq 'string_problemstatus') {
5508: $numinrow = 2;
5509: } elsif ($thistype eq 'string_questiontype') {
5510: if (keys(%skiptype) > 0) {
5511: $numinrow = 4;
5512: }
5513: }
5514: my $rem;
5515: if (ref($strings{$thistype}) eq 'ARRAY') {
5516: my $i=0;
5517: foreach my $possibilities (@{ $strings{$thistype} }) {
5518: next unless (ref($possibilities) eq 'ARRAY');
5519: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5520: next if ($skiptype{$name});
1.504 raeburn 5521: $rem = $i%($numinrow);
5522: if ($rem == 0) {
5523: if ($i > 0) {
5524: $result .= '</tr>';
5525: }
5526: $result .= '<tr>';
5527: }
1.549 raeburn 5528: my $colspan;
5529: if ($i == @{ $strings{$thistype} }-1) {
5530: $rem = @{ $strings{$thistype} }%($numinrow);
5531: if ($rem) {
5532: my $colsleft = $numinrow - $rem;
5533: if ($colsleft) {
5534: $colspan = $colsleft+1;
5535: $colspan = ' colspan="'.$colspan.'"';
5536: }
5537: }
5538: }
5539: my ($add,$onchange,$css_class);
5540: if ($thistype eq 'string_lenient') {
5541: if ($name eq 'weighted') {
5542: my $display;
5543: my %relatives = &Apache::lonlocal::texthash(
5544: corrchkd => 'Correct (checked)',
5545: corrunchkd => 'Correct (unchecked)',
5546: incorrchkd => 'Incorrect (checked)',
5547: incorrunchkd => 'Incorrect (unchecked)',
5548: );
5549: my %textval = (
5550: corrchkd => '1.0',
5551: corrunchkd => '1.0',
5552: incorrchkd => '0.0',
5553: incorrunchkd => '0.0',
5554: );
5555: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
5556: $textval{'corrchkd'} = $1;
5557: $textval{'corrunchkd'} = $2;
5558: $textval{'incorrchkd'} = $3;
5559: $textval{'incorrunchkd'} = $4;
5560: $display = 'inline';
5561: $showval = $name;
5562: } else {
5563: $display = 'none';
5564: }
5565: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
5566: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
5567: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
5568: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
5569: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 5570: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 5571: '</td></tr>';
5572: }
5573: $add .= '</table></div>'."\n";
5574: }
5575: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
5576: $css_class = ' class="LC_lenient_radio"';
5577: }
5578: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 5579: '<span class="LC_nobreak"><label>'.
5580: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 5581: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 5582: if ($showval eq $name) {
5583: $result .= ' checked="checked"';
5584: }
1.549 raeburn 5585: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 5586: $i++;
5587: }
5588: $result .= '</tr>';
1.473 amueller 5589: }
1.504 raeburn 5590: if ($result) {
5591: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 5592: }
5593: return $result;
5594: }
5595:
1.554 raeburn 5596: my %intervals =
5597: (
5598: 'date_interval'
5599: => [[ 'done', 'Yes' ],
1.558 raeburn 5600: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 5601: [ '', 'No' ]],
5602: );
5603:
5604: my %intervalmatches = (
5605: 'date_interval'
1.559 raeburn 5606: => [['done','\d+_done(|\:[^\:]+\:)$'],
5607: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 5608: );
5609:
5610: my %intervaltypes = (
5611: interval => 'date_interval',
5612: );
5613:
1.563 damieng 5614: # Returns regular expressions to match kinds of interval type, or undef if there are none.
5615: #
5616: # @param {string} $interval_type - a parameter type for intervals
5617: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 5618: sub standard_interval_matches {
5619: my ($interval_type) = @_;
5620: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
5621: return $intervalmatches{$interval_type};
5622: }
5623: return;
5624: }
5625:
1.563 damieng 5626: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
5627: #
5628: # @param {string} $name - parameter name
5629: # @returns {string}
1.554 raeburn 5630: sub get_intervaltype {
5631: my ($name) = @_;
5632: if (exists($intervaltypes{$name})) {
5633: return $intervaltypes{$name};
5634: }
5635: return;
5636: }
5637:
1.563 damieng 5638: # Returns the possible values and titles for a given interval type, or undef if there are none.
5639: # Used by courseprefs.
5640: #
5641: # @param {string} $interval_type - a parameter type for intervals
5642: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 5643: sub standard_interval_options {
5644: my ($interval_type) = @_;
5645: if (ref($intervals{$interval_type}) eq 'ARRAY') {
5646: return $intervals{$interval_type};
5647: }
5648: return;
5649: }
5650:
1.563 damieng 5651: # Returns HTML to edit a date interval parameter.
5652: #
5653: # @param {string} $thiskey - parameter key
5654: # @param {string} $name - parameter name
5655: # @param {string} $showval - parameter current value
5656: # @param {boolean} $readonly - true if the values should not be made editable
5657: # @returns {string}
1.554 raeburn 5658: sub date_interval_selector {
5659: my ($thiskey, $name, $showval, $readonly) = @_;
5660: my ($result,%skipval);
5661: if ($name eq 'interval') {
5662: my $intervaltype = &get_intervaltype($name);
5663: my ($got_chostname,$chostname,$cmajor,$cminor);
5664: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
5665: next unless (ref($possibilities) eq 'ARRAY');
5666: my ($parmval, $description) = @{ $possibilities };
5667: my $parmmatch;
5668: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
5669: foreach my $item (@{$intervalmatches{$intervaltype}}) {
5670: if (ref($item) eq 'ARRAY') {
5671: if ($parmval eq $item->[0]) {
5672: $parmmatch = $parmval;
5673: $parmval = '';
5674: last;
5675: }
5676: }
5677: }
5678: }
5679: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
5680: if ($needsrelease) {
5681: unless ($got_chostname) {
5682: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
5683: $got_chostname = 1;
5684: }
1.557 raeburn 5685: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 5686: $needsrelease,$cmajor,$cminor);
5687: if ($needsnewer) {
5688: if ($parmmatch ne '') {
5689: $skipval{$parmmatch} = 1;
5690: } elsif ($parmval ne '') {
5691: $skipval{$parmval} = 1;
5692: }
5693: }
5694: }
5695: }
5696: }
5697:
5698: my $currval = $showval;
5699: foreach my $which (['days', 86400, 31],
5700: ['hours', 3600, 23],
5701: ['minutes', 60, 59],
5702: ['seconds', 1, 59]) {
1.560 damieng 5703: my ($name, $factor, $max) = @{ $which };
5704: my $amount = int($showval/$factor);
5705: $showval %= $factor;
5706: my %select = ((map {$_ => $_} (0..$max)),
5707: 'select_form_order' => [0..$max]);
5708: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
5709: \%select,'',$readonly);
5710: $result .= ' '.&mt($name);
1.554 raeburn 5711: }
5712: if ($name eq 'interval') {
5713: unless ($skipval{'done'}) {
5714: my $checkedon = '';
1.558 raeburn 5715: my $checkedproc = '';
5716: my $currproctorkey = '';
5717: my $currprocdisplay = 'hidden';
1.559 raeburn 5718: my $currdonetext = &mt('Done');
1.554 raeburn 5719: my $checkedoff = ' checked="checked"';
1.559 raeburn 5720: if ($currval =~ /^(?:\d+)_done$/) {
5721: $checkedon = ' checked="checked"';
5722: $checkedoff = '';
5723: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
5724: $currdonetext = $1;
1.554 raeburn 5725: $checkedon = ' checked="checked"';
5726: $checkedoff = '';
1.558 raeburn 5727: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
5728: $currproctorkey = $1;
5729: $checkedproc = ' checked="checked"';
5730: $checkedoff = '';
5731: $currprocdisplay = 'text';
1.559 raeburn 5732: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
5733: $currdonetext = $1;
5734: $currproctorkey = $2;
5735: $checkedproc = ' checked="checked"';
5736: $checkedoff = '';
5737: $currprocdisplay = 'text';
1.554 raeburn 5738: }
1.558 raeburn 5739: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 5740: my $disabled;
5741: if ($readonly) {
5742: $disabled = ' disabled="disabled"';
5743: }
1.558 raeburn 5744: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 5745: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 5746: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 5747: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 5748: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 5749: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 5750: &mt('Yes, with proctor key').'</label>'.
5751: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 5752: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 5753: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567 raeburn 5754: '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 5755: }
5756: }
5757: unless ($readonly) {
5758: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
5759: }
5760: return $result;
5761: }
5762:
1.563 damieng 5763: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
5764: #
5765: # @param {string} $name - parameter name
5766: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
5767: # @param {string} $value - parameter value
5768: # @param {string} $chostname - course server name
5769: # @param {integer} $cmajor - major version number
5770: # @param {integer} $cminor - minor version number
5771: # @param {string} $needsrelease - release version needed (major.minor)
5772: # @returns {string}
1.549 raeburn 5773: sub oldversion_warning {
1.557 raeburn 5774: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
5775: my $standard_name = &standard_parameter_names($name);
5776: if ($namematch) {
5777: my $level = &standard_parameter_levels($namematch);
5778: my $msg = '';
5779: if ($level) {
5780: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
5781: $standard_name,'<b>','</b>','"'.$level.'"');
5782: } else {
5783: $msg = &mt('[_1] was [_2]not[_3] set.',
5784: $standard_name,'<b>','</b>');
5785: }
5786: return '<p class="LC_warning">'.$msg.'<br />'.
5787: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5788: $cmajor.'.'.$cminor,$chostname,
5789: $needsrelease).
5790: '</p>';
5791: }
1.549 raeburn 5792: my $desc;
5793: my $stringtype = &get_stringtype($name);
5794: if ($stringtype ne '') {
5795: if ($name eq 'examcode') {
5796: $desc = $value;
5797: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
5798: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
5799: next unless (ref($possibilities) eq 'ARRAY');
5800: my ($parmval, $description) = @{ $possibilities };
5801: my $parmmatch;
5802: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
5803: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
5804: if (ref($item) eq 'ARRAY') {
5805: my ($regexpname,$pattern) = @{$item};
5806: if ($parmval eq $regexpname) {
5807: if ($value =~ /$pattern/) {
5808: $desc = $description;
5809: $parmmatch = 1;
5810: last;
5811: }
5812: }
5813: }
5814: }
5815: last if ($parmmatch);
5816: } elsif ($parmval eq $value) {
5817: $desc = $description;
5818: last;
5819: }
5820: }
5821: }
5822: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
5823: my $now = time;
5824: if ($value =~ /^\d+$/) {
5825: if ($name eq 'printstartdate') {
5826: if ($value > $now) {
5827: $desc = &Apache::lonlocal::locallocaltime($value);
5828: }
5829: } elsif ($name eq 'printenddate') {
5830: if ($value < $now) {
5831: $desc = &Apache::lonlocal::locallocaltime($value);
5832: }
5833: }
5834: }
5835: }
5836: return '<p class="LC_warning">'.
1.557 raeburn 5837: &mt('[_1] was [_2]not[_3] set to [_4].',
5838: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
5839: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5840: $cmajor.'.'.$cminor,$chostname,
5841: $needsrelease).
5842: '</p>';
1.549 raeburn 5843: }
5844:
1.560 damieng 5845: } # end of block using some constants related to parameter types
5846:
1.549 raeburn 5847:
1.563 damieng 5848:
5849: # Shifts all start and end dates in the current course by $shift.
1.389 www 5850: #
1.563 damieng 5851: # @param {integer} $shift - time to shift, in seconds
5852: # @returns {string} - error name or 'ok'
1.389 www 5853: sub dateshift {
1.594 raeburn 5854: my ($shift,$numchanges)=@_;
1.389 www 5855: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5856: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 5857: my $sec = $env{'request.course.sec'};
1.595 raeburn 5858: my $secgrpregex;
5859: if ($sec ne '') {
5860: my @groups;
5861: if ($env{'request.course.groups'} ne '') {
5862: @groups = split(/:/,$env{'request.course.groups'});
5863: }
5864: if (@groups) {
5865: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
5866: } else {
5867: $secgrpregex = $sec;
5868: }
5869: }
1.389 www 5870: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
5871: # ugly retro fix for broken version of types
1.548 raeburn 5872: foreach my $key (keys(%data)) {
1.389 www 5873: if ($key=~/\wtype$/) {
5874: my $newkey=$key;
5875: $newkey=~s/type$/\.type/;
5876: $data{$newkey}=$data{$key};
5877: delete $data{$key};
5878: }
5879: }
1.391 www 5880: my %storecontent=();
1.389 www 5881: # go through all parameters and look for dates
1.548 raeburn 5882: foreach my $key (keys(%data)) {
1.389 www 5883: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 5884: if ($sec ne '') {
1.595 raeburn 5885: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 5886: }
1.389 www 5887: my $newdate=$data{$key}+$shift;
1.594 raeburn 5888: $$numchanges ++;
1.391 www 5889: $storecontent{$key}=$newdate;
1.389 www 5890: }
5891: }
1.391 www 5892: my $reply=&Apache::lonnet::cput
5893: ('resourcedata',\%storecontent,$dom,$crs);
5894: if ($reply eq 'ok') {
5895: &log_parmset(\%storecontent);
5896: }
5897: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
5898: return $reply;
1.389 www 5899: }
5900:
1.563 damieng 5901: # Overview mode UI to edit course parameters.
5902: #
5903: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 5904: sub newoverview {
1.568 raeburn 5905: my ($r,$parm_permission) = @_;
1.280 albertel 5906:
1.208 www 5907: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5908: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 5909: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 5910: my $readonly = 1;
5911: if ($parm_permission->{'edit'}) {
5912: undef($readonly);
5913: }
1.414 droeschl 5914: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 5915: text=>"Overview Mode"});
1.523 raeburn 5916:
5917: my %loaditems = (
1.549 raeburn 5918: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 5919: );
5920: my $js = '
5921: <script type="text/javascript">
5922: // <![CDATA[
5923: '.
5924: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
5925: &showhide_js()."\n".
1.549 raeburn 5926: &toggleparmtextbox_js()."\n".
5927: &validateparms_js()."\n".
5928: &ipacc_boxes_js()."\n".
1.558 raeburn 5929: &done_proctor_js()."\n".
1.588 raeburn 5930: &deeplink_js()."\n".
1.523 raeburn 5931: '// ]]>
5932: </script>
5933: ';
1.549 raeburn 5934:
1.523 raeburn 5935: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
5936: {'add_entries' => \%loaditems,});
1.298 albertel 5937: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 5938: $r->print($start_page.$breadcrumbs);
1.531 raeburn 5939: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 5940: $r->print(<<ENDOVER);
1.549 raeburn 5941: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208 www 5942: ENDOVER
1.211 www 5943: my @ids=();
5944: my %typep=();
5945: my %keyp=();
5946: my %allparms=();
5947: my %allparts=();
5948: my %allmaps=();
5949: my %mapp=();
5950: my %symbp=();
5951: my %maptitles=();
5952: my %uris=();
5953: my %keyorder=&standardkeyorder();
5954: my %defkeytype=();
5955:
5956: my %alllevs=();
5957: $alllevs{'Resource Level'}='full';
1.215 www 5958: $alllevs{'Map/Folder Level'}='map';
1.211 www 5959: $alllevs{'Course Level'}='general';
5960:
5961: my $csec=$env{'form.csec'};
1.269 raeburn 5962: my $cgroup=$env{'form.cgroup'};
1.211 www 5963:
5964: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
5965: my $pschp=$env{'form.pschp'};
1.506 www 5966:
1.211 www 5967: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 5968: if (!@psprt) { $psprt[0]='all'; }
1.211 www 5969:
1.446 bisitz 5970: my @selected_sections =
1.473 amueller 5971: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 5972: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 5973: foreach my $sec (@selected_sections) {
5974: if ($sec eq 'all') {
1.211 www 5975: @selected_sections = ('all');
5976: }
5977: }
1.552 raeburn 5978: if ($env{'request.course.sec'} ne '') {
5979: @selected_sections = ($env{'request.course.sec'});
5980: }
1.269 raeburn 5981: my @selected_groups =
5982: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 5983:
5984: my $pssymb='';
5985: my $parmlev='';
1.446 bisitz 5986:
1.211 www 5987: unless ($env{'form.parmlev'}) {
5988: $parmlev = 'map';
5989: } else {
5990: $parmlev = $env{'form.parmlev'};
5991: }
5992:
1.446 bisitz 5993: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 5994: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 5995: \%keyorder,\%defkeytype,$pssymb);
1.211 www 5996:
1.374 albertel 5997: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 5998: @psprt = keys(%allparts);
1.374 albertel 5999: }
1.211 www 6000: # Menu to select levels, etc
6001:
1.456 bisitz 6002: $r->print('<div class="LC_Box">');
1.445 neumanie 6003: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 6004: $r->print('<div>');
1.523 raeburn 6005: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 6006: &levelmenu($r,\%alllevs,$parmlev);
6007: if ($parmlev ne 'general') {
1.447 bisitz 6008: $r->print(&Apache::lonhtmlcommon::row_closure());
1.483 amueller 6009: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211 www 6010: }
1.447 bisitz 6011: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6012: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6013: $r->print('</div></div>');
1.446 bisitz 6014:
1.456 bisitz 6015: $r->print('<div class="LC_Box">');
1.452 bisitz 6016: $r->print('<div>');
1.581 raeburn 6017: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 6018: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 6019: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 6020: my $sectionselector = §ionmenu(\@selected_sections);
6021: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 6022: $r->print('<table>'.
1.553 raeburn 6023: '<tr><th>'.&mt('Parts').'</th>');
6024: if ($sectionselector) {
6025: $r->print('<th>'.&mt('Section(s)').'</th>');
6026: }
6027: if ($groupselector) {
6028: $r->print('<th>'.&mt('Group(s)').'</th>');
6029: }
6030: $r->print('</tr><tr><td>');
1.211 www 6031: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 6032: $r->print('</td>');
6033: if ($sectionselector) {
6034: $r->print('<td>'.$sectionselector.'</td>');
6035: }
6036: if ($groupselector) {
6037: $r->print('<td>'.$groupselector.'</td>');
6038: }
6039: $r->print('</tr></table>');
1.447 bisitz 6040: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6041: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6042: $r->print('</div></div>');
6043:
1.456 bisitz 6044: $r->print('<div class="LC_Box">');
1.452 bisitz 6045: $r->print('<div>');
1.214 www 6046: my $sortorder=$env{'form.sortorder'};
6047: unless ($sortorder) { $sortorder='realmstudent'; }
1.608 ! raeburn 6048: &sortmenu($r,$sortorder,'newoverview'));
1.445 neumanie 6049: $r->print('</div></div>');
1.446 bisitz 6050:
1.214 www 6051: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446 bisitz 6052:
1.211 www 6053: # Build the list data hash from the specified parms
6054:
6055: my $listdata;
6056: %{$listdata}=();
6057:
6058: foreach my $cat (@pscat) {
1.269 raeburn 6059: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
6060: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 6061: }
6062:
1.212 www 6063: if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211 www 6064:
1.481 amueller 6065: if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211 www 6066:
6067: # Read modified data
6068:
1.481 amueller 6069: my $resourcedata=&readdata($crs,$dom);
1.211 www 6070:
6071: # List data
6072:
1.608 ! raeburn 6073: my $hash_for_realm;
! 6074: if (($parmlev eq 'map') && (keys(%allmaps))) {
! 6075: %{$hash_for_realm} = reverse(%allmaps);
! 6076: } elsif (($parmlev eq 'full') && (keys(%symbp))) {
! 6077: for (my $i=0; $i<@ids; $i++) {
! 6078: $hash_for_realm->{$symbp{$ids[$i]}} = $i;
! 6079: }
! 6080: }
! 6081: &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568 raeburn 6082: }
6083: $r->print(&tableend());
6084: unless ($readonly) {
6085: $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211 www 6086: }
1.568 raeburn 6087: $r->print('</form>');
1.507 www 6088: &endSettingsScreen($r);
6089: $r->print(&Apache::loncommon::end_page());
1.208 www 6090: }
6091:
1.563 damieng 6092: # Fills $listdata with parameter information.
6093: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
6094: # The non-type value is always 1.
6095: #
6096: # @param {string} $cat - parameter name
1.566 damieng 6097: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 6098: # @param {string} $parmlev - selected level value (full|map|general), or ''
6099: # @param {hash reference} $listdata - the parameter data that will be modified
6100: # @param {array reference} $psprt - selected parts
6101: # @param {array reference} $selections - selected sections
6102: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6103: # @param {hash reference} $allmaps - hash map pc -> map src
6104: # @param {array reference} $ids - resource and map ids
6105: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6106: sub secgroup_lister {
6107: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6108: foreach my $item (@{$selections}) {
6109: foreach my $part (@{$psprt}) {
6110: my $rootparmkey=$env{'request.course.id'};
6111: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6112: $rootparmkey.='.['.$item.']';
6113: }
6114: if ($parmlev eq 'general') {
6115: # course-level parameter
6116: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6117: $$listdata{$newparmkey}=1;
6118: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6119: } elsif ($parmlev eq 'map') {
6120: # map-level parameter
1.548 raeburn 6121: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6122: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6123: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6124: $$listdata{$newparmkey}=1;
6125: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6126: }
6127: } else {
6128: # resource-level parameter
6129: foreach my $rid (@{$ids}) {
6130: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6131: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6132: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6133: $$listdata{$newparmkey}=1;
6134: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6135: }
6136: }
6137: }
6138: }
6139: }
6140:
1.563 damieng 6141: # UI to edit parameter settings starting with a list of all existing parameters.
6142: # (called by setoverview action)
6143: #
6144: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6145: sub overview {
1.568 raeburn 6146: my ($r,$parm_permission) = @_;
1.208 www 6147: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6148: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6149: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6150: my $readonly = 1;
6151: if ($parm_permission->{'edit'}) {
6152: undef($readonly);
6153: }
1.549 raeburn 6154: my $js = '<script type="text/javascript">'."\n".
6155: '// <![CDATA['."\n".
6156: &toggleparmtextbox_js()."\n".
6157: &validateparms_js()."\n".
6158: &ipacc_boxes_js()."\n".
1.558 raeburn 6159: &done_proctor_js()."\n".
1.588 raeburn 6160: &deeplink_js()."\n".
1.549 raeburn 6161: '// ]]>'."\n".
6162: '</script>'."\n";
1.414 droeschl 6163: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6164: text=>"Overview Mode"});
1.549 raeburn 6165: my %loaditems = (
6166: 'onload' => "showHideLenient();",
6167: );
6168:
6169: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6170: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6171: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6172: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6173: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6174:
1.208 www 6175: # Store modified
6176:
1.568 raeburn 6177: unless ($readonly) {
6178: &storedata($r,$crs,$dom);
6179: }
1.208 www 6180:
6181: # Read modified data
6182:
1.552 raeburn 6183: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6184:
1.214 www 6185:
6186: my $sortorder=$env{'form.sortorder'};
6187: unless ($sortorder) { $sortorder='realmstudent'; }
1.608 ! raeburn 6188: &sortmenu($r,$sortorder,'overview');
1.214 www 6189:
1.568 raeburn 6190: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6191:
6192: if ($readonly) {
6193: $r->print('<p>'.$submitbutton.'</p>');
6194: }
6195:
1.208 www 6196: # List data
6197:
1.568 raeburn 6198: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6199: $r->print(&tableend().'<p>');
6200: if ($foundkeys) {
6201: unless ($readonly) {
6202: $r->print('<p>'.$submitbutton.'</p>');
6203: }
6204: } else {
6205: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6206: }
6207: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6208: }
1.121 www 6209:
1.560 damieng 6210: # Unused sub.
1.563 damieng 6211: #
6212: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6213: sub clean_parameters {
6214: my ($r) = @_;
6215: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6216: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6217:
1.414 droeschl 6218: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6219: text=>"Clean Parameters"});
1.333 albertel 6220: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6221: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6222: $r->print(<<ENDOVER);
6223: $start_page
6224: $breadcrumbs
6225: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6226: ENDOVER
6227: # Store modified
6228:
6229: &storedata($r,$crs,$dom);
6230:
6231: # Read modified data
6232:
6233: my $resourcedata=&readdata($crs,$dom);
6234:
6235: # List data
6236:
6237: $r->print('<h3>'.
1.473 amueller 6238: &mt('These parameters refer to resources that do not exist.').
6239: '</h3>'.
6240: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6241: '<br />');
1.333 albertel 6242: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6243: '<tr>'.
6244: '<th>'.&mt('Delete').'</th>'.
6245: '<th>'.&mt('Parameter').'</th>'.
6246: '</tr>');
1.333 albertel 6247: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6248: next if (!exists($resourcedata->{$thiskey.'.type'})
6249: && $thiskey=~/\.type$/);
6250: my %data = &parse_key($thiskey);
6251: if (1) { #exists($data{'realm_exists'})
6252: #&& !$data{'realm_exists'}) {
6253: $r->print(&Apache::loncommon::start_data_table_row().
6254: '<tr>'.
6255: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6256:
6257: $r->print('<td>');
6258: my $display_value = $resourcedata->{$thiskey};
6259: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6260: $display_value =
6261: &Apache::lonlocal::locallocaltime($display_value);
6262: }
1.470 raeburn 6263: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6264: $parmitem = &mt($parmitem);
1.560 damieng 6265: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6266: $parmitem,$resourcedata->{$thiskey}));
6267: $r->print('<br />');
6268: if ($data{'scope_type'} eq 'all') {
6269: $r->print(&mt('All users'));
6270: } elsif ($data{'scope_type'} eq 'user') {
6271: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6272: } elsif ($data{'scope_type'} eq 'secgroup') {
6273: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6274: }
6275: $r->print('<br />');
6276: if ($data{'realm_type'} eq 'all') {
6277: $r->print(&mt('All Resources'));
6278: } elsif ($data{'realm_type'} eq 'folder') {
6279: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6280: } elsif ($data{'realm_type'} eq 'symb') {
6281: my ($map,$resid,$url) =
6282: &Apache::lonnet::decode_symb($data{'realm'});
6283: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6284: $url.' <br /> ',
6285: $resid.' <br /> ',$map));
6286: }
6287: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6288: $r->print('</td></tr>');
6289:
1.473 amueller 6290: }
1.333 albertel 6291: }
6292: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6293: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6294: '</p></form>');
6295: &endSettingsScreen($r);
6296: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6297: }
6298:
1.563 damieng 6299: # UI to shift all dates (called by dateshift1 action).
6300: # Used by overview mode.
6301: #
6302: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6303: sub date_shift_one {
6304: my ($r) = @_;
6305: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6306: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6307: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6308: my $sec = $env{'request.course.sec'};
1.414 droeschl 6309: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6310: text=>"Shifting Dates"});
1.594 raeburn 6311: my $submit_text = &mt('Shift all dates accordingly');
6312: if ($sec ne '') {
1.595 raeburn 6313: my @groups;
6314: if ($env{'request.course.groups'} ne '') {
6315: @groups = split(/:/,$env{'request.course.groups'});
6316: }
6317: if (@groups) {
6318: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6319: } else {
6320: $submit_text = &mt("Shift dates set just for your section, accordingly");
6321: }
1.594 raeburn 6322: }
1.390 www 6323: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6324: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6325: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6326: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6327: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6328: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6329: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6330: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6331: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6332: 'timeshifted',
6333: $env{'form.timebase'},,
6334: '').
6335: '</td></tr></table>'.
6336: '<input type="hidden" name="action" value="dateshift2" />'.
6337: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6338: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6339: &endSettingsScreen($r);
1.390 www 6340: $r->print(&Apache::loncommon::end_page());
6341: }
6342:
1.563 damieng 6343: # UI to shift all dates (second form).
6344: #
6345: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6346: sub date_shift_two {
6347: my ($r) = @_;
6348: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6349: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6350: my $sec = $env{'request.course.sec'};
1.531 raeburn 6351: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6352: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6353: text=>"Shifting Dates"});
1.390 www 6354: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6355: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6356: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6357: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6358: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6359: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6360: if ($sec ne '') {
1.595 raeburn 6361: my @groups;
6362: if ($env{'request.course.groups'} ne '') {
6363: @groups = split(/:/,$env{'request.course.groups'});
6364: }
6365: if (@groups) {
6366: $r->print('<p>'.
6367: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6368: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6369: &Apache::lonlocal::locallocaltime($timeshifted)).
6370: '</p>');
6371: } else {
6372: $r->print('<p>'.
6373: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6374: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6375: &Apache::lonlocal::locallocaltime($timeshifted)).
6376: '</p>');
6377: }
1.594 raeburn 6378: } else {
6379: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6380: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6381: &Apache::lonlocal::locallocaltime($timeshifted)).
6382: '</p>');
6383: }
1.390 www 6384: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6385: my $numchanges = 0;
6386: my $result = &dateshift($delta,\$numchanges);
6387: if ($result eq 'ok') {
6388: $r->print(
6389: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6390: $numchanges)));
6391: } elsif ($result eq 'con_delayed') {
6392: $r->print(
6393: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6394: $numchanges)));
6395: } else {
6396: $r->print(
6397: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6398: }
1.543 bisitz 6399: $r->print(
6400: '<br /><br />'.
6401: &Apache::lonhtmlcommon::actionbox(
6402: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6403: &endSettingsScreen($r);
1.390 www 6404: $r->print(&Apache::loncommon::end_page());
6405: }
6406:
1.563 damieng 6407: # Returns the different components of a resourcedata key.
6408: # Keys: scope_type, scope, realm_type, realm, realm_title,
6409: # realm_exists, parameter_part, parameter_name.
6410: # Was used by clean_parameters (which is unused).
6411: #
6412: # @param {string} $key - the parameter key
6413: # @returns {hash}
1.333 albertel 6414: sub parse_key {
6415: my ($key) = @_;
6416: my %data;
6417: my ($middle,$part,$name)=
1.572 damieng 6418: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6419: $data{'scope_type'} = 'all';
6420: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6421: $data{'scope'} = $1;
6422: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6423: $data{'scope_type'} = 'user';
6424: $data{'scope'} = [$1,$2];
6425: } else {
1.581 raeburn 6426: $data{'scope_type'} = 'secgroup';
1.560 damieng 6427: }
6428: $middle=~s/^\[(.*)\]//;
1.333 albertel 6429: }
6430: $middle=~s/\.+$//;
6431: $middle=~s/^\.+//;
6432: $data{'realm_type'}='all';
6433: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6434: $data{'realm'} = $1;
6435: $data{'realm_type'} = 'folder';
6436: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6437: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6438: } elsif ($middle) {
1.560 damieng 6439: $data{'realm'} = $middle;
6440: $data{'realm_type'} = 'symb';
6441: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6442: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6443: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6444: }
1.446 bisitz 6445:
1.333 albertel 6446: $data{'parameter_part'} = $part;
6447: $data{'parameter_name'} = $name;
6448:
6449: return %data;
6450: }
6451:
1.239 raeburn 6452:
1.563 damieng 6453: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6454: sub header {
1.507 www 6455: return &Apache::loncommon::start_page('Settings');
1.416 jms 6456: }
1.193 albertel 6457:
6458:
6459:
1.560 damieng 6460: ##################################################
6461: # MAIN MENU
6462: ##################################################
6463:
1.563 damieng 6464: # Content and problem settings main menu.
6465: #
6466: # @param {Apache2::RequestRec} $r - the Apache request
6467: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 6468: sub print_main_menu {
6469: my ($r,$parm_permission)=@_;
6470: #
1.414 droeschl 6471: $r->print(&header());
1.507 www 6472: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 6473: my $crstype = &Apache::loncommon::course_type();
6474: my $lc_crstype = lc($crstype);
6475:
6476: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 6477: $r->print(<<ENDMAINFORMHEAD);
6478: <form method="post" enctype="multipart/form-data"
6479: action="/adm/parmset" name="studentform">
6480: ENDMAINFORMHEAD
6481: #
1.195 albertel 6482: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6483: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 6484: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 6485: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 6486: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 6487: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
6488: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 6489: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
6490: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
6491: '/'.$env{'request.course.sec'});
6492: }
1.568 raeburn 6493: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
6494: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
6495: '/'.$env{'request.course.sec'});
6496: }
6497: my (%linktext,%linktitle,%url);
6498: if ($parm_permission->{'edit'}) {
6499: %linktext = (
6500: newoverview => 'Edit Resource Parameters - Overview Mode',
6501: settable => 'Edit Resource Parameters - Table Mode',
6502: setoverview => 'Modify Resource Parameters - Overview Mode',
6503: );
6504: %linktitle = (
6505: newoverview => 'Set/Modify resource parameters in overview mode.',
6506: settable => 'Set/Modify resource parameters in table mode.',
6507: setoverview => 'Set/Modify existing resource parameters in overview mode.',
6508: );
6509: } else {
6510: %linktext = (
6511: newoverview => 'View Resource Parameters - Overview Mode',
6512: settable => 'View Resource Parameters - Table Mode',
6513: setoverview => 'View Resource Parameters - Overview Mode',
6514: );
6515: %linktitle = (
6516: newoverview => 'Display resource parameters in overview mode.',
6517: settable => 'Display resource parameters in table mode.',
6518: setoverview => 'Display existing resource parameters in overview mode.',
6519: );
6520: }
6521: if ($mgr) {
6522: $linktext{'resettimes'} = 'Reset Student Access Times';
6523: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
6524: $url{'resettimes'} = '/adm/helper/resettimes.helper';
6525: } elsif ($vgr) {
6526: $linktext{'resettimes'} = 'Display Student Access Times',
6527: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
6528: $url{'resettimes'} = '/adm/accesstimes';
6529: }
1.193 albertel 6530: my @menu =
1.507 www 6531: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 6532: items => [
6533: { linktext => 'Portfolio Metadata',
6534: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 6535: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 6536: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 6537: icon =>'contact-new.png' ,
6538: },
1.568 raeburn 6539: { linktext => $linktext{'resettimes'},
6540: url => $url{'resettimes'},
6541: permission => ($vgr || $mgr),
6542: linktitle => $linktitle{'resettimes'},
6543: icon => 'start-here.png',
1.473 amueller 6544: },
1.520 raeburn 6545: { linktext => 'Blocking Communication/Resource Access',
6546: url => '/adm/setblock',
1.568 raeburn 6547: permission => ($vcb || $dcm),
1.520 raeburn 6548: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
6549: icon => 'comblock.png',
6550: },
1.473 amueller 6551: { linktext => 'Set Parameter Setting Default Actions',
6552: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 6553: permission => $parm_permission->{'setdefaults'},
1.473 amueller 6554: linktitle =>'Set default actions for parameters.' ,
6555: icon => 'folder-new.png' ,
6556: }]},
6557: { categorytitle => 'New and Existing Parameter Settings for Resources',
6558: items => [
6559: { linktext => 'Edit Resource Parameters - Helper Mode',
6560: url => '/adm/helper/parameter.helper',
1.568 raeburn 6561: permission => $parm_permission->{'helper'},
1.473 amueller 6562: linktitle =>'Set/Modify resource parameters in helper mode.' ,
6563: icon => 'dialog-information.png' ,
6564: #help => 'Parameter_Helper',
6565: },
1.568 raeburn 6566: { linktext => $linktext{'newoverview'},
1.473 amueller 6567: url => '/adm/parmset?action=newoverview',
1.568 raeburn 6568: permission => $parm_permission->{'newoverview'},
6569: linktitle => $linktitle{'newoverview'},
6570: icon => 'edit-find.png',
1.473 amueller 6571: #help => 'Parameter_Overview',
6572: },
1.568 raeburn 6573: { linktext => $linktext{'settable'},
1.473 amueller 6574: url => '/adm/parmset?action=settable',
1.568 raeburn 6575: permission => $parm_permission->{'settable'},
6576: linktitle => $linktitle{'settable'},
6577: icon => 'edit-copy.png',
1.473 amueller 6578: #help => 'Table_Mode',
6579: }]},
1.417 droeschl 6580: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 6581: items => [
1.570 raeburn 6582: { linktext => $linktext{'setoverview'},
1.473 amueller 6583: url => '/adm/parmset?action=setoverview',
1.568 raeburn 6584: permission => $parm_permission->{'setoverview'},
6585: linktitle => $linktitle{'setoverview'},
6586: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 6587: #help => 'Parameter_Overview',
6588: },
6589: { linktext => 'Change Log',
6590: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 6591: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 6592: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 6593: icon => 'document-properties.png',
1.473 amueller 6594: }]}
1.193 albertel 6595: );
1.414 droeschl 6596: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 6597: $r->print('</form>');
1.507 www 6598: &endSettingsScreen($r);
1.539 raeburn 6599: $r->print(&Apache::loncommon::end_page());
1.193 albertel 6600: return;
6601: }
1.414 droeschl 6602:
1.416 jms 6603:
6604:
1.560 damieng 6605: ##################################################
6606: # PORTFOLIO METADATA
6607: ##################################################
6608:
1.563 damieng 6609: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
6610: # It looks like field titles are not localized.
6611: #
6612: # @param {Apache2::RequestRec} $r - the Apache request
6613: # @param {string} $field_name - metadata field name
6614: # @param {string} $field_text - metadata field title, in English unless manually added
6615: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 6616: sub output_row {
1.347 banghart 6617: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 6618: my $output;
1.263 banghart 6619: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
6620: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 6621: if (!defined($options)) {
1.254 banghart 6622: $options = 'active,stuadd';
1.261 banghart 6623: $values = '';
1.252 banghart 6624: }
1.337 banghart 6625: if (!($options =~ /deleted/)) {
6626: my @options= ( ['active', 'Show to student'],
1.418 schafran 6627: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 6628: ['choices','Provide choices for students to select from']);
1.473 amueller 6629: # ['onlyone','Student may select only one choice']);
1.337 banghart 6630: if ($added_flag) {
6631: push @options,['deleted', 'Delete Metadata Field'];
6632: }
1.351 banghart 6633: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 6634: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 6635: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 6636: foreach my $opt (@options) {
1.560 damieng 6637: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
6638: $output .= &Apache::loncommon::continue_data_table_row();
6639: $output .= '<td>'.(' ' x 5).'<label>
6640: <input type="checkbox" name="'.
6641: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
6642: &mt($opt->[1]).'</label></td>';
6643: $output .= &Apache::loncommon::end_data_table_row();
6644: }
1.351 banghart 6645: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 6646: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 6647: $output .= &Apache::loncommon::end_data_table_row();
6648: my $multiple_checked;
6649: my $single_checked;
6650: if ($options =~ m/onlyone/) {
1.422 bisitz 6651: $multiple_checked = '';
1.423 bisitz 6652: $single_checked = ' checked="checked"';
1.351 banghart 6653: } else {
1.423 bisitz 6654: $multiple_checked = ' checked="checked"';
1.422 bisitz 6655: $single_checked = '';
1.351 banghart 6656: }
1.560 damieng 6657: $output .= &Apache::loncommon::continue_data_table_row();
6658: $output .= '<td>'.(' ' x 10).'
6659: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
6660: '.&mt('Student may select multiple choices from list').'</td>';
6661: $output .= &Apache::loncommon::end_data_table_row();
6662: $output .= &Apache::loncommon::continue_data_table_row();
6663: $output .= '<td>'.(' ' x 10).'
6664: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
6665: '.&mt('Student may select only one choice from list').'</td>';
6666: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 6667: }
6668: return ($output);
6669: }
1.416 jms 6670:
6671:
1.560 damieng 6672: # UI to order portfolio metadata fields.
1.563 damieng 6673: # Currently useless because addmetafield does not work.
6674: #
6675: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 6676: sub order_meta_fields {
6677: my ($r)=@_;
6678: my $idx = 1;
6679: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6680: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6681: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 6682: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 6683: &Apache::lonhtmlcommon::add_breadcrumb(
6684: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6685: text=>"Add Metadata Field"});
1.560 damieng 6686: &Apache::lonhtmlcommon::add_breadcrumb(
6687: {href=>"/adm/parmset?action=setrestrictmeta",
6688: text=>"Restrict Metadata"},
6689: {text=>"Order Metadata"});
1.345 banghart 6690: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 6691: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 6692: if ($env{'form.storeorder'}) {
6693: my $newpos = $env{'form.newpos'} - 1;
6694: my $currentpos = $env{'form.currentpos'} - 1;
6695: my @neworder = ();
1.548 raeburn 6696: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6697: my $i;
1.341 banghart 6698: if ($newpos > $currentpos) {
1.340 banghart 6699: # moving stuff up
6700: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 6701: $neworder[$i]=$oldorder[$i];
1.340 banghart 6702: }
6703: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 6704: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 6705: }
6706: $neworder[$newpos]=$oldorder[$currentpos];
6707: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 6708: $neworder[$i]=$oldorder[$i];
1.340 banghart 6709: }
6710: } else {
6711: # moving stuff down
1.473 amueller 6712: for ($i=0;$i<$newpos;$i++) {
6713: $neworder[$i]=$oldorder[$i];
6714: }
6715: $neworder[$newpos]=$oldorder[$currentpos];
6716: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
6717: $neworder[$i]=$oldorder[$i-1];
6718: }
6719: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
6720: $neworder[$i]=$oldorder[$i];
6721: }
1.340 banghart 6722: }
1.560 damieng 6723: my $ordered_fields = join ",", @neworder;
1.343 banghart 6724: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 6725: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6726: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 6727: }
1.357 raeburn 6728: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 6729: my $ordered_fields;
1.548 raeburn 6730: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6731: if (!@fields_in_order) {
6732: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 6733: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 6734: push @fields_in_order, $key;
1.341 banghart 6735: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 6736: }
1.341 banghart 6737: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 6738: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6739: }
1.340 banghart 6740: $r->print('<table>');
6741: my $num_fields = scalar(@fields_in_order);
6742: foreach my $key (@fields_in_order) {
6743: $r->print('<tr><td>');
6744: $r->print('<form method="post" action="">');
1.537 bisitz 6745: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 6746: for (my $i = 1;$i le $num_fields;$i ++) {
6747: if ($i eq $idx) {
6748: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
6749: } else {
6750: $r->print('<option value="'.$i.'">'.$i.'</option>');
6751: }
6752: }
6753: $r->print('</select></td><td>');
6754: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
6755: $r->print('<input type="hidden" name="storeorder" value="true" />');
6756: $r->print('</form>');
6757: $r->print($$fields{$key}.'</td></tr>');
6758: $idx ++;
6759: }
6760: $r->print('</table>');
1.507 www 6761: &endSettingsScreen($r);
1.340 banghart 6762: return 'ok';
6763: }
1.416 jms 6764:
6765:
1.563 damieng 6766: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
6767: # @returns {string}
1.359 banghart 6768: sub continue {
6769: my $output;
6770: $output .= '<form action="" method="post">';
6771: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 6772: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 6773: return ($output);
6774: }
1.416 jms 6775:
6776:
1.563 damieng 6777: # UI to add a metadata field.
6778: # Currenly does not work because of an HTML error (the field is not visible).
6779: #
6780: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 6781: sub addmetafield {
6782: my ($r)=@_;
1.414 droeschl 6783: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6784: text=>"Add Metadata Field"});
1.334 banghart 6785: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
6786: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 6787: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6788: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6789: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6790: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 6791: if (exists($env{'form.undelete'})) {
1.358 banghart 6792: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 6793: foreach my $meta_field(@meta_fields) {
6794: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
6795: $options =~ s/deleted//;
6796: $options =~ s/,,/,/;
6797: my $put_result = &Apache::lonnet::put('environment',
6798: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 6799:
1.586 raeburn 6800: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
6801: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
6802: '</strong>',$put_result).
6803: '<br />');
1.339 banghart 6804: }
1.359 banghart 6805: $r->print(&continue());
1.339 banghart 6806: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 6807: my $meta_field = $env{'form.fieldname'};
6808: my $display_field = $env{'form.fieldname'};
6809: $meta_field =~ s/\W/_/g;
1.338 banghart 6810: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 6811: my $put_result = &Apache::lonnet::put('environment',
6812: {'metadata.'.$meta_field.'.values'=>"",
6813: 'metadata.'.$meta_field.'.added'=>"$display_field",
6814: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 6815: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
6816: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
6817: '<br />');
1.359 banghart 6818: $r->print(&continue());
1.335 banghart 6819: } else {
1.357 raeburn 6820: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 6821: if ($fields) {
1.586 raeburn 6822: $r->print(&mt('You may undelete previously deleted fields.').
6823: '<br />'.
6824: &mt('Check those you wish to undelete and click Undelete.').
6825: '<br />');
1.339 banghart 6826: $r->print('<form method="post" action="">');
6827: foreach my $key(keys(%$fields)) {
1.581 raeburn 6828: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 6829: }
1.586 raeburn 6830: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 6831: $r->print('</form>');
6832: }
1.586 raeburn 6833: $r->print('<hr />'.
6834: &mt('[_1]Or[_2] you may enter a new metadata field name.',
6835: '<strong>','</strong>').
1.581 raeburn 6836: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 6837: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 6838: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 6839: $r->print('</form>');
1.334 banghart 6840: }
1.507 www 6841: &endSettingsScreen($r);
1.334 banghart 6842: }
1.416 jms 6843:
6844:
6845:
1.560 damieng 6846: # Display or save portfolio metadata.
1.563 damieng 6847: #
6848: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 6849: sub setrestrictmeta {
1.240 banghart 6850: my ($r)=@_;
1.242 banghart 6851: my $next_meta;
1.244 banghart 6852: my $output;
1.245 banghart 6853: my $item_num;
1.246 banghart 6854: my $put_result;
1.414 droeschl 6855: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 6856: text=>"Restrict Metadata"});
1.280 albertel 6857: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 6858: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 6859: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6860: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6861: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6862: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 6863: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 6864: my $save_field = '';
1.586 raeburn 6865: my %lt = &Apache::lonlocal::texthash(
6866: addm => 'Add Metadata Field',
6867: ordm => 'Order Metadata Fields',
6868: save => 'Save',
6869: );
1.259 banghart 6870: if ($env{'form.restrictmeta'}) {
1.254 banghart 6871: foreach my $field (sort(keys(%env))) {
1.252 banghart 6872: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 6873: my $options;
1.252 banghart 6874: my $meta_field = $1;
6875: my $meta_key = $2;
1.253 banghart 6876: if ($save_field ne $meta_field) {
1.252 banghart 6877: $save_field = $meta_field;
1.473 amueller 6878: if ($env{'form.'.$meta_field.'_stuadd'}) {
6879: $options.='stuadd,';
6880: }
6881: if ($env{'form.'.$meta_field.'_choices'}) {
6882: $options.='choices,';
6883: }
6884: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
6885: $options.='onlyone,';
6886: }
6887: if ($env{'form.'.$meta_field.'_active'}) {
6888: $options.='active,';
6889: }
6890: if ($env{'form.'.$meta_field.'_deleted'}) {
6891: $options.='deleted,';
6892: }
1.259 banghart 6893: my $name = $save_field;
1.560 damieng 6894: $put_result = &Apache::lonnet::put('environment',
6895: {'metadata.'.$meta_field.'.options'=>$options,
6896: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
6897: },$dom,$crs);
1.252 banghart 6898: }
6899: }
6900: }
6901: }
1.296 albertel 6902: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 6903: {'freshen_cache' => 1});
1.335 banghart 6904: # Get the default metadata fields
1.258 albertel 6905: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 6906: # Now get possible added metadata fields
1.357 raeburn 6907: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 6908: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 6909: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 6910: if ($field ne 'courserestricted') {
1.586 raeburn 6911: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 6912: }
1.255 banghart 6913: }
1.351 banghart 6914: my $buttons = (<<ENDButtons);
1.586 raeburn 6915: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 6916: </form><br />
6917: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 6918: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 6919: </form>
6920: <br />
6921: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 6922: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 6923: ENDButtons
1.337 banghart 6924: my $added_flag = 1;
1.335 banghart 6925: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 6926: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 6927: }
1.347 banghart 6928: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 6929: $r->print(<<ENDenv);
1.259 banghart 6930: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 6931: $output
1.351 banghart 6932: $buttons
1.340 banghart 6933: </form>
1.244 banghart 6934: ENDenv
1.507 www 6935: &endSettingsScreen($r);
1.280 albertel 6936: $r->print(&Apache::loncommon::end_page());
1.240 banghart 6937: return 'ok';
6938: }
1.416 jms 6939:
6940:
1.563 damieng 6941: # Returns metadata fields that have been manually added.
6942: #
6943: # @param {string} $cid - course id
6944: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 6945: sub get_added_meta_fieldnames {
1.357 raeburn 6946: my ($cid) = @_;
1.335 banghart 6947: my %fields;
6948: foreach my $key(%env) {
1.357 raeburn 6949: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 6950: my $field_name = $1;
6951: my ($display_field_name) = $env{$key};
6952: $fields{$field_name} = $display_field_name;
6953: }
6954: }
6955: return \%fields;
6956: }
1.416 jms 6957:
6958:
1.563 damieng 6959: # Returns metadata fields that have been manually added and deleted.
6960: #
6961: # @param {string} $cid - course id
6962: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 6963: sub get_deleted_meta_fieldnames {
1.357 raeburn 6964: my ($cid) = @_;
1.339 banghart 6965: my %fields;
6966: foreach my $key(%env) {
1.357 raeburn 6967: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 6968: my $field_name = $1;
6969: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
6970: my ($display_field_name) = $env{$key};
6971: $fields{$field_name} = $display_field_name;
6972: }
6973: }
6974: }
6975: return \%fields;
6976: }
1.560 damieng 6977:
6978:
6979: ##################################################
6980: # PARAMETER SETTINGS DEFAULT ACTIONS
6981: ##################################################
6982:
6983: # UI to change parameter setting default actions
1.563 damieng 6984: #
6985: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 6986: sub defaultsetter {
1.280 albertel 6987: my ($r) = @_;
6988:
1.414 droeschl 6989: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 6990: text=>"Set Defaults"});
1.531 raeburn 6991: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6992: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6993: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 6994: my $start_page =
1.531 raeburn 6995: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 6996: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 6997: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6998: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 6999: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 7000:
1.221 www 7001: my @ids=();
7002: my %typep=();
7003: my %keyp=();
7004: my %allparms=();
7005: my %allparts=();
7006: my %allmaps=();
7007: my %mapp=();
7008: my %symbp=();
7009: my %maptitles=();
7010: my %uris=();
7011: my %keyorder=&standardkeyorder();
7012: my %defkeytype=();
7013:
1.446 bisitz 7014: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 7015: \%mapp, \%symbp,\%maptitles,\%uris,
7016: \%keyorder,\%defkeytype);
1.224 www 7017: if ($env{'form.storerules'}) {
1.560 damieng 7018: my %newrules=();
7019: my @delrules=();
7020: my %triggers=();
7021: foreach my $key (keys(%env)) {
1.225 albertel 7022: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 7023: my $tempkey=$1;
7024: my $action=$env{$key};
1.226 www 7025: if ($action) {
1.560 damieng 7026: $newrules{$tempkey.'_action'}=$action;
7027: if ($action ne 'default') {
7028: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
7029: $triggers{$whichparm}.=$tempkey.':';
7030: }
7031: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
7032: if (&isdateparm($defkeytype{$tempkey})) {
7033: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
7034: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
7035: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
7036: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
7037: } else {
7038: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
7039: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
7040: }
7041: } else {
7042: push(@delrules,$tempkey.'_action');
7043: push(@delrules,$tempkey.'_type');
7044: push(@delrules,$tempkey.'_hours');
7045: push(@delrules,$tempkey.'_min');
7046: push(@delrules,$tempkey.'_sec');
7047: push(@delrules,$tempkey.'_value');
7048: }
1.473 amueller 7049: }
7050: }
1.560 damieng 7051: foreach my $key (keys(%allparms)) {
7052: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 7053: }
1.560 damieng 7054: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
7055: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
7056: &resetrulescache();
1.224 www 7057: }
1.227 www 7058: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 7059: 'hours' => 'Hours',
7060: 'min' => 'Minutes',
7061: 'sec' => 'Seconds',
7062: 'yes' => 'Yes',
7063: 'no' => 'No');
1.222 www 7064: my @standardoptions=('','default');
7065: my @standarddisplay=('',&mt('Default value when manually setting'));
7066: my @dateoptions=('','default');
7067: my @datedisplay=('',&mt('Default value when manually setting'));
7068: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7069: unless ($tempkey) { next; }
7070: push @standardoptions,'when_setting_'.$tempkey;
7071: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
7072: if (&isdateparm($defkeytype{$tempkey})) {
7073: push @dateoptions,'later_than_'.$tempkey;
7074: push @datedisplay,&mt('Automatically set later than ').$tempkey;
7075: push @dateoptions,'earlier_than_'.$tempkey;
7076: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
7077: }
1.222 www 7078: }
1.563 damieng 7079: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
7080: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 7081: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 7082: &Apache::loncommon::start_data_table_header_row().
7083: "<th>".&mt('Rule for parameter').'</th><th>'.
7084: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
7085: &Apache::loncommon::end_data_table_header_row());
1.221 www 7086: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7087: unless ($tempkey) { next; }
7088: $r->print("\n".&Apache::loncommon::start_data_table_row().
7089: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
7090: my $action=&rulescache($tempkey.'_action');
7091: $r->print('<select name="'.$tempkey.'_action">');
7092: if (&isdateparm($defkeytype{$tempkey})) {
7093: for (my $i=0;$i<=$#dateoptions;$i++) {
7094: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
7095: $r->print("\n<option value='$dateoptions[$i]'".
7096: ($dateoptions[$i] eq $action?' selected="selected"':'').
7097: ">$datedisplay[$i]</option>");
7098: }
7099: } else {
7100: for (my $i=0;$i<=$#standardoptions;$i++) {
7101: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
7102: $r->print("\n<option value='$standardoptions[$i]'".
7103: ($standardoptions[$i] eq $action?' selected="selected"':'').
7104: ">$standarddisplay[$i]</option>");
7105: }
1.473 amueller 7106: }
1.560 damieng 7107: $r->print('</select>');
7108: unless (&isdateparm($defkeytype{$tempkey})) {
7109: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7110: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7111: }
1.560 damieng 7112: $r->print("\n</td><td>\n");
1.222 www 7113:
1.221 www 7114: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7115: my $days=&rulescache($tempkey.'_days');
7116: my $hours=&rulescache($tempkey.'_hours');
7117: my $min=&rulescache($tempkey.'_min');
7118: my $sec=&rulescache($tempkey.'_sec');
7119: $r->print(<<ENDINPUTDATE);
7120: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7121: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7122: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7123: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7124: ENDINPUTDATE
1.560 damieng 7125: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7126: my $yeschecked='';
7127: my $nochecked='';
7128: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7129: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7130:
7131: $r->print(<<ENDYESNO);
7132: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7133: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7134: ENDYESNO
1.221 www 7135: } else {
1.560 damieng 7136: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7137: }
1.318 albertel 7138: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7139: }
1.318 albertel 7140: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7141: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7142: &mt('Save').'" /></form>'."\n");
7143: &endSettingsScreen($r);
7144: $r->print(&Apache::loncommon::end_page());
1.220 www 7145: return;
7146: }
1.193 albertel 7147:
1.560 damieng 7148: ##################################################
7149: # PARAMETER CHANGES LOG
7150: ##################################################
7151:
1.563 damieng 7152: # Returns some info for a parameter log entry.
7153: # Returned entries:
7154: # $realm - HTML title for the parameter level and resource
7155: # $section - parameter section
7156: # $name - parameter name
7157: # $part - parameter part
7158: # $what - $part.'.'.$name
7159: # $middle - resource symb ?
7160: # $uname - user name (same as given)
7161: # $udom - user domain (same as given)
7162: # $issection - section or group name
7163: # $realmdescription - title for the parameter level and resource (without using HTML)
7164: #
7165: # @param {string} $key - parameter log key
7166: # @param {string} $uname - user name
7167: # @param {string} $udom - user domain
7168: # @param {boolean} $typeflag - .type log entry
7169: # @returns {Array}
1.290 www 7170: sub components {
1.581 raeburn 7171: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7172:
7173: if ($typeflag) {
1.560 damieng 7174: $key=~s/\.type$//;
1.290 www 7175: }
1.330 albertel 7176:
7177: my ($middle,$part,$name)=
1.572 damieng 7178: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7179: my $issection;
1.330 albertel 7180:
1.290 www 7181: my $section=&mt('All Students');
7182: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7183: $issection=$1;
7184: $section=&mt('Group/Section').': '.$issection;
7185: $middle=~s/^\[(.*)\]//;
1.290 www 7186: }
7187: $middle=~s/\.+$//;
7188: $middle=~s/^\.+//;
1.291 www 7189: if ($uname) {
1.560 damieng 7190: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7191: $issection='';
1.291 www 7192: }
1.316 albertel 7193: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7194: my $realmdescription=&mt('all resources');
1.556 raeburn 7195: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7196: my $mapurl = $1;
7197: my $maplevel = $2;
7198: my $leveltitle = &mt('Folder/Map');
7199: if ($maplevel eq 'rec') {
7200: $leveltitle = &mt('Recursive');
7201: }
1.560 damieng 7202: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7203: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7204: $mapurl.')</span></span>';
7205: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7206: } elsif ($middle) {
7207: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7208: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7209: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7210: ' in '.$map.' id: '.$id.')</span></span>';
7211: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7212: }
1.291 www 7213: my $what=$part.'.'.$name;
1.330 albertel 7214: return ($realm,$section,$name,$part,
1.473 amueller 7215: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7216: }
1.293 www 7217:
1.563 damieng 7218: my %standard_parms; # hash parameter name -> parameter title (not localized)
7219: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7220:
1.563 damieng 7221: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7222: sub load_parameter_names {
1.583 raeburn 7223: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7224: while (my $configline=<$config>) {
1.560 damieng 7225: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7226: chomp($configline);
7227: my ($short,$plain)=split(/:/,$configline);
7228: my (undef,$name,$type)=split(/\&/,$short,3);
7229: if ($type eq 'display') {
7230: $standard_parms{$name} = $plain;
1.469 raeburn 7231: } elsif ($type eq 'type') {
1.560 damieng 7232: $standard_parms_types{$name} = $plain;
1.469 raeburn 7233: }
1.328 albertel 7234: }
7235: close($config);
7236: $standard_parms{'int_pos'} = 'Positive Integer';
7237: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7238: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7239: }
7240:
1.563 damieng 7241: # Returns a parameter title for standard parameters, the name for others.
7242: #
7243: # @param {string} $name - parameter name
7244: # @returns {string}
1.292 www 7245: sub standard_parameter_names {
7246: my ($name)=@_;
1.328 albertel 7247: if (!%standard_parms) {
1.560 damieng 7248: &load_parameter_names();
1.328 albertel 7249: }
1.292 www 7250: if ($standard_parms{$name}) {
1.560 damieng 7251: return $standard_parms{$name};
1.446 bisitz 7252: } else {
1.560 damieng 7253: return $name;
1.292 www 7254: }
7255: }
1.290 www 7256:
1.563 damieng 7257: # Returns a parameter type for standard parameters, undef for others.
7258: #
7259: # @param {string} $name - parameter name
7260: # @returns {string}
1.469 raeburn 7261: sub standard_parameter_types {
7262: my ($name)=@_;
7263: if (!%standard_parms_types) {
7264: &load_parameter_names();
7265: }
7266: if ($standard_parms_types{$name}) {
7267: return $standard_parms_types{$name};
7268: }
7269: return;
7270: }
1.309 www 7271:
1.563 damieng 7272: # Returns a parameter level title (not localized) from the parameter level name.
7273: #
7274: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7275: # @returns {string}
1.557 raeburn 7276: sub standard_parameter_levels {
7277: my ($name)=@_;
7278: my %levels = (
7279: 'resourcelevel' => 'a single resource',
7280: 'maplevel' => 'the enclosing map/folder',
7281: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7282: 'courselevel' => 'the general (course) level',
7283: );
7284: if ($levels{$name}) {
7285: return $levels{$name};
7286: }
7287: return;
7288: }
7289:
1.560 damieng 7290: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7291: #
7292: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7293: sub parm_change_log {
1.568 raeburn 7294: my ($r,$parm_permission)=@_;
1.531 raeburn 7295: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7296: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7297: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7298: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7299: text=>"Parameter Change Log"});
1.522 raeburn 7300: my $js = '<script type="text/javascript">'."\n".
7301: '// <![CDATA['."\n".
7302: &Apache::loncommon::display_filter_js('parmslog')."\n".
7303: '// ]]>'."\n".
7304: '</script>'."\n";
7305: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7306: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7307: &startSettingsScreen($r,'parmset',$crstype);
7308: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7309:
1.301 www 7310: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7311:
1.522 raeburn 7312: $r->print('<div class="LC_left_float">'.
7313: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7314: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7315: method="post" name="parameterlog">');
1.446 bisitz 7316:
1.311 albertel 7317: my %saveable_parameters = ('show' => 'scalar',);
7318: &Apache::loncommon::store_course_settings('parameter_log',
7319: \%saveable_parameters);
7320: &Apache::loncommon::restore_course_settings('parameter_log',
7321: \%saveable_parameters);
1.522 raeburn 7322: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7323: '<input type="submit" value="'.&mt('Display').'" />'.
7324: '</form></fieldset></div><br clear="all" />');
1.301 www 7325:
1.568 raeburn 7326: my $readonly = 1;
7327: if ($parm_permission->{'edit'}) {
7328: undef($readonly);
7329: }
1.531 raeburn 7330: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7331: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7332: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7333: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7334: unless ($readonly) {
7335: $r->print('<th>'.&mt('Announce').'</th>');
7336: }
7337: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7338: my $shown=0;
1.349 www 7339: my $folder='';
7340: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7341: my $last='';
7342: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7343: &GDBM_READER(),0640)) {
7344: $last=$hash{'last_known'};
7345: untie(%hash);
7346: }
7347: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7348: }
1.595 raeburn 7349: my $numgroups = 0;
7350: my @groups;
7351: if ($env{'request.course.groups'} ne '') {
7352: @groups = split(/:/,$env{'request.course.groups'});
7353: $numgroups = scalar(@groups);
7354: }
1.560 damieng 7355: foreach my $id (sort {
7356: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7357: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7358: }
7359: my $aid = (split('00000',$a))[-1];
7360: my $bid = (split('00000',$b))[-1];
7361: return $bid<=>$aid;
1.473 amueller 7362: } (keys(%parmlog))) {
1.294 www 7363: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7364: my $count = 0;
7365: my $time =
7366: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7367: my $plainname =
7368: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7369: $parmlog{$id}{'exe_udom'});
7370: my $about_me_link =
7371: &Apache::loncommon::aboutmewrapper($plainname,
7372: $parmlog{$id}{'exe_uname'},
7373: $parmlog{$id}{'exe_udom'});
7374: my $send_msg_link='';
1.568 raeburn 7375: if ((!$readonly) &&
7376: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7377: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7378: $send_msg_link ='<br />'.
7379: &Apache::loncommon::messagewrapper(&mt('Send message'),
7380: $parmlog{$id}{'exe_uname'},
7381: $parmlog{$id}{'exe_udom'});
7382: }
7383: my $row_start=&Apache::loncommon::start_data_table_row();
7384: my $makenewrow=0;
7385: my %istype=();
7386: my $output;
7387: foreach my $changed (reverse(sort(@changes))) {
7388: my $value=$parmlog{$id}{'logentry'}{$changed};
7389: my $typeflag = ($changed =~/\.type$/ &&
7390: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7391: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7392: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7393: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7394: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7395: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7396: if ($uname ne '') {
7397: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7398: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7399: }
7400: }
7401: if ($env{'form.displayfilter'} eq 'currentfolder') {
7402: if ($folder) {
7403: if ($middle!~/^\Q$folder\E/) { next; }
7404: }
7405: }
7406: if ($typeflag) {
7407: $istype{$parmname}=$value;
7408: if (!$env{'form.includetypes'}) { next; }
7409: }
7410: $count++;
7411: if ($makenewrow) {
7412: $output .= $row_start;
7413: } else {
7414: $makenewrow=1;
7415: }
1.470 raeburn 7416: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7417: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7418: &mt($parmitem).'</td><td>'.
7419: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7420: my $stillactive=0;
7421: if ($parmlog{$id}{'delflag'}) {
7422: $output .= &mt('Deleted');
7423: } else {
7424: if ($typeflag) {
1.470 raeburn 7425: my $parmitem = &standard_parameter_names($value);
7426: $parmitem = &mt($parmitem);
1.560 damieng 7427: $output .= &mt('Type: [_1]',$parmitem);
7428: } else {
1.584 raeburn 7429: my $toolsymb;
7430: if ($middle =~ /ext\.tool$/) {
7431: $toolsymb = $middle;
7432: }
1.560 damieng 7433: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7434: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7435: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7436: my $showvalue = $value;
7437: if ($istype{$parmname} eq '') {
7438: my $type = &standard_parameter_types($parmname);
7439: if ($type ne '') {
7440: if (&isdateparm($type)) {
7441: $showvalue =
7442: &Apache::lonlocal::locallocaltime($value);
7443: }
7444: }
7445: } else {
1.560 damieng 7446: if (&isdateparm($istype{$parmname})) {
7447: $showvalue = &Apache::lonlocal::locallocaltime($value);
7448: }
1.469 raeburn 7449: }
7450: $output .= $showvalue;
1.560 damieng 7451: if ($value ne $all[$level]) {
7452: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7453: } else {
7454: $stillactive=1;
7455: }
7456: }
1.473 amueller 7457: }
1.568 raeburn 7458: $output .= '</td>';
7459:
7460: unless ($readonly) {
7461: $output .= '<td>';
7462: if ($stillactive) {
7463: my $parmitem = &standard_parameter_names($parmname);
7464: $parmitem = &mt($parmitem);
7465: my $title=&mt('Changed [_1]',$parmitem);
7466: my $description=&mt('Changed [_1] for [_2] to [_3]',
7467: $parmitem,$realmdescription,
7468: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
7469: if (($uname) && ($udom)) {
7470: $output .=
7471: &Apache::loncommon::messagewrapper('Notify User',
7472: $uname,$udom,$title,
7473: $description);
7474: } else {
7475: $output .=
7476: &Apache::lonrss::course_blog_link($id,$title,
7477: $description);
7478: }
1.560 damieng 7479: }
1.568 raeburn 7480: $output .= '</td>';
1.560 damieng 7481: }
1.568 raeburn 7482: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 7483: }
1.560 damieng 7484: if ($env{'form.displayfilter'} eq 'containing') {
7485: my $wholeentry=$about_me_link.':'.
7486: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
7487: $output;
7488: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 7489: }
1.349 www 7490: if ($count) {
1.560 damieng 7491: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
7492: <td rowspan="'.$count.'">'.$about_me_link.
7493: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
7494: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
7495: $send_msg_link.'</td>'.$output);
7496: $shown++;
7497: }
7498: if (!($env{'form.show'} eq &mt('all')
7499: || $shown<=$env{'form.show'})) { last; }
1.286 www 7500: }
1.301 www 7501: $r->print(&Apache::loncommon::end_data_table());
1.507 www 7502: &endSettingsScreen($r);
1.284 www 7503: $r->print(&Apache::loncommon::end_page());
7504: }
7505:
1.560 damieng 7506: ##################################################
7507: # MISC !
7508: ##################################################
7509:
1.563 damieng 7510: # Stores slot information.
1.560 damieng 7511: # Used by table UI
1.563 damieng 7512: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7513: #
7514: # @param {string} $slot_name - slot name
7515: # @param {string} $cdom - course domain
7516: # @param {string} $cnum - course number
7517: # @param {string} $symb - resource symb
7518: # @param {string} $uname - user name
7519: # @param {string} $udom - user domain
7520: # @returns {string} - 'ok' or error name
1.437 raeburn 7521: sub update_slots {
7522: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
7523: my %slot=&Apache::lonnet::get_slot($slot_name);
7524: if (!keys(%slot)) {
7525: return 'error: slot does not exist';
7526: }
7527: my $max=$slot{'maxspace'};
7528: if (!defined($max)) { $max=99999; }
7529:
7530: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
7531: "^$slot_name\0");
7532: my ($tmp)=%consumed;
7533: if ($tmp=~/^error: 2 / ) {
7534: return 'error: unable to determine current slot status';
7535: }
7536: my $last=0;
7537: foreach my $key (keys(%consumed)) {
7538: my $num=(split('\0',$key))[1];
7539: if ($num > $last) { $last=$num; }
7540: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7541: return 'ok';
7542: }
7543: }
7544:
7545: if (scalar(keys(%consumed)) >= $max) {
7546: return 'error: no space left in slot';
7547: }
7548: my $wanted=$last+1;
7549:
7550: my %reservation=('name' => $uname.':'.$udom,
7551: 'timestamp' => time,
7552: 'symb' => $symb);
7553:
7554: my $success=&Apache::lonnet::newput('slot_reservations',
7555: {"$slot_name\0$wanted" =>
7556: \%reservation},
7557: $cdom, $cnum);
1.438 raeburn 7558: if ($success eq 'ok') {
7559: my %storehash = (
7560: symb => $symb,
7561: slot => $slot_name,
7562: action => 'reserve',
7563: context => 'parameter',
7564: );
1.526 raeburn 7565: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7566: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 7567:
1.526 raeburn 7568: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7569: '',$uname,$udom,$uname,$udom);
1.438 raeburn 7570: }
1.437 raeburn 7571: return $success;
7572: }
7573:
1.563 damieng 7574: # Deletes a slot reservation.
1.560 damieng 7575: # Used by table UI
1.563 damieng 7576: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7577: #
7578: # @param {string} $slot_name - slot name
7579: # @param {string} $cdom - course domain
7580: # @param {string} $cnum - course number
7581: # @param {string} $uname - user name
7582: # @param {string} $udom - user domain
7583: # @param {string} $symb - resource symb
7584: # @returns {string} - 'ok' or error name
1.437 raeburn 7585: sub delete_slots {
7586: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
7587: my $delresult;
7588: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
7589: $cnum, "^$slot_name\0");
7590: if (&Apache::lonnet::error(%consumed)) {
7591: return 'error: unable to determine current slot status';
7592: }
7593: my ($tmp)=%consumed;
7594: if ($tmp=~/^error: 2 /) {
7595: return 'error: unable to determine current slot status';
7596: }
7597: foreach my $key (keys(%consumed)) {
7598: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7599: my $num=(split('\0',$key))[1];
7600: my $entry = $slot_name.'\0'.$num;
7601: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
7602: $cdom,$cnum);
7603: if ($delresult eq 'ok') {
7604: my %storehash = (
7605: symb => $symb,
7606: slot => $slot_name,
7607: action => 'release',
7608: context => 'parameter',
7609: );
1.526 raeburn 7610: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7611: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 7612: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7613: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 7614: }
7615: }
7616: }
7617: return $delresult;
7618: }
7619:
1.563 damieng 7620: # Returns true if there is a current course.
1.560 damieng 7621: # Used by handler
1.563 damieng 7622: #
7623: # @returns {boolean}
1.355 albertel 7624: sub check_for_course_info {
7625: my $navmap = Apache::lonnavmaps::navmap->new();
7626: return 1 if ($navmap);
7627: return 0;
7628: }
7629:
1.563 damieng 7630: # Returns the current course host and host LON-CAPA version.
7631: #
7632: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 7633: sub parameter_release_vars {
1.504 raeburn 7634: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7635: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
7636: my $chostname = &Apache::lonnet::hostname($chome);
7637: my ($cmajor,$cminor) =
7638: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
7639: return ($chostname,$cmajor,$cminor);
7640: }
7641:
1.563 damieng 7642: # Checks if the course host version can handle a parameter required version,
7643: # and if it does, stores the release needed for the course.
7644: #
7645: # @param {string} $name - parameter name
7646: # @param {string} $value - parameter value
7647: # @param {string} $valmatch - name of the test used for checking the value
7648: # @param {string} $namematch - name of the test used for checking the name
7649: # @param {string} $needsrelease - version needed by the parameter, major.minor
7650: # @param {integer} $cmajor - course major version number
7651: # @param {integer} $cminor - course minor version number
7652: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 7653: sub parameter_releasecheck {
1.557 raeburn 7654: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 7655: my $needsnewer;
7656: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
7657: if (($cmajor < $needsmajor) ||
7658: ($cmajor == $needsmajor && $cminor < $needsminor)) {
7659: $needsnewer = 1;
1.557 raeburn 7660: } elsif ($name) {
7661: if ($valmatch) {
7662: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
7663: } elsif ($value) {
7664: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
7665: }
7666: } elsif ($namematch) {
7667: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 7668: }
7669: return $needsnewer;
7670: }
7671:
1.568 raeburn 7672: sub get_permission {
7673: my %permission;
7674: my $allowed = 0;
7675: return (\%permission,$allowed) unless ($env{'request.course.id'});
7676: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
7677: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
7678: $env{'request.course.sec'}))) {
7679: %permission= (
7680: 'edit' => 1,
7681: 'set' => 1,
7682: 'setoverview' => 1,
7683: 'addmetadata' => 1,
7684: 'ordermetadata' => 1,
7685: 'setrestrictmeta' => 1,
7686: 'newoverview' => 1,
7687: 'setdefaults' => 1,
7688: 'settable' => 1,
7689: 'parameterchangelog' => 1,
7690: 'cleanparameters' => 1,
7691: 'dateshift1' => 1,
7692: 'dateshift2' => 1,
7693: 'helper' => 1,
7694: );
7695: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
7696: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
7697: $env{'request.course.sec'}))) {
7698: %permission = (
7699: 'set' => 1,
7700: 'settable' => 1,
7701: 'newoverview' => 1,
7702: 'setoverview' => 1,
7703: 'parameterchangelog' => 1,
7704: );
7705: }
7706: foreach my $perm (values(%permission)) {
7707: if ($perm) { $allowed=1; last; }
7708: }
7709: return (\%permission,$allowed);
7710: }
7711:
1.560 damieng 7712: ##################################################
7713: # HANDLER
7714: ##################################################
7715:
7716: # Main handler for lonparmset.
7717: # Sub called based on request parameters action and command:
7718: # no command or action: print_main_menu
7719: # command 'set': assessparms (direct access to table mode for a resource)
7720: # (this can also be accessed simply with the symb parameter)
7721: # action 'setoverview': overview (display all existing parameter settings)
7722: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
7723: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
7724: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
7725: # action 'newoverview': newoverview (overview mode)
7726: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
7727: # action 'settable': assessparms (table mode)
7728: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
7729: # blog postings, user notification changes)
7730: # action 'cleanparameters': clean_parameters (unused)
7731: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
7732: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 7733: sub handler {
1.43 albertel 7734: my $r=shift;
1.30 www 7735:
1.376 albertel 7736: &reset_caches();
7737:
1.414 droeschl 7738: &Apache::loncommon::content_type($r,'text/html');
7739: $r->send_http_header;
7740: return OK if $r->header_only;
7741:
1.193 albertel 7742: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 7743: ['action','state',
1.205 www 7744: 'pres_marker',
7745: 'pres_value',
1.206 www 7746: 'pres_type',
1.506 www 7747: 'filter','part',
1.390 www 7748: 'udom','uname','symb','serial','timebase']);
1.131 www 7749:
1.83 bowersj2 7750:
1.193 albertel 7751: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 7752: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 7753: text=>"Content and Problem Settings",
1.473 amueller 7754: faq=>10,
7755: bug=>'Instructor Interface',
1.442 droeschl 7756: help =>
7757: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 7758:
1.30 www 7759: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 7760: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 7761: my $exists = &check_for_course_info();
7762:
1.568 raeburn 7763: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 7764: #
7765: # Main switch on form.action and form.state, as appropriate
7766: #
7767: # Check first if coming from someone else headed directly for
7768: # the table mode
1.568 raeburn 7769: if (($parm_permission->{'set'}) &&
7770: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
7771: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
7772: &assessparms($r,$parm_permission);
1.193 albertel 7773: } elsif (! exists($env{'form.action'})) {
7774: &print_main_menu($r,$parm_permission);
1.568 raeburn 7775: } elsif (!$parm_permission->{$env{'form.action'}}) {
7776: &print_main_menu($r,$parm_permission);
1.414 droeschl 7777: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 7778: &overview($r,$parm_permission);
1.560 damieng 7779: } elsif ($env{'form.action'} eq 'addmetadata') {
7780: &addmetafield($r);
7781: } elsif ($env{'form.action'} eq 'ordermetadata') {
7782: &order_meta_fields($r);
1.414 droeschl 7783: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 7784: &setrestrictmeta($r);
1.414 droeschl 7785: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 7786: &newoverview($r,$parm_permission);
1.414 droeschl 7787: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 7788: &defaultsetter($r);
7789: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 7790: &assessparms($r,$parm_permission);
1.414 droeschl 7791: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 7792: &parm_change_log($r,$parm_permission);
1.414 droeschl 7793: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 7794: &clean_parameters($r);
1.414 droeschl 7795: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 7796: &date_shift_one($r);
1.414 droeschl 7797: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 7798: &date_shift_two($r);
1.446 bisitz 7799: }
1.43 albertel 7800: } else {
1.1 www 7801: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 7802: if ($exists) {
7803: $env{'user.error.msg'}=
7804: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
7805: } else {
7806: $env{'user.error.msg'}=
7807: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
7808: }
7809: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 7810: }
1.376 albertel 7811: &reset_caches();
7812:
1.43 albertel 7813: return OK;
1.1 www 7814: }
7815:
7816: 1;
7817: __END__
7818:
7819:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>