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