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