Annotation of loncom/interface/lonparmset.pm, revision 1.626
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.626 ! raeburn 4: # $Id: lonparmset.pm,v 1.625 2025/06/30 21:35:05 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.623 raeburn 332: use POSIX qw (floor);
1.617 raeburn 333: use Text::Wrap();
1.416 jms 334: use LONCAPA qw(:DEFAULT :match);
335:
336:
1.560 damieng 337: ##################################################
338: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
339: ##################################################
340:
341: # Page header
1.561 damieng 342: #
343: # @param {Apache2::RequestRec} $r - Apache request object
344: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
345: # @param {string} $crstype - course type ('Community' for community settings)
1.507 www 346: sub startSettingsScreen {
1.531 raeburn 347: my ($r,$mode,$crstype)=@_;
1.507 www 348:
1.531 raeburn 349: my $tabtext = &mt('Course Settings');
350: if ($crstype eq 'Community') {
351: $tabtext = &mt('Community Settings');
352: }
1.507 www 353: $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
354: $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b> '.
1.531 raeburn 355: $tabtext.
1.507 www 356: ' </b></a></li>');
357:
1.523 raeburn 358: $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507 www 359: &mt('Content and Problem Settings').'</b></a></li>');
360: $r->print("\n".'</ul>'."\n");
1.523 raeburn 361: $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 362: }
363:
1.560 damieng 364: # Page footer
1.507 www 365: sub endSettingsScreen {
366: my ($r)=@_;
367: $r->print('</div></div></div>');
368: }
369:
370:
371:
1.560 damieng 372: ##################################################
1.563 damieng 373: # (mostly) TABLE MODE
1.560 damieng 374: # (parmval is also used for the log of parameter changes)
375: ##################################################
376:
1.566 damieng 377: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561 damieng 378: #
379: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 380: # @param {string} $id - resource id or map pc
1.561 damieng 381: # @param {string} $def - the resource's default value for this parameter
382: # @param {string} $uname - user name
383: # @param {string} $udom - user domain
384: # @param {string} $csec - section name
385: # @param {string} $cgroup - group name
386: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
387: # @returns {Array}
1.2 www 388: sub parmval {
1.275 raeburn 389: my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
390: return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
391: $cgroup,$courseopt);
1.201 www 392: }
393:
1.561 damieng 394: # Returns an array containing
395: # - the most specific level that is defined for that parameter (integer)
396: # - an array with the level as index and the parameter value as value (when defined)
397: # (level 1 is the most specific and will have precedence)
398: #
399: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 400: # @param {string} $symb - resource symb or map src
1.561 damieng 401: # @param {string} $def - the resource's default value for this parameter
402: # @param {string} $uname - user name
403: # @param {string} $udom - user domain
404: # @param {string} $csec - section name
405: # @param {string} $cgroup - group name
406: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
407: # @returns {Array}
1.201 www 408: sub parmval_by_symb {
1.275 raeburn 409: my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200 www 410:
1.352 albertel 411: my $useropt;
412: if ($uname ne '' && $udom ne '') {
1.561 damieng 413: $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352 albertel 414: }
1.200 www 415:
1.8 www 416: my $result='';
1.44 albertel 417: my @outpar=();
1.2 www 418: # ----------------------------------------------------- Cascading lookup scheme
1.446 bisitz 419: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 420: $map = &Apache::lonnet::deversion($map);
1.561 damieng 421:
422: # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
423: # any change should be reflected there.
424:
1.201 www 425: my $symbparm=$symb.'.'.$what;
1.556 raeburn 426: my $recurseparm=$map.'___(rec).'.$what;
1.201 www 427: my $mapparm=$map.'___(all).'.$what;
1.10 www 428:
1.269 raeburn 429: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
430: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 431: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 432: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
433:
1.190 albertel 434: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
435: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 436: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 437: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
438:
439: my $courselevel=$env{'request.course.id'}.'.'.$what;
440: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 441: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 442: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2 www 443:
1.11 www 444:
1.182 albertel 445: # --------------------------------------------------------- first, check course
1.11 www 446:
1.561 damieng 447: # 18 - General Course
1.200 www 448: if (defined($$courseopt{$courselevel})) {
1.556 raeburn 449: $outpar[18]=$$courseopt{$courselevel};
450: $result=18;
451: }
452:
1.561 damieng 453: # 17 - Map or Folder level in course (recursive)
1.556 raeburn 454: if (defined($$courseopt{$courseleveli})) {
455: $outpar[17]=$$courseopt{$courseleveli};
456: $result=17;
1.43 albertel 457: }
1.11 www 458:
1.561 damieng 459: # 16 - Map or Folder level in course (non-recursive)
1.200 www 460: if (defined($$courseopt{$courselevelm})) {
1.556 raeburn 461: $outpar[16]=$$courseopt{$courselevelm};
462: $result=16;
1.43 albertel 463: }
1.11 www 464:
1.182 albertel 465: # ------------------------------------------------------- second, check default
466:
1.561 damieng 467: # 15 - resource default
1.556 raeburn 468: if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182 albertel 469:
470: # ------------------------------------------------------ third, check map parms
471:
1.556 raeburn 472:
1.561 damieng 473: # 14 - map default
1.376 albertel 474: my $thisparm=&parmhash($symbparm);
1.556 raeburn 475: if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182 albertel 476:
1.561 damieng 477: # 13 - resource level in course
1.200 www 478: if (defined($$courseopt{$courselevelr})) {
1.556 raeburn 479: $outpar[13]=$$courseopt{$courselevelr};
480: $result=13;
1.43 albertel 481: }
1.11 www 482:
1.182 albertel 483: # ------------------------------------------------------ fourth, back to course
1.352 albertel 484: if ($csec ne '') {
1.561 damieng 485: # 12 - General for section
1.200 www 486: if (defined($$courseopt{$seclevel})) {
1.556 raeburn 487: $outpar[12]=$$courseopt{$seclevel};
488: $result=12;
489: }
1.561 damieng 490: # 11 - Map or Folder level for section (recursive)
1.556 raeburn 491: if (defined($$courseopt{$secleveli})) {
492: $outpar[11]=$$courseopt{$secleveli};
493: $result=11;
494: }
1.561 damieng 495: # 10 - Map or Folder level for section (non-recursive)
1.200 www 496: if (defined($$courseopt{$seclevelm})) {
1.556 raeburn 497: $outpar[10]=$$courseopt{$seclevelm};
498: $result=10;
499: }
1.561 damieng 500: # 9 - resource level in section
1.200 www 501: if (defined($$courseopt{$seclevelr})) {
1.556 raeburn 502: $outpar[9]=$$courseopt{$seclevelr};
503: $result=9;
504: }
1.43 albertel 505: }
1.275 raeburn 506: # ------------------------------------------------------ fifth, check course group
1.352 albertel 507: if ($cgroup ne '') {
1.561 damieng 508: # 8 - General for group
1.269 raeburn 509: if (defined($$courseopt{$grplevel})) {
1.556 raeburn 510: $outpar[8]=$$courseopt{$grplevel};
511: $result=8;
512: }
1.561 damieng 513: # 7 - Map or Folder level for group (recursive)
1.556 raeburn 514: if (defined($$courseopt{$grpleveli})) {
515: $outpar[7]=$$courseopt{$grpleveli};
516: $result=7;
1.269 raeburn 517: }
1.561 damieng 518: # 6 - Map or Folder level for group (non-recursive)
1.269 raeburn 519: if (defined($$courseopt{$grplevelm})) {
1.556 raeburn 520: $outpar[6]=$$courseopt{$grplevelm};
521: $result=6;
1.269 raeburn 522: }
1.561 damieng 523: # 5 - resource level in group
1.269 raeburn 524: if (defined($$courseopt{$grplevelr})) {
1.556 raeburn 525: $outpar[5]=$$courseopt{$grplevelr};
526: $result=5;
1.269 raeburn 527: }
528: }
1.11 www 529:
1.556 raeburn 530: # ---------------------------------------------------------- sixth, check user
1.11 www 531:
1.352 albertel 532: if ($uname ne '') {
1.561 damieng 533: # 4 - General for specific student
534: if (defined($$useropt{$courselevel})) {
535: $outpar[4]=$$useropt{$courselevel};
536: $result=4;
537: }
1.556 raeburn 538:
1.561 damieng 539: # 3 - Map or Folder level for specific student (recursive)
540: if (defined($$useropt{$courseleveli})) {
541: $outpar[3]=$$useropt{$courseleveli};
542: $result=3;
543: }
1.473 amueller 544:
1.561 damieng 545: # 2 - Map or Folder level for specific student (non-recursive)
546: if (defined($$useropt{$courselevelm})) {
547: $outpar[2]=$$useropt{$courselevelm};
548: $result=2;
549: }
1.473 amueller 550:
1.561 damieng 551: # 1 - resource level for specific student
552: if (defined($$useropt{$courselevelr})) {
553: $outpar[1]=$$useropt{$courselevelr};
554: $result=1;
555: }
1.43 albertel 556: }
1.44 albertel 557: return ($result,@outpar);
1.2 www 558: }
559:
1.198 www 560:
561:
1.376 albertel 562: # --- Caches local to lonparmset
563:
1.446 bisitz 564:
1.561 damieng 565: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376 albertel 566: sub reset_caches {
567: &resetparmhash();
568: &resetsymbcache();
569: &resetrulescache();
1.203 www 570: }
571:
1.561 damieng 572: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
573: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376 albertel 574: {
1.561 damieng 575: my $parmhashid; # course identifier, to initialize the cache only once for a course
576: my %parmhash; # the parameter cache
577: # reset map parameter hash
1.376 albertel 578: sub resetparmhash {
1.560 damieng 579: undef($parmhashid);
580: undef(%parmhash);
1.376 albertel 581: }
1.446 bisitz 582:
1.561 damieng 583: # dump the _parms.db database into %parmhash
1.376 albertel 584: sub cacheparmhash {
1.560 damieng 585: if ($parmhashid eq $env{'request.course.fn'}) { return; }
586: my %parmhashfile;
587: if (tie(%parmhashfile,'GDBM_File',
588: $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
589: %parmhash=%parmhashfile;
590: untie(%parmhashfile);
591: $parmhashid=$env{'request.course.fn'};
592: }
1.201 www 593: }
1.446 bisitz 594:
1.561 damieng 595: # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376 albertel 596: sub parmhash {
1.560 damieng 597: my ($id) = @_;
598: &cacheparmhash();
599: return $parmhash{$id};
1.376 albertel 600: }
1.560 damieng 601: }
1.376 albertel 602:
1.566 damieng 603: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446 bisitz 604: {
1.561 damieng 605: my $symbsid; # course identifier, to initialize the cache only once for a course
606: my %symbs; # hash id->symb
607: # reset the id->symb cache
1.376 albertel 608: sub resetsymbcache {
1.560 damieng 609: undef($symbsid);
610: undef(%symbs);
1.376 albertel 611: }
1.446 bisitz 612:
1.566 damieng 613: # returns the resource symb or map src corresponding to a resource id or map pc
614: # (using lonnavmaps and a cache)
1.376 albertel 615: sub symbcache {
1.560 damieng 616: my $id=shift;
617: if ($symbsid ne $env{'request.course.id'}) {
618: undef(%symbs);
619: }
620: if (!$symbs{$id}) {
621: my $navmap = Apache::lonnavmaps::navmap->new();
622: if ($id=~/\./) {
623: my $resource=$navmap->getById($id);
624: $symbs{$id}=$resource->symb();
625: } else {
626: my $resource=$navmap->getByMapPc($id);
627: $symbs{$id}=&Apache::lonnet::declutter($resource->src());
628: }
629: $symbsid=$env{'request.course.id'};
1.473 amueller 630: }
1.560 damieng 631: return $symbs{$id};
1.473 amueller 632: }
1.560 damieng 633: }
1.201 www 634:
1.561 damieng 635: # cache for parameter default actions (stored in parmdefactions.db)
1.446 bisitz 636: {
1.561 damieng 637: my $rulesid; # course identifier, to initialize the cache only once for a course
638: my %rules; # parameter default actions hash
1.376 albertel 639: sub resetrulescache {
1.560 damieng 640: undef($rulesid);
641: undef(%rules);
1.376 albertel 642: }
1.446 bisitz 643:
1.561 damieng 644: # returns the value for a given key in the parameter default action hash
1.376 albertel 645: sub rulescache {
1.560 damieng 646: my $id=shift;
647: if ($rulesid ne $env{'request.course.id'}
648: && !defined($rules{$id})) {
649: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
650: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
651: %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
652: $rulesid=$env{'request.course.id'};
653: }
654: return $rules{$id};
1.221 www 655: }
656: }
657:
1.416 jms 658:
1.561 damieng 659: # Returns the values of the parameter type default action
660: # "default value when manually setting".
661: # If none is defined, ('','','','','') is returned.
662: #
663: # @param {string} $type - parameter type
664: # @returns {Array<string>} - (hours, min, sec, value)
1.229 www 665: sub preset_defaults {
666: my $type=shift;
667: if (&rulescache($type.'_action') eq 'default') {
1.560 damieng 668: # yes, there is something
669: return (&rulescache($type.'_hours'),
670: &rulescache($type.'_min'),
671: &rulescache($type.'_sec'),
672: &rulescache($type.'_value'));
1.229 www 673: } else {
1.560 damieng 674: # nothing there or something else
675: return ('','','','','');
1.229 www 676: }
677: }
678:
1.416 jms 679:
1.561 damieng 680: # Checks that a date is after enrollment start date and before
681: # enrollment end date.
682: # Returns HTML with a warning if it is not, or the empty string otherwise.
683: # This is used by both overview and table modes.
684: #
685: # @param {integer} $checkdate - the date to check.
686: # @returns {string} - HTML possibly containing a localized warning message.
1.277 www 687: sub date_sanity_info {
688: my $checkdate=shift;
689: unless ($checkdate) { return ''; }
690: my $result='';
691: my $crsprefix='course.'.$env{'request.course.id'}.'.';
692: if ($env{$crsprefix.'default_enrollment_end_date'}) {
693: if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413 bisitz 694: $result.='<div class="LC_warning">'
695: .&mt('After course enrollment end!')
696: .'</div>';
1.277 www 697: }
698: }
699: if ($env{$crsprefix.'default_enrollment_start_date'}) {
700: if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413 bisitz 701: $result.='<div class="LC_warning">'
702: .&mt('Before course enrollment start!')
703: .'</div>';
1.277 www 704: }
705: }
1.413 bisitz 706: # Preparation for additional warnings about dates in the past/future.
707: # An improved, more context sensitive version is recommended,
708: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
709: # if ($checkdate<time) {
710: # $result.='<div class="LC_info">'
711: # .'('.&mt('in the past').')'
712: # .'</div>';
713: # }
714: # if ($checkdate>time) {
715: # $result.='<div class="LC_info">'
716: # .'('.&mt('in the future').')'
717: # .'</div>';
718: # }
1.277 www 719: return $result;
720: }
1.561 damieng 721:
722:
723: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186 www 724: #
1.566 damieng 725: # @param {string} $sresid - resource id or map pc
1.565 damieng 726: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 727: # @param {integer} $snum - level
728: # @param {string} $nval - new value
729: # @param {string} $ntype - new type
730: # @param {string} $uname - username
731: # @param {string} $udom - userdomain
732: # @param {string} $csec - section name
733: # @param {string} $cgroup - group name
1.186 www 734: sub storeparm {
1.269 raeburn 735: my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275 raeburn 736: &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197 www 737: }
738:
1.561 damieng 739: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
740:
741: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
742: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
743: #
1.566 damieng 744: # @param {string} $symb - resource symb or map src
1.565 damieng 745: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 746: # @param {integer} $snum - level
747: # @param {string} $nval - new value
748: # @param {string} $ntype - new type
749: # @param {string} $uname - username
750: # @param {string} $udom - userdomain
751: # @param {string} $csec - section name
752: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
753: # @param {string} $cgroup - group name
1.197 www 754: sub storeparm_by_symb {
1.275 raeburn 755: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226 www 756: unless ($recflag) {
1.560 damieng 757: # first time call
758: %recstack=();
759: $recflag=1;
1.226 www 760: }
1.560 damieng 761: # store parameter
1.226 www 762: &storeparm_by_symb_inner
1.473 amueller 763: ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560 damieng 764: # don't do anything if parameter was reset
1.266 www 765: unless ($nval) { return; }
1.226 www 766: my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560 damieng 767: # remember that this was set
1.226 www 768: $recstack{$parm}=1;
1.560 damieng 769: # what does this trigger?
1.226 www 770: foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560 damieng 771: # don't backfire
772: unless ((!$triggered) || ($recstack{$triggered})) {
773: my $action=&rulescache($triggered.'_action');
774: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
775: # set triggered parameter on same level
776: my $newspnam=$prefix.$triggered;
777: my $newvalue='';
778: my $active=1;
779: if ($action=~/^when\_setting/) {
780: # are there restrictions?
781: if (&rulescache($triggered.'_triggervalue')=~/\w/) {
782: $active=0;
1.565 damieng 783: foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560 damieng 784: if (lc($possiblevalue) eq lc($nval)) { $active=1; }
785: }
786: }
787: $newvalue=&rulescache($triggered.'_value');
788: } else {
789: my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
790: if ($action=~/^later\_than/) {
791: $newvalue=$nval+$totalsecs;
792: } else {
793: $newvalue=$nval-$totalsecs;
794: }
795: }
796: if ($active) {
797: &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
798: $uname,$udom,$csec,$recflag,$cgroup);
799: }
800: }
1.226 www 801: }
802: return '';
803: }
804:
1.561 damieng 805: # Adds all given arguments to the course parameter log.
806: # @returns {string} - the answer to the lonnet query.
1.293 www 807: sub log_parmset {
1.525 raeburn 808: return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284 www 809: }
810:
1.561 damieng 811: # Store a parameter value and type by symb, without using the parameter default actions.
812: # Expire related sheets.
813: #
1.566 damieng 814: # @param {string} $symb - resource symb or map src
1.561 damieng 815: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
816: # @param {integer} $snum - level
817: # @param {string} $nval - new value
818: # @param {string} $ntype - new type
819: # @param {string} $uname - username
820: # @param {string} $udom - userdomain
821: # @param {string} $csec - section name
822: # @param {string} $cgroup - group name
823: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226 www 824: sub storeparm_by_symb_inner {
1.197 www 825: # ---------------------------------------------------------- Get symb, map, etc
1.269 raeburn 826: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197 www 827: # ---------------------------------------------------------- Construct prefixes
1.186 www 828: $spnam=~s/\_([^\_]+)$/\.$1/;
1.446 bisitz 829: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 830: $map = &Apache::lonnet::deversion($map);
831:
1.197 www 832: my $symbparm=$symb.'.'.$spnam;
1.556 raeburn 833: my $recurseparm=$map.'___(rec).'.$spnam;
1.197 www 834: my $mapparm=$map.'___(all).'.$spnam;
835:
1.269 raeburn 836: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
837: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 838: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 839: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
840:
1.190 albertel 841: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
842: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 843: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 844: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446 bisitz 845:
1.190 albertel 846: my $courselevel=$env{'request.course.id'}.'.'.$spnam;
847: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 848: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 849: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446 bisitz 850:
1.186 www 851: my $storeunder='';
1.578 raeburn 852: my $possreplace='';
1.556 raeburn 853: if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578 raeburn 854: if (($snum==17) || ($snum==3)) {
855: $storeunder=$courseleveli;
856: $possreplace=$courselevelm;
857: }
858: if (($snum==16) || ($snum==2)) {
859: $storeunder=$courselevelm;
860: $possreplace=$courseleveli;
861: }
1.556 raeburn 862: if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
863: if ($snum==12) { $storeunder=$seclevel; }
1.578 raeburn 864: if ($snum==11) {
865: $storeunder=$secleveli;
866: $possreplace=$seclevelm;
867: }
868: if ($snum==10) {
869: $storeunder=$seclevelm;
870: $possreplace=$secleveli;
871: }
1.556 raeburn 872: if ($snum==9) { $storeunder=$seclevelr; }
873: if ($snum==8) { $storeunder=$grplevel; }
1.578 raeburn 874: if ($snum==7) {
875: $storeunder=$grpleveli;
876: $possreplace=$grplevelm;
877: }
878: if ($snum==6) {
879: $storeunder=$grplevelm;
880: $possreplace=$grpleveli;
881: }
1.556 raeburn 882: if ($snum==5) { $storeunder=$grplevelr; }
1.269 raeburn 883:
1.446 bisitz 884:
1.186 www 885: my $delete;
886: if ($nval eq '') { $delete=1;}
887: my %storecontent = ($storeunder => $nval,
1.473 amueller 888: $storeunder.'.type' => $ntype);
1.186 www 889: my $reply='';
1.560 damieng 890:
1.556 raeburn 891: if ($snum>4) {
1.186 www 892: # ---------------------------------------------------------------- Store Course
893: #
1.560 damieng 894: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
895: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
896: # Expire sheets
897: &Apache::lonnet::expirespread('','','studentcalc');
898: if (($snum==13) || ($snum==9) || ($snum==5)) {
899: &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578 raeburn 900: } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560 damieng 901: &Apache::lonnet::expirespread('','','assesscalc',$map);
902: } else {
903: &Apache::lonnet::expirespread('','','assesscalc');
904: }
905: # Store parameter
906: if ($delete) {
907: $reply=&Apache::lonnet::del
908: ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
909: &log_parmset(\%storecontent,1);
910: } else {
911: $reply=&Apache::lonnet::cput
912: ('resourcedata',\%storecontent,$cdom,$cnum);
913: &log_parmset(\%storecontent);
1.578 raeburn 914: if ($possreplace) {
915: my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
916: if (ref($resdata) eq 'HASH') {
917: if (exists($resdata->{$possreplace})) {
918: if (&Apache::lonnet::del
919: ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
920: &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);
921: }
922: }
923: }
924: }
1.560 damieng 925: }
926: &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186 www 927: } else {
928: # ------------------------------------------------------------------ Store User
929: #
1.560 damieng 930: # Expire sheets
931: &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
932: if ($snum==1) {
933: &Apache::lonnet::expirespread
934: ($uname,$udom,'assesscalc',$symb);
1.578 raeburn 935: } elsif (($snum==2) || ($snum==3)) {
1.560 damieng 936: &Apache::lonnet::expirespread
937: ($uname,$udom,'assesscalc',$map);
938: } else {
939: &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
940: }
941: # Store parameter
942: if ($delete) {
943: $reply=&Apache::lonnet::del
944: ('resourcedata',[keys(%storecontent)],$udom,$uname);
945: &log_parmset(\%storecontent,1,$uname,$udom);
946: } else {
947: $reply=&Apache::lonnet::cput
948: ('resourcedata',\%storecontent,$udom,$uname);
949: &log_parmset(\%storecontent,0,$uname,$udom);
1.578 raeburn 950: if ($possreplace) {
951: my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
952: if (ref($resdata) eq 'HASH') {
953: if (exists($resdata->{$possreplace})) {
954: if (&Apache::lonnet::del
955: ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
956: &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
957: $uname,$udom);
958: }
959: }
960: }
961: }
1.560 damieng 962: }
963: &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186 www 964: }
1.446 bisitz 965:
1.186 www 966: if ($reply=~/^error\:(.*)/) {
1.560 damieng 967: return "<span class=\"LC_error\">Write Error: $1</span>";
1.186 www 968: }
969: return '';
970: }
971:
1.9 www 972:
1.561 damieng 973: # Returns HTML with the value of the given parameter,
974: # using a readable format for dates, and
975: # a warning if there is a problem with a date.
976: # Used by table mode.
977: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
978: #
979: # @param {string} $value - the parameter value
980: # @param {string} $type - the parameter type
981: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9 www 982: sub valout {
1.600 raeburn 983: my ($value,$type,$editable)=@_;
1.59 matthew 984: my $result = '';
985: # Values of zero are valid.
986: if (! $value && $value ne '0') {
1.528 bisitz 987: if ($editable) {
988: $result =
989: '<img src="/res/adm/pages/editmap.png"'
990: .' alt="'.&mt('Change').'"'
1.539 raeburn 991: .' title="'.&mt('Change').'" style="border:0;" />';
1.528 bisitz 992: } else {
993: $result=' ';
994: }
1.59 matthew 995: } else {
1.622 raeburn 996: if (($type eq 'date_interval') || ($type eq 'string_grace')) {
997: if ($type eq 'string_grace') {
998: my @items;
999: if ($value =~ /,/) {
1000: @items = split(/,/,$value);
1.558 raeburn 1001: } else {
1.622 raeburn 1002: @items = ($value);
1003: }
1004: foreach my $item (@items) {
1005: if ($item =~ /^\d+:(0|1)\.?\d*:(0|1)$/) {
1006: my ($totalsecs,$fraction,$grad) = split(/:/,$item);
1.623 raeburn 1007: $result .= &grace_to_humanstr($totalsecs);
1.622 raeburn 1008: if (($fraction >=0) && ($fraction <=1)) {
1009: $result .= ' | '.$fraction.' '.&mt('pts');
1010: if ($grad == 1) {
1011: $result .= ' ('.&mt('gradual').')';
1012: }
1013: }
1014: $result .= ', ';
1015: }
1016: }
1017: $result =~ s/, $//;
1018: } else {
1019: my ($totalsecs,$donesuffix) = split(/_/,$value,2);
1020: $result = &interval_to_humanstr($totalsecs);
1021: my ($usesdone,$donebuttontext,$proctor,$secretkey);
1022: if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
1023: $donebuttontext = $1;
1024: (undef,$proctor,$secretkey) = split(/_/,$2);
1025: $usesdone = 'done';
1026: } elsif ($donesuffix =~ /^done(|_.+)$/) {
1027: $donebuttontext = &mt('Done');
1028: ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
1029: }
1030: if ($usesdone eq 'done') {
1031: if ($secretkey) {
1032: $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
1033: } else {
1034: $result .= ' + "'.$donebuttontext.'"';
1035: }
1.559 raeburn 1036: }
1.554 raeburn 1037: }
1.213 www 1038: } elsif (&isdateparm($type)) {
1.361 albertel 1039: $result = &Apache::lonlocal::locallocaltime($value).
1.560 damieng 1040: &date_sanity_info($value);
1.59 matthew 1041: } else {
1042: $result = $value;
1.517 www 1043: $result=~s/\,/\, /gs;
1.560 damieng 1044: $result = &HTML::Entities::encode($result,'"<>&');
1.59 matthew 1045: }
1046: }
1047: return $result;
1.9 www 1048: }
1049:
1.622 raeburn 1050: sub interval_to_humanstr {
1051: my ($totalsecs) = @_;
1052: my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1053: my @timer;
1054: $year=$year-70;
1055: $mday--;
1056: if ($year) {
1057: push(@timer,&mt('[quant,_1,yr]',$year));
1058: }
1059: if ($mon) {
1060: push(@timer,&mt('[quant,_1,mth]',$mon));
1061: }
1062: if ($mday) {
1063: push(@timer,&mt('[quant,_1,day]',$mday));
1064: }
1065: if ($hour) {
1066: push(@timer,&mt('[quant,_1,hr]',$hour));
1067: }
1068: if ($min) {
1069: push(@timer,&mt('[quant,_1,min]',$min));
1070: }
1071: if ($sec) {
1072: push(@timer,&mt('[quant,_1,sec]',$sec));
1073: }
1074: if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
1075: push(@timer,&mt('[quant,_1,sec]',0));
1076: }
1077: return '<span style="white-space:nowrap">'.join('</span>, <span style="white-space:nowrap">',@timer).'</span>';
1078: }
1.59 matthew 1079:
1.623 raeburn 1080: sub grace_to_humanstr {
1081: my ($totalsecs) = @_;
1082: my @timer;
1083: my $weeks = floor($totalsecs/604800);
1084: $totalsecs -= $weeks*604800;
1085: my $days = floor($totalsecs/86400);
1086: $totalsecs -= $days*86400;
1087: my $hours = floor($totalsecs/3600);
1088: $totalsecs -= $hours*3600;
1089: my $mins= floor($totalsecs/60);
1090: $totalsecs -= $mins*60;
1091: if ($weeks) {
1092: push(@timer,&mt('[quant,_1,wk]',$weeks));
1093: }
1094: if ($days) {
1095: push(@timer,&mt('[quant,_1,day]',$days));
1096: }
1097: if ($hours) {
1098: push(@timer,&mt('[quant,_1,hr]',$hours));
1099: }
1100: if ($mins) {
1101: push(@timer,&mt('[quant,_1,min]',$mins));
1102: }
1103: if (!@timer) { # Special case: all entries 0 -> display "0 mins" intead of empty field to keep this field editable
1104: push(@timer,&mt('[quant,_1,min]',0));
1105: }
1106: return '<span style="white-space:nowrap">'.join('</span>, <span style="white-space:nowrap">',@timer).'</span>';
1107: }
1108:
1.561 damieng 1109: # Returns HTML containing a link on a parameter value, for table mode.
1110: # The link uses the javascript function 'pjump'.
1111: #
1112: # @param {string} $type - parameter type
1113: # @param {string} $dis - dialog title for editing the parameter value and type
1114: # @param {string} $value - parameter value
1115: # @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.
1116: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
1117: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588 raeburn 1118: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
1119: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5 www 1120: sub plink {
1.588 raeburn 1121: my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23 www 1122: my $winvalue=$value;
1123: unless ($winvalue) {
1.592 raeburn 1124: if (&isdateparm($type) || (&is_specialstring($type))) {
1.190 albertel 1125: $winvalue=$env{'form.recent_'.$type};
1.591 raeburn 1126: } elsif ($type eq 'string_yesno') {
1127: if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
1128: $winvalue=$env{'form.recent_string'};
1129: }
1.23 www 1130: } else {
1.190 albertel 1131: $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23 www 1132: }
1133: }
1.229 www 1134: my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
1135: my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
1136: unless (defined($winvalue)) { $winvalue=$val; }
1.593 raeburn 1137: my $valout = &valout($value,$type,1);
1.429 raeburn 1138: my $unencmarker = $marker;
1.378 albertel 1139: foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588 raeburn 1140: \$hour, \$min, \$sec, \$extra) {
1.560 damieng 1141: $$item = &HTML::Entities::encode($$item,'"<>&');
1142: $$item =~ s/\'/\\\'/g;
1.378 albertel 1143: }
1.429 raeburn 1144: return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473 amueller 1145: '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588 raeburn 1146: .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578 raeburn 1147: $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
1148: &mt('recursive').'</td></tr>' : '').'</table>';
1149:
1.5 www 1150: }
1151:
1.561 damieng 1152: # Javascript for table mode.
1.280 albertel 1153: sub page_js {
1154:
1.81 www 1155: my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88 matthew 1156: my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280 albertel 1157:
1158: return(<<ENDJS);
1159: <script type="text/javascript">
1.454 bisitz 1160: // <![CDATA[
1.44 albertel 1161:
1.88 matthew 1162: $pjump_def
1.44 albertel 1163:
1164: function psub() {
1.591 raeburn 1165: var specstring = /^string_!(yesno|any)/i;
1.44 albertel 1166: if (document.parmform.pres_marker.value!='') {
1167: document.parmform.action+='#'+document.parmform.pres_marker.value;
1168: var typedef=new Array();
1169: typedef=document.parmform.pres_type.value.split('_');
1.562 damieng 1170: if (document.parmform.pres_type.value!='') {
1.589 raeburn 1171: if ((typedef[0]=='date') ||
1.591 raeburn 1172: (specstring.test(document.parmform.pres_type.value))) {
1.562 damieng 1173: eval('document.parmform.recent_'+
1174: document.parmform.pres_type.value+
1175: '.value=document.parmform.pres_value.value;');
1176: } else {
1177: eval('document.parmform.recent_'+typedef[0]+
1178: '.value=document.parmform.pres_value.value;');
1179: }
1.44 albertel 1180: }
1181: document.parmform.submit();
1182: } else {
1183: document.parmform.pres_value.value='';
1184: document.parmform.pres_marker.value='';
1185: }
1186: }
1187:
1.57 albertel 1188: function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
1189: var options = "width=" + w + ",height=" + h + ",";
1190: options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
1191: options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
1192: var newWin = window.open(url, wdwName, options);
1193: newWin.focus();
1194: }
1.523 raeburn 1195:
1.454 bisitz 1196: // ]]>
1.523 raeburn 1197:
1.44 albertel 1198: </script>
1.81 www 1199: $selscript
1.280 albertel 1200: ENDJS
1201:
1202: }
1.507 www 1203:
1.561 damieng 1204: # Javascript to show or hide the map selection (function showHide_courseContent),
1205: # for table and overview modes.
1.523 raeburn 1206: sub showhide_js {
1207: return <<"COURSECONTENTSCRIPT";
1208:
1209: function showHide_courseContent() {
1210: var parmlevValue=document.getElementById("parmlev").value;
1211: if (parmlevValue == 'general') {
1212: document.getElementById('mapmenu').style.display="none";
1213: } else {
1214: if ((parmlevValue == "full") || (parmlevValue == "map")) {
1215: document.getElementById('mapmenu').style.display ="";
1216: } else {
1217: document.getElementById('mapmenu').style.display="none";
1218: }
1219: }
1220: return;
1221: }
1222:
1223: COURSECONTENTSCRIPT
1224: }
1225:
1.561 damieng 1226: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549 raeburn 1227: sub toggleparmtextbox_js {
1228: return <<"ENDSCRIPT";
1229:
1230: if (!document.getElementsByClassName) {
1231: function getElementsByClassName(node, classname) {
1232: var a = [];
1233: var re = new RegExp('(^| )'+classname+'( |$)');
1234: var els = node.getElementsByTagName("*");
1235: for(var i=0,j=els.length; i<j; i++)
1236: if(re.test(els[i].className))a.push(els[i]);
1237: return a;
1238: }
1239: }
1240:
1241: function showHideLenient() {
1242: var lenients;
1243: var setRegExp = /^set_/;
1244: if (document.getElementsByClassName) {
1245: lenients = document.getElementsByClassName('LC_lenient_radio');
1246: } else {
1247: lenients = getElementsByClassName(document.body,'LC_lenient_radio');
1248: }
1249: if (lenients != 'undefined') {
1250: for (var i=0; i<lenients.length; i++) {
1251: if (lenients[i].checked) {
1252: if (lenients[i].value == 'weighted') {
1253: if (setRegExp.test(lenients[i].name)) {
1254: var identifier = lenients[i].name.replace(setRegExp,'');
1255: toggleParmTextbox(document.parmform,identifier);
1256: }
1257: }
1258: }
1259: }
1260: }
1261: return;
1262: }
1263:
1264: function toggleParmTextbox(form,key) {
1265: var divfortext = document.getElementById('LC_parmtext_'+key);
1266: if (divfortext) {
1267: var caller = form.elements['set_'+key];
1268: if (caller.length) {
1269: for (i=0; i<caller.length; i++) {
1270: if (caller[i].checked) {
1271: if (caller[i].value == 'weighted') {
1272: divfortext.style.display = 'inline';
1273: } else {
1274: divfortext.style.display = 'none';
1275: }
1276: }
1277: }
1278: }
1279: }
1280: return;
1281: }
1282:
1283: ENDSCRIPT
1284: }
1285:
1.561 damieng 1286: # Javascript function validateParms, for overview mode
1.549 raeburn 1287: sub validateparms_js {
1.625 raeburn 1288: my %lt = &Apache::lonlocal::texthash (
1289: nodom => "A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.",
1290: nocrs => "A link type of 'course LTI launch' was selected but no course LTI launcher was selected.",
1291: plss => 'Please select one, or choose a different supported link type.',
1292: disa => 'disallowed character(s) removed from deeplink key.',
1293: nokyr => "A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.",
1294: plse => 'Please enter a key using one or more of:',
1295: nokey => "A link type of 'deep with key' was selected but the key value was blank.",
1296: plsk => 'Please enter a key.',
1297: dise => 'disallowed character(s) removed from Exit Button text.',
1298: exit => "An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.",
1299: disc => 'Disallowed characters are ',
1300: notxt => "An exit link type of 'In use' was selected but the button text value was blank.",
1301: plst => 'Please enter the text to use.',
1302: gppc => 'Grace Period Past-Due: enter partial credit (number between 0 and 1.0).',
1303: gpsn => 'Grace Period Past-Due: select a number in at least one of the time past due select boxes, or delete the value for partial credit.',
1304: );
1305: &js_escape(\%lt);
1306: return <<"ENDSCRIPT";
1.549 raeburn 1307:
1308: function validateParms() {
1309: var textRegExp = /^settext_/;
1.626 ! raeburn 1310: var tailLenient = /\\.lenient\$/;
! 1311: var patternRelWeight = /^\\-?[\\d.]+\$/;
1.625 raeburn 1312: var patternLenientStd = /^(yes|no|default)\$/;
1.597 raeburn 1313: var ipRegExp = /^setip/;
1.549 raeburn 1314: var ipallowRegExp = /^setipallow_/;
1315: var ipdenyRegExp = /^setipdeny_/;
1.622 raeburn 1316: var graceRegExp = /^setgrace_/;
1.597 raeburn 1317: var deeplinkRegExp = /^deeplink_/;
1.601 raeburn 1318: var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;
1319: var dlLinkProtectRegExp = /^deeplink_protect_/;
1320: var dlLtidRegExp = /^deeplink_ltid_/;
1321: var dlLticRegExp = /^deeplink_ltic_/;
1.597 raeburn 1322: var dlKeyRegExp = /^deeplink_key_/;
1323: var dlMenusRegExp = /^deeplink_menus_/;
1324: var dlCollsRegExp = /^deeplink_colls_/;
1.613 raeburn 1325: var dlTargetRegExp = /^deeplink_target_/;
1.616 raeburn 1326: var dlExitRegExp = /^deeplink_exit_/;
1327: var dlExitTextRegExp = /^deeplink_exittext_/;
1.626 ! raeburn 1328: var patternIP = /[\\[\\]\\*\\.a-zA-Z\\d\\-]+/;
! 1329: var patternGrace = /^\\d+:(0|1)\\.?\\d*:(0|1)\$/;
1.616 raeburn 1330: var numelements = document.parmform.elements.length;
1331: if ((typeof(numelements) != 'undefined') && (numelements != null)) {
1332: if (numelements) {
1333: for (i=0; i<numelements; i++) {
1.549 raeburn 1334: var name=document.parmform.elements[i].name;
1.588 raeburn 1335: if (textRegExp.test(name)) {
1.549 raeburn 1336: var identifier = name.replace(textRegExp,'');
1337: if (tailLenient.test(identifier)) {
1338: if (document.parmform.elements['set_'+identifier].length) {
1339: for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
1340: if (document.parmform.elements['set_'+identifier][j].checked) {
1341: if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
1342: var relweight = document.parmform.elements[i].value;
1.625 raeburn 1343: relweight = relweight.replace(/^\s+|\s+\$/g,'');
1.549 raeburn 1344: if (!patternRelWeight.test(relweight)) {
1345: relweight = '0.0';
1346: }
1347: if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
1348: document.parmform.elements['set_'+identifier][j].value = relweight;
1349: } else {
1350: document.parmform.elements['set_'+identifier][j].value += ','+relweight;
1351: }
1352: }
1353: break;
1354: }
1355: }
1356: }
1357: }
1.597 raeburn 1358: } else if (ipRegExp.test(name)) {
1359: if (ipallowRegExp.test(name)) {
1360: var identifier = name.replace(ipallowRegExp,'');
1361: var possallow = document.parmform.elements[i].value;
1.625 raeburn 1362: possallow = possallow.replace(/^\s+|\s+\$/g,'');
1.597 raeburn 1363: if (patternIP.test(possallow)) {
1364: if (document.parmform.elements['set_'+identifier].value) {
1365: possallow = ','+possallow;
1366: }
1367: document.parmform.elements['set_'+identifier].value += possallow;
1368: }
1369: } else if (ipdenyRegExp.test(name)) {
1370: var identifier = name.replace(ipdenyRegExp,'');
1371: var possdeny = document.parmform.elements[i].value;
1.625 raeburn 1372: possdeny = possdeny.replace(/^\s+|\s+\$/g,'');
1.597 raeburn 1373: if (patternIP.test(possdeny)) {
1374: possdeny = '!'+possdeny;
1375: if (document.parmform.elements['set_'+identifier].value) {
1376: possdeny = ','+possdeny;
1377: }
1378: document.parmform.elements['set_'+identifier].value += possdeny;
1.588 raeburn 1379: }
1380: }
1381: } else if (deeplinkRegExp.test(name)) {
1.597 raeburn 1382: if (dlListScopeRegExp.test(name)) {
1383: var identifier = name.replace(dlListScopeRegExp,'');
1384: var idx = document.parmform.elements[i].selectedIndex;
1385: if (idx > 0) {
1386: var possdeeplink = document.parmform.elements[i].options[idx].value
1.625 raeburn 1387: possdeeplink = possdeeplink.replace(/^\s+|\s+\$/g,'');
1.597 raeburn 1388: if (document.parmform.elements['set_'+identifier].value) {
1389: possdeeplink = ','+possdeeplink;
1390: }
1391: document.parmform.elements['set_'+identifier].value += possdeeplink;
1392: }
1.601 raeburn 1393: } else if (dlLinkProtectRegExp.test(name)) {
1.597 raeburn 1394: if (document.parmform.elements[i].checked) {
1.601 raeburn 1395: var identifier = name.replace(dlLinkProtectRegExp,'');
1.597 raeburn 1396: var posslinkurl = document.parmform.elements[i].value;
1.625 raeburn 1397: posslinkurl = posslinkurl.replace(/^\s+|\s+\$/g,'');
1.597 raeburn 1398: if (document.parmform.elements['set_'+identifier].value) {
1399: posslinkurl = ','+posslinkurl;
1400: }
1401: document.parmform.elements['set_'+identifier].value += posslinkurl;
1402: }
1.601 raeburn 1403: } else if (dlLtidRegExp.test(name)) {
1404: var identifier = name.replace(dlLtidRegExp,'');
1405: if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
1406: var possltid = document.parmform.elements[i].value;
1407: possltid = possltid.replace(/\D+/g,'');
1408: if (possltid.length) {
1.597 raeburn 1409: if (document.parmform.elements['set_'+identifier].value) {
1.601 raeburn 1410: possltid = ':'+possltid;
1.597 raeburn 1411: }
1.601 raeburn 1412: document.parmform.elements['set_'+identifier].value += possltid;
1.597 raeburn 1413: } else {
1414: document.parmform.elements['set_'+identifier].value = '';
1.625 raeburn 1415: alert("$lt{'nodom'}\\n$lt{'plss'}");
1.597 raeburn 1416: return false;
1417: }
1418: }
1.601 raeburn 1419: } else if (dlLticRegExp.test(name)) {
1420: var identifier = name.replace(dlLticRegExp,'');
1421: if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
1422: var possltic = document.parmform.elements[i].value;
1423: possltic = possltic.replace(/\D+/g,'');
1424: if (possltic.length) {
1425: if (document.parmform.elements['set_'+identifier].value) {
1426: possltic = ':'+possltic;
1427: }
1428: document.parmform.elements['set_'+identifier].value += possltic;
1429: } else {
1430: document.parmform.elements['set_'+identifier].value = '';
1.625 raeburn 1431: alert("$lt{'nocrs'}\\n$lt{'plss'}");
1.601 raeburn 1432: return false;
1433: }
1434: }
1.597 raeburn 1435: } else if (dlKeyRegExp.test(name)) {
1436: var identifier = name.replace(dlKeyRegExp,'');
1.601 raeburn 1437: if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597 raeburn 1438: var posskey = document.parmform.elements[i].value;
1.625 raeburn 1439: posskey = posskey.replace(/^\s+|\s+\$/g,'');
1.597 raeburn 1440: var origlength = posskey.length;
1.625 raeburn 1441: posskey = posskey.replace(/[^a-zA-Z\d_.!\@#\$%^&*()+=-]/g,'');
1.597 raeburn 1442: var newlength = posskey.length;
1443: if (newlength > 0) {
1444: var change = origlength - newlength;
1445: if (change) {
1.625 raeburn 1446: alert(change+" $lt{'disa'}");
1.597 raeburn 1447: }
1448: if (document.parmform.elements['set_'+identifier].value) {
1449: posskey = ':'+posskey;
1450: }
1451: document.parmform.elements['set_'+identifier].value += posskey;
1452: } else {
1453: document.parmform.elements['set_'+identifier].value = '';
1454: if (newlength < origlength) {
1.625 raeburn 1455: alert("$lt{'nokyr'}\\n$lt{'plse'} "+'a-zA-Z0-9_.!\@#\$%^&*()+=-');
1.597 raeburn 1456: } else {
1.625 raeburn 1457: alert("$lt{'nokey'}\\n$lt{'plsk'}");
1.597 raeburn 1458: }
1459: return false;
1460: }
1461: }
1462: } else if (dlMenusRegExp.test(name)) {
1463: if (document.parmform.elements[i].checked) {
1464: var identifier = name.replace(dlMenusRegExp,'');
1465: var posslinkmenu = document.parmform.elements[i].value;
1.625 raeburn 1466: posslinkmenu = posslinkmenu.replace(/^\s+|\s+\$/g,'');
1.597 raeburn 1467: if (posslinkmenu == 'std') {
1468: posslinkmenu = '0';
1469: if (document.parmform.elements['set_'+identifier].value) {
1470: posslinkmenu = ','+posslinkmenu;
1471: }
1472: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1473: }
1474: }
1475: } else if (dlCollsRegExp.test(name)) {
1476: var identifier = name.replace(dlCollsRegExp,'');
1477: if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
1478: var posslinkmenu = document.parmform.elements[i].value;
1479: if (document.parmform.elements['set_'+identifier].value) {
1480: posslinkmenu = ','+posslinkmenu;
1481: }
1482: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1483: }
1.614 raeburn 1484: } else if (dlTargetRegExp.test(name)) {
1485: var identifier = name.replace(dlTargetRegExp,'');
1.613 raeburn 1486: var idx = document.parmform.elements[i].selectedIndex;
1487: if (idx > 0) {
1.616 raeburn 1488: var linktarget = document.parmform.elements[i].options[idx].value
1.625 raeburn 1489: linktarget = linktarget.replace(/^\s+|\s+\$/g,'');
1.616 raeburn 1490: if (document.parmform.elements['set_'+identifier].value) {
1491: linktarget = ','+linktarget;
1492: }
1493: document.parmform.elements['set_'+identifier].value += linktarget;
1494: }
1495: } else if (dlExitRegExp.test(name)) {
1496: if (document.parmform.elements[i].checked) {
1497: var identifier = name.replace(dlExitRegExp,'');
1498: var posslinkexit = document.parmform.elements[i].value;
1.625 raeburn 1499: posslinkexit = posslinkexit.replace(/^\s+|\s+\$/g,'');
1.613 raeburn 1500: if (document.parmform.elements['set_'+identifier].value) {
1.616 raeburn 1501: posslinkexit = ','+posslinkexit;
1502: }
1503: document.parmform.elements['set_'+identifier].value += posslinkexit;
1504: }
1505: } else if (dlExitTextRegExp.test(name)) {
1506: var identifier = name.replace(dlExitTextRegExp,'');
1507: if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
1508: (isRadioSet('deeplink_exit_'+identifier,'url'))) {
1509: var posstext = document.parmform.elements[i].value;
1.625 raeburn 1510: posstext = posstext.replace(/^\s+|\s+\$/g,'');
1.616 raeburn 1511: var origlength = posstext.length;
1512: posstext = posstext.replace(/[:;'",]/g,'');
1513: var newlength = posstext.length;
1514: if (newlength > 0) {
1515: var change = origlength - newlength;
1516: if (change) {
1.625 raeburn 1517: alert(change+" $lt{'dise'}");
1.616 raeburn 1518: }
1519: if (posstext !== 'Exit Tool') {
1520: posstext = ':'+posstext;
1521: document.parmform.elements['set_'+identifier].value += posstext;
1522: }
1523: } else {
1524: document.parmform.elements['set_'+identifier].value = '';
1525: if (newlength < origlength) {
1.625 raeburn 1526: alert("$lt{'exit'}\\n$lt{'disc'}"+'":;\\'');
1.616 raeburn 1527: } else {
1.625 raeburn 1528: alert("$lt{'notxt'}\\n$lt{'plst'}");
1.616 raeburn 1529: }
1530: return false;
1.613 raeburn 1531: }
1532: }
1.549 raeburn 1533: }
1.622 raeburn 1534: } else if (graceRegExp.test(name)) {
1535: var identifier = name.replace(graceRegExp,'');
1536: var divElem = document.parmform.elements[i].closest('div');
1537: var timeSels = divElem.getElementsByTagName("select");
1538: var total = 0;
1.623 raeburn 1539: var numnotnull = 0;
1.622 raeburn 1540: if (timeSels.length) {
1541: for (var j=0; j<timeSels.length; j++) {
1542: var sname = timeSels[j].getAttribute('name');
1.623 raeburn 1543: var value = timeSels[j].options[timeSels[j].selectedIndex].value;
1544: if ((value !== null) && (value !== '') && (value !== 'undefined')) {
1545: numnotnull ++;
1546: var poss = parseInt(value);
1547: if (sname == 'weeks_'+identifier) {
1548: if ((poss > 0) && (poss <= 52)) {
1549: total += (poss * 604800);
1550: }
1551: } else if (sname == 'days_'+identifier) {
1552: if ((poss > 0) && (poss <= 6)) {
1553: total += (poss * 86400);
1554: }
1555: } else if (sname == 'hours_'+identifier) {
1556: if ((poss > 0) && (poss < 24)) {
1557: total += (poss * 3600);
1558: }
1559: } else if (sname == 'minutes_'+identifier) {
1560: if ((poss > 0) && (poss < 60)) {
1561: total += (poss * 60);
1562: }
1.622 raeburn 1563: }
1564: }
1565: }
1566: }
1.623 raeburn 1567: if (!numnotnull) {
1568: total = '';
1569: }
1.622 raeburn 1570: var inputElems = divElem.getElementsByTagName("input");
1571: var frac = '';
1572: var grad = '';
1573: if (inputElems.length) {
1574: for (var j=0; j<inputElems.length; j++) {
1575: var iname = inputElems[j].getAttribute('name');
1576: if (iname == 'frac_'+identifier) {
1577: var ival = inputElems[j].value;
1578: ival.trim();
1.623 raeburn 1579: if ((ival != '') && (value != 'undefined')) {
1580: var poss = parseFloat(ival);
1581: if ((typeof poss === 'number') && (!isNaN(poss))) {
1582: if ((poss => 0) && (poss <= 1)) {
1583: frac = poss;
1584: numnotnull ++;
1585: }
1.622 raeburn 1586: }
1587: }
1588: } else if (iname == 'grad_'+identifier) {
1589: if (inputElems[j].checked) {
1590: grad = 1;
1591: } else {
1592: grad = 0;
1593: }
1594: }
1595: }
1596: }
1.623 raeburn 1597: if (numnotnull) {
1598: var possgrace = total+':'+frac+':'+grad;
1599: if (patternGrace.test(possgrace)) {
1600: document.parmform.elements[i].value = possgrace;
1601: if (document.parmform.elements['set_'+identifier].value) {
1602: document.parmform.elements['set_'+identifier].value += ',';
1603: }
1604: document.parmform.elements['set_'+identifier].value += document.parmform.elements[i].value;
1605: } else {
1606: if (frac == '') {
1.625 raeburn 1607: alert("$lt{'gppc'}");
1.623 raeburn 1608: return false;
1609: } else {
1.625 raeburn 1610: alert("$lt{'gpsn'}");
1.623 raeburn 1611: return false;
1612: }
1613: }
1.622 raeburn 1614: }
1.549 raeburn 1615: }
1616: }
1617: }
1618: }
1619: return true;
1620: }
1621:
1.597 raeburn 1622: function isRadioSet(name,expected) {
1623: var menuitems = document.getElementsByName(name);
1624: var radioLength = menuitems.length;
1625: result = false;
1626: if (radioLength > 1) {
1627: for (var j=0; j<radioLength; j++) {
1628: if (menuitems[j].checked) {
1629: if (menuitems[j].value == expected) {
1630: result = true;
1631: break;
1632: }
1633: }
1634: }
1635: }
1636: return result;
1637: }
1638:
1.549 raeburn 1639: ENDSCRIPT
1640: }
1641:
1.561 damieng 1642: # Javascript initialization, for overview mode
1.549 raeburn 1643: sub ipacc_boxes_js {
1644: my $remove = &mt('Remove');
1645: return <<"END";
1646: \$(document).ready(function() {
1647: var wrapper = \$(".LC_string_ipacc_wrap");
1648: var add_button = \$(".LC_add_ipacc_button");
1649: var ipaccRegExp = /^LC_string_ipacc_/;
1650:
1651: \$(add_button).click(function(e){
1652: e.preventDefault();
1653: var identifier = \$(this).closest("div").attr("id");
1654: identifier = identifier.replace(ipaccRegExp,'');
1.551 raeburn 1655: \$(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 1656: });
1657:
1658: \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
1659: e.preventDefault(); \$(this).closest("div").remove();
1660: })
1661: });
1662:
1663:
1664: END
1665: }
1666:
1.622 raeburn 1667: sub grace_js {
1668: my %lt = &grace_titles();
1669: &js_escape(\%lt);
1670: my $overdue = '<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
1.623 raeburn 1671: foreach my $which (['weeks', 604800, 52],
1672: ['days', 86400, 6],
1.622 raeburn 1673: ['hours', 3600, 23],
1.623 raeburn 1674: ['minutes', 60, 59]) {
1.622 raeburn 1675: my ($name, $factor, $max) = @{ $which };
1676: my %select = ((map {$_ => $_} (0..$max)),
1677: 'select_form_order' => [0..$max]);
1.623 raeburn 1678: unshift(@{$select{'select_form_order'}},'');
1679: $select{''} = '';
1.622 raeburn 1680: my $selector = &Apache::loncommon::select_form('',$name."_'+identifier+'",
1681: \%select);
1682: $selector =~ s/([\r\n\f]+)//g;
1683: $overdue .= $selector.' '.$lt{$name}.(' 'x2).' ';
1684: }
1685: $overdue .= '</fieldset>';
1686: return <<"END";
1687: \$(document).ready(function() {
1688: var wrapper = \$(".LC_string_grace_wrap");
1689: var add_button = \$(".LC_add_grace_button");
1690: var graceRegExp = /^LC_string_grace_/;
1691:
1692: \$(add_button).click(function(e){
1693: e.preventDefault();
1694: var identifier = \$(this).closest("div").attr("id");
1695: identifier = identifier.replace(graceRegExp,'');
1.623 raeburn 1696: \$(this).closest('div').find('.LC_string_grace_inner').append('<div><input type="hidden" name="setgrace_'+identifier+'" value="" />$overdue<fieldset class="LC_grace"><legend>$lt{pcr}</legend><input type="text" size="3" name="frac_'+identifier+'" value="" /> <label><input type="checkbox" value="1" name="grad_'+identifier+'" />$lt{grad}</label></fieldset><a href="#" class="LC_remove_grace">$lt{remo}</a></div>');
1.622 raeburn 1697: });
1698:
1699: \$(wrapper).delegate(".LC_remove_grace","click", function(e){
1700: e.preventDefault(); \$(this).closest("div").remove();
1701: })
1702: });
1703:
1704:
1705: END
1706: }
1707:
1.561 damieng 1708: # Javascript function toggleSecret, for overview mode.
1.558 raeburn 1709: sub done_proctor_js {
1.611 raeburn 1710: my $defaultdone = &mt('Done');
1711: &js_escape(\$defaultdone);
1.558 raeburn 1712: return <<"END";
1713: function toggleSecret(form,radio,key) {
1714: var radios = form[radio+key];
1715: if (radios.length) {
1716: for (var i=0; i<radios.length; i++) {
1717: if (radios[i].checked) {
1718: if (radios[i].value == '_done_proctor') {
1719: if (document.getElementById('done_'+key+'_proctorkey')) {
1720: document.getElementById('done_'+key+'_proctorkey').type='text';
1721: }
1722: } else {
1723: if (document.getElementById('done_'+key+'_proctorkey')) {
1724: document.getElementById('done_'+key+'_proctorkey').type='hidden';
1725: document.getElementById('done_'+key+'_proctorkey').value='';
1726: }
1727: }
1.611 raeburn 1728: if (document.getElementById('done_'+key+'_buttontext')) {
1729: if (radios[i].value == '') {
1730: document.getElementById('done_'+key+'_buttontext').value = '';
1731: } else {
1732: if (document.getElementById('done_'+key+'_buttontext').value == '') {
1733: document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
1734: }
1735: }
1736: }
1.558 raeburn 1737: }
1738: }
1739: }
1740: }
1741: END
1742:
1743: }
1744:
1.588 raeburn 1745: # Javascript function toggle
1746: sub deeplink_js {
1747: return <<"END";
1748: function toggleDeepLink(form,item,key) {
1749: var radios = form['deeplink_'+item+'_'+key];
1750: if (radios.length) {
1751: var keybox;
1752: if (document.getElementById('deeplink_key_'+item+'_'+key)) {
1753: keybox = document.getElementById('deeplink_key_'+item+'_'+key);
1754: }
1.601 raeburn 1755: var divoptions = new Array();
1756: if (item == 'protect') {
1757: divoptions = ['ltic','ltid'];
1.597 raeburn 1758: } else {
1759: if (item == 'menus') {
1.601 raeburn 1760: divoptions = ['colls'];
1.597 raeburn 1761: }
1762: }
1.601 raeburn 1763: var seldivs = new Array();
1764: if ((item == 'protect') || (item == 'menus')) {
1765: for (var i=0; i<divoptions.length; i++) {
1766: if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
1767: seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
1768: } else {
1769: seldivs[i] = '';
1770: }
1771: }
1.588 raeburn 1772: }
1773: for (var i=0; i<radios.length; i++) {
1774: if (radios[i].checked) {
1.601 raeburn 1775: if ((item == 'protect') || (item == 'menus')) {
1776: for (var j=0; j<seldivs.length; j++) {
1777: if (radios[i].value == divoptions[j]) {
1778: if (seldivs[j] != '') {
1779: seldivs[j].style.display = 'inline-block';
1780: }
1781: if (item == 'protect') {
1782: keybox.type = 'hidden';
1783: keybox.value = '';
1784: }
1785: } else {
1786: if (seldivs[j] != '') {
1787: seldivs[j].style.display = 'none';
1788: form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
1789: }
1790: }
1.597 raeburn 1791: }
1.601 raeburn 1792: if (item == 'protect') {
1.597 raeburn 1793: if (radios[i].value == 'key') {
1794: keybox.type = 'text';
1795: } else {
1796: keybox.type = 'hidden';
1797: }
1.588 raeburn 1798: }
1.616 raeburn 1799: } else if (item == 'exit') {
1800: if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
1801: if (radios[i].value == 'no') {
1802: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';
1803: if (document.getElementById('deeplink_exittext_'+key)) {
1804: if (document.getElementById('deeplink_exittext_'+key).value != '') {
1805: document.getElementById('deeplink_exittext_'+key).value = '';
1806: }
1807: }
1808: } else {
1809: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
1810: if (document.getElementById('deeplink_exittext_'+key)) {
1811: if (document.getElementById('deeplink_exittext_'+key).value == '') {
1812: document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
1813: }
1814: }
1815: }
1816: }
1.588 raeburn 1817: }
1818: }
1819: }
1820: }
1821: }
1822: END
1823:
1824: }
1825:
1.561 damieng 1826: # Prints HTML page start for table mode.
1827: # @param {Apache2::RequestRec} $r - the Apache request
1828: # @param {string} $psymb - resource symb
1829: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280 albertel 1830: sub startpage {
1.531 raeburn 1831: my ($r,$psymb,$crstype) = @_;
1.281 albertel 1832:
1.515 raeburn 1833: my %loaditems = (
1834: 'onload' => "group_or_section('cgroup')",
1835: );
1836: if (!$psymb) {
1.523 raeburn 1837: $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515 raeburn 1838: }
1.280 albertel 1839:
1.560 damieng 1840: if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
1841: (!$env{'form.dis'})) || ($env{'form.symb'})) {
1842: &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
1843: text=>"Problem Parameters"});
1.414 droeschl 1844: } else {
1.560 damieng 1845: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1846: text=>"Table Mode",
1847: help => 'Course_Setting_Parameters'});
1.414 droeschl 1848: }
1.523 raeburn 1849: my $js = &page_js().'
1850: <script type="text/javascript">
1851: // <![CDATA[
1852: '.
1853: &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
1854: // ]]>
1855: </script>
1856: ';
1.446 bisitz 1857: my $start_page =
1.523 raeburn 1858: &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
1859: {'add_entries' => \%loaditems,});
1.446 bisitz 1860: my $breadcrumbs =
1.473 amueller 1861: &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506 www 1862: my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
1863: my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507 www 1864: $r->print($start_page.$breadcrumbs);
1.531 raeburn 1865: &startSettingsScreen($r,'parmset',$crstype);
1.280 albertel 1866: $r->print(<<ENDHEAD);
1.193 albertel 1867: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419 bisitz 1868: <input type="hidden" value="" name="pres_value" />
1869: <input type="hidden" value="" name="pres_type" />
1870: <input type="hidden" value="" name="pres_marker" />
1871: <input type="hidden" value="1" name="prevvisit" />
1.506 www 1872: <input type="hidden" value="$escfilter" name="filter" />
1873: <input type="hidden" value="$escpart" name="part" />
1.44 albertel 1874: ENDHEAD
1875: }
1876:
1.209 www 1877:
1.561 damieng 1878: # Prints a row for table mode (except for the tr start).
1879: # Every time a hash reference is passed, a single entry is used, so print_row
1880: # could just use these values, but why make it simple when it can be complicated ?
1881: #
1882: # @param {Apache2::RequestRec} $r - the Apache request
1883: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
1884: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
1885: # @param {hash reference} $name - parameter key -> parameter name
1.566 damieng 1886: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561 damieng 1887: # @param {string} $rid - resource id
1888: # @param {hash reference} $default - parameter key -> resource parameter default value
1889: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
1890: # @param {hash reference} $display - parameter key -> full title for the parameter
1891: # @param {string} $defbgone - user level and other levels background color
1892: # @param {string} $defbgtwo - section level background color, also used for part number
1893: # @param {string} $defbgthree - group level background color
1894: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1895: # @param {string} $uname - user name
1896: # @param {string} $udom - user domain
1897: # @param {string} $csec - section name
1898: # @param {string} $cgroup - group name
1899: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1900: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582 raeburn 1901: # @param {boolean} $readonly - true if no editing allowed.
1902: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
1903: # @param {hash reference} - $maptitles - - hash map id or src -> map title
1904: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
1905: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set
1.44 albertel 1906: sub print_row {
1.201 www 1907: my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568 raeburn 1908: $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582 raeburn 1909: $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275 raeburn 1910: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1911: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1912: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582 raeburn 1913: my $numlinks = 0;
1.553 raeburn 1914:
1.560 damieng 1915: # get the values for the parameter in cascading order
1916: # empty levels will remain empty
1.44 albertel 1917: my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473 amueller 1918: $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1919: # get the type for the parameters
1920: # problem: these may not be set for all levels
1.66 www 1921: my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275 raeburn 1922: $$name{$which}.'.type',$rid,
1.473 amueller 1923: $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1924: # cascade down manually
1.182 albertel 1925: my $cascadetype=$$defaulttype{$which};
1.556 raeburn 1926: for (my $i=18;$i>0;$i--) {
1.560 damieng 1927: if ($typeoutpar[$i]) {
1.66 www 1928: $cascadetype=$typeoutpar[$i];
1.560 damieng 1929: } else {
1.66 www 1930: $typeoutpar[$i]=$cascadetype;
1931: }
1932: }
1.57 albertel 1933: my $parm=$$display{$which};
1934:
1.203 www 1935: if ($parmlev eq 'full') {
1.419 bisitz 1936: $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506 www 1937: .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433 raeburn 1938: } else {
1.57 albertel 1939: $parm=~s|\[.*\]\s||g;
1940: }
1.231 www 1941: my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
1942: if ($automatic) {
1.560 damieng 1943: $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231 www 1944: }
1.619 raeburn 1945: my $advice;
1946: if ((ref($name) eq 'HASH') && ($name->{$which} eq 'mapalias') &&
1947: (ref($symbp) eq 'HASH') && ($parmlev eq 'full')) {
1948: if ($symbp->{$rid} =~ m{^uploaded/}) {
1949: if ($result == 14) {
1950: $advice = &mt('Use Course Editor to modify this.');
1951: } else {
1952: $advice = &mt('Use Course Editor to set this.');
1953: }
1954: } else {
1955: if ($result == 14) {
1956: $advice = &mt('Use Resource Assembly Tool to modify this.');
1957: } else {
1958: $advice = &mt('Use Resource Assembly Tool to set this.');
1959: }
1960: }
1961: $parm .= '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
1962: }
1.427 bisitz 1963: $r->print('<td>'.$parm.'</td>');
1.446 bisitz 1964:
1.44 albertel 1965: my $thismarker=$which;
1966: $thismarker=~s/^parameter\_//;
1967: my $mprefix=$rid.'&'.$thismarker.'&';
1.582 raeburn 1968: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1969: my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588 raeburn 1970: $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582 raeburn 1971: if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
1972: if ($result eq '') {
1973: $recurse_check = 1;
1974: } elsif (($uname ne '') && ($result > 3)) {
1975: $recurse_check = 1;
1976: } elsif (($cgroup ne '') && ($result > 7)) {
1977: $recurse_check = 1;
1978: } elsif (($csec ne '') && ($result > 11)) {
1979: $recurse_check = 1;
1980: } elsif ($result > 17) {
1981: $recurse_check = 1;
1982: }
1983: if ($recurse_check) {
1984: my $what = $$part{$which}.'.'.$$name{$which};
1985: my $prefix;
1986: if (($uname ne '') && ($udom ne '')) {
1987: my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1988: $prefix = $env{'request.course.id'};
1989: $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
1990: if (ref($recursinfo) eq 'ARRAY') {
1991: $effparm_rec = 1;
1992: $effparm_level = &mt('user: [_1]',$uname);
1993: }
1994: }
1995: if (($cgroup ne '') && (!$effparm_rec)) {
1996: $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
1997: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1998: if (ref($recursinfo) eq 'ARRAY') {
1999: $effparm_rec = 1;
2000: $effparm_level = &mt('group: [_1]',$cgroup);
2001: }
2002: }
2003: if (($csec ne '') && (!$effparm_rec)) {
2004: $prefix = $env{'request.course.id'}.'.['.$csec.']';
2005: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
2006: if (ref($recursinfo) eq 'ARRAY') {
2007: $effparm_rec = 1;
2008: $effparm_level = &mt('section: [_1]',$csec);
2009: }
2010: }
2011: if (!$effparm_rec) {
2012: $prefix = $env{'request.course.id'};
2013: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
2014: if (ref($recursinfo) eq 'ARRAY') {
2015: $effparm_rec = 1;
2016: }
2017: }
2018: }
2019: }
2020: if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
2021: $effparm_rec = 1;
2022: }
2023: if ((!$effparm_rec) &&
2024: (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) &&
2025: ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578 raeburn 2026: $effparm_rec = 1;
2027: }
1.588 raeburn 2028: if ($parmname eq 'deeplink') {
1.601 raeburn 2029: my ($domltistr,$crsltistr);
1.588 raeburn 2030: my %lti =
2031: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 2032: 'linkprot');
1.601 raeburn 2033: if (keys(%lti)) {
2034: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1.604 raeburn 2035: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
2036: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588 raeburn 2037: }
2038: }
1.601 raeburn 2039: $domltistr =~ s/,$//;
2040: if ($domltistr) {
2041: $extra = 'ltid_'.$domltistr;
2042: }
1.588 raeburn 2043: }
1.620 raeburn 2044: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider');
1.601 raeburn 2045: if (keys(%courselti)) {
2046: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
2047: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
2048: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
2049: }
2050: }
2051: $crsltistr =~ s/,$//;
2052: if ($crsltistr) {
2053: if ($extra) {
2054: $extra .= '&';
2055: }
2056: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 2057: }
2058: }
1.597 raeburn 2059: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
2060: my @colls;
2061: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
2062: my ($num,$value) = split(/\%/,$item);
2063: if ($num =~ /^\d+$/) {
2064: push(@colls,$num);
2065: }
2066: }
2067: if (@colls) {
2068: if ($extra) {
2069: $extra .= '&';
2070: }
2071: $extra .= 'menus_'.join(',',@colls);
2072: }
2073: }
1.588 raeburn 2074: }
1.57 albertel 2075: if ($parmlev eq 'general') {
2076: if ($uname) {
1.588 raeburn 2077: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 2078: } elsif ($cgroup) {
1.588 raeburn 2079: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 2080: } elsif ($csec) {
1.588 raeburn 2081: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 2082: } else {
1.588 raeburn 2083: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 2084: }
2085: } elsif ($parmlev eq 'map') {
2086: if ($uname) {
1.588 raeburn 2087: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 2088: } elsif ($cgroup) {
1.588 raeburn 2089: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 2090: } elsif ($csec) {
1.588 raeburn 2091: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 2092: } else {
1.588 raeburn 2093: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 2094: }
2095: } else {
1.275 raeburn 2096: if ($uname) {
2097: if (@{$usersgroups} > 1) {
1.582 raeburn 2098: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 2099: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 2100: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 2101: if (($coursereply) && ($result > 4)) {
1.275 raeburn 2102: if (defined($controlgrp)) {
2103: if ($cgroup ne $controlgrp) {
1.582 raeburn 2104: $eff_groupparm = $grp_parm;
2105: undef($result);
2106: undef($effparm_rec);
2107: if ($grp_is_rec) {
2108: $effparm_rec = 1;
2109: }
1.275 raeburn 2110: }
2111: }
2112: }
2113: }
2114: }
1.57 albertel 2115:
1.588 raeburn 2116: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2117: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
2118: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2119: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2120: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 2121:
2122: if ($csec) {
1.588 raeburn 2123: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2124: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
2125: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 2126: }
1.269 raeburn 2127:
2128: if ($cgroup) {
1.588 raeburn 2129: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
2130: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
2131: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 2132: }
1.446 bisitz 2133:
1.548 raeburn 2134: if ($uname) {
1.275 raeburn 2135: if ($othergrp) {
2136: $r->print($othergrp);
2137: }
1.588 raeburn 2138: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
2139: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
2140: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 2141: }
1.57 albertel 2142: } # end of $parmlev if/else
1.582 raeburn 2143: if (ref($recursinfo) eq 'ARRAY') {
2144: my $rectitle = &mt('recursive');
2145: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
2146: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
2147: $rectitle = &mt('set in: [_1]','"'.
2148: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
2149: "'$parmname','$$part{$which}'".');">'.
2150: $maptitles->{$recursinfo->[2]}.'</a>"');
2151:
2152: $numlinks ++;
2153: }
2154: }
2155: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 2156: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 2157: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
2158: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
2159: $effparm_level.'</span></td>');
2160: } else {
2161: if ($result) {
1.593 raeburn 2162: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 2163: }
2164: if ($eff_groupparm) {
2165: $effective_parm = $eff_groupparm;
2166: }
2167: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
2168: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
2169: '</span>':'').'</td>');
2170: }
1.203 www 2171: if ($parmlev eq 'full') {
1.136 albertel 2172: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 2173: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 2174: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 2175: if (!defined($sessionvaltype)) {
2176: $sessionvaltype=$$defaulttype{$which};
2177: }
1.419 bisitz 2178: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 2179: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 2180: '</font></td>');
1.136 albertel 2181: }
1.44 albertel 2182: $r->print('</tr>');
1.57 albertel 2183: $r->print("\n");
1.582 raeburn 2184: if (($numlinks) && (ref($reclinks))) {
2185: $$reclinks = $numlinks;
2186: }
1.44 albertel 2187: }
1.59 matthew 2188:
1.561 damieng 2189: # Prints a cell for table mode.
2190: #
2191: # FIXME: some of these parameter names are uninspired ($which and $value)
2192: # Also, it would make more sense to pass the display for this cell rather
2193: # than the full display hash and the key to use.
2194: #
2195: # @param {Apache2::RequestRec} $r - the Apache request
2196: # @param {integer} $which - level
2197: # @param {string} $defbg - cell background color
2198: # @param {integer} $result - the most specific level that is defined for that parameter
2199: # @param {array reference} $outpar - array level -> parameter value (when defined)
2200: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
2201: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
2202: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
2203: # @param {hash reference} $display - parameter key -> full title for the parameter
2204: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 2205: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 2206: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 2207: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 2208: sub print_td {
1.578 raeburn 2209: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 2210: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 2211: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
2212: $ineffect = 0;
2213: $currval = $$outpar[$which];
2214: $currtype = $$typeoutpar[$which];
2215: $currlevel = $which;
2216: if (($result) && ($result == $which)) {
2217: $ineffect = 1;
2218: }
2219: if ($ismaplevel) {
2220: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
2221: if (($result) && ($result == $which)) {
2222: $recursive = 1;
2223: }
2224: } elsif ($$outpar[$which+1] ne '') {
2225: $recursive = 1;
2226: $currlevel = $which+1;
2227: $currval = $$outpar[$currlevel];
2228: $currtype = $$typeoutpar[$currlevel];
2229: if (($result) && ($result == $currlevel)) {
2230: $ineffect = 1;
2231: }
2232: }
2233: }
2234: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 2235: ';" align="center">');
1.437 raeburn 2236: my $nolink = 0;
1.568 raeburn 2237: if ($readonly) {
1.552 raeburn 2238: $nolink = 1;
1.568 raeburn 2239: } else {
1.578 raeburn 2240: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 2241: $nolink = 1;
1.568 raeburn 2242: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 2243: $nolink = 1;
1.568 raeburn 2244: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
2245: if ($noeditgrp) {
2246: $nolink = 1;
2247: }
2248: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 2249: $nolink = 1;
1.568 raeburn 2250: } elsif ($mprefix =~ /examcode\&$/) {
2251: unless ($which == 2) {
2252: $nolink = 1;
2253: }
1.533 raeburn 2254: }
1.437 raeburn 2255: }
2256: if ($nolink) {
1.577 raeburn 2257: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 2258: $r->print(&valout($currval,$currtype));
1.114 www 2259: } else {
1.578 raeburn 2260: $r->print(&plink($currtype,
2261: $$display{$value},$currval,
1.588 raeburn 2262: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
2263: $extra));
1.114 www 2264: }
2265: $r->print('</td>'."\n");
1.57 albertel 2266: }
2267:
1.561 damieng 2268: # Returns HTML and other info for the cell added when a user is selected
2269: # and that user is in several groups. This is the cell with the title "Control by other group".
2270: #
2271: # @param {string} $what - parameter part.'.'.parameter name
2272: # @param {string} $rid - resource id
2273: # @param {string} $cgroup - group name
2274: # @param {string} $defbg - cell background color
2275: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2276: # @param {integer} $result - level
2277: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 2278: # @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 2279: sub check_other_groups {
2280: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 2281: my $courseid = $env{'request.course.id'};
2282: my $output;
2283: my $symb = &symbcache($rid);
2284: my $symbparm=$symb.'.'.$what;
2285: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 2286: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 2287: my $mapparm=$map.'___(all).'.$what;
2288: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 2289: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
2290: $recurseparm,$what,$courseopt);
1.275 raeburn 2291: my $bgcolor = $defbg;
1.582 raeburn 2292: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2293: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2294: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2295: if ($result > 3) {
1.419 bisitz 2296: $bgcolor = '#AAFFAA';
1.275 raeburn 2297: }
1.593 raeburn 2298: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2299: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2300: if ($resultgroup && $resultlevel) {
1.582 raeburn 2301: if ($resultlevel eq 'recursive') {
2302: $resultlevel = 'map/folder';
2303: $grp_is_rec = 1;
2304: }
2305: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2306: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2307:
1.275 raeburn 2308: } else {
2309: $output .= ' ';
2310: }
2311: $output .= '</td>';
2312: } else {
1.419 bisitz 2313: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2314: }
1.582 raeburn 2315: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2316: }
2317:
1.561 damieng 2318: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2319: # Used by check_other_groups.
1.561 damieng 2320: #
2321: # @param {string} $courseid - the course id
2322: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2323: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2324: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2325: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2326: # @param {string} $what - parameter part.'.'.parameter name
2327: # @param {hash reference} $courseopt - course parameters hash
2328: # @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 2329: sub parm_control_group {
1.556 raeburn 2330: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2331: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2332: my $grpfound = 0;
1.556 raeburn 2333: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2334: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2335: foreach my $group (@{$usersgroups}) {
2336: if ($grpfound) { last; }
2337: for (my $i=0; $i<@levels; $i++) {
2338: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2339: if (defined($$courseopt{$item})) {
2340: $coursereply = $$courseopt{$item};
2341: $resultitem = $item;
2342: $resultgroup = $group;
2343: $resultlevel = $levelnames[$i];
2344: $resulttype = $$courseopt{$item.'.type'};
2345: $grpfound = 1;
2346: last;
2347: }
2348: }
2349: }
2350: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2351: }
1.201 www 2352:
1.63 bowersj2 2353:
2354:
1.562 damieng 2355: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2356: # All the parameters are references and are filled by the sub.
2357: #
1.566 damieng 2358: # @param {array reference} $ids - resource and map ids
2359: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2360: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2361: # @param {hash reference} $allparms - hash parameter name -> parameter title
2362: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2363: # @param {hash reference} $allmaps - hash map pc -> map src
2364: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2365: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2366: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2367: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2368: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2369: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608 raeburn 2370: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63 bowersj2 2371: sub extractResourceInformation {
2372: my $ids = shift;
2373: my $typep = shift;
2374: my $keyp = shift;
2375: my $allparms = shift;
2376: my $allparts = shift;
2377: my $allmaps = shift;
2378: my $mapp = shift;
2379: my $symbp = shift;
1.82 www 2380: my $maptitles=shift;
1.196 www 2381: my $uris=shift;
1.210 www 2382: my $keyorder=shift;
1.211 www 2383: my $defkeytype=shift;
1.603 raeburn 2384: my $pssymb=shift;
1.196 www 2385:
1.210 www 2386: my $keyordercnt=100;
1.63 bowersj2 2387:
1.196 www 2388: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 raeburn 2389: return unless(ref($navmap));
2390: my @allres;
2391: if ($pssymb ne '') {
2392: my $res = $navmap->getBySymb($pssymb);
2393: if (ref($res)) {
2394: @allres = ($res);
2395: }
2396: }
2397: if (!@allres) {
2398: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
2399: }
1.196 www 2400: foreach my $resource (@allres) {
1.480 amueller 2401: my $id=$resource->id();
1.196 www 2402: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2403: if ($mapid eq '0') { next; }
2404: $$ids[$#$ids+1]=$id;
2405: my $srcf=$resource->src();
2406: $srcf=~/\.(\w+)$/;
2407: $$typep{$id}=$1;
1.584 raeburn 2408: my $toolsymb;
2409: if ($srcf =~ /ext\.tool$/) {
2410: $toolsymb = $resource->symb();
2411: }
1.480 amueller 2412: $$keyp{$id}='';
1.196 www 2413: $$uris{$id}=$srcf;
1.512 foxr 2414:
1.584 raeburn 2415: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2416: next if ($key!~/^parameter_/);
1.363 albertel 2417:
1.209 www 2418: # Hidden parameters
1.584 raeburn 2419: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2420: #
2421: # allparms is a hash of parameter names
2422: #
1.584 raeburn 2423: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2424: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2425: my ($display,$parmdis);
2426: $display = &standard_parameter_names($name);
2427: if ($display eq '') {
1.584 raeburn 2428: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2429: $parmdis = $display;
2430: $parmdis =~ s/\s*\[Part.*$//g;
2431: } else {
2432: $parmdis = &mt($display);
2433: }
2434: $$allparms{$name}=$parmdis;
2435: if (ref($defkeytype)) {
2436: $$defkeytype{$name}=
1.584 raeburn 2437: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2438: }
2439: }
1.363 albertel 2440:
1.209 www 2441: #
2442: # allparts is a hash of all parts
2443: #
1.584 raeburn 2444: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2445: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2446: #
2447: # Remember all keys going with this resource
2448: #
1.480 amueller 2449: if ($$keyp{$id}) {
2450: $$keyp{$id}.=','.$key;
2451: } else {
2452: $$keyp{$id}=$key;
2453: }
1.210 www 2454: #
2455: # Put in order
1.446 bisitz 2456: #
1.480 amueller 2457: unless ($$keyorder{$key}) {
2458: $$keyorder{$key}=$keyordercnt;
2459: $keyordercnt++;
2460: }
1.473 amueller 2461: }
2462:
2463:
1.480 amueller 2464: if (!exists($$mapp{$mapid})) {
2465: $$mapp{$id}=
2466: &Apache::lonnet::declutter($resource->enclosing_map_src());
2467: $$mapp{$mapid}=$$mapp{$id};
2468: $$allmaps{$mapid}=$$mapp{$id};
2469: if ($mapid eq '1') {
1.532 raeburn 2470: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2471: } else {
2472: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2473: }
2474: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2475: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2476: # Lines 1038 and 1114 which use $symbp{$mapid}
2477: # are commented out in rev. 1.57
1.473 amueller 2478: } else {
1.480 amueller 2479: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2480: }
1.480 amueller 2481: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2482: }
2483: }
2484:
1.582 raeburn 2485: sub get_recursive {
2486: my ($recurseup,$resdata,$what,$prefix) = @_;
2487: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2488: foreach my $item (@{$recurseup}) {
2489: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2490: if (defined($resdata->{$norecursechk})) {
2491: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2492: my $type = $resdata->{$norecursechk.'.type'};
2493: return [$resdata->{$norecursechk},$type,$item];
2494: } else {
2495: last;
2496: }
2497: }
2498: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2499: if (defined($resdata->{$recursechk})) {
2500: my $type = $resdata->{$recursechk.'.type'};
2501: return [$resdata->{$recursechk},$type,$item];
2502: }
2503: }
2504: }
2505: return;
2506: }
2507:
1.208 www 2508:
1.562 damieng 2509: # Tells if a parameter type is a date.
2510: #
2511: # @param {string} type - parameter type
2512: # @returns{boolean} - true if it is a date
1.213 www 2513: sub isdateparm {
2514: my $type=shift;
2515: return (($type=~/^date/) && (!($type eq 'date_interval')));
2516: }
2517:
1.589 raeburn 2518: # Determine if parameter type is specialized string type (i.e.,
2519: # not just string or string_yesno.
2520:
2521: sub is_specialstring {
2522: my $type=shift;
1.603 raeburn 2523: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2524: }
2525:
1.562 damieng 2526: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2527: #
1.581 raeburn 2528: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2529: sub parmmenu {
1.581 raeburn 2530: my ($r)=@_;
1.208 www 2531: $r->print(<<ENDSCRIPT);
2532: <script type="text/javascript">
1.454 bisitz 2533: // <![CDATA[
1.208 www 2534: function checkall(value, checkName) {
1.453 schualex 2535:
2536: var li = "_li";
2537: var displayOverview = "";
2538:
2539: if (value == false) {
2540: displayOverview = "none"
2541: }
2542:
1.562 damieng 2543: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2544: ele = document.forms.parmform.elements[i];
2545: if (ele.name == checkName) {
2546: document.forms.parmform.elements[i].checked=value;
2547: }
2548: }
2549: }
1.210 www 2550:
2551: function checkthis(thisvalue, checkName) {
1.562 damieng 2552: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2553: ele = document.forms.parmform.elements[i];
2554: if (ele.name == checkName) {
1.562 damieng 2555: if (ele.value == thisvalue) {
2556: document.forms.parmform.elements[i].checked=true;
2557: }
1.210 www 2558: }
2559: }
2560: }
2561:
2562: function checkdates() {
1.562 damieng 2563: checkthis('duedate','pscat');
2564: checkthis('opendate','pscat');
2565: checkthis('answerdate','pscat');
1.218 www 2566: }
2567:
2568: function checkdisset() {
1.562 damieng 2569: checkthis('discussend','pscat');
2570: checkthis('discusshide','pscat');
2571: checkthis('discussvote','pscat');
1.218 www 2572: }
2573:
2574: function checkcontdates() {
1.562 damieng 2575: checkthis('contentopen','pscat');
2576: checkthis('contentclose','pscat');
1.218 www 2577: }
1.446 bisitz 2578:
1.210 www 2579: function checkvisi() {
1.562 damieng 2580: checkthis('hiddenresource','pscat');
2581: checkthis('encrypturl','pscat');
2582: checkthis('problemstatus','pscat');
2583: checkthis('contentopen','pscat');
2584: checkthis('opendate','pscat');
1.210 www 2585: }
2586:
2587: function checkparts() {
1.562 damieng 2588: checkthis('hiddenparts','pscat');
2589: checkthis('display','pscat');
2590: checkthis('ordered','pscat');
1.210 www 2591: }
2592:
2593: function checkstandard() {
2594: checkall(false,'pscat');
1.562 damieng 2595: checkdates();
2596: checkthis('weight','pscat');
2597: checkthis('maxtries','pscat');
2598: checkthis('type','pscat');
2599: checkthis('problemstatus','pscat');
1.210 www 2600: }
2601:
1.454 bisitz 2602: // ]]>
1.208 www 2603: </script>
2604: ENDSCRIPT
1.453 schualex 2605:
1.491 bisitz 2606: $r->print('<hr />');
1.581 raeburn 2607: &shortCuts($r);
1.491 bisitz 2608: $r->print('<hr />');
1.453 schualex 2609: }
1.562 damieng 2610:
2611: # Returns parameter categories.
2612: #
2613: # @returns {hash} - category name -> title in English
1.465 amueller 2614: sub categories {
2615: return ('time_settings' => 'Time Settings',
2616: 'grading' => 'Grading',
2617: 'tries' => 'Tries',
2618: 'problem_appearance' => 'Problem Appearance',
2619: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2620: 'hiding' => 'Hiding',
2621: 'high_level_randomization' => 'High Level Randomization',
2622: 'slots' => 'Slots',
2623: 'file_submission' => 'File Submission',
2624: 'misc' => 'Miscellaneous' );
2625: }
2626:
1.562 damieng 2627: # Returns the category for each parameter.
2628: #
2629: # @returns {hash} - parameter name -> category name
1.465 amueller 2630: sub lookUpTableParameter {
2631:
2632: return (
2633: 'opendate' => 'time_settings',
2634: 'duedate' => 'time_settings',
2635: 'answerdate' => 'time_settings',
1.622 raeburn 2636: 'grace' => 'time_settings',
1.465 amueller 2637: 'interval' => 'time_settings',
2638: 'contentopen' => 'time_settings',
2639: 'contentclose' => 'time_settings',
2640: 'discussend' => 'time_settings',
1.560 damieng 2641: 'printstartdate' => 'time_settings',
2642: 'printenddate' => 'time_settings',
1.465 amueller 2643: 'weight' => 'grading',
2644: 'handgrade' => 'grading',
2645: 'maxtries' => 'tries',
2646: 'hinttries' => 'tries',
1.503 raeburn 2647: 'randomizeontries' => 'tries',
1.465 amueller 2648: 'type' => 'problem_appearance',
2649: 'problemstatus' => 'problem_appearance',
2650: 'display' => 'problem_appearance',
2651: 'ordered' => 'problem_appearance',
2652: 'numbubbles' => 'problem_appearance',
2653: 'tol' => 'behaviour_of_input_fields',
2654: 'sig' => 'behaviour_of_input_fields',
2655: 'turnoffunit' => 'behaviour_of_input_fields',
2656: 'hiddenresource' => 'hiding',
2657: 'hiddenparts' => 'hiding',
2658: 'discusshide' => 'hiding',
2659: 'buttonshide' => 'hiding',
2660: 'turnoffeditor' => 'hiding',
2661: 'encrypturl' => 'hiding',
1.587 raeburn 2662: 'deeplink' => 'hiding',
1.465 amueller 2663: 'randomorder' => 'high_level_randomization',
2664: 'randompick' => 'high_level_randomization',
2665: 'available' => 'slots',
2666: 'useslots' => 'slots',
2667: 'availablestudent' => 'slots',
2668: 'uploadedfiletypes' => 'file_submission',
2669: 'maxfilesize' => 'file_submission',
2670: 'cssfile' => 'misc',
2671: 'mapalias' => 'misc',
2672: 'acc' => 'misc',
2673: 'maxcollaborators' => 'misc',
2674: 'scoreformat' => 'misc',
1.514 raeburn 2675: 'lenient' => 'grading',
1.519 raeburn 2676: 'retrypartial' => 'tries',
1.521 raeburn 2677: 'discussvote' => 'misc',
1.621 raeburn 2678: 'texdisplay' => 'misc',
1.584 raeburn 2679: 'examcode' => 'high_level_randomization',
1.575 raeburn 2680: );
1.465 amueller 2681: }
2682:
1.562 damieng 2683: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2684: #
2685: # @param {string} $name - parameter name
2686: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2687: sub whatIsMyCategory {
2688: my $name = shift;
2689: my $catList = shift;
2690: my @list;
2691: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2692: my $cat = $lookUpList{$name};
2693: if (defined($cat)) {
2694: if (!defined($$catList{$cat})){
2695: push @list, ($name);
2696: $$catList{$cat} = \@list;
2697: } else {
2698: push @{${$catList}{$cat}}, ($name);
2699: }
2700: } else {
2701: if (!defined($$catList{'misc'})){
2702: push @list, ($name);
2703: $$catList{'misc'} = \@list;
2704: } else {
2705: push @{${$catList}{'misc'}}, ($name);
2706: }
2707: }
2708: }
2709:
1.562 damieng 2710: # Sorts parameter names based on appearance order.
2711: #
2712: # @param {array reference} name - array reference of parameter names
2713: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2714: # @returns {Array} - array of parameter names
1.465 amueller 2715: sub keysindisplayorderCategory {
2716: my ($name,$keyorder)=@_;
2717: return sort {
1.473 amueller 2718: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2719: } ( @{$name});
2720: }
2721:
1.562 damieng 2722: # Returns a hash category name -> order, starting at 1 (integer)
2723: #
2724: # @returns {hash}
1.467 amueller 2725: sub category_order {
2726: return (
2727: 'time_settings' => 1,
2728: 'grading' => 2,
2729: 'tries' => 3,
2730: 'problem_appearance' => 4,
2731: 'hiding' => 5,
2732: 'behaviour_of_input_fields' => 6,
2733: 'high_level_randomization' => 7,
2734: 'slots' => 8,
2735: 'file_submission' => 9,
2736: 'misc' => 10
2737: );
2738:
2739: }
1.453 schualex 2740:
1.562 damieng 2741: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2742: #
2743: # @param {Apache2::RequestRec} $r - the Apache request
2744: # @param {hash reference} $allparms - hash parameter name -> parameter title
2745: # @param {array reference} $pscat - list of selected parameter names
2746: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2747: sub parmboxes {
2748: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2749: my %categories = &categories();
1.467 amueller 2750: my %category_order = &category_order();
1.465 amueller 2751: my %categoryList = (
2752: 'time_settings' => [],
2753: 'grading' => [],
2754: 'tries' => [],
2755: 'problem_appearance' => [],
2756: 'behaviour_of_input_fields' => [],
2757: 'hiding' => [],
2758: 'high_level_randomization' => [],
2759: 'slots' => [],
2760: 'file_submission' => [],
2761: 'misc' => [],
1.489 bisitz 2762: );
1.510 www 2763:
1.548 raeburn 2764: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2765: &whatIsMyCategory($tempparameter, \%categoryList);
2766: }
1.453 schualex 2767: #part to print the parm-list
1.618 raeburn 2768: $Text::Wrap::columns=60;
2769: $Text::Wrap::separator='<br />';
1.536 raeburn 2770: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2771: next if (@{$categoryList{$key}} == 0);
2772: next if ($key eq '');
2773: $r->print('<div class="LC_Box LC_400Box">'
2774: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2775: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2776: next if ($tempkey eq '');
1.536 raeburn 2777: $r->print('<span class="LC_nobreak">'
2778: .'<label><input type="checkbox" name="pscat" '
2779: .'value="'.$tempkey.'" ');
2780: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2781: $r->print( ' checked="checked"');
2782: }
1.617 raeburn 2783: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ?
2784: Text::Wrap::wrap('',' 'x4,$$allparms{$tempkey})
2785: : $tempkey)
1.536 raeburn 2786: .'</label></span><br />'."\n");
1.465 amueller 2787: }
1.536 raeburn 2788: $r->print('</div>');
1.465 amueller 2789: }
1.536 raeburn 2790: $r->print("\n");
1.453 schualex 2791: }
1.562 damieng 2792:
2793: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2794: #
1.562 damieng 2795: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2796: sub shortCuts {
1.581 raeburn 2797: my ($r)=@_;
1.453 schualex 2798:
1.491 bisitz 2799: # Parameter Selection
2800: $r->print(
2801: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2802: .&Apache::lonhtmlcommon::add_item_funclist(
2803: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2804: .&Apache::lonhtmlcommon::add_item_funclist(
2805: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2806: .&Apache::lonhtmlcommon::add_item_funclist(
2807: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2808: .&Apache::lonhtmlcommon::end_funclist()
2809: );
2810:
2811: # Add Selection for...
2812: $r->print(
2813: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2814: .&Apache::lonhtmlcommon::add_item_funclist(
2815: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2816: .&Apache::lonhtmlcommon::add_item_funclist(
2817: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2818: .&Apache::lonhtmlcommon::add_item_funclist(
2819: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2820: .&Apache::lonhtmlcommon::add_item_funclist(
2821: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2822: .&Apache::lonhtmlcommon::add_item_funclist(
2823: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2824: .&Apache::lonhtmlcommon::end_funclist()
2825: );
1.208 www 2826: }
2827:
1.562 damieng 2828: # Prints HTML to select parts to view (except for the title).
2829: # Used by table and overview modes.
2830: #
2831: # @param {Apache2::RequestRec} $r - the Apache request
2832: # @param {hash reference} $allparts - hash parameter part -> part title
2833: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2834: sub partmenu {
1.446 bisitz 2835: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2836: my $selsize = 1+scalar(keys(%{$allparts}));
2837: if ($selsize > 8) {
2838: $selsize = 8;
2839: }
1.446 bisitz 2840:
1.523 raeburn 2841: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2842: $r->print('<option value="all"');
1.562 damieng 2843: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2844: $r->print('>'.&mt('All Parts').'</option>');
2845: my %temphash=();
2846: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2847: foreach my $tempkey (sort {
1.560 damieng 2848: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2849: } keys(%{$allparts})) {
2850: unless ($tempkey =~ /\./) {
2851: $r->print('<option value="'.$tempkey.'"');
2852: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2853: $r->print(' selected="selected"');
2854: }
2855: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2856: }
1.208 www 2857: }
1.446 bisitz 2858: $r->print('</select>');
1.209 www 2859: }
2860:
1.562 damieng 2861: # Prints HTML to select a user and/or a group.
2862: # Used by table mode.
2863: #
2864: # @param {Apache2::RequestRec} $r - the Apache request
2865: # @param {string} $uname - selected user name
2866: # @param {string} $id - selected Student/Employee ID
2867: # @param {string} $udom - selected user domain
2868: # @param {string} $csec - selected section name
2869: # @param {string} $cgroup - selected group name
2870: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2871: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2872: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2873: sub usermenu {
1.553 raeburn 2874: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2875: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2876: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2877: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2878: function setCourseadv(form,caller) {
2879: if (caller.value == 'st') {
2880: form.courseadv.value = 'none';
2881: } else {
2882: form.courseadv.value = '';
2883: }
2884: return;
2885: }
2886: ENDJS
1.412 bisitz 2887:
1.596 raeburn 2888: my (%chkroles,$stuonly,$courseadv);
2889: if ($env{'form.userroles'} eq 'any') {
2890: $chkroles{'any'} = ' checked="checked"';
2891: } else {
2892: $chkroles{'st'} = ' checked="checked"';
2893: $courseadv = 'none';
2894: }
2895: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2896: if ($crstype eq 'Community') {
2897: $stuonly = &mt('member only');
2898: } else {
2899: $stuonly = &mt('student only');
2900: }
2901: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2902: &mt("User's role").': '.
2903: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2904: $stuonly.'</label> '.
2905: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2906: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2907: my $sections='';
1.300 albertel 2908: my %sectionhash = &Apache::loncommon::get_sections();
2909:
1.269 raeburn 2910: my $groups;
1.553 raeburn 2911: my %grouphash;
2912: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2913: %grouphash = &Apache::longroup::coursegroups();
2914: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2915: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2916: }
1.299 albertel 2917:
1.412 bisitz 2918: my $g_s_header='';
2919: my $g_s_footer='';
1.446 bisitz 2920:
1.552 raeburn 2921: my $currsec = $env{'request.course.sec'};
2922: if ($currsec) {
2923: $sections=&mt('Section:').' '.$currsec;
2924: if (%grouphash) {
2925: $sections .= ';'.(' ' x2);
2926: }
2927: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2928: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2929: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2930: $sections .= qq| onchange="group_or_section('csec')" |;
2931: }
2932: $sections .= '>';
1.548 raeburn 2933: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2934: $sections.='<option value="'.$section.'" '.
2935: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2936: '</option>';
1.209 www 2937: }
2938: $sections.='</select>';
1.269 raeburn 2939: }
1.412 bisitz 2940:
1.552 raeburn 2941: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2942: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2943: $sections .= qq|
2944: <script type="text/javascript">
1.454 bisitz 2945: // <![CDATA[
1.269 raeburn 2946: function group_or_section(caller) {
2947: if (caller == "cgroup") {
2948: if (document.parmform.cgroup.selectedIndex != 0) {
2949: document.parmform.csec.selectedIndex = 0;
2950: }
2951: } else {
2952: if (document.parmform.csec.selectedIndex != 0) {
2953: document.parmform.cgroup.selectedIndex = 0;
2954: }
2955: }
2956: }
1.454 bisitz 2957: // ]]>
1.269 raeburn 2958: </script>
2959: |;
1.554 raeburn 2960: } else {
1.269 raeburn 2961: $sections .= qq|
2962: <script type="text/javascript">
1.454 bisitz 2963: // <![CDATA[
1.269 raeburn 2964: function group_or_section(caller) {
2965: return;
2966: }
1.454 bisitz 2967: // ]]>
1.269 raeburn 2968: </script>
2969: |;
1.446 bisitz 2970: }
1.299 albertel 2971:
2972: if (%grouphash) {
1.597 raeburn 2973: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2974: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2975: $groups .= qq| onchange="group_or_section('cgroup')" |;
2976: }
2977: $groups .= '>';
1.548 raeburn 2978: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2979: $groups.='<option value="'.$grp.'" ';
2980: if ($grp eq $cgroup) {
2981: unless ((defined($uname)) && ($grp eq '')) {
2982: $groups .= 'selected="selected" ';
2983: }
2984: } elsif (!defined($cgroup)) {
2985: if (@{$usersgroups} == 1) {
2986: if ($grp eq $$usersgroups[0]) {
2987: $groups .= 'selected="selected" ';
2988: }
2989: }
2990: }
2991: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2992: }
2993: $groups.='</select>';
2994: }
1.412 bisitz 2995:
1.445 neumanie 2996: if (%sectionhash || %grouphash) {
1.446 bisitz 2997: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2998: $r->print($sections.$groups);
1.448 bisitz 2999: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 3000: } else {
3001: $r->print($sections);
1.445 neumanie 3002: }
1.446 bisitz 3003:
3004: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 3005: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 3006: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
3007: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 3008: ,$chooseopt));
1.209 www 3009: }
3010:
1.562 damieng 3011: # Prints HTML to select parameters from a list of all parameters.
3012: # Uses parmmenu and parmboxes.
3013: # Used by table and overview modes.
1.468 amueller 3014: #
1.562 damieng 3015: # @param {Apache2::RequestRec} $r - the Apache request
3016: # @param {hash reference} $allparms - hash parameter name -> parameter title
3017: # @param {array reference} $pscat - list of selected parameter names
3018: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3019: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 3020: sub displaymenu {
1.581 raeburn 3021: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 3022:
1.445 neumanie 3023: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 3024: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
3025:
1.581 raeburn 3026: &parmmenu($r);
1.536 raeburn 3027: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 3028: &parmboxes($r,$allparms,$pscat,$keyorder);
3029: $r->print(&Apache::loncommon::end_scrollbox());
3030:
3031: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 3032: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 3033:
1.209 www 3034: }
3035:
1.562 damieng 3036: # Prints HTML to select a map.
3037: # Used by table mode and overview mode.
3038: #
3039: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 3040: # @param {hash reference} $allmaps - hash map pc -> map src
3041: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 3042: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 3043: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610 raeburn 3044: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445 neumanie 3045: sub mapmenu {
1.610 raeburn 3046: my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468 amueller 3047: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 3048: my $navmap = Apache::lonnavmaps::navmap->new();
3049: my $tree=[];
3050: my $treeinfo={};
3051: if (defined($navmap)) {
1.499 raeburn 3052: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 3053: my $curRes;
3054: my $depth = 0;
1.468 amueller 3055: my %parent = ();
3056: my $startcount = 5;
3057: my $lastcontainer = $startcount;
3058: # preparing what is to show ...
1.461 neumanie 3059: while ($curRes = $it->next()) {
3060: if ($curRes == $it->BEGIN_MAP()) {
3061: $depth++;
1.468 amueller 3062: $parent{$depth}= $lastcontainer;
1.461 neumanie 3063: }
3064: if ($curRes == $it->END_MAP()) {
3065: $depth--;
1.468 amueller 3066: $lastcontainer = $parent{$depth};
1.461 neumanie 3067: }
3068: if (ref($curRes)) {
1.468 amueller 3069: my $symb = $curRes->symb();
3070: my $ressymb = $symb;
1.461 neumanie 3071: if (($curRes->is_sequence()) || ($curRes->is_page())) {
3072: my $type = 'sequence';
3073: if ($curRes->is_page()) {
3074: $type = 'page';
3075: }
3076: my $id= $curRes->id();
1.468 amueller 3077: my $srcf = $curRes->src();
3078: my $resource_name = &Apache::lonnet::gettitle($srcf);
3079: if(!exists($treeinfo->{$id})) {
3080: push(@$tree,$id);
1.473 amueller 3081: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 3082: $treeinfo->{$id} = {
1.461 neumanie 3083: depth => $depth,
3084: type => $type,
1.468 amueller 3085: name => $resource_name,
3086: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 3087: };
1.462 neumanie 3088: }
1.461 neumanie 3089: }
3090: }
3091: }
1.462 neumanie 3092: }
1.473 amueller 3093: # Show it ...
1.610 raeburn 3094: my $rowattr = ' id="mapmenu"';
3095: if ($parmlev eq 'general') {
3096: $rowattr .= ' style="display:none"';
3097: }
3098: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461 neumanie 3099: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
3100: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 3101: my $whitespace =
3102: '<img src="'
3103: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
3104: .'" alt="" />';
3105:
1.498 bisitz 3106: # Info about selectable folders/maps
3107: $r->print(
3108: '<div class="LC_info">'
1.508 www 3109: .&mt('You can only select maps and folders which have modifiable settings.')
3110: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 3111: .'</div>'
3112: );
3113:
1.536 raeburn 3114: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 3115: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 3116:
1.498 bisitz 3117: # Display row: "All Maps or Folders"
3118: $r->print(
1.523 raeburn 3119: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 3120: .'<td>'
3121: .'<label>'
3122: .'<input type="radio" name="pschp"'
1.497 bisitz 3123: );
3124: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 3125: $r->print(
3126: ' value="all" /> '.$icon.' '
3127: .&mt('All Maps or Folders')
3128: .'</label>'
3129: .'<hr /></td>'
3130: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 3131: );
1.497 bisitz 3132:
1.532 raeburn 3133: # Display row: "Main Content"
1.468 amueller 3134: if (exists($$allmaps{1})) {
1.498 bisitz 3135: $r->print(
3136: &Apache::loncommon::start_data_table_row()
3137: .'<td>'
3138: .'<label>'
3139: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 3140: );
1.497 bisitz 3141: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 3142: $r->print(
3143: '/> '.$icon.' '
3144: .$$maptitles{1}
3145: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
3146: .'</label>'
3147: .'</td>'
3148: .&Apache::loncommon::end_data_table_row()
1.468 amueller 3149: );
3150: }
1.497 bisitz 3151:
3152: # Display rows for all course maps and folders
1.468 amueller 3153: foreach my $id (@{$tree}) {
3154: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 3155: # Indentation
1.468 amueller 3156: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 3157: my $indent;
3158: for (my $i = 0; $i < $depth; $i++) {
3159: $indent.= $whitespace;
3160: }
1.461 neumanie 3161: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 3162: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 3163: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
3164: }
1.468 amueller 3165: my $symb_name = $$symbp{$id};
3166: my ($front, $tail) = split (/___${resid}___/, $symb_name);
3167: $symb_name = $tail;
1.498 bisitz 3168: $r->print(
3169: &Apache::loncommon::start_data_table_row()
3170: .'<td>'
3171: .'<label>'
1.463 bisitz 3172: );
1.498 bisitz 3173: # Only offer radio button for folders/maps which can be parameterized
3174: if ($allmaps_inverted{$symb_name}) {
3175: $r->print(
3176: '<input type ="radio" name="pschp"'
3177: .' value="'.$allmaps_inverted{$symb_name}.'"'
3178: );
3179: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
3180: $r->print('/>');
3181: } else {
3182: $r->print($whitespace);
1.461 neumanie 3183: }
1.498 bisitz 3184: $r->print(
3185: $indent.$icon.' '
3186: .$treeinfo->{$id}->{name}
3187: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
3188: .'</label>'
3189: .'</td>'
3190: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 3191: );
1.461 neumanie 3192: }
1.497 bisitz 3193:
1.523 raeburn 3194: $r->print(&Apache::loncommon::end_data_table().
3195: '<br style="line-height:2px;" />'.
3196: &Apache::loncommon::end_scrollbox());
1.209 www 3197: }
3198: }
3199:
1.563 damieng 3200: # Prints HTML to select the parameter level (resource, map/folder or course).
3201: # Used by table and overview modes.
3202: #
3203: # @param {Apache2::RequestRec} $r - the Apache request
3204: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
3205: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 3206: sub levelmenu {
1.446 bisitz 3207: my ($r,$alllevs,$parmlev)=@_;
3208:
1.548 raeburn 3209: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
3210: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 3211: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 3212: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
3213: $r->print('<option value="'.$$alllevs{$lev}.'"');
3214: if ($parmlev eq $$alllevs{$lev}) {
3215: $r->print(' selected="selected"');
3216: }
3217: $r->print('>'.&mt($lev).'</option>');
1.208 www 3218: }
1.446 bisitz 3219: $r->print("</select>");
1.208 www 3220: }
3221:
1.211 www 3222:
1.563 damieng 3223: # Returns HTML to select a section (with a select HTML element).
3224: # Used by overview mode.
3225: #
3226: # @param {array reference} $selectedsections - list of selected section ids
3227: # @returns {string}
1.211 www 3228: sub sectionmenu {
1.553 raeburn 3229: my ($selectedsections)=@_;
1.300 albertel 3230: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 3231: return '' if (!%sectionhash);
1.300 albertel 3232:
1.552 raeburn 3233: my (@possibles,$disabled);
3234: if ($env{'request.course.sec'} ne '') {
3235: @possibles = ($env{'request.course.sec'});
3236: $selectedsections = [$env{'request.course.sec'}];
3237: $disabled = ' disabled="disabled"';
3238: } else {
3239: @possibles = ('all',sort(keys(%sectionhash)));
3240: }
1.553 raeburn 3241: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 3242: foreach my $s (@possibles) {
1.553 raeburn 3243: $output .= ' <option value="'.$s.'"';
3244: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
3245: $output .= ' selected="selected"';
1.473 amueller 3246: }
1.553 raeburn 3247: $output .= '>'."$s</option>\n";
1.300 albertel 3248: }
1.553 raeburn 3249: $output .= "</select>\n";
3250: return $output;
1.269 raeburn 3251: }
3252:
1.563 damieng 3253: # Returns HTML to select a group (with a select HTML element).
3254: # Used by overview mode.
3255: #
3256: # @param {array reference} $selectedgroups - list of selected group names
3257: # @returns {string}
1.269 raeburn 3258: sub groupmenu {
1.553 raeburn 3259: my ($selectedgroups)=@_;
3260: my %grouphash;
3261: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3262: %grouphash = &Apache::longroup::coursegroups();
3263: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 3264: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 3265: }
3266: return '' if (!%grouphash);
1.299 albertel 3267:
1.553 raeburn 3268: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 3269: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 3270: $output .= ' <option value="'.$group.'"';
3271: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
3272: $output .= ' selected="selected"';
1.473 amueller 3273: }
1.553 raeburn 3274: $output .= '>'."$group</option>\n";
1.211 www 3275: }
1.553 raeburn 3276: $output .= "</select>\n";
3277: return $output;
1.211 www 3278: }
3279:
1.563 damieng 3280: # Returns an array with the given parameter split by comma.
3281: # Used by assessparms (table mode).
3282: #
3283: # @param {string} $keyp - the string to split
3284: # @returns {Array<string>}
1.210 www 3285: sub keysplit {
3286: my $keyp=shift;
3287: return (split(/\,/,$keyp));
3288: }
3289:
1.563 damieng 3290: # Returns the keys in $name, sorted using $keyorder.
3291: # Parameters are sorted by key, which means they are sorted by part first, then by name.
3292: # Used by assessparms (table mode) for resource level.
3293: #
3294: # @param {hash reference} $name - parameter key -> parameter name
3295: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3296: # @returns {Array<string>}
1.210 www 3297: sub keysinorder {
3298: my ($name,$keyorder)=@_;
3299: return sort {
1.560 damieng 3300: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 3301: } (keys(%{$name}));
1.210 www 3302: }
3303:
1.563 damieng 3304: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3305: # Used by assessparms (table mode) for map and general levels.
3306: #
3307: # @param {hash reference} $name - parameter key -> parameter name
3308: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3309: # @returns {Array<string>}
1.236 albertel 3310: sub keysinorder_bytype {
3311: my ($name,$keyorder)=@_;
3312: return sort {
1.563 damieng 3313: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3314: my $tb=(split('_',$b))[-1];
3315: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3316: return ($a cmp $b);
3317: }
3318: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3319: } (keys(%{$name}));
1.236 albertel 3320: }
3321:
1.563 damieng 3322: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3323: # Used by defaultsetter (parameter settings default actions).
3324: #
3325: # @param {hash reference} $name - hash parameter name -> parameter title
3326: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3327: # @returns {Array<string>}
1.211 www 3328: sub keysindisplayorder {
3329: my ($name,$keyorder)=@_;
3330: return sort {
1.560 damieng 3331: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3332: } (keys(%{$name}));
1.211 www 3333: }
3334:
1.563 damieng 3335: # Prints HTML with a choice to sort results by realm or student first.
3336: # Used by overview mode.
3337: #
3338: # @param {Apache2::RequestRec} $r - the Apache request
3339: # @param {string} $sortorder - realmstudent|studentrealm
1.608 raeburn 3340: # @param {string} $context - newoverview|overview
1.214 www 3341: sub sortmenu {
1.608 raeburn 3342: my ($r,$sortorder,$context)=@_;
3343: my %text;
3344: if ($context eq 'newoverview') {
3345: %text = &Apache::lonlocal::texthash (
3346: realmstudent => 'Sort by location in course first, then student (group/section)',
3347: studentrealm => 'Sort by student (group/section) first, then location in course',
3348: );
3349: } else {
3350: %text = &Apache::lonlocal::texthash (
3351: realmstudent => 'Sort by realm first, then student (group/section)',
3352: studentrealm => 'Sort by student (group/section) first, then realm',
3353: );
1.214 www 3354: }
1.608 raeburn 3355: my %sortchecked = (
3356: realmstudent => ' checked="checked"',
3357: studentrealm => '',
3358: );
1.214 www 3359: if ($sortorder eq 'studentrealm') {
1.608 raeburn 3360: $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
3361: $sortchecked{'realmstudent'} = '';
3362: }
3363: foreach my $sorttype ('realmstudent','studentrealm') {
3364: $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
3365: $text{$sorttype}.'</label>');
1.214 www 3366: }
3367: }
3368:
1.563 damieng 3369: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3370: #
3371: # @returns {hash}
1.211 www 3372: sub standardkeyorder {
3373: return ('parameter_0_opendate' => 1,
1.473 amueller 3374: 'parameter_0_duedate' => 2,
3375: 'parameter_0_answerdate' => 3,
1.622 raeburn 3376: 'parameter_0_grace' => 4,
3377: 'parameter_0_interval' => 5,
3378: 'parameter_0_weight' => 6,
3379: 'parameter_0_maxtries' => 7,
3380: 'parameter_0_hinttries' => 8,
3381: 'parameter_0_contentopen' => 9,
3382: 'parameter_0_contentclose' => 10,
3383: 'parameter_0_type' => 11,
3384: 'parameter_0_problemstatus' => 12,
3385: 'parameter_0_hiddenresource' => 13,
3386: 'parameter_0_hiddenparts' => 14,
3387: 'parameter_0_display' => 15,
3388: 'parameter_0_ordered' => 16,
3389: 'parameter_0_tol' => 17,
3390: 'parameter_0_sig' => 18,
3391: 'parameter_0_turnoffunit' => 19,
3392: 'parameter_0_discussend' => 20,
3393: 'parameter_0_discusshide' => 21,
3394: 'parameter_0_discussvote' => 22,
3395: 'parameter_0_printstartdate' => 23,
3396: 'parameter_0_printenddate' => 24);
1.211 www 3397: }
3398:
1.59 matthew 3399:
1.560 damieng 3400: # Table mode UI.
1.563 damieng 3401: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3402: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3403: #
3404: # Parameters used from the request:
3405: # action - handler action (see handler), usermenu is checking for value 'settable'
3406: # cgroup - selected group
3407: # command - 'set': direct access to table mode for a resource
3408: # csec - selected section
3409: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3410: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3411: # id - student/employee ID
3412: # parmlev - selected level (full|map|general)
3413: # part - selected part (unused ?)
3414: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3415: # pres_type - &&&-separated parameter types
3416: # pres_value - &&&-separated parameter values
3417: # prevvisit - '1' if the user has submitted the form before
3418: # pscat (multiple values) - selected parameter names
1.566 damieng 3419: # pschp - selected map pc, or 'all'
1.563 damieng 3420: # psprt (multiple values) - list of selected parameter parts
3421: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3422: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3423: # symb - resource symb (when a single resource is selected)
3424: # udom - selected user domain
3425: # uname - selected user name
3426: # url - used only with command 'set', the resource url
3427: #
3428: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3429: # @param $parm_permission - ref to hash of permissions
3430: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3431: sub assessparms {
1.1 www 3432:
1.568 raeburn 3433: my ($r,$parm_permission) = @_;
1.201 www 3434:
1.512 foxr 3435:
3436: # -------------------------------------------------------- Variable declaration
1.566 damieng 3437: my @ids=(); # resource and map ids
3438: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3439: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3440: my %typep=(); # hash resource/map id -> resource type (file extension)
3441: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3442: my %uris=(); # hash resource/map id -> resource src
3443: my %maptitles=(); # hash map pc or src -> map title
3444: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3445: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3446: my %alllevs=(); # hash English level title -> value
3447:
3448: my $uname; # selected user name
3449: my $udom; # selected user domain
3450: my $uhome; # server with the user's files, or 'no_host'
3451: my $csec; # selected section name
3452: my $cgroup; # selected group name
3453: my @usersgroups = (); # list of the user groups
1.582 raeburn 3454: my $numreclinks = 0;
1.446 bisitz 3455:
1.190 albertel 3456: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3457:
1.57 albertel 3458: $alllevs{'Resource Level'}='full';
1.215 www 3459: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3460: $alllevs{'Course Level'}='general';
3461:
1.563 damieng 3462: my %allparms; # hash parameter name -> parameter title
3463: my %allparts; # hash parameter part -> part title
1.512 foxr 3464: # ------------------------------------------------------------------------------
3465:
1.210 www 3466: #
3467: # Order in which these parameters will be displayed
3468: #
1.211 www 3469: my %keyorder=&standardkeyorder();
3470:
1.512 foxr 3471: # @ids=();
3472: # %symbp=(); # These seem defined above already.
3473: # %typep=();
1.43 albertel 3474:
3475: my $message='';
3476:
1.190 albertel 3477: $csec=$env{'form.csec'};
1.552 raeburn 3478: if ($env{'request.course.sec'} ne '') {
3479: $csec = $env{'request.course.sec'};
3480: }
3481:
1.553 raeburn 3482: # Check group privs.
1.269 raeburn 3483: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3484: my $noeditgrp;
3485: if ($cgroup ne '') {
3486: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3487: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3488: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3489: $noeditgrp = 1;
3490: }
3491: }
3492: }
1.188 www 3493:
1.190 albertel 3494: if ($udom=$env{'form.udom'}) {
3495: } elsif ($udom=$env{'request.role.domain'}) {
3496: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3497: } else {
1.473 amueller 3498: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3499: }
1.468 amueller 3500:
1.43 albertel 3501:
1.134 albertel 3502: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3503: my $pschp=$env{'form.pschp'};
1.506 www 3504:
3505:
1.134 albertel 3506: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3507: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3508: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3509:
1.43 albertel 3510: my $pssymb='';
1.57 albertel 3511: my $parmlev='';
1.446 bisitz 3512:
1.190 albertel 3513: unless ($env{'form.parmlev'}) {
1.57 albertel 3514: $parmlev = 'map';
3515: } else {
1.190 albertel 3516: $parmlev = $env{'form.parmlev'};
1.57 albertel 3517: }
1.26 www 3518:
1.29 www 3519: # ----------------------------------------------- Was this started from grades?
3520:
1.560 damieng 3521: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3522: (!$env{'form.dis'})) {
1.473 amueller 3523: my $url=$env{'form.url'};
3524: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3525: $pssymb=&Apache::lonnet::symbread($url);
3526: if (!@pscat) { @pscat=('all'); }
3527: $pschp='';
1.57 albertel 3528: $parmlev = 'full';
1.190 albertel 3529: } elsif ($env{'form.symb'}) {
1.473 amueller 3530: $pssymb=$env{'form.symb'};
3531: if (!@pscat) { @pscat=('all'); }
3532: $pschp='';
1.57 albertel 3533: $parmlev = 'full';
1.43 albertel 3534: } else {
1.473 amueller 3535: $env{'form.url'}='';
1.43 albertel 3536: }
3537:
1.190 albertel 3538: my $id=$env{'form.id'};
1.43 albertel 3539: if (($id) && ($udom)) {
1.555 raeburn 3540: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3541: if ($uname) {
3542: $id='';
3543: } else {
3544: $message=
1.540 bisitz 3545: '<p class="LC_warning">'.
3546: &mt('Unknown ID [_1] at domain [_2]',
3547: "'".$id."'","'".$udom."'").
3548: '</p>';
1.473 amueller 3549: }
1.43 albertel 3550: } else {
1.473 amueller 3551: $uname=$env{'form.uname'};
1.43 albertel 3552: }
3553: unless ($udom) { $uname=''; }
3554: $uhome='';
3555: if ($uname) {
1.473 amueller 3556: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3557: if ($uhome eq 'no_host') {
1.473 amueller 3558: $message=
1.540 bisitz 3559: '<p class="LC_warning">'.
3560: &mt('Unknown user [_1] at domain [_2]',
3561: "'".$uname."'","'".$udom."'").
3562: '</p>';
1.473 amueller 3563: $uname='';
1.12 www 3564: } else {
1.473 amueller 3565: $csec=&Apache::lonnet::getsection($udom,$uname,
3566: $env{'request.course.id'});
3567: if ($csec eq '-1') {
1.596 raeburn 3568: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3569: if ($env{'form.userroles'} eq 'any') {
3570: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3571: $csec = $env{'request.course.sec'};
3572: $message = '<span class="LC_info">';
3573: if ($crstype eq 'Community') {
3574: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3575: $uname,$udom);
3576: } else {
3577: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3578: $uname,$udom);
3579: }
3580: $message .= '</span>';
3581: } else {
3582: my @possroles = ('in','ep','ta','cr');
3583: if ($crstype eq 'Community') {
3584: unshift(@possroles,'co');
3585: } else {
3586: unshift(@possroles,'cc');
3587: }
3588: my %not_student_roles =
3589: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3590: \@possroles,[$udom],1,1);
3591: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3592: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3593: my %sections_by_role;
3594: foreach my $role (keys(%not_student_roles)) {
3595: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3596: my ($rolename,$sec) = ($1,$2);
3597: if ($rolename =~ m{^cr/}) {
3598: $rolename = 'cr';
3599: }
3600: push(@{$sections_by_role{$rolename}},$sec);
3601: }
3602: }
3603: my $numroles = scalar(keys(%sections_by_role));
3604: if ($numroles) {
3605: foreach my $role (@possroles) {
3606: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3607: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3608: $csec = $secs[0];
3609: last;
3610: }
3611: }
3612: }
3613: if ($csec eq '-1') {
3614: $message = '<span class="LC_warning">';
3615: if ($crstype eq 'Community') {
3616: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3617: $uname,$udom);
3618: } else {
3619: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3620: $uname,$udom);
3621: }
3622: $message .= '</span>';
3623: $uname='';
3624: if ($env{'request.course.sec'} ne '') {
3625: $csec=$env{'request.course.sec'};
3626: } else {
3627: $csec=$env{'form.csec'};
3628: }
3629: $cgroup=$env{'form.cgroup'};
3630: } else {
3631: $message = '<span class="LC_info">';
3632: if ($crstype eq 'Community') {
3633: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3634: $uname,$udom);
3635: } else {
3636: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3637: $uname,$udom);
3638: }
3639: $message .= '</span>';
3640: }
3641: }
1.594 raeburn 3642: } else {
1.596 raeburn 3643: $message = '<span class="LC_warning">';
3644: if ($crstype eq 'Community') {
3645: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3646: $uname,$udom);
3647: } else {
3648: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3649: $uname,$udom);
3650: }
3651: $message .= '</span>';
3652: $uname='';
3653: if ($env{'request.course.sec'} ne '') {
3654: $csec=$env{'request.course.sec'};
3655: } else {
3656: $csec=$env{'form.csec'};
3657: }
3658: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3659: }
3660: } elsif ($env{'request.course.sec'} ne '') {
3661: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3662: $message='<span class="LC_warning">'.
1.594 raeburn 3663: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3664: $uname,$udom,$env{'request.course.sec'}).
3665: '</span>';
3666: $uname='';
3667: $csec=$env{'request.course.sec'};
3668: }
1.269 raeburn 3669: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3670: }
3671: if ($uname ne '') {
1.473 amueller 3672: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3673: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3674: $message .= "\n<p>\n".&mt('Full Name').': '
3675: .$name{'firstname'}.' '.$name{'middlename'}.' '
3676: .$name{'lastname'}.' '.$name{'generation'}
3677: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3678: @usersgroups = &Apache::lonnet::get_users_groups(
3679: $udom,$uname,$env{'request.course.id'});
3680: if (@usersgroups > 0) {
3681: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3682: $cgroup = $usersgroups[0];
3683: }
3684: } else {
3685: $cgroup = '';
1.297 raeburn 3686: }
1.269 raeburn 3687: }
1.12 www 3688: }
1.43 albertel 3689: }
1.2 www 3690:
1.43 albertel 3691: unless ($csec) { $csec=''; }
1.269 raeburn 3692: unless ($cgroup) { $cgroup=''; }
1.12 www 3693:
1.14 www 3694: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3695: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3696: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 3697: \%keyorder,undef,$pssymb);
1.63 bowersj2 3698:
1.582 raeburn 3699: %allmaps_inverted = reverse(%allmaps);
3700:
1.57 albertel 3701: $mapp{'0.0'} = '';
3702: $symbp{'0.0'} = '';
1.99 albertel 3703:
1.14 www 3704: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3705: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3706: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3707: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3708: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3709: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3710: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3711: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3712: my ($got_chostname,$chostname,$cmajor,$cminor);
3713: my $totalstored = 0;
1.605 raeburn 3714: my $totalskippeduser = 0;
1.546 raeburn 3715: my $now = time;
1.473 amueller 3716: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3717: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3718: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3719: next if ($csec ne $env{'request.course.sec'});
3720: }
1.556 raeburn 3721: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3722: next if ($noeditgrp);
1.605 raeburn 3723: } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
3724: if ($uname eq '') {
3725: $totalskippeduser ++;
3726: next;
3727: }
1.557 raeburn 3728: }
3729: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3730: $namematch = 'maplevelrecurse';
3731: }
1.556 raeburn 3732: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3733: my (@ok_slots,@fail_slots,@del_slots);
3734: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3735: my ($level,@all) =
3736: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3737: $csec,$cgroup,$courseopt);
3738: foreach my $slot_name (split(/:/,$values[$i])) {
3739: next if ($slot_name eq '');
3740: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3741: push(@ok_slots,$slot_name);
3742:
3743: } else {
3744: push(@fail_slots,$slot_name);
3745: }
3746: }
3747: if (@ok_slots) {
3748: $values[$i] = join(':',@ok_slots);
3749: } else {
3750: $values[$i] = '';
3751: }
3752: if ($all[$level] ne '') {
3753: my @existing = split(/:/,$all[$level]);
3754: foreach my $slot_name (@existing) {
3755: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3756: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3757: push(@del_slots,$slot_name);
3758: }
3759: }
3760: }
3761: }
1.554 raeburn 3762: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3763: $name = $1;
1.533 raeburn 3764: my $val = $values[$i];
1.549 raeburn 3765: my $valmatch = '';
1.533 raeburn 3766: if ($name eq 'examcode') {
1.544 raeburn 3767: if (&Apache::lonnet::validCODE($values[$i])) {
3768: $val = 'valid';
3769: }
1.546 raeburn 3770: } elsif ($name eq 'printstartdate') {
3771: if ($val =~ /^\d+$/) {
3772: if ($val > $now) {
3773: $val = 'future';
3774: }
3775: }
3776: } elsif ($name eq 'printenddate') {
3777: if ($val =~ /^\d+$/) {
3778: if ($val < $now) {
3779: $val = 'past';
3780: }
3781: }
1.549 raeburn 3782: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3783: my $stringtype = &get_stringtype($name);
3784: my $stringmatch = &standard_string_matches($stringtype);
3785: if (ref($stringmatch) eq 'ARRAY') {
3786: foreach my $item (@{$stringmatch}) {
3787: if (ref($item) eq 'ARRAY') {
3788: my ($regexpname,$pattern) = @{$item};
3789: if ($pattern ne '') {
3790: if ($val =~ /$pattern/) {
3791: $valmatch = $regexpname;
3792: $val = '';
3793: last;
3794: }
3795: }
3796: }
3797: }
3798: }
1.554 raeburn 3799: } elsif ($name eq 'interval') {
3800: my $intervaltype = &get_intervaltype($name);
3801: my $intervalmatch = &standard_interval_matches($intervaltype);
3802: if (ref($intervalmatch) eq 'ARRAY') {
3803: foreach my $item (@{$intervalmatch}) {
3804: if (ref($item) eq 'ARRAY') {
3805: my ($regexpname,$pattern) = @{$item};
3806: if ($pattern ne '') {
3807: if ($val =~ /$pattern/) {
3808: $valmatch = $regexpname;
3809: $val = '';
3810: last;
3811: }
3812: }
3813: }
3814: }
3815: }
1.533 raeburn 3816: }
1.504 raeburn 3817: $needsrelease =
1.557 raeburn 3818: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3819: if ($needsrelease) {
1.505 raeburn 3820: unless ($got_chostname) {
1.514 raeburn 3821: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3822: $got_chostname = 1;
1.546 raeburn 3823: }
1.557 raeburn 3824: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3825: $needsrelease,
3826: $cmajor,$cminor);
1.500 raeburn 3827: }
1.437 raeburn 3828: }
1.504 raeburn 3829: if ($needsnewer) {
1.557 raeburn 3830: undef($namematch);
3831: } else {
3832: my $currneeded;
3833: if ($needsrelease) {
3834: $currneeded = $needsrelease;
3835: }
3836: if ($namematch) {
3837: $needsrelease =
3838: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3839: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3840: unless ($got_chostname) {
3841: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3842: $got_chostname = 1;
3843: }
3844: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3845: $needsrelease,
3846: $cmajor,$cminor);
3847: } else {
3848: undef($namematch);
3849: }
3850: }
3851: }
3852: if ($needsnewer) {
3853: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3854: $cminor,$needsrelease);
3855: } else {
3856: $message.=&storeparm(split(/\&/,$markers[$i]),
3857: $values[$i],
3858: $types[$i],
3859: $uname,$udom,$csec,$cgroup);
3860: $totalstored ++;
3861: }
1.473 amueller 3862: }
1.68 www 3863: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3864: if ($totalstored) {
3865: $message.='<p class="LC_warning">'
1.605 raeburn 3866: .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
3867: .'<br />'
1.504 raeburn 3868: .&mt('Changes can take up to 10 minutes before being active for all students.')
3869: .&Apache::loncommon::help_open_topic('Caching')
3870: .'</p>';
1.605 raeburn 3871: } else {
3872: $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
3873: }
3874: if ($totalskippeduser) {
3875: $message .= '<p class="LC_warning">';
3876: if ($uhome eq 'no_host') {
3877: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
3878: $totalskippeduser);
3879: } elsif ($env{'form.userroles'} eq 'any') {
3880: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
3881: $totalskippeduser);
3882: } else {
3883: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
3884: $totalskippeduser);
3885: }
3886: $message .= '</p>';
1.504 raeburn 3887: }
1.68 www 3888: }
1.584 raeburn 3889:
1.57 albertel 3890: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3891: if ($pscat[0] eq "all") {
3892: @pscat = (keys(%allparms));
3893: }
3894: if (!@pscat) {
3895: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3896: };
3897: if ($psprt[0] eq "all" || !@psprt) {
3898: @psprt = (keys(%allparts));
3899: }
1.2 www 3900: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3901:
1.531 raeburn 3902: my $crstype = &Apache::loncommon::course_type();
3903: &startpage($r,$pssymb,$crstype);
1.57 albertel 3904:
1.548 raeburn 3905: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3906: 'date_interval','int','float','string','string_lenient',
3907: 'string_examcode','string_deeplink','string_discussvote',
3908: 'string_useslots','string_problemstatus','string_ip',
1.622 raeburn 3909: 'string_questiontype','string_tex','string_grace') {
1.473 amueller 3910: $r->print('<input type="hidden" value="'.
1.563 damieng 3911: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3912: '" name="recent_'.$item.'" />');
1.44 albertel 3913: }
1.446 bisitz 3914:
1.459 bisitz 3915: # ----- Start Parameter Selection
3916:
1.606 raeburn 3917: # Hide parm selection and possibly table?
3918: my ($tablejs,$tabledivsty);
3919: if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
3920: ($env{'form.dis'}) && ($pssymb eq '')) {
3921: $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
3922: $tabledivsty = ' style="display:none"';
3923: }
1.459 bisitz 3924: $r->print(<<ENDPARMSELSCRIPT);
3925: <script type="text/javascript">
3926: // <![CDATA[
3927: function parmsel_show() {
1.562 damieng 3928: document.getElementById('parmsel').style.display = "";
3929: document.getElementById('parmsellink').style.display = "none";
1.606 raeburn 3930: $tablejs
1.459 bisitz 3931: }
3932: // ]]>
3933: </script>
3934: ENDPARMSELSCRIPT
1.474 amueller 3935:
1.445 neumanie 3936: if (!$pssymb) {
1.563 damieng 3937: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3938: my $parmselhiddenstyle=' style="display:none"';
3939: if($env{'form.hideparmsel'} eq 'hidden') {
3940: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3941: } else {
3942: $r->print('<div id="parmsel">');
3943: }
3944:
1.491 bisitz 3945: # Step 1
1.523 raeburn 3946: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3947: $r->print('
1.474 amueller 3948: <script type="text/javascript">
1.523 raeburn 3949: // <![CDATA['.
3950: &showhide_js().'
1.474 amueller 3951: // ]]>
3952: </script>
1.523 raeburn 3953: ');
3954: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3955: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3956: $r->print(&Apache::lonhtmlcommon::row_closure());
1.610 raeburn 3957: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491 bisitz 3958: $r->print(&Apache::lonhtmlcommon::row_closure());
3959: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3960: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3961: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3962: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3963:
3964: # Step 2
1.523 raeburn 3965: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3966: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3967:
3968: # Step 3
1.523 raeburn 3969: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3970: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3971: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3972: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3973: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3974:
3975: # Update Display Button
1.486 www 3976: $r->print('<p>'
3977: .'<input type="submit" name="dis"'
1.511 www 3978: .' value="'.&mt('Update Display').'" />'
1.486 www 3979: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3980: .'</p>');
3981: $r->print('</div>');
1.491 bisitz 3982:
1.486 www 3983: # Offer link to display parameter selection again
3984: $r->print('<p id="parmsellink"');
3985: if ($env{'form.hideparmsel'} ne 'hidden') {
3986: $r->print($parmselhiddenstyle);
3987: }
3988: $r->print('>'
3989: .'<a href="javascript:parmsel_show()">'
3990: .&mt('Change Parameter Selection')
3991: .'</a>'
3992: .'</p>');
1.44 albertel 3993: } else {
1.478 amueller 3994: # parameter screen for a single resource.
1.486 www 3995: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3996: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3997: $r->print(&mt('Specific Resource: [_1] ([_2])',
3998: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3999: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 4000: '<br />');
4001: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
4002: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 4003: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 4004: $r->print(&Apache::lonhtmlcommon::row_closure(1));
4005: $r->print(&Apache::lonhtmlcommon::end_pick_box());
4006: $r->print('<p>'
1.459 bisitz 4007: .'<input type="submit" name="dis"'
1.511 www 4008: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 4009: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 4010: .'</p>');
1.459 bisitz 4011: }
1.478 amueller 4012:
1.486 www 4013: # ----- End Parameter Selection
1.57 albertel 4014:
1.459 bisitz 4015: # Display Messages
4016: $r->print('<div>'.$message.'</div>');
1.210 www 4017:
1.57 albertel 4018:
4019: my @temp_pscat;
4020: map {
4021: my $cat = $_;
4022: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
4023: } @pscat;
4024:
4025: @pscat = @temp_pscat;
4026:
1.548 raeburn 4027:
1.209 www 4028: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 4029: # ----------------------------------------------------------------- Start Table
1.57 albertel 4030: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 4031: my $csuname=$env{'user.name'};
4032: my $csudom=$env{'user.domain'};
1.568 raeburn 4033: my $readonly = 1;
4034: if ($parm_permission->{'edit'}) {
4035: undef($readonly);
4036: }
1.606 raeburn 4037: $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57 albertel 4038:
1.203 www 4039: if ($parmlev eq 'full') {
1.506 www 4040: #
4041: # This produces the cascading table output of parameters
4042: #
1.578 raeburn 4043: my $coursespan=$csec?8:5;
4044: my $userspan=3;
1.560 damieng 4045: if ($cgroup ne '') {
1.578 raeburn 4046: $coursespan += 3;
1.560 damieng 4047: }
1.473 amueller 4048:
1.560 damieng 4049: $r->print(&Apache::loncommon::start_data_table());
4050: #
4051: # This produces the headers
4052: #
4053: $r->print('<tr><td colspan="5"></td>');
4054: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
4055: if ($uname) {
1.473 amueller 4056: if (@usersgroups > 1) {
1.560 damieng 4057: $userspan ++;
4058: }
4059: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
4060: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
4061: }
4062: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 4063: 'pie' => "Parameter in Effect",
4064: 'csv' => "Current Session Value",
1.472 amueller 4065: 'rl' => "Resource Level",
1.473 amueller 4066: 'ic' => 'in Course',
4067: 'aut' => "Assessment URL and Title",
4068: 'type' => 'Type',
4069: 'emof' => "Enclosing Map or Folder",
4070: 'part' => 'Part',
1.472 amueller 4071: 'pn' => 'Parameter Name',
1.473 amueller 4072: 'def' => 'default',
4073: 'femof' => 'from Enclosing Map or Folder',
4074: 'gen' => 'general',
4075: 'foremf' => 'for Enclosing Map or Folder',
4076: 'fr' => 'for Resource'
4077: );
1.560 damieng 4078: $r->print(<<ENDTABLETWO);
1.419 bisitz 4079: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 4080: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 4081: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 4082: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 4083:
1.10 www 4084: ENDTABLETWO
1.560 damieng 4085: if ($csec) {
1.578 raeburn 4086: $r->print('<th colspan="3">'.
1.560 damieng 4087: &mt("in Section")." $csec</th>");
4088: }
4089: if ($cgroup) {
1.578 raeburn 4090: $r->print('<th colspan="3">'.
1.472 amueller 4091: &mt("in Group")." $cgroup</th>");
1.560 damieng 4092: }
4093: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 4094: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
4095: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 4096: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 4097: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 4098: ENDTABLEHEADFOUR
1.57 albertel 4099:
1.560 damieng 4100: if ($csec) {
1.578 raeburn 4101: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 4102: }
1.473 amueller 4103:
1.560 damieng 4104: if ($cgroup) {
1.578 raeburn 4105: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 4106: }
4107:
4108: if ($uname) {
4109: if (@usersgroups > 1) {
4110: $r->print('<th>'.&mt('Control by other group?').'</th>');
4111: }
1.578 raeburn 4112: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 4113: }
4114:
4115: $r->print('</tr>');
1.506 www 4116: #
4117: # Done with the headers
4118: #
1.560 damieng 4119: my $defbgone='';
4120: my $defbgtwo='';
4121: my $defbgthree = '';
1.57 albertel 4122:
1.560 damieng 4123: foreach my $rid (@ids) {
1.57 albertel 4124:
4125: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 4126: if ((!$pssymb &&
1.560 damieng 4127: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
4128: ||
4129: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 4130: # ------------------------------------------------------ Entry for one resource
1.473 amueller 4131: if ($defbgone eq '#E0E099') {
4132: $defbgone='#E0E0DD';
1.57 albertel 4133: } else {
1.419 bisitz 4134: $defbgone='#E0E099';
1.57 albertel 4135: }
1.419 bisitz 4136: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 4137: $defbgtwo='#FFFFDD';
1.57 albertel 4138: } else {
1.473 amueller 4139: $defbgtwo='#FFFF99';
1.57 albertel 4140: }
1.419 bisitz 4141: if ($defbgthree eq '#FFBB99') {
4142: $defbgthree='#FFBBDD';
1.269 raeburn 4143: } else {
1.419 bisitz 4144: $defbgthree='#FFBB99';
1.269 raeburn 4145: }
4146:
1.57 albertel 4147: my $thistitle='';
4148: my %name= ();
4149: undef %name;
4150: my %part= ();
4151: my %display=();
4152: my %type= ();
4153: my %default=();
1.196 www 4154: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4155: my $toolsymb;
4156: if ($uri =~ /ext\.tool$/) {
4157: $toolsymb = $symbp{$rid};
4158: }
1.57 albertel 4159:
1.506 www 4160: my $filter=$env{'form.filter'};
1.548 raeburn 4161: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 4162: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 4163: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 4164: # We may only want certain parameters listed
4165: if ($filter) {
4166: unless ($filter=~/\Q$parmname\E/) { next; }
4167: }
4168: $name{$tempkeyp}=$parmname;
1.584 raeburn 4169: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 4170:
1.584 raeburn 4171: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 4172: if ($allparms{$name{$tempkeyp}} ne '') {
4173: my $identifier;
4174: if ($parmdis =~ /(\s*\[Part.*)$/) {
4175: $identifier = $1;
4176: }
4177: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4178: } else {
4179: $display{$tempkeyp} = $parmdis;
4180: }
4181: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4182: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 4183: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
4184: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
4185: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 4186: }
4187: }
1.548 raeburn 4188: my $totalparms=scalar(keys(%name));
1.57 albertel 4189: if ($totalparms>0) {
1.560 damieng 4190: my $firstrow=1;
1.473 amueller 4191: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 4192: my $navmap = Apache::lonnavmaps::navmap->new();
4193: my @recurseup;
4194: if (ref($navmap) && $mapp{$rid}) {
4195: @recurseup = $navmap->recurseup_maps($mapp{$rid});
4196: }
1.419 bisitz 4197: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 4198: ' rowspan='.$totalparms.
1.419 bisitz 4199: '><tt><font size="-1">'.
1.57 albertel 4200: join(' / ',split(/\//,$uri)).
4201: '</font></tt><p><b>'.
1.154 albertel 4202: "<a href=\"javascript:openWindow('".
1.473 amueller 4203: &Apache::lonnet::clutter($uri).'?symb='.
4204: &escape($symbp{$rid}).
1.336 albertel 4205: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
4206: " target=\"_self\">$title");
1.57 albertel 4207:
4208: if ($thistitle) {
1.473 amueller 4209: $r->print(' ('.$thistitle.')');
1.57 albertel 4210: }
4211: $r->print('</a></b></td>');
1.419 bisitz 4212: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 4213: ' rowspan='.$totalparms.'>'.$typep{$rid}.
4214: '</td>');
4215:
1.419 bisitz 4216: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 4217: ' rowspan='.$totalparms.
1.238 www 4218: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 4219: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 4220: unless ($firstrow) {
4221: $r->print('<tr>');
4222: } else {
4223: undef $firstrow;
4224: }
1.548 raeburn 4225: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 4226: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 4227: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 4228: $cgroup,\@usersgroups,$noeditgrp,$readonly,
4229: \@recurseup,\%maptitles,\%allmaps_inverted,
4230: \$numreclinks);
1.57 albertel 4231: }
4232: }
4233: }
4234: } # end foreach ids
1.43 albertel 4235: # -------------------------------------------------- End entry for one resource
1.517 www 4236: $r->print(&Apache::loncommon::end_data_table);
1.203 www 4237: } # end of full
1.57 albertel 4238: #--------------------------------------------------- Entry for parm level map
4239: if ($parmlev eq 'map') {
1.419 bisitz 4240: my $defbgone = '#E0E099';
4241: my $defbgtwo = '#FFFF99';
4242: my $defbgthree = '#FFBB99';
1.57 albertel 4243:
4244: my %maplist;
4245:
4246: if ($pschp eq 'all') {
1.446 bisitz 4247: %maplist = %allmaps;
1.57 albertel 4248: } else {
4249: %maplist = ($pschp => $mapp{$pschp});
4250: }
4251:
4252: #-------------------------------------------- for each map, gather information
4253: my $mapid;
1.607 raeburn 4254: foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60 albertel 4255: my $maptitle = $maplist{$mapid};
1.57 albertel 4256:
4257: #----------------------- loop through ids and get all parameter types for map
4258: #----------------------------------------- and associated information
4259: my %name = ();
4260: my %part = ();
4261: my %display = ();
4262: my %type = ();
4263: my %default = ();
4264: my $map = 0;
4265:
1.473 amueller 4266: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 4267:
1.548 raeburn 4268: foreach my $id (@ids) {
4269: ($map)=($id =~ /([\d]*?)\./);
4270: my $rid = $id;
1.446 bisitz 4271:
1.57 albertel 4272: # $r->print("$mapid:$map: $rid <br /> \n");
4273:
1.560 damieng 4274: if ($map eq $mapid) {
1.473 amueller 4275: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4276: my $toolsymb;
4277: if ($uri =~ /ext\.tool$/) {
4278: $toolsymb = $symbp{$rid};
4279: }
1.582 raeburn 4280:
1.57 albertel 4281: # $r->print("Keys: $keyp{$rid} <br />\n");
4282:
4283: #--------------------------------------------------------------------
4284: # @catmarker contains list of all possible parameters including part #s
4285: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4286: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4287: # When storing information, store as part 0
4288: # When requesting information, request from full part
4289: #-------------------------------------------------------------------
1.548 raeburn 4290: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4291: my $tempkeyp = $fullkeyp;
4292: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 4293:
1.548 raeburn 4294: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4295: $part{$tempkeyp}="0";
1.584 raeburn 4296: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4297: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4298: if ($allparms{$name{$tempkeyp}} ne '') {
4299: my $identifier;
4300: if ($parmdis =~ /(\s*\[Part.*)$/) {
4301: $identifier = $1;
4302: }
4303: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4304: } else {
4305: $display{$tempkeyp} = $parmdis;
4306: }
4307: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4308: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4309: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4310: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4311: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 4312: }
4313: } # end loop through keys
1.560 damieng 4314: }
1.57 albertel 4315: } # end loop through ids
1.446 bisitz 4316:
1.57 albertel 4317: #---------------------------------------------------- print header information
1.133 www 4318: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 4319: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 4320: my $tmp="";
1.57 albertel 4321: if ($uname) {
1.473 amueller 4322: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 4323: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
4324: &mt('in')." \n";
1.57 albertel 4325: } else {
1.401 bisitz 4326: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 4327: }
1.269 raeburn 4328: if ($cgroup) {
1.401 bisitz 4329: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
4330: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4331: $csec = '';
4332: } elsif ($csec) {
1.401 bisitz 4333: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
4334: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4335: }
1.401 bisitz 4336: $r->print('<div align="center"><h4>'
4337: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 4338: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 4339: ,$tmp
4340: ,'<font color="red"><i>'.$coursename.'</i></font>'
4341: )
4342: ."<br /></h4>\n"
1.422 bisitz 4343: );
1.57 albertel 4344: #---------------------------------------------------------------- print table
1.419 bisitz 4345: $r->print('<p>'.&Apache::loncommon::start_data_table()
4346: .&Apache::loncommon::start_data_table_header_row()
4347: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 4348: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4349: .'<th>'.&mt('Parameter in Effect').'</th>'
4350: .&Apache::loncommon::end_data_table_header_row()
4351: );
1.57 albertel 4352:
1.582 raeburn 4353: my $navmap = Apache::lonnavmaps::navmap->new();
4354: my @recurseup;
4355: if (ref($navmap)) {
4356: my $mapres = $navmap->getByMapPc($mapid);
4357: if (ref($mapres)) {
4358: @recurseup = $navmap->recurseup_maps($mapres->src());
4359: }
4360: }
4361:
4362:
1.548 raeburn 4363: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4364: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4365: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4366: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4367: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4368: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4369: \$numreclinks);
1.57 albertel 4370: }
1.422 bisitz 4371: $r->print(&Apache::loncommon::end_data_table().'</p>'
4372: .'</div>'
4373: );
1.57 albertel 4374: } # end each map
4375: } # end of $parmlev eq map
4376: #--------------------------------- Entry for parm level general (Course level)
4377: if ($parmlev eq 'general') {
1.473 amueller 4378: my $defbgone = '#E0E099';
1.419 bisitz 4379: my $defbgtwo = '#FFFF99';
4380: my $defbgthree = '#FFBB99';
1.57 albertel 4381:
4382: #-------------------------------------------- for each map, gather information
4383: my $mapid="0.0";
4384: #----------------------- loop through ids and get all parameter types for map
4385: #----------------------------------------- and associated information
4386: my %name = ();
4387: my %part = ();
4388: my %display = ();
4389: my %type = ();
4390: my %default = ();
1.446 bisitz 4391:
1.548 raeburn 4392: foreach $id (@ids) {
4393: my $rid = $id;
1.446 bisitz 4394:
1.196 www 4395: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4396: my $toolsymb;
4397: if ($uri =~ /ext\.tool$/) {
4398: $toolsymb = $symbp{$rid};
4399: }
1.57 albertel 4400:
4401: #--------------------------------------------------------------------
4402: # @catmarker contains list of all possible parameters including part #s
4403: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4404: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4405: # When storing information, store as part 0
4406: # When requesting information, request from full part
4407: #-------------------------------------------------------------------
1.548 raeburn 4408: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4409: my $tempkeyp = $fullkeyp;
4410: $tempkeyp =~ s/_\w+_/_0_/;
4411: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4412: $part{$tempkeyp}="0";
1.584 raeburn 4413: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4414: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4415: if ($allparms{$name{$tempkeyp}} ne '') {
4416: my $identifier;
4417: if ($parmdis =~ /(\s*\[Part.*)$/) {
4418: $identifier = $1;
4419: }
4420: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4421: } else {
4422: $display{$tempkeyp} = $parmdis;
4423: }
4424: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4425: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4426: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4427: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4428: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4429: }
1.57 albertel 4430: } # end loop through keys
4431: } # end loop through ids
1.446 bisitz 4432:
1.57 albertel 4433: #---------------------------------------------------- print header information
1.473 amueller 4434: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4435: $r->print(<<ENDMAPONE);
1.419 bisitz 4436: <center>
4437: <h4>$setdef
1.135 albertel 4438: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4439: ENDMAPONE
4440: if ($uname) {
1.473 amueller 4441: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4442: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4443: } else {
1.135 albertel 4444: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4445: }
1.446 bisitz 4446:
1.135 albertel 4447: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4448: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4449: $r->print("</h4>\n");
1.57 albertel 4450: #---------------------------------------------------------------- print table
1.419 bisitz 4451: $r->print('<p>'.&Apache::loncommon::start_data_table()
4452: .&Apache::loncommon::start_data_table_header_row()
4453: .'<th>'.&mt('Parameter Name').'</th>'
4454: .'<th>'.&mt('Default Value').'</th>'
4455: .'<th>'.&mt('Parameter in Effect').'</th>'
4456: .&Apache::loncommon::end_data_table_header_row()
4457: );
1.57 albertel 4458:
1.548 raeburn 4459: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4460: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4461: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4462: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4463: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4464: $readonly);
1.57 albertel 4465: }
1.419 bisitz 4466: $r->print(&Apache::loncommon::end_data_table()
4467: .'</p>'
4468: .'</center>'
4469: );
1.57 albertel 4470: } # end of $parmlev eq general
1.606 raeburn 4471: $r->print('</div>');
1.43 albertel 4472: }
1.507 www 4473: $r->print('</form>');
1.582 raeburn 4474: if ($numreclinks) {
4475: $r->print(<<"END");
4476: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4477: <input type="hidden" name="pschp" />
4478: <input type="hidden" name="pscat" />
4479: <input type="hidden" name="psprt" />
4480: <input type="hidden" name="hideparmsel" value="hidden" />
4481: </form>
4482: <script type="text/javascript">
4483: function pjumprec(rid,name,part) {
4484: document.forms.recurseform.pschp.value = rid;
4485: document.forms.recurseform.pscat.value = name;
4486: document.forms.recurseform.psprt.value = part;
4487: document.forms.recurseform.submit();
4488: return false;
4489: }
4490: </script>
4491: END
4492: }
1.507 www 4493: &endSettingsScreen($r);
4494: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4495: } # end sub assessparms
1.30 www 4496:
1.560 damieng 4497:
4498:
1.120 www 4499: ##################################################
1.560 damieng 4500: # OVERVIEW MODE
1.207 www 4501: ##################################################
1.124 www 4502:
1.563 damieng 4503: my $tableopen; # boolean, true if HTML table is already opened
4504:
4505: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4506: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4507: # @returns {string}
1.124 www 4508: sub tablestart {
1.576 raeburn 4509: my ($readonly,$is_map) = @_;
1.124 www 4510: if ($tableopen) {
1.552 raeburn 4511: return '';
1.124 www 4512: } else {
1.552 raeburn 4513: $tableopen=1;
4514: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4515: if ($readonly) {
4516: $output .= '<th>'.&mt('Current value').'</th>';
4517: } else {
1.576 raeburn 4518: $output .= '<th>'.&mt('Delete').'</th>'.
4519: '<th>'.&mt('Set to ...').'</th>';
4520: if ($is_map) {
4521: $output .= '<th>'.&mt('Recursive?').'</th>';
4522: }
1.552 raeburn 4523: }
4524: $output .= '</tr>';
4525: return $output;
1.124 www 4526: }
4527: }
4528:
1.563 damieng 4529: # Returns HTML with the HTML table end tag, unless the table is not opened.
4530: # @returns {string}
1.124 www 4531: sub tableend {
4532: if ($tableopen) {
1.560 damieng 4533: $tableopen=0;
4534: return &Apache::loncommon::end_data_table();
1.124 www 4535: } else {
1.560 damieng 4536: return'';
1.124 www 4537: }
4538: }
4539:
1.563 damieng 4540: # Reads course and user information.
4541: # 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).
4542: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4543: # If the context is looking for a list, returns a list with the scalar data and the class list.
4544: # @param {string} $crs - course number
4545: # @param {string} $dom - course domain
4546: # @returns {hash reference|Array}
1.207 www 4547: sub readdata {
4548: my ($crs,$dom)=@_;
4549: # Read coursedata
4550: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4551: # Read userdata
4552:
4553: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4554: foreach my $user (keys(%$classlist)) {
4555: if ($user=~/^($match_username)\:($match_domain)$/) {
4556: my ($tuname,$tudom)=($1,$2);
4557: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4558: foreach my $userkey (keys(%{$useropt})) {
4559: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4560: my $newkey=$userkey;
1.548 raeburn 4561: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4562: $$resourcedata{$newkey}=$$useropt{$userkey};
4563: }
4564: }
1.473 amueller 4565: }
4566: }
1.552 raeburn 4567: if (wantarray) {
4568: return ($resourcedata,$classlist);
4569: } else {
4570: return $resourcedata;
4571: }
1.207 www 4572: }
4573:
4574:
1.563 damieng 4575: # Stores parameter data, using form parameters directly.
4576: #
4577: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.622 raeburn 4578: # set_* (except settext, setipallow, setipdeny, setdeeplink, setgrace) - set a parameter value
1.563 damieng 4579: # del_* - remove a parameter
4580: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4581: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4582: # key_* - date values
4583: # days_* - for date intervals
4584: # hours_* - for date intervals
4585: # minutes_* - for date intervals
4586: # seconds_* - for date intervals
4587: # done_* - for date intervals
4588: # typeof_* - parameter type
4589: #
4590: # @param {Apache2::RequestRec} $r - the Apache request
4591: # @param {string} $crs - course number
4592: # @param {string} $dom - course domain
1.208 www 4593: sub storedata {
4594: my ($r,$crs,$dom)=@_;
1.207 www 4595: # Set userlevel immediately
4596: # Do an intermediate store of course level
4597: my $olddata=&readdata($crs,$dom);
1.124 www 4598: my %newdata=();
4599: undef %newdata;
4600: my @deldata=();
1.576 raeburn 4601: my @delrec=();
4602: my @delnonrec=();
1.124 www 4603: undef @deldata;
1.504 raeburn 4604: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4605: my $now = time;
1.560 damieng 4606: foreach my $key (keys(%env)) {
4607: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4608: my $cmd=$1;
4609: my $thiskey=$2;
1.576 raeburn 4610: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.622 raeburn 4611: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink' || $cmd eq 'setgrace');
1.576 raeburn 4612: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4613: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4614: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4615: $altkey = $thiskey;
4616: $altkey =~ s/\Q___(all)\E/___(rec)/;
4617: if ($env{'form.rec_'.$thiskey}) {
4618: $recursive = 1;
4619: }
4620: }
4621: }
1.560 damieng 4622: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4623: if ($tuname) {
1.576 raeburn 4624: $tkey=$thiskey;
1.560 damieng 4625: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4626: if ($altkey) {
4627: $tkeynonrec = $tkey;
4628: $tkeyrec = $altkey;
4629: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4630: }
1.560 damieng 4631: }
4632: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4633: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4634: if ($cmd eq 'set') {
4635: $data=$env{$key};
4636: $valmatch = '';
4637: $valchk = $data;
4638: $typeof=$env{'form.typeof_'.$thiskey};
4639: $text = &mt('Saved modified parameter for');
4640: if ($typeof eq 'string_questiontype') {
4641: $name = 'type';
1.588 raeburn 4642: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4643: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4644: my $stringmatch = &standard_string_matches($typeof);
4645: if (ref($stringmatch) eq 'ARRAY') {
4646: foreach my $item (@{$stringmatch}) {
4647: if (ref($item) eq 'ARRAY') {
4648: my ($regexpname,$pattern) = @{$item};
4649: if ($pattern ne '') {
4650: if ($data =~ /$pattern/) {
4651: $valmatch = $regexpname;
4652: $valchk = '';
4653: last;
4654: }
1.560 damieng 4655: }
1.549 raeburn 4656: }
4657: }
4658: }
1.563 damieng 4659: } elsif ($typeof eq 'string_discussvote') {
4660: $name = 'discussvote';
4661: } elsif ($typeof eq 'string_examcode') {
4662: $name = 'examcode';
4663: if (&Apache::lonnet::validCODE($data)) {
4664: $valchk = 'valid';
4665: }
4666: } elsif ($typeof eq 'string_yesno') {
4667: if ($thiskey =~ /\.retrypartial$/) {
4668: $name = 'retrypartial';
4669: }
1.621 raeburn 4670: } elsif ($typeof eq 'string_tex') {
4671: $name = 'texdisplay';
1.549 raeburn 4672: }
1.563 damieng 4673: } elsif ($cmd eq 'datepointer') {
4674: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4675: $typeof=$env{'form.typeof_'.$thiskey};
4676: $text = &mt('Saved modified date for');
4677: if ($typeof eq 'date_start') {
4678: if ($thiskey =~ /\.printstartdate$/) {
4679: $name = 'printstartdate';
4680: if (($data) && ($data > $now)) {
4681: $valchk = 'future';
4682: }
1.560 damieng 4683: }
1.563 damieng 4684: } elsif ($typeof eq 'date_end') {
4685: if ($thiskey =~ /\.printenddate$/) {
4686: $name = 'printenddate';
4687: if (($data) && ($data < $now)) {
4688: $valchk = 'past';
4689: }
1.560 damieng 4690: }
1.504 raeburn 4691: }
1.563 damieng 4692: } elsif ($cmd eq 'dateinterval') {
4693: $data=&get_date_interval_from_form($thiskey);
4694: if ($thiskey =~ /\.interval$/) {
4695: $name = 'interval';
4696: my $intervaltype = &get_intervaltype($name);
4697: my $intervalmatch = &standard_interval_matches($intervaltype);
4698: if (ref($intervalmatch) eq 'ARRAY') {
4699: foreach my $item (@{$intervalmatch}) {
4700: if (ref($item) eq 'ARRAY') {
4701: my ($regexpname,$pattern) = @{$item};
4702: if ($pattern ne '') {
4703: if ($data =~ /$pattern/) {
4704: $valmatch = $regexpname;
4705: $valchk = '';
4706: last;
4707: }
1.560 damieng 4708: }
1.554 raeburn 4709: }
4710: }
4711: }
4712: }
1.563 damieng 4713: $typeof=$env{'form.typeof_'.$thiskey};
4714: $text = &mt('Saved modified date for');
1.554 raeburn 4715: }
1.576 raeburn 4716: if ($recursive) {
1.563 damieng 4717: $namematch = 'maplevelrecurse';
1.560 damieng 4718: }
1.563 damieng 4719: if (($name ne '') || ($namematch ne '')) {
4720: my ($needsrelease,$needsnewer);
4721: if ($name ne '') {
4722: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4723: if ($needsrelease) {
4724: unless ($got_chostname) {
1.563 damieng 4725: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4726: $got_chostname = 1;
4727: }
1.563 damieng 4728: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4729: $needsrelease,
4730: $cmajor,$cminor);
4731: }
4732: }
4733: if ($namematch ne '') {
4734: if ($needsnewer) {
4735: undef($namematch);
1.560 damieng 4736: } else {
1.563 damieng 4737: my $currneeded;
4738: if ($needsrelease) {
4739: $currneeded = $needsrelease;
4740: }
4741: $needsrelease =
4742: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4743: if (($needsrelease) &&
4744: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4745: unless ($got_chostname) {
4746: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4747: $got_chostname = 1;
4748: }
4749: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4750: $namematch, $needsrelease,$cmajor,$cminor);
4751: } else {
4752: undef($namematch);
4753: }
1.560 damieng 4754: }
1.557 raeburn 4755: }
1.563 damieng 4756: if ($needsnewer) {
4757: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4758: $chostname,$cmajor,
4759: $cminor,$needsrelease));
4760: next;
4761: }
1.504 raeburn 4762: }
1.576 raeburn 4763: my ($reconlychg,$haschange,$storekey);
4764: if ($tuname) {
4765: my $ustorekey;
4766: if ($altkey) {
4767: if ($recursive) {
4768: if (exists($$olddata{$thiskey})) {
4769: if ($$olddata{$thiskey} eq $data) {
4770: $reconlychg = 1;
4771: }
4772: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4773: }
4774: if (exists($$olddata{$altkey})) {
4775: if (defined($data) && $$olddata{$altkey} ne $data) {
4776: $haschange = 1;
4777: }
4778: } elsif ((!$reconlychg) && ($data ne '')) {
4779: $haschange = 1;
4780: }
4781: $ustorekey = $tkeyrec;
4782: } else {
4783: if (exists($$olddata{$altkey})) {
4784: if ($$olddata{$altkey} eq $data) {
4785: $reconlychg = 1;
4786: }
4787: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4788: }
4789: if (exists($$olddata{$thiskey})) {
4790: if (defined($data) && $$olddata{$thiskey} ne $data) {
4791: $haschange = 1;
4792: }
4793: } elsif ((!$reconlychg) && ($data ne '')) {
4794: $haschange = 1;
4795: }
4796: $ustorekey = $tkeynonrec;
4797: }
4798: } else {
4799: if (exists($$olddata{$tkey})) {
4800: if (defined($data) && $$olddata{$tkey} ne $data) {
4801: $haschange = 1;
4802: }
4803: $ustorekey = $tkey;
4804: }
4805: }
4806: if ($haschange || $reconlychg) {
4807: unless ($env{'form.del_'.$thiskey}) {
4808: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4809: $ustorekey.'.type' => $typeof},
4810: $tudom,$tuname) eq 'ok') {
4811: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4812: $r->print('<br />'.$text.' '.
4813: &Apache::loncommon::plainname($tuname,$tudom));
4814: } else {
4815: $r->print('<div class="LC_error">'.
4816: &mt('Error saving parameters').'</div>');
4817: }
4818: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4819: }
4820: }
4821: } else {
4822: if ($altkey) {
4823: if ($recursive) {
4824: if (exists($$olddata{$thiskey})) {
4825: if ($$olddata{$thiskey} eq $data) {
4826: $reconlychg = 1;
4827: }
4828: push(@delnonrec,($thiskey,$thiskey.'.type'));
4829: }
4830: if (exists($$olddata{$altkey})) {
4831: if (defined($data) && $$olddata{$altkey} ne $data) {
4832: $haschange = 1;
4833: }
4834: } elsif (($data ne '') && (!$reconlychg)) {
4835: $haschange = 1;
4836: }
4837: $storekey = $altkey;
1.563 damieng 4838: } else {
1.576 raeburn 4839: if (exists($$olddata{$altkey})) {
4840: if ($$olddata{$altkey} eq $data) {
4841: $reconlychg = 1;
4842: }
4843: push(@delrec,($altkey,$altkey.'.type'));
4844: }
4845: if (exists($$olddata{$thiskey})) {
4846: if (defined($data) && $$olddata{$thiskey} ne $data) {
4847: $haschange = 1;
4848: }
4849: } elsif (($data ne '') && (!$reconlychg)) {
4850: $haschange = 1;
4851: }
4852: $storekey = $thiskey;
1.563 damieng 4853: }
1.560 damieng 4854: } else {
1.576 raeburn 4855: if (defined($data) && $$olddata{$thiskey} ne $data) {
4856: $haschange = 1;
4857: $storekey = $thiskey;
4858: }
4859: }
4860: }
4861: if ($reconlychg || $haschange) {
4862: unless ($env{'form.del_'.$thiskey}) {
4863: $newdata{$storekey}=$data;
4864: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4865: }
4866: }
4867: } elsif ($cmd eq 'del') {
4868: if ($tuname) {
1.576 raeburn 4869: my $error;
4870: if ($altkey) {
4871: if (exists($$olddata{$altkey})) {
4872: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4873: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4874: if ($recursive) {
4875: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4876: }
4877: } elsif ($recursive) {
4878: $error = 1;
4879: }
4880: }
4881: if (exists($$olddata{$thiskey})) {
4882: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4883: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4884: unless ($recursive) {
4885: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4886: }
4887: } elsif (!$recursive) {
4888: $error = 1;
4889: }
4890: }
1.560 damieng 4891: } else {
1.576 raeburn 4892: if (exists($$olddata{$thiskey})) {
4893: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4894: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4895: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4896: } else {
4897: $error = 1;
4898: }
4899: }
4900: }
4901: if ($error) {
1.560 damieng 4902: $r->print('<div class="LC_error">'.
4903: &mt('Error deleting parameters').'</div>');
4904: }
4905: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4906: } else {
1.576 raeburn 4907: if ($altkey) {
4908: if (exists($$olddata{$altkey})) {
4909: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4910: push(@deldata,($altkey,$altkey.'.type'));
4911: }
4912: }
4913: if (exists($$olddata{$thiskey})) {
4914: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4915: push(@deldata,($thiskey,$thiskey.'.type'));
4916: }
4917: }
4918: } elsif (exists($$olddata{$thiskey})) {
4919: push(@deldata,($thiskey,$thiskey.'.type'));
4920: }
1.560 damieng 4921: }
1.473 amueller 4922: }
4923: }
4924: }
1.207 www 4925: # Store all course level
1.144 www 4926: my $delentries=$#deldata+1;
1.576 raeburn 4927: my @alldels;
4928: if (@delrec) {
4929: push(@alldels,@delrec);
4930: }
4931: if (@delnonrec) {
4932: push(@alldels,@delnonrec);
4933: }
4934: if (@deldata) {
4935: push(@alldels,@deldata);
4936: }
1.548 raeburn 4937: my @newdatakeys=keys(%newdata);
1.144 www 4938: my $putentries=$#newdatakeys+1;
1.576 raeburn 4939: my ($delresult,$devalidate);
4940: if (@alldels) {
4941: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4942: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4943: &log_parmset(\%loghash,1);
1.576 raeburn 4944: if ($delentries) {
4945: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4946: }
4947: } elsif ($delentries) {
1.560 damieng 4948: $r->print('<div class="LC_error">'.
4949: &mt('Error deleting parameters').'</div>');
4950: }
1.576 raeburn 4951: $devalidate = 1;
1.144 www 4952: }
4953: if ($putentries) {
1.560 damieng 4954: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4955: &log_parmset(\%newdata,0);
4956: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4957: } else {
4958: $r->print('<div class="LC_error">'.
4959: &mt('Error saving parameters').'</div>');
4960: }
1.576 raeburn 4961: $devalidate = 1;
4962: }
4963: if ($devalidate) {
1.560 damieng 4964: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4965: }
1.208 www 4966: }
1.207 www 4967:
1.563 damieng 4968: # Returns the username and domain from a key created in readdata from a resourcedata key.
4969: #
4970: # @param {string} $key - the key
4971: # @returns {Array}
1.208 www 4972: sub extractuser {
4973: my $key=shift;
1.350 albertel 4974: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4975: }
1.206 www 4976:
1.563 damieng 4977: # Parses a parameter key and returns the components.
4978: #
4979: # @param {string} $key -
4980: # @param {hash reference} $listdata -
4981: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4982: sub parse_listdata_key {
4983: my ($key,$listdata) = @_;
4984: # split into student/section affected, and
4985: # the realm (folder/resource part and parameter
1.446 bisitz 4986: my ($student,$realm) =
1.473 amueller 4987: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4988: # if course wide student would be undefined
4989: if (!defined($student)) {
1.560 damieng 4990: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4991: }
4992: # strip off the .type if it's not the Question type parameter
4993: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4994: $realm=~s/\.type//;
1.381 albertel 4995: }
4996: # split into resource+part and parameter name
1.388 albertel 4997: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4998: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4999: return ($student,$res,$part,$parm);
5000: }
5001:
1.563 damieng 5002: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
5003: #
5004: # @param {Apache2::RequestRec} $r - the Apache request
5005: # @param {hash reference} $resourcedata - parameter data returned by readdata
5006: # @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
5007: # @param {string} $sortorder - realmstudent|studentrealm
5008: # @param {string} $caller - name of the calling sub (overview|newoverview)
5009: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 5010: # @param {boolean} $readonly - true if editing not allowed
1.608 raeburn 5011: # @param {string} $parmlev - full|map
5012: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order
5013: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 5014: # @returns{integer} - number of $listdata parameters processed
1.208 www 5015: sub listdata {
1.608 raeburn 5016: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552 raeburn 5017:
1.207 www 5018: # Start list output
1.206 www 5019:
1.122 www 5020: my $oldsection='';
5021: my $oldrealm='';
5022: my $oldpart='';
1.123 www 5023: my $pointer=0;
1.124 www 5024: $tableopen=0;
1.145 www 5025: my $foundkeys=0;
1.248 albertel 5026: my %keyorder=&standardkeyorder();
1.594 raeburn 5027: my $readonlyall = $readonly;
1.381 albertel 5028:
1.552 raeburn 5029: my ($secidx,%grouphash);
5030: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
5031: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 5032: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
5033: %grouphash = &Apache::longroup::coursegroups();
5034: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 5035: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 5036: }
1.552 raeburn 5037: }
5038:
1.576 raeburn 5039: foreach my $key (sort {
1.560 damieng 5040: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
5041: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608 raeburn 5042: my ($aid,$bid);
5043: if ($caller eq 'newoverview') {
5044: if (ref($hash_for_realm) eq 'HASH') {
5045: if (($parmlev eq 'map') && ($pschp eq 'all')) {
5046: my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
5047: my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
5048: $aid = $hash_for_realm->{$aurl};
5049: $bid = $hash_for_realm->{$burl};
5050: } elsif ($parmlev eq 'full') {
5051: $aid = $hash_for_realm->{$ares};
5052: $bid = $hash_for_realm->{$bres};
5053: }
5054: }
5055: }
1.381 albertel 5056:
1.560 damieng 5057: # get the numerical order for the param
5058: $aparm=$keyorder{'parameter_0_'.$aparm};
5059: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 5060:
1.560 damieng 5061: my $result=0;
1.381 albertel 5062:
1.560 damieng 5063: if ($sortorder eq 'realmstudent') {
1.381 albertel 5064: if ($ares ne $bres ) {
1.608 raeburn 5065: if ($caller eq 'newoverview') {
5066: if (ref($hash_for_realm) eq 'HASH') {
5067: if (($parmlev eq 'map') && ($pschp eq 'all')) {
5068: $result = ($aid <=> $bid);
5069: } elsif ($parmlev eq 'full') {
5070: $result = ($aid <=> $bid);
5071: } else {
5072: $result = ($ares cmp $bres);
5073: }
5074: } else {
5075: $result = ($ares cmp $bres);
5076: }
5077: } else {
5078: $result = ($ares cmp $bres);
5079: }
1.446 bisitz 5080: } elsif ($astudent ne $bstudent) {
1.560 damieng 5081: $result = ($astudent cmp $bstudent);
5082: } elsif ($apart ne $bpart ) {
5083: $result = ($apart cmp $bpart);
5084: }
5085: } else {
5086: if ($astudent ne $bstudent) {
5087: $result = ($astudent cmp $bstudent);
5088: } elsif ($ares ne $bres ) {
1.608 raeburn 5089: if ($caller eq 'newoverview') {
5090: if (ref($hash_for_realm) eq 'HASH') {
5091: if (($parmlev eq 'map') && ($pschp eq 'all')) {
5092: $result = ($aid <=> $bid);
5093: } elsif ($parmlev eq 'full') {
5094: $result = ($aid <=> $bid);
5095: } else {
5096: $result = ($ares cmp $bres);
5097: }
5098: } else {
5099: $result = ($ares cmp $bres);
5100: }
5101: } else {
5102: $result = ($ares cmp $bres);
5103: }
1.560 damieng 5104: } elsif ($apart ne $bpart ) {
5105: $result = ($apart cmp $bpart);
5106: }
1.473 amueller 5107: }
1.446 bisitz 5108:
1.560 damieng 5109: if (!$result) {
1.381 albertel 5110: if (defined($aparm) && defined($bparm)) {
1.560 damieng 5111: $result = ($aparm <=> $bparm);
1.381 albertel 5112: } elsif (defined($aparm)) {
1.560 damieng 5113: $result = -1;
1.381 albertel 5114: } elsif (defined($bparm)) {
1.560 damieng 5115: $result = 1;
5116: }
1.473 amueller 5117: }
1.381 albertel 5118:
1.560 damieng 5119: $result;
5120:
1.576 raeburn 5121: } keys(%{$listdata})) { # foreach my $key
5122: my $thiskey = $key;
1.560 damieng 5123: if ($$listdata{$thiskey.'.type'}) {
5124: my $thistype=$$listdata{$thiskey.'.type'};
5125: if ($$resourcedata{$thiskey.'.type'}) {
5126: $thistype=$$resourcedata{$thiskey.'.type'};
5127: }
5128: my ($middle,$part,$name)=
1.572 damieng 5129: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 5130: my $section=&mt('All Students');
1.594 raeburn 5131: $readonly = $readonlyall;
1.599 raeburn 5132: my $userscope;
1.576 raeburn 5133: my $showval = $$resourcedata{$thiskey};
1.560 damieng 5134: if ($middle=~/^\[(.*)\]/) {
5135: my $issection=$1;
5136: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
5137: my ($stuname,$studom) = ($1,$2);
5138: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
5139: if (ref($classlist) eq 'HASH') {
5140: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
5141: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
5142: }
5143: }
5144: }
5145: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 5146: $userscope = 1;
1.560 damieng 5147: } else {
5148: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
5149: if (exists($grouphash{$issection})) {
5150: $section=&mt('Group').': '.$issection;
5151: } elsif ($issection eq $env{'request.course.sec'}) {
5152: $section = &mt('Section').': '.$issection;
5153: } else {
5154: next;
1.552 raeburn 5155: }
1.560 damieng 5156: } else {
5157: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 5158: }
5159: }
1.560 damieng 5160: $middle=~s/^\[(.*)\]//;
5161: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
5162: $readonly = 1;
5163: }
5164: $middle=~s/\.+$//;
5165: $middle=~s/^\.+//;
5166: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 5167: my ($is_map,$is_recursive,$mapurl,$maplevel);
5168: if ($caller eq 'overview') {
5169: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
5170: $mapurl = $1;
5171: $maplevel = $2;
5172: $is_map = 1;
5173: }
5174: } elsif ($caller eq 'newoverview') {
5175: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
5176: $mapurl = $1;
5177: $maplevel = $2;
5178: $is_map = 1;
5179: }
5180: }
5181: if ($is_map) {
1.560 damieng 5182: my $leveltitle = &mt('Folder/Map');
1.615 raeburn 5183: my $title = &Apache::lonnet::gettitle($mapurl);
1.608 raeburn 5184: if (ref($hash_for_realm) eq 'HASH') {
5185: if ($hash_for_realm->{$mapurl} eq '1') {
5186: $title = &mt('Main Content');
5187: }
5188: }
1.576 raeburn 5189: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
5190: if ($caller eq 'newoverview') {
5191: my $altkey = $thiskey;
5192: $altkey =~ s/\Q___(all)\E/___(rec)/;
5193: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
5194: $is_recursive = 1;
5195: if ($$resourcedata{$altkey.'.type'}) {
5196: $thistype=$$resourcedata{$altkey.'.type'};
5197: }
5198: $showval = $$resourcedata{$altkey};
5199: }
5200: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
5201: $thiskey =~ s/\Q___(rec)\E/___(all)/;
5202: $is_recursive = 1;
5203: }
1.560 damieng 5204: }
1.608 raeburn 5205: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560 damieng 5206: } elsif ($middle) {
5207: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609 raeburn 5208: next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560 damieng 5209: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
5210: ': '.&Apache::lonnet::gettitle($middle).
5211: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
5212: $id.')</span></span>';
5213: }
5214: if ($sortorder eq 'realmstudent') {
5215: if ($realm ne $oldrealm) {
5216: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
5217: $oldrealm=$realm;
5218: $oldsection='';
5219: }
5220: if ($section ne $oldsection) {
5221: $r->print(&tableend()."\n<h2>$section</h2>");
5222: $oldsection=$section;
5223: $oldpart='';
5224: }
1.552 raeburn 5225: } else {
1.560 damieng 5226: if ($section ne $oldsection) {
5227: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
5228: $oldsection=$section;
5229: $oldrealm='';
5230: }
5231: if ($realm ne $oldrealm) {
5232: $r->print(&tableend()."\n<h2>$realm</h2>");
5233: $oldrealm=$realm;
5234: $oldpart='';
1.552 raeburn 5235: }
5236: }
1.560 damieng 5237: if ($part ne $oldpart) {
5238: $r->print(&tableend().
5239: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
5240: $oldpart=$part;
1.556 raeburn 5241: }
1.560 damieng 5242: #
5243: # Ready to print
5244: #
1.470 raeburn 5245: my $parmitem = &standard_parameter_names($name);
1.619 raeburn 5246: my $advice;
5247: if (($name eq 'mapalias') && ($middle) && (!$is_map)) {
5248: if ($middle =~ m{^uploaded/}) {
5249: $advice = &mt('Use Course Editor to set this.');
5250: } else {
5251: $advice = &mt('Use Resource Assembly Tool to set this.');
5252: }
5253: $advice = '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
5254: }
1.576 raeburn 5255: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 5256: &Apache::loncommon::start_data_table_row().
5257: '<td><b>'.&mt($parmitem).
1.619 raeburn 5258: '</b>'.$advice.'</td>');
1.560 damieng 5259: unless ($readonly) {
1.599 raeburn 5260: my $disabled;
5261: if (($name eq 'availablestudent') &&
5262: (($showval eq '') || ($userscope))) {
5263: $disabled = ' disabled="disabled"';
1.619 raeburn 5264: } elsif (($name eq 'mapalias') && ($showval eq '')) {
5265: $disabled = ' disabled="disabled"';
1.599 raeburn 5266: }
1.560 damieng 5267: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 5268: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 5269: }
5270: $r->print('<td>');
5271: $foundkeys++;
5272: if (&isdateparm($thistype)) {
5273: my $jskey='key_'.$pointer;
5274: my $state;
5275: $pointer++;
5276: if ($readonly) {
5277: $state = 'disabled';
5278: }
5279: $r->print(
5280: &Apache::lonhtmlcommon::date_setter('parmform',
5281: $jskey,
1.576 raeburn 5282: $showval,
1.560 damieng 5283: '',1,$state));
5284: unless ($readonly) {
5285: $r->print(
5286: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 5287: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 5288: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 5289: &date_sanity_info($showval)
1.560 damieng 5290: );
5291: }
5292: } elsif ($thistype eq 'date_interval') {
5293: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 5294: $showval,$readonly));
1.560 damieng 5295: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 5296: if ($name eq 'availablestudent') {
5297: $readonly = 1;
1.619 raeburn 5298: } elsif (($name eq 'mapalias') && ($showval eq '')) {
5299: $readonly = 1;
1.599 raeburn 5300: }
1.560 damieng 5301: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 5302: $showval,$name,$readonly));
1.560 damieng 5303: } else {
1.576 raeburn 5304: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 5305: }
1.560 damieng 5306: unless ($readonly) {
5307: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
5308: $thistype.'" />');
1.552 raeburn 5309: }
1.576 raeburn 5310: $r->print('</td>');
5311: if ($is_map) {
5312: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
5313: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
5314: } else {
5315: my ($disabled,$recon,$recoff);
5316: if ($readonly) {
5317: $disabled = ' disabled="disabled"';
5318: }
5319: if ($is_recursive) {
5320: $recon = ' checked="checked"';
5321: } else {
5322: $recoff = ' checked="checked"';
5323: }
5324: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
5325: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
5326: }
5327: }
5328: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 5329: }
1.121 www 5330: }
1.208 www 5331: return $foundkeys;
5332: }
5333:
1.563 damieng 5334: # Returns a string representing the interval, directly using form data matching the given key.
5335: # The returned string may also include information related to proctored exams.
5336: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
5337: #
5338: # @param {string} $key - suffix for form fields related to the interval
5339: # @returns {string}
1.385 albertel 5340: sub get_date_interval_from_form {
5341: my ($key) = @_;
5342: my $seconds = 0;
1.611 raeburn 5343: my $numnotnull = 0;
1.385 albertel 5344: foreach my $which (['days', 86400],
1.473 amueller 5345: ['hours', 3600],
5346: ['minutes', 60],
5347: ['seconds', 1]) {
1.560 damieng 5348: my ($name, $factor) = @{ $which };
5349: if (defined($env{'form.'.$name.'_'.$key})) {
1.611 raeburn 5350: unless ($env{'form.'.$name.'_'.$key} eq '') {
5351: $numnotnull ++;
5352: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
5353: }
1.560 damieng 5354: }
1.473 amueller 5355: }
1.560 damieng 5356: if (($key =~ /\.interval$/) &&
5357: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 5358: if ($env{'form.done_'.$key.'_buttontext'}) {
5359: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
5360: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
5361: if ($env{'form.done_'.$key} eq '_done_proctor') {
5362: $seconds .= '_proctor';
5363: }
5364: } else {
5365: $seconds .= $env{'form.done_'.$key};
5366: }
5367: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 5368: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 5369: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
5370: }
1.554 raeburn 5371: }
1.611 raeburn 5372: return if (!$numnotnull);
1.385 albertel 5373: return $seconds;
5374: }
5375:
1.563 damieng 5376: # Returns HTML to enter a text value for a parameter.
5377: #
5378: # @param {string} $thiskey - parameter key
5379: # @param {string} $showval - the current value
5380: # @param {boolean} $readonly - true if the field should not be made editable
5381: # @returns {string}
1.383 albertel 5382: sub default_selector {
1.552 raeburn 5383: my ($thiskey, $showval, $readonly) = @_;
5384: my $disabled;
5385: if ($readonly) {
5386: $disabled = ' disabled="disabled"';
5387: }
5388: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 5389: }
5390:
1.563 damieng 5391: # Returns HTML to enter allow/deny rules related to IP addresses.
5392: #
5393: # @param {string} $thiskey - parameter key
5394: # @param {string} $showval - the current value
5395: # @param {boolean} $readonly - true if the fields should not be made editable
5396: # @returns {string}
1.549 raeburn 5397: sub string_ip_selector {
1.552 raeburn 5398: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 5399: my %access = (
5400: allow => [],
5401: deny => [],
5402: );
5403: if ($showval ne '') {
5404: my @current;
5405: if ($showval =~ /,/) {
5406: @current = split(/,/,$showval);
5407: } else {
5408: @current = ($showval);
5409: }
5410: foreach my $item (@current) {
5411: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
5412: push(@{$access{'deny'}},$1);
5413: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
5414: push(@{$access{'allow'}},$item);
5415: }
5416: }
5417: }
5418: if (!@{$access{'allow'}}) {
5419: @{$access{'allow'}} = ('');
5420: }
5421: if (!@{$access{'deny'}}) {
5422: @{$access{'deny'}} = ('');
5423: }
1.552 raeburn 5424: my ($disabled,$addmore);
1.567 raeburn 5425: if ($readonly) {
1.552 raeburn 5426: $disabled=' disabled="disabled"';
5427: } else {
5428: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5429: }
1.549 raeburn 5430: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5431: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5432: foreach my $acctype ('allow','deny') {
5433: $output .= '
5434: <td valign="top">
5435: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5436: <div class="LC_string_ipacc_inner">'."\n";
5437: my $num = 0;
5438: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5439: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5440: if ($num > 0) {
5441: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5442: }
5443: $output .= '</div>'."\n";
5444: $num ++;
5445: }
5446: $output .= '
1.552 raeburn 5447: </div>'.$addmore.'
1.549 raeburn 5448: </div>
5449: </td>';
5450: }
5451: $output .= '
5452: </tr>
5453: </table>'."\n";
5454: return $output;
5455: }
5456:
1.588 raeburn 5457: sub string_deeplink_selector {
5458: my ($thiskey, $showval, $readonly) = @_;
1.616 raeburn 5459: my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
5460: %selectnull,%domlti,%crslti,@possmenus,%components);
5461: @tables = ('upper','lower');
5462: %components = (
5463: upper => ['state','others','listing','scope'],
5464: lower => ['protect','menus','target','exit'],
5465: );
1.588 raeburn 5466: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5467: state => 'Access status',
5468: others => 'Hide other resources',
1.588 raeburn 5469: listing => 'In Contents and/or Gradebook',
5470: scope => 'Access scope for link',
1.601 raeburn 5471: protect => 'Link protection',
1.597 raeburn 5472: menus => 'Menu Items Displayed',
1.613 raeburn 5473: target => 'Embedded?',
1.616 raeburn 5474: exit => 'Exit Tool Button?',
1.588 raeburn 5475: );
5476: %options = (
1.601 raeburn 5477: state => ['only','off','both'],
5478: others => ['hide','unhide'],
1.588 raeburn 5479: listing => ['full','absent','grades','details','datestatus'],
5480: scope => ['res','map','rec'],
1.601 raeburn 5481: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5482: menus => ['std','colls'],
1.613 raeburn 5483: target => ['_self','_top'],
1.616 raeburn 5484: exit => ['no','yes','url'],
1.588 raeburn 5485: );
5486: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5487: only => 'deep only',
5488: off => 'deeplink off',
5489: both => 'regular + deep',
5490: hide => 'Hidden',
5491: unhide => 'Unhidden',
1.588 raeburn 5492: full => 'Listed (linked) in both',
5493: absent => 'Not listed',
5494: grades => 'Listed in grades only',
5495: details => 'Listed (unlinked) in both',
5496: datestatus => 'Listed (unlinked) inc. status in both',
5497: res => 'resource only',
5498: map => 'enclosing map/folder',
5499: rec => 'recursive map/folder',
1.601 raeburn 5500: none => 'not in use',
5501: key => 'key access',
5502: ltic => 'LTI access (course)',
5503: ltid => 'LTI access (domain)' ,
1.597 raeburn 5504: std => 'Standard (all menus)',
5505: colls => 'Numbered collection',
1.614 raeburn 5506: _self => 'Embedded',
1.613 raeburn 5507: _top => 'Not embedded',
1.616 raeburn 5508: no => 'Not in use',
5509: yes => 'In use, no URL redirect',
5510: url => 'In use, redirect to URL',
1.597 raeburn 5511: );
5512: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5513: ltic => 'Select Launcher',
5514: ltid => 'Select Launcher',
1.597 raeburn 5515: colls => 'Select',
1.588 raeburn 5516: );
5517: if ($showval =~ /,/) {
1.597 raeburn 5518: %values=();
1.588 raeburn 5519: @current = split(/,/,$showval);
1.601 raeburn 5520: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5521: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5522: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5523: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5524: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5525: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613 raeburn 5526: ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616 raeburn 5527: ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588 raeburn 5528: } else {
1.601 raeburn 5529: $defaults{'state'} = 'off',
5530: $defaults{'others'} = 'unhide',
1.588 raeburn 5531: $defaults{'listing'} = 'full';
5532: $defaults{'scope'} = 'res';
1.601 raeburn 5533: $defaults{'protect'} = 'none';
1.597 raeburn 5534: $defaults{'menus'} = '0';
1.613 raeburn 5535: $defaults{'target'} = '_top';
1.616 raeburn 5536: $defaults{'exit'} = 'yes';
1.588 raeburn 5537: }
5538: my $disabled;
5539: if ($readonly) {
5540: $disabled=' disabled="disabled"';
5541: }
1.601 raeburn 5542: my %courselti =
5543: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
1.620 raeburn 5544: $env{'course.'.$env{'request.course.id'}.'.domain'},
5545: 'provider');
1.601 raeburn 5546: foreach my $item (keys(%courselti)) {
5547: if (ref($courselti{$item}) eq 'HASH') {
5548: $crslti{$item} = $courselti{$item}{'name'};
5549: }
5550: }
5551: my %lti =
1.588 raeburn 5552: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 5553: 'linkprot');
1.588 raeburn 5554: foreach my $item (keys(%lti)) {
1.604 raeburn 5555: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
5556: $domlti{$item} = $lti{$item}{'name'};
1.588 raeburn 5557: }
5558: }
1.597 raeburn 5559: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5560: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5561: my ($num,$value) = split(/\%/,$item);
5562: if ($num =~ /^\d+$/) {
5563: push(@possmenus,$num);
5564: }
5565: }
5566: }
5567:
1.616 raeburn 5568: my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
5569: foreach my $table ('upper','lower') {
5570: next unless (ref($components{$table}) eq 'ARRAY');
5571: $output .= '<table width="100%"><tr>';
5572: foreach my $item (@{$components{$table}}) {
5573: $output .= '<th>'.$titles{$item}.'</th>';
5574: }
5575: $output .= '</tr><tr>';
5576: foreach my $item (@{$components{$table}}) {
5577: $output .= '<td>';
5578: if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
5579: my $selected = $values{$item};
5580: foreach my $option (@{$options{$item}}) {
5581: if ($item eq 'protect') {
5582: if ($option eq 'ltid') {
5583: next unless (keys(%domlti));
5584: } elsif ($option eq 'ltic') {
5585: next unless (keys(%crslti));
5586: }
5587: } elsif (($item eq 'menus') && ($option eq 'colls')) {
5588: next unless (@possmenus);
5589: }
5590: my $checked;
5591: if ($item eq 'menus') {
5592: if (($selected =~ /^\d+$/) && (@possmenus) &&
5593: (grep(/^\Q$selected\E$/,@possmenus))) {
5594: if ($option eq 'colls') {
5595: $checked = ' checked="checked"';
5596: }
5597: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597 raeburn 5598: $checked = ' checked="checked"';
5599: }
1.616 raeburn 5600: } elsif ($selected =~ /^\Q$option\E/) {
1.597 raeburn 5601: $checked = ' checked="checked"';
5602: }
1.616 raeburn 5603: my $onclick;
5604: unless ($readonly) {
5605: my $esc_key = &js_escape($thiskey);
5606: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
5607: }
5608: $output .= '<span class="LC_nobreak"><label>'.
5609: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
5610: $optiontext{$option}.'</label>';
5611: if (($item eq 'protect') && ($option eq 'key')) {
5612: my $visibility="hidden";
5613: my $currkey;
5614: if ($checked) {
5615: $visibility = "text";
5616: $currkey = (split(/\:/,$values{$item}))[1];
5617: }
5618: $output .= ' '.
5619: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
5620: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
5621: my $display="none";
5622: my ($current,$blankcheck,@possibles);
5623: if ($checked) {
5624: $display = 'inline-block';
5625: if (($option eq 'ltic') || ($option eq 'ltid')) {
5626: $current = (split(/\:/,$selected))[1];
5627: } else {
5628: $current = $selected;
5629: }
1.597 raeburn 5630: } else {
1.616 raeburn 5631: $blankcheck = ' selected="selected"';
1.597 raeburn 5632: }
1.601 raeburn 5633: if ($option eq 'ltid') {
1.616 raeburn 5634: @possibles = keys(%domlti);
1.601 raeburn 5635: } elsif ($option eq 'ltic') {
1.616 raeburn 5636: @possibles = keys(%crslti);
5637: } else {
5638: @possibles = @possmenus;
5639: }
5640: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
5641: ' style="display: '.$display.'"> <select name="'.
5642: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
5643: if (@possibles > 1) {
5644: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
5645: '</option>'."\n";
5646: }
5647: foreach my $poss (sort { $a <=> $b } @possibles) {
5648: my $selected;
5649: if (($poss == $current) || (scalar(@possibles) ==1)) {
5650: $selected = ' selected="selected"';
5651: }
5652: my $shown = $poss;
5653: if ($option eq 'ltid') {
5654: $shown = $domlti{$poss};
5655: } elsif ($option eq 'ltic') {
5656: $shown = $crslti{$poss};
5657: }
5658: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
5659: }
5660: $output .= '</select></div>';
5661: }
5662: $output .= '</span> ';
5663: }
5664: if ($item eq 'exit') {
5665: my $exitsty = 'none';
5666: my $displayval;
5667: if ($values{$item} =~ /^(yes|url)/) {
5668: $exitsty = 'inline-block';
5669: my $currval = (split(/\:/,$values{$item}))[1];
5670: if ($currval eq '') {
5671: $displayval = 'Exit Tool';
5672: } else {
5673: $displayval = $currval;
1.597 raeburn 5674: }
1.588 raeburn 5675: }
1.616 raeburn 5676: $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
5677: ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
5678: '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
5679: ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
5680: ' size="10"'.$disabled.' /></div>';
1.588 raeburn 5681: }
1.616 raeburn 5682: } else {
5683: my $selected = $values{$item};
5684: my $defsel;
5685: if ($selected eq '') {
5686: $defsel = ' selected="selected"';
5687: }
5688: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
5689: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
5690: foreach my $option (@{$options{$item}}) {
5691: $output .= '<option value="'.$option.'"';
5692: if ($option eq $selected) {
5693: $output .= ' selected="selected"';
5694: }
5695: $output .= '>'.$optiontext{$option}.'</option>';
1.588 raeburn 5696: }
1.616 raeburn 5697: $output .= '</select>';
1.588 raeburn 5698: }
1.616 raeburn 5699: $output .= '</td>';
5700: }
5701: $output .= '</tr></table>'."\n";
5702: if ($table eq 'upper') {
5703: $output .= '<br />';
1.588 raeburn 5704: }
5705: }
5706: return $output;
5707: }
5708:
1.622 raeburn 5709: sub string_grace_selector {
5710: my ($thiskey, $showval, $readonly) = @_;
5711: my $addmore;
5712: unless ($readonly) {
5713: $addmore = "\n".'<button class="LC_add_grace_button">'.&mt('Add more').'</button>';
5714: }
5715: my $output = '<input type="hidden" name="set_'.$thiskey.'" value="" />'.
5716: '<div class="LC_string_grace_wrap" id="LC_string_grace_'.$thiskey.'">'."\n".
5717: '<div class="LC_string_grace_inner">'."\n";
5718: if ($showval ne '') {
5719: my @current;
5720: if ($showval =~ /,/) {
5721: @current = split(/,/,$showval);
5722: } else {
5723: @current = ($showval);
5724: }
5725: my $num = scalar(@current);
5726: foreach my $item (@current) {
5727: my ($delta,$fraction,$gradational) = split(/:/,$item);
5728: if (($delta =~ /^\d+$/) && ($fraction =~ /^(0|1)\.?\d*$/) &&
5729: (($gradational eq 1) || ($gradational eq '0'))) {
5730: my $gradchk = '';
5731: if ($gradational) {
5732: $gradchk = ' checked="checked"';
5733: }
5734: $output .= &grace_form($thiskey,$delta,$fraction,$gradchk,
5735: $readonly);
5736: }
5737: }
5738: } elsif (!$readonly) {
5739: $output .= &grace_form($thiskey,'','','',$readonly);
5740: }
5741: $output .= '</div>'.$addmore.'</div>';
5742: return $output;
5743: }
5744:
5745: sub grace_form {
5746: my ($thiskey,$delta,$fraction,$gradchkon,$readonly) = @_;
5747: my $disabled;
5748: if ($readonly) {
5749: $disabled = ' disabled="disabled"';
5750: }
5751: my %lt = &grace_titles();
5752: my $output = '<div><input type="hidden" name="setgrace_'.$thiskey.'" value="" />'.
5753: '<fieldset class="LC_grace"><legend>'.$lt{'sinc'}.'</legend>';
1.623 raeburn 5754: foreach my $which (['weeks', 604800, 52],
5755: ['days', 86400, 6],
1.622 raeburn 5756: ['hours', 3600, 23],
1.623 raeburn 5757: ['minutes', 60, 59]) {
1.622 raeburn 5758: my ($name, $factor, $max) = @{ $which };
5759: my $amount;
1.623 raeburn 5760: my %select = ((map {$_ => $_} (0..$max)),
5761: 'select_form_order' => [0..$max]);
5762: if ($delta eq '') {
5763: unshift(@{$select{'select_form_order'}},'');
5764: $select{''} = '';
5765: $amount = '';
5766: } else {
1.622 raeburn 5767: $amount = int($delta/$factor);
5768: $delta %= $factor;
5769: }
5770: $output .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
5771: \%select,'',$readonly);
5772: $output .= ' '.$lt{$name}.' ';
5773: }
5774: $output .= '</fieldset>'.
5775: '<fieldset class="LC_grace"><legend>'.$lt{'pcr'}.'</legend>'.
5776: '<input type="text" size="3" name="frac_'.$thiskey.'" value="'.$fraction.'"'.$disabled.' />'.
5777: ' <label><input type="checkbox" value="1" name="grad_'.$thiskey.'"'.$gradchkon.$disabled.' />'.
5778: $lt{'grad'}.'</label></fieldset>';
5779: unless ($readonly) {
5780: $output .= '<a href="#" class="LC_remove_grace">'.$lt{'remo'}.'</a>';
5781: }
5782: $output .= '</div>'."\n";
5783: return $output;
5784: }
5785:
5786: sub grace_titles {
5787: return &Apache::lonlocal::texthash (
5788: sinc => 'Time past due',
5789: remo => 'Remove',
5790: pcr => 'Partial credit',
5791: grad => 'gradual',
1.623 raeburn 5792: weeks => 'weeks',
1.622 raeburn 5793: days => 'days',
5794: hours => 'hours',
5795: minutes => 'minutes',
5796: );
5797: }
1.560 damieng 5798:
5799: { # block using some constants related to parameter types (overview mode)
5800:
1.446 bisitz 5801: my %strings =
1.383 albertel 5802: (
5803: 'string_yesno'
5804: => [[ 'yes', 'Yes' ],
1.560 damieng 5805: [ 'no', 'No' ]],
1.383 albertel 5806: 'string_problemstatus'
5807: => [[ 'yes', 'Yes' ],
1.473 amueller 5808: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5809: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5810: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5811: 'string_questiontype'
5812: => [[ 'problem', 'Standard Problem'],
5813: [ 'survey', 'Survey'],
5814: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5815: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5816: [ 'anonsurvey', 'Anonymous Survey'],
5817: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5818: [ 'practice', 'Practice'],
5819: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5820: 'string_lenient'
5821: => [['yes', 'Yes' ],
5822: [ 'no', 'No' ],
1.549 raeburn 5823: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5824: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5825: 'string_discussvote'
5826: => [['yes','Yes'],
5827: ['notended','Yes, unless discussion ended'],
5828: ['no','No']],
1.549 raeburn 5829: 'string_ip'
5830: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5831: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5832: 'string_deeplink'
1.616 raeburn 5833: => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.621 raeburn 5834: 'string_tex'
5835: => [['tth', 'tth (TeX to HTML)'],
5836: ['mathjax', 'MathJax']],
1.622 raeburn 5837: 'string_grace'
5838: => [['on','Set grading scale and grace period for submissions after due date']],
1.587 raeburn 5839: );
5840:
1.383 albertel 5841:
1.549 raeburn 5842: my %stringmatches = (
5843: 'string_lenient'
5844: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5845: 'string_ip'
5846: => [['_allowfrom_','[^\!]+'],
5847: ['_denyfrom_','\!']],
1.588 raeburn 5848: 'string_deeplink'
1.616 raeburn 5849: => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],
1.622 raeburn 5850: 'string_grace'
5851: => [['on','^\d+,(0|1)\.?\d*,(0|1)']],
1.549 raeburn 5852: );
5853:
5854: my %stringtypes = (
5855: type => 'string_questiontype',
5856: lenient => 'string_lenient',
5857: retrypartial => 'string_yesno',
5858: discussvote => 'string_discussvote',
5859: examcode => 'string_examcode',
5860: acc => 'string_ip',
1.587 raeburn 5861: deeplink => 'string_deeplink',
1.622 raeburn 5862: grace => 'string_grace',
1.621 raeburn 5863: texdisplay => 'string_tex',
1.549 raeburn 5864: );
5865:
1.563 damieng 5866: # Returns the possible values and titles for a given string type, or undef if there are none.
5867: # Used by courseprefs.
5868: #
5869: # @param {string} $string_type - a parameter type for strings
5870: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5871: sub standard_string_options {
5872: my ($string_type) = @_;
5873: if (ref($strings{$string_type}) eq 'ARRAY') {
5874: return $strings{$string_type};
5875: }
5876: return;
5877: }
1.383 albertel 5878:
1.563 damieng 5879: # Returns regular expressions to match kinds of string types, or undef if there are none.
5880: #
5881: # @param {string} $string_type - a parameter type for strings
5882: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5883: sub standard_string_matches {
5884: my ($string_type) = @_;
5885: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5886: return $stringmatches{$string_type};
5887: }
5888: return;
5889: }
5890:
1.563 damieng 5891: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5892: #
5893: # @param {string} $name - parameter name
5894: # @returns {string}
1.549 raeburn 5895: sub get_stringtype {
5896: my ($name) = @_;
5897: if (exists($stringtypes{$name})) {
5898: return $stringtypes{$name};
5899: }
5900: return;
5901: }
5902:
1.563 damieng 5903: # Returns HTML to edit a string parameter.
5904: #
5905: # @param {string} $thistype - parameter type
5906: # @param {string} $thiskey - parameter key
5907: # @param {string} $showval - parameter current value
5908: # @param {string} $name - parameter name
5909: # @param {boolean} $readonly - true if the values should not be made editable
5910: # @returns {string}
1.383 albertel 5911: sub string_selector {
1.552 raeburn 5912: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5913:
1.383 albertel 5914: if (!exists($strings{$thistype})) {
1.552 raeburn 5915: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5916: }
5917:
1.504 raeburn 5918: my %skiptype;
1.514 raeburn 5919: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5920: ($thistype eq 'string_lenient') ||
5921: ($thistype eq 'string_discussvote') ||
5922: ($thistype eq 'string_ip') ||
1.588 raeburn 5923: ($thistype eq 'string_deeplink') ||
1.621 raeburn 5924: ($thistype eq 'string_tex') ||
1.622 raeburn 5925: ($thistype eq 'string_grace') ||
1.560 damieng 5926: ($name eq 'retrypartial')) {
1.504 raeburn 5927: my ($got_chostname,$chostname,$cmajor,$cminor);
5928: foreach my $possibilities (@{ $strings{$thistype} }) {
5929: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5930: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5931: my $parmmatch;
5932: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5933: foreach my $item (@{$stringmatches{$thistype}}) {
5934: if (ref($item) eq 'ARRAY') {
5935: if ($parmval eq $item->[0]) {
5936: $parmmatch = $parmval;
5937: $parmval = '';
5938: last;
5939: }
5940: }
5941: }
5942: }
5943: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5944: if ($needsrelease) {
5945: unless ($got_chostname) {
1.514 raeburn 5946: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5947: $got_chostname = 1;
5948: }
1.557 raeburn 5949: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5950: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5951: if ($needsnewer) {
1.549 raeburn 5952: if ($parmmatch ne '') {
5953: $skiptype{$parmmatch} = 1;
5954: } elsif ($parmval ne '') {
5955: $skiptype{$parmval} = 1;
5956: }
1.504 raeburn 5957: }
5958: }
5959: }
5960: }
1.549 raeburn 5961:
5962: if ($thistype eq 'string_ip') {
1.622 raeburn 5963: return &string_ip_selector($thiskey,$showval,$readonly);
5964: } elsif ($thistype eq 'string_grace') {
5965: return &string_grace_selector($thiskey,$showval,$readonly);
1.588 raeburn 5966: } elsif ($thistype eq 'string_deeplink') {
5967: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5968: }
1.504 raeburn 5969:
1.552 raeburn 5970: my ($result,$disabled);
5971:
5972: if ($readonly) {
5973: $disabled = ' disabled="disabled"';
5974: }
1.504 raeburn 5975: my $numinrow = 3;
5976: if ($thistype eq 'string_problemstatus') {
5977: $numinrow = 2;
5978: } elsif ($thistype eq 'string_questiontype') {
5979: if (keys(%skiptype) > 0) {
5980: $numinrow = 4;
5981: }
5982: }
5983: my $rem;
5984: if (ref($strings{$thistype}) eq 'ARRAY') {
5985: my $i=0;
5986: foreach my $possibilities (@{ $strings{$thistype} }) {
5987: next unless (ref($possibilities) eq 'ARRAY');
5988: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5989: next if ($skiptype{$name});
1.504 raeburn 5990: $rem = $i%($numinrow);
5991: if ($rem == 0) {
5992: if ($i > 0) {
5993: $result .= '</tr>';
5994: }
5995: $result .= '<tr>';
5996: }
1.549 raeburn 5997: my $colspan;
5998: if ($i == @{ $strings{$thistype} }-1) {
5999: $rem = @{ $strings{$thistype} }%($numinrow);
6000: if ($rem) {
6001: my $colsleft = $numinrow - $rem;
6002: if ($colsleft) {
6003: $colspan = $colsleft+1;
6004: $colspan = ' colspan="'.$colspan.'"';
6005: }
6006: }
6007: }
6008: my ($add,$onchange,$css_class);
6009: if ($thistype eq 'string_lenient') {
6010: if ($name eq 'weighted') {
6011: my $display;
6012: my %relatives = &Apache::lonlocal::texthash(
6013: corrchkd => 'Correct (checked)',
6014: corrunchkd => 'Correct (unchecked)',
6015: incorrchkd => 'Incorrect (checked)',
6016: incorrunchkd => 'Incorrect (unchecked)',
6017: );
6018: my %textval = (
6019: corrchkd => '1.0',
6020: corrunchkd => '1.0',
6021: incorrchkd => '0.0',
6022: incorrunchkd => '0.0',
6023: );
6024: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
6025: $textval{'corrchkd'} = $1;
6026: $textval{'corrunchkd'} = $2;
6027: $textval{'incorrchkd'} = $3;
6028: $textval{'incorrunchkd'} = $4;
6029: $display = 'inline';
6030: $showval = $name;
6031: } else {
6032: $display = 'none';
6033: }
6034: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
6035: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
6036: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
6037: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
6038: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 6039: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 6040: '</td></tr>';
6041: }
6042: $add .= '</table></div>'."\n";
6043: }
6044: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
6045: $css_class = ' class="LC_lenient_radio"';
6046: }
6047: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 6048: '<span class="LC_nobreak"><label>'.
6049: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 6050: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 6051: if ($showval eq $name) {
6052: $result .= ' checked="checked"';
6053: }
1.549 raeburn 6054: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 6055: $i++;
6056: }
6057: $result .= '</tr>';
1.473 amueller 6058: }
1.504 raeburn 6059: if ($result) {
6060: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 6061: }
6062: return $result;
6063: }
6064:
1.554 raeburn 6065: my %intervals =
6066: (
6067: 'date_interval'
6068: => [[ 'done', 'Yes' ],
1.558 raeburn 6069: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 6070: [ '', 'No' ]],
6071: );
6072:
6073: my %intervalmatches = (
6074: 'date_interval'
1.559 raeburn 6075: => [['done','\d+_done(|\:[^\:]+\:)$'],
6076: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 6077: );
6078:
6079: my %intervaltypes = (
6080: interval => 'date_interval',
6081: );
6082:
1.563 damieng 6083: # Returns regular expressions to match kinds of interval type, or undef if there are none.
6084: #
6085: # @param {string} $interval_type - a parameter type for intervals
6086: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 6087: sub standard_interval_matches {
6088: my ($interval_type) = @_;
6089: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
6090: return $intervalmatches{$interval_type};
6091: }
6092: return;
6093: }
6094:
1.563 damieng 6095: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
6096: #
6097: # @param {string} $name - parameter name
6098: # @returns {string}
1.554 raeburn 6099: sub get_intervaltype {
6100: my ($name) = @_;
6101: if (exists($intervaltypes{$name})) {
6102: return $intervaltypes{$name};
6103: }
6104: return;
6105: }
6106:
1.563 damieng 6107: # Returns the possible values and titles for a given interval type, or undef if there are none.
6108: # Used by courseprefs.
6109: #
6110: # @param {string} $interval_type - a parameter type for intervals
6111: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 6112: sub standard_interval_options {
6113: my ($interval_type) = @_;
6114: if (ref($intervals{$interval_type}) eq 'ARRAY') {
6115: return $intervals{$interval_type};
6116: }
6117: return;
6118: }
6119:
1.563 damieng 6120: # Returns HTML to edit a date interval parameter.
6121: #
6122: # @param {string} $thiskey - parameter key
6123: # @param {string} $name - parameter name
6124: # @param {string} $showval - parameter current value
6125: # @param {boolean} $readonly - true if the values should not be made editable
6126: # @returns {string}
1.554 raeburn 6127: sub date_interval_selector {
6128: my ($thiskey, $name, $showval, $readonly) = @_;
6129: my ($result,%skipval);
6130: if ($name eq 'interval') {
6131: my $intervaltype = &get_intervaltype($name);
6132: my ($got_chostname,$chostname,$cmajor,$cminor);
6133: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
6134: next unless (ref($possibilities) eq 'ARRAY');
6135: my ($parmval, $description) = @{ $possibilities };
6136: my $parmmatch;
6137: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
6138: foreach my $item (@{$intervalmatches{$intervaltype}}) {
6139: if (ref($item) eq 'ARRAY') {
6140: if ($parmval eq $item->[0]) {
6141: $parmmatch = $parmval;
6142: $parmval = '';
6143: last;
6144: }
6145: }
6146: }
6147: }
6148: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
6149: if ($needsrelease) {
6150: unless ($got_chostname) {
6151: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
6152: $got_chostname = 1;
6153: }
1.557 raeburn 6154: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 6155: $needsrelease,$cmajor,$cminor);
6156: if ($needsnewer) {
6157: if ($parmmatch ne '') {
6158: $skipval{$parmmatch} = 1;
6159: } elsif ($parmval ne '') {
6160: $skipval{$parmval} = 1;
6161: }
6162: }
6163: }
6164: }
6165: }
6166:
6167: my $currval = $showval;
6168: foreach my $which (['days', 86400, 31],
6169: ['hours', 3600, 23],
6170: ['minutes', 60, 59],
6171: ['seconds', 1, 59]) {
1.560 damieng 6172: my ($name, $factor, $max) = @{ $which };
6173: my $amount = int($showval/$factor);
6174: $showval %= $factor;
6175: my %select = ((map {$_ => $_} (0..$max)),
6176: 'select_form_order' => [0..$max]);
1.611 raeburn 6177: if ($currval eq '') {
6178: unshift(@{$select{'select_form_order'}},'');
6179: $select{''} = '';
6180: $amount = '';
6181: }
1.560 damieng 6182: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
6183: \%select,'',$readonly);
6184: $result .= ' '.&mt($name);
1.554 raeburn 6185: }
6186: if ($name eq 'interval') {
6187: unless ($skipval{'done'}) {
6188: my $checkedon = '';
1.611 raeburn 6189: my $checkedoff = '';
1.558 raeburn 6190: my $checkedproc = '';
6191: my $currproctorkey = '';
6192: my $currprocdisplay = 'hidden';
1.559 raeburn 6193: my $currdonetext = &mt('Done');
6194: if ($currval =~ /^(?:\d+)_done$/) {
6195: $checkedon = ' checked="checked"';
6196: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
6197: $currdonetext = $1;
1.554 raeburn 6198: $checkedon = ' checked="checked"';
1.558 raeburn 6199: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
6200: $currproctorkey = $1;
6201: $checkedproc = ' checked="checked"';
6202: $currprocdisplay = 'text';
1.559 raeburn 6203: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
6204: $currdonetext = $1;
6205: $currproctorkey = $2;
6206: $checkedproc = ' checked="checked"';
6207: $currprocdisplay = 'text';
1.611 raeburn 6208: } elsif ($currval ne '') {
6209: $checkedoff = ' checked="checked"';
6210: } else {
6211: $currdonetext = '';
1.554 raeburn 6212: }
1.558 raeburn 6213: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 6214: my $disabled;
6215: if ($readonly) {
6216: $disabled = ' disabled="disabled"';
6217: }
1.558 raeburn 6218: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 6219: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 6220: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 6221: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 6222: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 6223: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 6224: &mt('Yes, with proctor key').'</label>'.
6225: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 6226: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 6227: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611 raeburn 6228: '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
6229: &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 6230: }
6231: }
6232: unless ($readonly) {
6233: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
6234: }
6235: return $result;
6236: }
6237:
1.563 damieng 6238: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
6239: #
6240: # @param {string} $name - parameter name
6241: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
6242: # @param {string} $value - parameter value
6243: # @param {string} $chostname - course server name
6244: # @param {integer} $cmajor - major version number
6245: # @param {integer} $cminor - minor version number
6246: # @param {string} $needsrelease - release version needed (major.minor)
6247: # @returns {string}
1.549 raeburn 6248: sub oldversion_warning {
1.557 raeburn 6249: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
6250: my $standard_name = &standard_parameter_names($name);
6251: if ($namematch) {
6252: my $level = &standard_parameter_levels($namematch);
6253: my $msg = '';
6254: if ($level) {
6255: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
6256: $standard_name,'<b>','</b>','"'.$level.'"');
6257: } else {
6258: $msg = &mt('[_1] was [_2]not[_3] set.',
6259: $standard_name,'<b>','</b>');
6260: }
6261: return '<p class="LC_warning">'.$msg.'<br />'.
6262: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
6263: $cmajor.'.'.$cminor,$chostname,
6264: $needsrelease).
6265: '</p>';
6266: }
1.549 raeburn 6267: my $desc;
6268: my $stringtype = &get_stringtype($name);
6269: if ($stringtype ne '') {
6270: if ($name eq 'examcode') {
6271: $desc = $value;
6272: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
6273: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
6274: next unless (ref($possibilities) eq 'ARRAY');
6275: my ($parmval, $description) = @{ $possibilities };
6276: my $parmmatch;
6277: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
6278: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
6279: if (ref($item) eq 'ARRAY') {
6280: my ($regexpname,$pattern) = @{$item};
6281: if ($parmval eq $regexpname) {
6282: if ($value =~ /$pattern/) {
6283: $desc = $description;
6284: $parmmatch = 1;
6285: last;
6286: }
6287: }
6288: }
6289: }
6290: last if ($parmmatch);
6291: } elsif ($parmval eq $value) {
6292: $desc = $description;
6293: last;
6294: }
6295: }
6296: }
6297: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
6298: my $now = time;
6299: if ($value =~ /^\d+$/) {
6300: if ($name eq 'printstartdate') {
6301: if ($value > $now) {
6302: $desc = &Apache::lonlocal::locallocaltime($value);
6303: }
6304: } elsif ($name eq 'printenddate') {
6305: if ($value < $now) {
6306: $desc = &Apache::lonlocal::locallocaltime($value);
6307: }
6308: }
6309: }
6310: }
6311: return '<p class="LC_warning">'.
1.557 raeburn 6312: &mt('[_1] was [_2]not[_3] set to [_4].',
6313: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
6314: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
6315: $cmajor.'.'.$cminor,$chostname,
6316: $needsrelease).
6317: '</p>';
1.549 raeburn 6318: }
6319:
1.560 damieng 6320: } # end of block using some constants related to parameter types
6321:
1.549 raeburn 6322:
1.563 damieng 6323:
6324: # Shifts all start and end dates in the current course by $shift.
1.389 www 6325: #
1.563 damieng 6326: # @param {integer} $shift - time to shift, in seconds
6327: # @returns {string} - error name or 'ok'
1.389 www 6328: sub dateshift {
1.594 raeburn 6329: my ($shift,$numchanges)=@_;
1.389 www 6330: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6331: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6332: my $sec = $env{'request.course.sec'};
1.595 raeburn 6333: my $secgrpregex;
6334: if ($sec ne '') {
6335: my @groups;
6336: if ($env{'request.course.groups'} ne '') {
6337: @groups = split(/:/,$env{'request.course.groups'});
6338: }
6339: if (@groups) {
6340: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
6341: } else {
6342: $secgrpregex = $sec;
6343: }
6344: }
1.389 www 6345: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
6346: # ugly retro fix for broken version of types
1.548 raeburn 6347: foreach my $key (keys(%data)) {
1.389 www 6348: if ($key=~/\wtype$/) {
6349: my $newkey=$key;
6350: $newkey=~s/type$/\.type/;
6351: $data{$newkey}=$data{$key};
6352: delete $data{$key};
6353: }
6354: }
1.391 www 6355: my %storecontent=();
1.389 www 6356: # go through all parameters and look for dates
1.548 raeburn 6357: foreach my $key (keys(%data)) {
1.389 www 6358: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 6359: if ($sec ne '') {
1.595 raeburn 6360: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 6361: }
1.389 www 6362: my $newdate=$data{$key}+$shift;
1.594 raeburn 6363: $$numchanges ++;
1.391 www 6364: $storecontent{$key}=$newdate;
1.389 www 6365: }
6366: }
1.391 www 6367: my $reply=&Apache::lonnet::cput
6368: ('resourcedata',\%storecontent,$dom,$crs);
6369: if ($reply eq 'ok') {
6370: &log_parmset(\%storecontent);
6371: }
6372: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
6373: return $reply;
1.389 www 6374: }
6375:
1.563 damieng 6376: # Overview mode UI to edit course parameters.
6377: #
6378: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6379: sub newoverview {
1.568 raeburn 6380: my ($r,$parm_permission) = @_;
1.280 albertel 6381:
1.208 www 6382: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6383: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6384: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6385: my $readonly = 1;
6386: if ($parm_permission->{'edit'}) {
6387: undef($readonly);
6388: }
1.414 droeschl 6389: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6390: text=>"Overview Mode"});
1.523 raeburn 6391:
6392: my %loaditems = (
1.549 raeburn 6393: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 6394: );
6395: my $js = '
6396: <script type="text/javascript">
6397: // <![CDATA[
6398: '.
6399: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
6400: &showhide_js()."\n".
1.549 raeburn 6401: &toggleparmtextbox_js()."\n".
6402: &validateparms_js()."\n".
6403: &ipacc_boxes_js()."\n".
1.622 raeburn 6404: &grace_js()."\n".
1.558 raeburn 6405: &done_proctor_js()."\n".
1.588 raeburn 6406: &deeplink_js()."\n".
1.523 raeburn 6407: '// ]]>
6408: </script>
6409: ';
1.549 raeburn 6410:
1.523 raeburn 6411: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
6412: {'add_entries' => \%loaditems,});
1.298 albertel 6413: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6414: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6415: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 6416: $r->print(<<ENDOVER);
1.624 raeburn 6417: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" id="newoverviewform">
6418: <input type="hidden" name="newoverviewsubm" value="dis" id="newoverviewsubm" />
1.208 www 6419: ENDOVER
1.211 www 6420: my @ids=();
6421: my %typep=();
6422: my %keyp=();
6423: my %allparms=();
6424: my %allparts=();
6425: my %allmaps=();
6426: my %mapp=();
6427: my %symbp=();
6428: my %maptitles=();
6429: my %uris=();
6430: my %keyorder=&standardkeyorder();
6431: my %defkeytype=();
6432:
6433: my %alllevs=();
6434: $alllevs{'Resource Level'}='full';
1.215 www 6435: $alllevs{'Map/Folder Level'}='map';
1.211 www 6436: $alllevs{'Course Level'}='general';
6437:
6438: my $csec=$env{'form.csec'};
1.269 raeburn 6439: my $cgroup=$env{'form.cgroup'};
1.211 www 6440:
6441: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
6442: my $pschp=$env{'form.pschp'};
1.506 www 6443:
1.211 www 6444: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 6445: if (!@psprt) { $psprt[0]='all'; }
1.211 www 6446:
1.446 bisitz 6447: my @selected_sections =
1.473 amueller 6448: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 6449: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 6450: foreach my $sec (@selected_sections) {
6451: if ($sec eq 'all') {
1.211 www 6452: @selected_sections = ('all');
6453: }
6454: }
1.552 raeburn 6455: if ($env{'request.course.sec'} ne '') {
6456: @selected_sections = ($env{'request.course.sec'});
6457: }
1.269 raeburn 6458: my @selected_groups =
6459: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 6460:
6461: my $pssymb='';
6462: my $parmlev='';
1.446 bisitz 6463:
1.211 www 6464: unless ($env{'form.parmlev'}) {
6465: $parmlev = 'map';
6466: } else {
6467: $parmlev = $env{'form.parmlev'};
6468: }
6469:
1.446 bisitz 6470: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 6471: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 6472: \%keyorder,\%defkeytype,$pssymb);
1.211 www 6473:
1.374 albertel 6474: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 6475: @psprt = keys(%allparts);
1.374 albertel 6476: }
1.211 www 6477: # Menu to select levels, etc
6478:
1.456 bisitz 6479: $r->print('<div class="LC_Box">');
1.445 neumanie 6480: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 6481: $r->print('<div>');
1.523 raeburn 6482: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 6483: &levelmenu($r,\%alllevs,$parmlev);
1.610 raeburn 6484: $r->print(&Apache::lonhtmlcommon::row_closure());
6485: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447 bisitz 6486: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6487: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6488: $r->print('</div></div>');
1.446 bisitz 6489:
1.456 bisitz 6490: $r->print('<div class="LC_Box">');
1.452 bisitz 6491: $r->print('<div>');
1.581 raeburn 6492: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 6493: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 6494: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 6495: my $sectionselector = §ionmenu(\@selected_sections);
6496: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 6497: $r->print('<table>'.
1.553 raeburn 6498: '<tr><th>'.&mt('Parts').'</th>');
6499: if ($sectionselector) {
6500: $r->print('<th>'.&mt('Section(s)').'</th>');
6501: }
6502: if ($groupselector) {
6503: $r->print('<th>'.&mt('Group(s)').'</th>');
6504: }
6505: $r->print('</tr><tr><td>');
1.211 www 6506: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 6507: $r->print('</td>');
6508: if ($sectionselector) {
6509: $r->print('<td>'.$sectionselector.'</td>');
6510: }
6511: if ($groupselector) {
6512: $r->print('<td>'.$groupselector.'</td>');
6513: }
6514: $r->print('</tr></table>');
1.447 bisitz 6515: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6516: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6517: $r->print('</div></div>');
6518:
1.456 bisitz 6519: $r->print('<div class="LC_Box">');
1.452 bisitz 6520: $r->print('<div>');
1.214 www 6521: my $sortorder=$env{'form.sortorder'};
6522: unless ($sortorder) { $sortorder='realmstudent'; }
1.612 raeburn 6523: &sortmenu($r,$sortorder,'newoverview');
1.445 neumanie 6524: $r->print('</div></div>');
1.446 bisitz 6525:
1.624 raeburn 6526: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" id="newoverviewdis" /></p>');
1.446 bisitz 6527:
1.211 www 6528: # Build the list data hash from the specified parms
6529:
6530: my $listdata;
6531: %{$listdata}=();
6532:
6533: foreach my $cat (@pscat) {
1.269 raeburn 6534: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
6535: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 6536: }
6537:
1.624 raeburn 6538: my $foundkeys;
6539: if ($env{'form.newoverviewsubm'}) {
1.211 www 6540:
1.624 raeburn 6541: if ($env{'form.newoverviewsubm'} eq 'store') { &storedata($r,$crs,$dom); }
1.211 www 6542:
6543: # Read modified data
6544:
1.481 amueller 6545: my $resourcedata=&readdata($crs,$dom);
1.211 www 6546:
6547: # List data
6548:
1.608 raeburn 6549: my $hash_for_realm;
6550: if (($parmlev eq 'map') && (keys(%allmaps))) {
6551: %{$hash_for_realm} = reverse(%allmaps);
6552: } elsif (($parmlev eq 'full') && (keys(%symbp))) {
6553: for (my $i=0; $i<@ids; $i++) {
6554: $hash_for_realm->{$symbp{$ids[$i]}} = $i;
6555: }
6556: }
1.624 raeburn 6557: $foundkeys = &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568 raeburn 6558: }
6559: $r->print(&tableend());
1.624 raeburn 6560: if ((!$readonly) && ($foundkeys)) {
6561: $r->print( ($env{'form.newoverviewsubm'}? '<p><input type="submit" name="store" id="newoverviewstore" value="'.&mt('Save').'" /></p>':'') );
1.211 www 6562: }
1.568 raeburn 6563: $r->print('</form>');
1.624 raeburn 6564: if ($env{'form.newoverviewsubm'}) {
6565: $r->print(<<"END");
6566: <script type="text/javascript">
6567: const form = document.getElementById('newoverviewform');
6568: const storebutton = document.getElementById('newoverviewstore');
6569: const disbutton = document.getElementById('newoverviewdis');
6570: const submethod = document.getElementById('newoverviewsubm');
6571: if (storebutton) {
6572: storebutton.addEventListener('keydown', (e) => {
6573: if (e.key === 'Enter') {
6574: if (validateParms()) {
6575: if (form) {
6576: if (submethod) {
6577: submethod.value='store';
6578: }
6579: form.submit();
6580: }
6581: }
6582: e.preventDefault();
6583: return;
6584: }
6585: });
6586: storebutton.addEventListener('click', (e) => {
6587: if (validateParms()) {
6588: if (form) {
6589: if (submethod) {
6590: submethod.value='store';
6591: }
6592: form.submit();
6593: }
6594: }
6595: e.preventDefault();
6596: return;
6597: });
6598: }
6599: if (disbutton) {
6600: disbutton.addEventListener('keydown', (e) => {
6601: if (e.key === 'Enter') {
6602: if (form) {
6603: if (submethod) {
6604: submethod.value='dis';
6605: }
6606: form.submit();
6607: }
6608: e.preventDefault();
6609: }
6610: });
6611: disbutton.addEventListener('click', (e) => {
6612: if (form) {
6613: if (submethod) {
6614: submethod.value='dis';
6615: }
6616: form.submit();
6617: return;
6618: }
6619: e.preventDefault();
6620: });
6621: }
6622:
6623: </script>
6624:
6625: END
6626: }
1.507 www 6627: &endSettingsScreen($r);
6628: $r->print(&Apache::loncommon::end_page());
1.208 www 6629: }
6630:
1.563 damieng 6631: # Fills $listdata with parameter information.
6632: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
6633: # The non-type value is always 1.
6634: #
6635: # @param {string} $cat - parameter name
1.566 damieng 6636: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 6637: # @param {string} $parmlev - selected level value (full|map|general), or ''
6638: # @param {hash reference} $listdata - the parameter data that will be modified
6639: # @param {array reference} $psprt - selected parts
6640: # @param {array reference} $selections - selected sections
6641: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6642: # @param {hash reference} $allmaps - hash map pc -> map src
6643: # @param {array reference} $ids - resource and map ids
6644: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6645: sub secgroup_lister {
6646: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6647: foreach my $item (@{$selections}) {
6648: foreach my $part (@{$psprt}) {
6649: my $rootparmkey=$env{'request.course.id'};
6650: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6651: $rootparmkey.='.['.$item.']';
6652: }
6653: if ($parmlev eq 'general') {
6654: # course-level parameter
6655: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6656: $$listdata{$newparmkey}=1;
6657: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6658: } elsif ($parmlev eq 'map') {
6659: # map-level parameter
1.548 raeburn 6660: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6661: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6662: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6663: $$listdata{$newparmkey}=1;
6664: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6665: }
6666: } else {
6667: # resource-level parameter
6668: foreach my $rid (@{$ids}) {
6669: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6670: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6671: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6672: $$listdata{$newparmkey}=1;
6673: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6674: }
6675: }
6676: }
6677: }
6678: }
6679:
1.563 damieng 6680: # UI to edit parameter settings starting with a list of all existing parameters.
6681: # (called by setoverview action)
6682: #
6683: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6684: sub overview {
1.568 raeburn 6685: my ($r,$parm_permission) = @_;
1.208 www 6686: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6687: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6688: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6689: my $readonly = 1;
6690: if ($parm_permission->{'edit'}) {
6691: undef($readonly);
6692: }
1.549 raeburn 6693: my $js = '<script type="text/javascript">'."\n".
6694: '// <![CDATA['."\n".
6695: &toggleparmtextbox_js()."\n".
6696: &validateparms_js()."\n".
6697: &ipacc_boxes_js()."\n".
1.622 raeburn 6698: &grace_js()."\n".
1.558 raeburn 6699: &done_proctor_js()."\n".
1.588 raeburn 6700: &deeplink_js()."\n".
1.549 raeburn 6701: '// ]]>'."\n".
6702: '</script>'."\n";
1.414 droeschl 6703: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6704: text=>"Overview Mode"});
1.549 raeburn 6705: my %loaditems = (
6706: 'onload' => "showHideLenient();",
6707: );
6708:
6709: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6710: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6711: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6712: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6713: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6714:
1.208 www 6715: # Store modified
6716:
1.568 raeburn 6717: unless ($readonly) {
6718: &storedata($r,$crs,$dom);
6719: }
1.208 www 6720:
6721: # Read modified data
6722:
1.552 raeburn 6723: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6724:
1.214 www 6725:
6726: my $sortorder=$env{'form.sortorder'};
6727: unless ($sortorder) { $sortorder='realmstudent'; }
1.608 raeburn 6728: &sortmenu($r,$sortorder,'overview');
1.214 www 6729:
1.568 raeburn 6730: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6731:
6732: if ($readonly) {
6733: $r->print('<p>'.$submitbutton.'</p>');
6734: }
6735:
1.208 www 6736: # List data
6737:
1.568 raeburn 6738: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6739: $r->print(&tableend().'<p>');
6740: if ($foundkeys) {
6741: unless ($readonly) {
6742: $r->print('<p>'.$submitbutton.'</p>');
6743: }
6744: } else {
6745: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6746: }
6747: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6748: }
1.121 www 6749:
1.560 damieng 6750: # Unused sub.
1.563 damieng 6751: #
6752: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6753: sub clean_parameters {
6754: my ($r) = @_;
6755: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6756: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6757:
1.414 droeschl 6758: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6759: text=>"Clean Parameters"});
1.333 albertel 6760: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6761: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6762: $r->print(<<ENDOVER);
6763: $start_page
6764: $breadcrumbs
6765: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6766: ENDOVER
6767: # Store modified
6768:
6769: &storedata($r,$crs,$dom);
6770:
6771: # Read modified data
6772:
6773: my $resourcedata=&readdata($crs,$dom);
6774:
6775: # List data
6776:
6777: $r->print('<h3>'.
1.473 amueller 6778: &mt('These parameters refer to resources that do not exist.').
6779: '</h3>'.
6780: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6781: '<br />');
1.333 albertel 6782: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6783: '<tr>'.
6784: '<th>'.&mt('Delete').'</th>'.
6785: '<th>'.&mt('Parameter').'</th>'.
6786: '</tr>');
1.333 albertel 6787: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6788: next if (!exists($resourcedata->{$thiskey.'.type'})
6789: && $thiskey=~/\.type$/);
6790: my %data = &parse_key($thiskey);
6791: if (1) { #exists($data{'realm_exists'})
6792: #&& !$data{'realm_exists'}) {
6793: $r->print(&Apache::loncommon::start_data_table_row().
6794: '<tr>'.
6795: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6796:
6797: $r->print('<td>');
6798: my $display_value = $resourcedata->{$thiskey};
6799: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6800: $display_value =
6801: &Apache::lonlocal::locallocaltime($display_value);
6802: }
1.470 raeburn 6803: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6804: $parmitem = &mt($parmitem);
1.560 damieng 6805: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6806: $parmitem,$resourcedata->{$thiskey}));
6807: $r->print('<br />');
6808: if ($data{'scope_type'} eq 'all') {
6809: $r->print(&mt('All users'));
6810: } elsif ($data{'scope_type'} eq 'user') {
6811: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6812: } elsif ($data{'scope_type'} eq 'secgroup') {
6813: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6814: }
6815: $r->print('<br />');
6816: if ($data{'realm_type'} eq 'all') {
6817: $r->print(&mt('All Resources'));
6818: } elsif ($data{'realm_type'} eq 'folder') {
6819: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6820: } elsif ($data{'realm_type'} eq 'symb') {
6821: my ($map,$resid,$url) =
6822: &Apache::lonnet::decode_symb($data{'realm'});
6823: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6824: $url.' <br /> ',
6825: $resid.' <br /> ',$map));
6826: }
6827: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6828: $r->print('</td></tr>');
6829:
1.473 amueller 6830: }
1.333 albertel 6831: }
6832: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6833: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6834: '</p></form>');
6835: &endSettingsScreen($r);
6836: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6837: }
6838:
1.563 damieng 6839: # UI to shift all dates (called by dateshift1 action).
6840: # Used by overview mode.
6841: #
6842: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6843: sub date_shift_one {
6844: my ($r) = @_;
6845: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6846: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6847: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6848: my $sec = $env{'request.course.sec'};
1.414 droeschl 6849: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6850: text=>"Shifting Dates"});
1.594 raeburn 6851: my $submit_text = &mt('Shift all dates accordingly');
6852: if ($sec ne '') {
1.595 raeburn 6853: my @groups;
6854: if ($env{'request.course.groups'} ne '') {
6855: @groups = split(/:/,$env{'request.course.groups'});
6856: }
6857: if (@groups) {
6858: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6859: } else {
6860: $submit_text = &mt("Shift dates set just for your section, accordingly");
6861: }
1.594 raeburn 6862: }
1.390 www 6863: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6864: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6865: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6866: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6867: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6868: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6869: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6870: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6871: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6872: 'timeshifted',
6873: $env{'form.timebase'},,
6874: '').
6875: '</td></tr></table>'.
6876: '<input type="hidden" name="action" value="dateshift2" />'.
6877: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6878: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6879: &endSettingsScreen($r);
1.390 www 6880: $r->print(&Apache::loncommon::end_page());
6881: }
6882:
1.563 damieng 6883: # UI to shift all dates (second form).
6884: #
6885: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6886: sub date_shift_two {
6887: my ($r) = @_;
6888: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6889: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6890: my $sec = $env{'request.course.sec'};
1.531 raeburn 6891: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6892: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6893: text=>"Shifting Dates"});
1.390 www 6894: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6895: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6896: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6897: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6898: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6899: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6900: if ($sec ne '') {
1.595 raeburn 6901: my @groups;
6902: if ($env{'request.course.groups'} ne '') {
6903: @groups = split(/:/,$env{'request.course.groups'});
6904: }
6905: if (@groups) {
6906: $r->print('<p>'.
6907: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6908: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6909: &Apache::lonlocal::locallocaltime($timeshifted)).
6910: '</p>');
6911: } else {
6912: $r->print('<p>'.
6913: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6914: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6915: &Apache::lonlocal::locallocaltime($timeshifted)).
6916: '</p>');
6917: }
1.594 raeburn 6918: } else {
6919: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6920: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6921: &Apache::lonlocal::locallocaltime($timeshifted)).
6922: '</p>');
6923: }
1.390 www 6924: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6925: my $numchanges = 0;
6926: my $result = &dateshift($delta,\$numchanges);
6927: if ($result eq 'ok') {
6928: $r->print(
6929: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6930: $numchanges)));
6931: } elsif ($result eq 'con_delayed') {
6932: $r->print(
6933: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6934: $numchanges)));
6935: } else {
6936: $r->print(
6937: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6938: }
1.543 bisitz 6939: $r->print(
6940: '<br /><br />'.
6941: &Apache::lonhtmlcommon::actionbox(
6942: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6943: &endSettingsScreen($r);
1.390 www 6944: $r->print(&Apache::loncommon::end_page());
6945: }
6946:
1.563 damieng 6947: # Returns the different components of a resourcedata key.
6948: # Keys: scope_type, scope, realm_type, realm, realm_title,
6949: # realm_exists, parameter_part, parameter_name.
6950: # Was used by clean_parameters (which is unused).
6951: #
6952: # @param {string} $key - the parameter key
6953: # @returns {hash}
1.333 albertel 6954: sub parse_key {
6955: my ($key) = @_;
6956: my %data;
6957: my ($middle,$part,$name)=
1.572 damieng 6958: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6959: $data{'scope_type'} = 'all';
6960: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6961: $data{'scope'} = $1;
6962: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6963: $data{'scope_type'} = 'user';
6964: $data{'scope'} = [$1,$2];
6965: } else {
1.581 raeburn 6966: $data{'scope_type'} = 'secgroup';
1.560 damieng 6967: }
6968: $middle=~s/^\[(.*)\]//;
1.333 albertel 6969: }
6970: $middle=~s/\.+$//;
6971: $middle=~s/^\.+//;
6972: $data{'realm_type'}='all';
6973: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6974: $data{'realm'} = $1;
6975: $data{'realm_type'} = 'folder';
6976: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6977: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6978: } elsif ($middle) {
1.560 damieng 6979: $data{'realm'} = $middle;
6980: $data{'realm_type'} = 'symb';
6981: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6982: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6983: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6984: }
1.446 bisitz 6985:
1.333 albertel 6986: $data{'parameter_part'} = $part;
6987: $data{'parameter_name'} = $name;
6988:
6989: return %data;
6990: }
6991:
1.239 raeburn 6992:
1.563 damieng 6993: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6994: sub header {
1.507 www 6995: return &Apache::loncommon::start_page('Settings');
1.416 jms 6996: }
1.193 albertel 6997:
6998:
6999:
1.560 damieng 7000: ##################################################
7001: # MAIN MENU
7002: ##################################################
7003:
1.563 damieng 7004: # Content and problem settings main menu.
7005: #
7006: # @param {Apache2::RequestRec} $r - the Apache request
7007: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 7008: sub print_main_menu {
7009: my ($r,$parm_permission)=@_;
7010: #
1.414 droeschl 7011: $r->print(&header());
1.507 www 7012: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 7013: my $crstype = &Apache::loncommon::course_type();
7014: my $lc_crstype = lc($crstype);
7015:
7016: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 7017: $r->print(<<ENDMAINFORMHEAD);
7018: <form method="post" enctype="multipart/form-data"
7019: action="/adm/parmset" name="studentform">
7020: ENDMAINFORMHEAD
7021: #
1.195 albertel 7022: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
7023: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 7024: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 7025: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 7026: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 7027: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
7028: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 7029: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
7030: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
7031: '/'.$env{'request.course.sec'});
7032: }
1.568 raeburn 7033: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
7034: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
7035: '/'.$env{'request.course.sec'});
7036: }
7037: my (%linktext,%linktitle,%url);
7038: if ($parm_permission->{'edit'}) {
7039: %linktext = (
7040: newoverview => 'Edit Resource Parameters - Overview Mode',
7041: settable => 'Edit Resource Parameters - Table Mode',
7042: setoverview => 'Modify Resource Parameters - Overview Mode',
7043: );
7044: %linktitle = (
7045: newoverview => 'Set/Modify resource parameters in overview mode.',
7046: settable => 'Set/Modify resource parameters in table mode.',
7047: setoverview => 'Set/Modify existing resource parameters in overview mode.',
7048: );
7049: } else {
7050: %linktext = (
7051: newoverview => 'View Resource Parameters - Overview Mode',
7052: settable => 'View Resource Parameters - Table Mode',
7053: setoverview => 'View Resource Parameters - Overview Mode',
7054: );
7055: %linktitle = (
7056: newoverview => 'Display resource parameters in overview mode.',
7057: settable => 'Display resource parameters in table mode.',
7058: setoverview => 'Display existing resource parameters in overview mode.',
7059: );
7060: }
7061: if ($mgr) {
7062: $linktext{'resettimes'} = 'Reset Student Access Times';
7063: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
7064: $url{'resettimes'} = '/adm/helper/resettimes.helper';
7065: } elsif ($vgr) {
7066: $linktext{'resettimes'} = 'Display Student Access Times',
7067: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
7068: $url{'resettimes'} = '/adm/accesstimes';
7069: }
1.193 albertel 7070: my @menu =
1.507 www 7071: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 7072: items => [
7073: { linktext => 'Portfolio Metadata',
7074: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 7075: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 7076: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 7077: icon =>'contact-new.png' ,
7078: },
1.568 raeburn 7079: { linktext => $linktext{'resettimes'},
7080: url => $url{'resettimes'},
7081: permission => ($vgr || $mgr),
7082: linktitle => $linktitle{'resettimes'},
7083: icon => 'start-here.png',
1.473 amueller 7084: },
1.520 raeburn 7085: { linktext => 'Blocking Communication/Resource Access',
7086: url => '/adm/setblock',
1.568 raeburn 7087: permission => ($vcb || $dcm),
1.520 raeburn 7088: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
7089: icon => 'comblock.png',
7090: },
1.473 amueller 7091: { linktext => 'Set Parameter Setting Default Actions',
7092: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 7093: permission => $parm_permission->{'setdefaults'},
1.473 amueller 7094: linktitle =>'Set default actions for parameters.' ,
7095: icon => 'folder-new.png' ,
7096: }]},
7097: { categorytitle => 'New and Existing Parameter Settings for Resources',
7098: items => [
7099: { linktext => 'Edit Resource Parameters - Helper Mode',
7100: url => '/adm/helper/parameter.helper',
1.568 raeburn 7101: permission => $parm_permission->{'helper'},
1.473 amueller 7102: linktitle =>'Set/Modify resource parameters in helper mode.' ,
7103: icon => 'dialog-information.png' ,
7104: #help => 'Parameter_Helper',
7105: },
1.568 raeburn 7106: { linktext => $linktext{'newoverview'},
1.473 amueller 7107: url => '/adm/parmset?action=newoverview',
1.568 raeburn 7108: permission => $parm_permission->{'newoverview'},
7109: linktitle => $linktitle{'newoverview'},
7110: icon => 'edit-find.png',
1.473 amueller 7111: #help => 'Parameter_Overview',
7112: },
1.568 raeburn 7113: { linktext => $linktext{'settable'},
1.473 amueller 7114: url => '/adm/parmset?action=settable',
1.568 raeburn 7115: permission => $parm_permission->{'settable'},
7116: linktitle => $linktitle{'settable'},
7117: icon => 'edit-copy.png',
1.473 amueller 7118: #help => 'Table_Mode',
7119: }]},
1.417 droeschl 7120: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 7121: items => [
1.570 raeburn 7122: { linktext => $linktext{'setoverview'},
1.473 amueller 7123: url => '/adm/parmset?action=setoverview',
1.568 raeburn 7124: permission => $parm_permission->{'setoverview'},
7125: linktitle => $linktitle{'setoverview'},
7126: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 7127: #help => 'Parameter_Overview',
7128: },
7129: { linktext => 'Change Log',
7130: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 7131: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 7132: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 7133: icon => 'document-properties.png',
1.473 amueller 7134: }]}
1.193 albertel 7135: );
1.414 droeschl 7136: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 7137: $r->print('</form>');
1.507 www 7138: &endSettingsScreen($r);
1.539 raeburn 7139: $r->print(&Apache::loncommon::end_page());
1.193 albertel 7140: return;
7141: }
1.414 droeschl 7142:
1.416 jms 7143:
7144:
1.560 damieng 7145: ##################################################
7146: # PORTFOLIO METADATA
7147: ##################################################
7148:
1.563 damieng 7149: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
7150: # It looks like field titles are not localized.
7151: #
7152: # @param {Apache2::RequestRec} $r - the Apache request
7153: # @param {string} $field_name - metadata field name
7154: # @param {string} $field_text - metadata field title, in English unless manually added
7155: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 7156: sub output_row {
1.347 banghart 7157: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 7158: my $output;
1.263 banghart 7159: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
7160: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 7161: if (!defined($options)) {
1.254 banghart 7162: $options = 'active,stuadd';
1.261 banghart 7163: $values = '';
1.252 banghart 7164: }
1.337 banghart 7165: if (!($options =~ /deleted/)) {
7166: my @options= ( ['active', 'Show to student'],
1.418 schafran 7167: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 7168: ['choices','Provide choices for students to select from']);
1.473 amueller 7169: # ['onlyone','Student may select only one choice']);
1.337 banghart 7170: if ($added_flag) {
7171: push @options,['deleted', 'Delete Metadata Field'];
7172: }
1.351 banghart 7173: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 7174: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 7175: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 7176: foreach my $opt (@options) {
1.560 damieng 7177: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
7178: $output .= &Apache::loncommon::continue_data_table_row();
7179: $output .= '<td>'.(' ' x 5).'<label>
7180: <input type="checkbox" name="'.
7181: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
7182: &mt($opt->[1]).'</label></td>';
7183: $output .= &Apache::loncommon::end_data_table_row();
7184: }
1.351 banghart 7185: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 7186: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 7187: $output .= &Apache::loncommon::end_data_table_row();
7188: my $multiple_checked;
7189: my $single_checked;
7190: if ($options =~ m/onlyone/) {
1.422 bisitz 7191: $multiple_checked = '';
1.423 bisitz 7192: $single_checked = ' checked="checked"';
1.351 banghart 7193: } else {
1.423 bisitz 7194: $multiple_checked = ' checked="checked"';
1.422 bisitz 7195: $single_checked = '';
1.351 banghart 7196: }
1.560 damieng 7197: $output .= &Apache::loncommon::continue_data_table_row();
7198: $output .= '<td>'.(' ' x 10).'
7199: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
7200: '.&mt('Student may select multiple choices from list').'</td>';
7201: $output .= &Apache::loncommon::end_data_table_row();
7202: $output .= &Apache::loncommon::continue_data_table_row();
7203: $output .= '<td>'.(' ' x 10).'
7204: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
7205: '.&mt('Student may select only one choice from list').'</td>';
7206: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 7207: }
7208: return ($output);
7209: }
1.416 jms 7210:
7211:
1.560 damieng 7212: # UI to order portfolio metadata fields.
1.563 damieng 7213: # Currently useless because addmetafield does not work.
7214: #
7215: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 7216: sub order_meta_fields {
7217: my ($r)=@_;
7218: my $idx = 1;
7219: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7220: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7221: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 7222: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 7223: &Apache::lonhtmlcommon::add_breadcrumb(
7224: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 7225: text=>"Add Metadata Field"});
1.560 damieng 7226: &Apache::lonhtmlcommon::add_breadcrumb(
7227: {href=>"/adm/parmset?action=setrestrictmeta",
7228: text=>"Restrict Metadata"},
7229: {text=>"Order Metadata"});
1.345 banghart 7230: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 7231: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 7232: if ($env{'form.storeorder'}) {
7233: my $newpos = $env{'form.newpos'} - 1;
7234: my $currentpos = $env{'form.currentpos'} - 1;
7235: my @neworder = ();
1.548 raeburn 7236: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 7237: my $i;
1.341 banghart 7238: if ($newpos > $currentpos) {
1.340 banghart 7239: # moving stuff up
7240: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 7241: $neworder[$i]=$oldorder[$i];
1.340 banghart 7242: }
7243: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 7244: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 7245: }
7246: $neworder[$newpos]=$oldorder[$currentpos];
7247: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 7248: $neworder[$i]=$oldorder[$i];
1.340 banghart 7249: }
7250: } else {
7251: # moving stuff down
1.473 amueller 7252: for ($i=0;$i<$newpos;$i++) {
7253: $neworder[$i]=$oldorder[$i];
7254: }
7255: $neworder[$newpos]=$oldorder[$currentpos];
7256: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
7257: $neworder[$i]=$oldorder[$i-1];
7258: }
7259: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
7260: $neworder[$i]=$oldorder[$i];
7261: }
1.340 banghart 7262: }
1.560 damieng 7263: my $ordered_fields = join ",", @neworder;
1.343 banghart 7264: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 7265: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
7266: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 7267: }
1.357 raeburn 7268: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 7269: my $ordered_fields;
1.548 raeburn 7270: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 7271: if (!@fields_in_order) {
7272: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 7273: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 7274: push @fields_in_order, $key;
1.341 banghart 7275: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 7276: }
1.341 banghart 7277: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 7278: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
7279: }
1.340 banghart 7280: $r->print('<table>');
7281: my $num_fields = scalar(@fields_in_order);
7282: foreach my $key (@fields_in_order) {
7283: $r->print('<tr><td>');
7284: $r->print('<form method="post" action="">');
1.537 bisitz 7285: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 7286: for (my $i = 1;$i le $num_fields;$i ++) {
7287: if ($i eq $idx) {
7288: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
7289: } else {
7290: $r->print('<option value="'.$i.'">'.$i.'</option>');
7291: }
7292: }
7293: $r->print('</select></td><td>');
7294: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
7295: $r->print('<input type="hidden" name="storeorder" value="true" />');
7296: $r->print('</form>');
7297: $r->print($$fields{$key}.'</td></tr>');
7298: $idx ++;
7299: }
7300: $r->print('</table>');
1.507 www 7301: &endSettingsScreen($r);
1.340 banghart 7302: return 'ok';
7303: }
1.416 jms 7304:
7305:
1.563 damieng 7306: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
7307: # @returns {string}
1.359 banghart 7308: sub continue {
7309: my $output;
7310: $output .= '<form action="" method="post">';
7311: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 7312: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 7313: return ($output);
7314: }
1.416 jms 7315:
7316:
1.563 damieng 7317: # UI to add a metadata field.
7318: # Currenly does not work because of an HTML error (the field is not visible).
7319: #
7320: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 7321: sub addmetafield {
7322: my ($r)=@_;
1.414 droeschl 7323: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 7324: text=>"Add Metadata Field"});
1.334 banghart 7325: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
7326: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 7327: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7328: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7329: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
7330: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 7331: if (exists($env{'form.undelete'})) {
1.358 banghart 7332: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 7333: foreach my $meta_field(@meta_fields) {
7334: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
7335: $options =~ s/deleted//;
7336: $options =~ s/,,/,/;
7337: my $put_result = &Apache::lonnet::put('environment',
7338: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 7339:
1.586 raeburn 7340: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
7341: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
7342: '</strong>',$put_result).
7343: '<br />');
1.339 banghart 7344: }
1.359 banghart 7345: $r->print(&continue());
1.339 banghart 7346: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 7347: my $meta_field = $env{'form.fieldname'};
7348: my $display_field = $env{'form.fieldname'};
7349: $meta_field =~ s/\W/_/g;
1.338 banghart 7350: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 7351: my $put_result = &Apache::lonnet::put('environment',
7352: {'metadata.'.$meta_field.'.values'=>"",
7353: 'metadata.'.$meta_field.'.added'=>"$display_field",
7354: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 7355: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
7356: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
7357: '<br />');
1.359 banghart 7358: $r->print(&continue());
1.335 banghart 7359: } else {
1.357 raeburn 7360: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 7361: if ($fields) {
1.586 raeburn 7362: $r->print(&mt('You may undelete previously deleted fields.').
7363: '<br />'.
7364: &mt('Check those you wish to undelete and click Undelete.').
7365: '<br />');
1.339 banghart 7366: $r->print('<form method="post" action="">');
7367: foreach my $key(keys(%$fields)) {
1.581 raeburn 7368: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 7369: }
1.586 raeburn 7370: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 7371: $r->print('</form>');
7372: }
1.586 raeburn 7373: $r->print('<hr />'.
7374: &mt('[_1]Or[_2] you may enter a new metadata field name.',
7375: '<strong>','</strong>').
1.581 raeburn 7376: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 7377: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 7378: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 7379: $r->print('</form>');
1.334 banghart 7380: }
1.507 www 7381: &endSettingsScreen($r);
1.334 banghart 7382: }
1.416 jms 7383:
7384:
7385:
1.560 damieng 7386: # Display or save portfolio metadata.
1.563 damieng 7387: #
7388: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 7389: sub setrestrictmeta {
1.240 banghart 7390: my ($r)=@_;
1.242 banghart 7391: my $next_meta;
1.244 banghart 7392: my $output;
1.245 banghart 7393: my $item_num;
1.246 banghart 7394: my $put_result;
1.414 droeschl 7395: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 7396: text=>"Restrict Metadata"});
1.280 albertel 7397: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 7398: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 7399: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7400: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7401: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
7402: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 7403: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 7404: my $save_field = '';
1.586 raeburn 7405: my %lt = &Apache::lonlocal::texthash(
7406: addm => 'Add Metadata Field',
7407: ordm => 'Order Metadata Fields',
7408: save => 'Save',
7409: );
1.259 banghart 7410: if ($env{'form.restrictmeta'}) {
1.254 banghart 7411: foreach my $field (sort(keys(%env))) {
1.252 banghart 7412: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 7413: my $options;
1.252 banghart 7414: my $meta_field = $1;
7415: my $meta_key = $2;
1.253 banghart 7416: if ($save_field ne $meta_field) {
1.252 banghart 7417: $save_field = $meta_field;
1.473 amueller 7418: if ($env{'form.'.$meta_field.'_stuadd'}) {
7419: $options.='stuadd,';
7420: }
7421: if ($env{'form.'.$meta_field.'_choices'}) {
7422: $options.='choices,';
7423: }
7424: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
7425: $options.='onlyone,';
7426: }
7427: if ($env{'form.'.$meta_field.'_active'}) {
7428: $options.='active,';
7429: }
7430: if ($env{'form.'.$meta_field.'_deleted'}) {
7431: $options.='deleted,';
7432: }
1.259 banghart 7433: my $name = $save_field;
1.560 damieng 7434: $put_result = &Apache::lonnet::put('environment',
7435: {'metadata.'.$meta_field.'.options'=>$options,
7436: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
7437: },$dom,$crs);
1.252 banghart 7438: }
7439: }
7440: }
7441: }
1.296 albertel 7442: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 7443: {'freshen_cache' => 1});
1.335 banghart 7444: # Get the default metadata fields
1.258 albertel 7445: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 7446: # Now get possible added metadata fields
1.357 raeburn 7447: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 7448: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 7449: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 7450: if ($field ne 'courserestricted') {
1.586 raeburn 7451: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 7452: }
1.255 banghart 7453: }
1.351 banghart 7454: my $buttons = (<<ENDButtons);
1.586 raeburn 7455: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 7456: </form><br />
7457: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 7458: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 7459: </form>
7460: <br />
7461: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 7462: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 7463: ENDButtons
1.337 banghart 7464: my $added_flag = 1;
1.335 banghart 7465: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 7466: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 7467: }
1.347 banghart 7468: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 7469: $r->print(<<ENDenv);
1.259 banghart 7470: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 7471: $output
1.351 banghart 7472: $buttons
1.340 banghart 7473: </form>
1.244 banghart 7474: ENDenv
1.507 www 7475: &endSettingsScreen($r);
1.280 albertel 7476: $r->print(&Apache::loncommon::end_page());
1.240 banghart 7477: return 'ok';
7478: }
1.416 jms 7479:
7480:
1.563 damieng 7481: # Returns metadata fields that have been manually added.
7482: #
7483: # @param {string} $cid - course id
7484: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 7485: sub get_added_meta_fieldnames {
1.357 raeburn 7486: my ($cid) = @_;
1.335 banghart 7487: my %fields;
7488: foreach my $key(%env) {
1.357 raeburn 7489: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 7490: my $field_name = $1;
7491: my ($display_field_name) = $env{$key};
7492: $fields{$field_name} = $display_field_name;
7493: }
7494: }
7495: return \%fields;
7496: }
1.416 jms 7497:
7498:
1.563 damieng 7499: # Returns metadata fields that have been manually added and deleted.
7500: #
7501: # @param {string} $cid - course id
7502: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 7503: sub get_deleted_meta_fieldnames {
1.357 raeburn 7504: my ($cid) = @_;
1.339 banghart 7505: my %fields;
7506: foreach my $key(%env) {
1.357 raeburn 7507: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 7508: my $field_name = $1;
7509: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
7510: my ($display_field_name) = $env{$key};
7511: $fields{$field_name} = $display_field_name;
7512: }
7513: }
7514: }
7515: return \%fields;
7516: }
1.560 damieng 7517:
7518:
7519: ##################################################
7520: # PARAMETER SETTINGS DEFAULT ACTIONS
7521: ##################################################
7522:
7523: # UI to change parameter setting default actions
1.563 damieng 7524: #
7525: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 7526: sub defaultsetter {
1.280 albertel 7527: my ($r) = @_;
7528:
1.414 droeschl 7529: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 7530: text=>"Set Defaults"});
1.531 raeburn 7531: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7532: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
7533: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 7534: my $start_page =
1.531 raeburn 7535: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 7536: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 7537: $r->print($start_page.$breadcrumbs);
1.531 raeburn 7538: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 7539: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 7540:
1.221 www 7541: my @ids=();
7542: my %typep=();
7543: my %keyp=();
7544: my %allparms=();
7545: my %allparts=();
7546: my %allmaps=();
7547: my %mapp=();
7548: my %symbp=();
7549: my %maptitles=();
7550: my %uris=();
7551: my %keyorder=&standardkeyorder();
7552: my %defkeytype=();
7553:
1.446 bisitz 7554: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 7555: \%mapp, \%symbp,\%maptitles,\%uris,
7556: \%keyorder,\%defkeytype);
1.224 www 7557: if ($env{'form.storerules'}) {
1.560 damieng 7558: my %newrules=();
7559: my @delrules=();
7560: my %triggers=();
7561: foreach my $key (keys(%env)) {
1.225 albertel 7562: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 7563: my $tempkey=$1;
7564: my $action=$env{$key};
1.226 www 7565: if ($action) {
1.560 damieng 7566: $newrules{$tempkey.'_action'}=$action;
7567: if ($action ne 'default') {
7568: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
7569: $triggers{$whichparm}.=$tempkey.':';
7570: }
7571: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
7572: if (&isdateparm($defkeytype{$tempkey})) {
7573: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
7574: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
7575: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
7576: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
7577: } else {
7578: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
7579: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
7580: }
7581: } else {
7582: push(@delrules,$tempkey.'_action');
7583: push(@delrules,$tempkey.'_type');
7584: push(@delrules,$tempkey.'_hours');
7585: push(@delrules,$tempkey.'_min');
7586: push(@delrules,$tempkey.'_sec');
7587: push(@delrules,$tempkey.'_value');
7588: }
1.473 amueller 7589: }
7590: }
1.560 damieng 7591: foreach my $key (keys(%allparms)) {
7592: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 7593: }
1.560 damieng 7594: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
7595: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
7596: &resetrulescache();
1.224 www 7597: }
1.227 www 7598: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 7599: 'hours' => 'Hours',
7600: 'min' => 'Minutes',
7601: 'sec' => 'Seconds',
7602: 'yes' => 'Yes',
7603: 'no' => 'No');
1.222 www 7604: my @standardoptions=('','default');
7605: my @standarddisplay=('',&mt('Default value when manually setting'));
7606: my @dateoptions=('','default');
7607: my @datedisplay=('',&mt('Default value when manually setting'));
7608: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7609: unless ($tempkey) { next; }
7610: push @standardoptions,'when_setting_'.$tempkey;
7611: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
7612: if (&isdateparm($defkeytype{$tempkey})) {
7613: push @dateoptions,'later_than_'.$tempkey;
7614: push @datedisplay,&mt('Automatically set later than ').$tempkey;
7615: push @dateoptions,'earlier_than_'.$tempkey;
7616: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
7617: }
1.222 www 7618: }
1.563 damieng 7619: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
7620: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 7621: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 7622: &Apache::loncommon::start_data_table_header_row().
7623: "<th>".&mt('Rule for parameter').'</th><th>'.
7624: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
7625: &Apache::loncommon::end_data_table_header_row());
1.221 www 7626: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7627: unless ($tempkey) { next; }
7628: $r->print("\n".&Apache::loncommon::start_data_table_row().
7629: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
7630: my $action=&rulescache($tempkey.'_action');
7631: $r->print('<select name="'.$tempkey.'_action">');
7632: if (&isdateparm($defkeytype{$tempkey})) {
7633: for (my $i=0;$i<=$#dateoptions;$i++) {
7634: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
7635: $r->print("\n<option value='$dateoptions[$i]'".
7636: ($dateoptions[$i] eq $action?' selected="selected"':'').
7637: ">$datedisplay[$i]</option>");
7638: }
7639: } else {
7640: for (my $i=0;$i<=$#standardoptions;$i++) {
7641: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
7642: $r->print("\n<option value='$standardoptions[$i]'".
7643: ($standardoptions[$i] eq $action?' selected="selected"':'').
7644: ">$standarddisplay[$i]</option>");
7645: }
1.473 amueller 7646: }
1.560 damieng 7647: $r->print('</select>');
7648: unless (&isdateparm($defkeytype{$tempkey})) {
7649: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7650: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7651: }
1.560 damieng 7652: $r->print("\n</td><td>\n");
1.222 www 7653:
1.221 www 7654: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7655: my $days=&rulescache($tempkey.'_days');
7656: my $hours=&rulescache($tempkey.'_hours');
7657: my $min=&rulescache($tempkey.'_min');
7658: my $sec=&rulescache($tempkey.'_sec');
7659: $r->print(<<ENDINPUTDATE);
7660: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7661: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7662: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7663: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7664: ENDINPUTDATE
1.560 damieng 7665: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7666: my $yeschecked='';
7667: my $nochecked='';
7668: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7669: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7670:
7671: $r->print(<<ENDYESNO);
7672: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7673: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7674: ENDYESNO
1.221 www 7675: } else {
1.560 damieng 7676: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7677: }
1.318 albertel 7678: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7679: }
1.318 albertel 7680: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7681: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7682: &mt('Save').'" /></form>'."\n");
7683: &endSettingsScreen($r);
7684: $r->print(&Apache::loncommon::end_page());
1.220 www 7685: return;
7686: }
1.193 albertel 7687:
1.560 damieng 7688: ##################################################
7689: # PARAMETER CHANGES LOG
7690: ##################################################
7691:
1.563 damieng 7692: # Returns some info for a parameter log entry.
7693: # Returned entries:
7694: # $realm - HTML title for the parameter level and resource
7695: # $section - parameter section
7696: # $name - parameter name
7697: # $part - parameter part
7698: # $what - $part.'.'.$name
7699: # $middle - resource symb ?
7700: # $uname - user name (same as given)
7701: # $udom - user domain (same as given)
7702: # $issection - section or group name
7703: # $realmdescription - title for the parameter level and resource (without using HTML)
7704: #
7705: # @param {string} $key - parameter log key
7706: # @param {string} $uname - user name
7707: # @param {string} $udom - user domain
7708: # @param {boolean} $typeflag - .type log entry
7709: # @returns {Array}
1.290 www 7710: sub components {
1.581 raeburn 7711: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7712:
7713: if ($typeflag) {
1.560 damieng 7714: $key=~s/\.type$//;
1.290 www 7715: }
1.330 albertel 7716:
7717: my ($middle,$part,$name)=
1.572 damieng 7718: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7719: my $issection;
1.330 albertel 7720:
1.290 www 7721: my $section=&mt('All Students');
7722: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7723: $issection=$1;
7724: $section=&mt('Group/Section').': '.$issection;
7725: $middle=~s/^\[(.*)\]//;
1.290 www 7726: }
7727: $middle=~s/\.+$//;
7728: $middle=~s/^\.+//;
1.291 www 7729: if ($uname) {
1.560 damieng 7730: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7731: $issection='';
1.291 www 7732: }
1.316 albertel 7733: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7734: my $realmdescription=&mt('all resources');
1.556 raeburn 7735: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7736: my $mapurl = $1;
7737: my $maplevel = $2;
7738: my $leveltitle = &mt('Folder/Map');
7739: if ($maplevel eq 'rec') {
7740: $leveltitle = &mt('Recursive');
7741: }
1.560 damieng 7742: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7743: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7744: $mapurl.')</span></span>';
7745: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7746: } elsif ($middle) {
7747: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7748: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7749: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7750: ' in '.$map.' id: '.$id.')</span></span>';
7751: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7752: }
1.291 www 7753: my $what=$part.'.'.$name;
1.330 albertel 7754: return ($realm,$section,$name,$part,
1.473 amueller 7755: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7756: }
1.293 www 7757:
1.563 damieng 7758: my %standard_parms; # hash parameter name -> parameter title (not localized)
7759: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7760:
1.563 damieng 7761: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7762: sub load_parameter_names {
1.583 raeburn 7763: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7764: while (my $configline=<$config>) {
1.560 damieng 7765: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7766: chomp($configline);
7767: my ($short,$plain)=split(/:/,$configline);
7768: my (undef,$name,$type)=split(/\&/,$short,3);
7769: if ($type eq 'display') {
7770: $standard_parms{$name} = $plain;
1.469 raeburn 7771: } elsif ($type eq 'type') {
1.560 damieng 7772: $standard_parms_types{$name} = $plain;
1.469 raeburn 7773: }
1.328 albertel 7774: }
7775: close($config);
7776: $standard_parms{'int_pos'} = 'Positive Integer';
7777: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7778: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7779: }
7780:
1.563 damieng 7781: # Returns a parameter title for standard parameters, the name for others.
7782: #
7783: # @param {string} $name - parameter name
7784: # @returns {string}
1.292 www 7785: sub standard_parameter_names {
7786: my ($name)=@_;
1.328 albertel 7787: if (!%standard_parms) {
1.560 damieng 7788: &load_parameter_names();
1.328 albertel 7789: }
1.292 www 7790: if ($standard_parms{$name}) {
1.560 damieng 7791: return $standard_parms{$name};
1.446 bisitz 7792: } else {
1.560 damieng 7793: return $name;
1.292 www 7794: }
7795: }
1.290 www 7796:
1.563 damieng 7797: # Returns a parameter type for standard parameters, undef for others.
7798: #
7799: # @param {string} $name - parameter name
7800: # @returns {string}
1.469 raeburn 7801: sub standard_parameter_types {
7802: my ($name)=@_;
7803: if (!%standard_parms_types) {
7804: &load_parameter_names();
7805: }
7806: if ($standard_parms_types{$name}) {
7807: return $standard_parms_types{$name};
7808: }
7809: return;
7810: }
1.309 www 7811:
1.563 damieng 7812: # Returns a parameter level title (not localized) from the parameter level name.
7813: #
7814: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7815: # @returns {string}
1.557 raeburn 7816: sub standard_parameter_levels {
7817: my ($name)=@_;
7818: my %levels = (
7819: 'resourcelevel' => 'a single resource',
7820: 'maplevel' => 'the enclosing map/folder',
7821: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7822: 'courselevel' => 'the general (course) level',
7823: );
7824: if ($levels{$name}) {
7825: return $levels{$name};
7826: }
7827: return;
7828: }
7829:
1.560 damieng 7830: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7831: #
7832: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7833: sub parm_change_log {
1.568 raeburn 7834: my ($r,$parm_permission)=@_;
1.531 raeburn 7835: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7836: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7837: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7838: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7839: text=>"Parameter Change Log"});
1.522 raeburn 7840: my $js = '<script type="text/javascript">'."\n".
7841: '// <![CDATA['."\n".
7842: &Apache::loncommon::display_filter_js('parmslog')."\n".
7843: '// ]]>'."\n".
7844: '</script>'."\n";
7845: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7846: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7847: &startSettingsScreen($r,'parmset',$crstype);
7848: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7849:
1.301 www 7850: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7851:
1.522 raeburn 7852: $r->print('<div class="LC_left_float">'.
7853: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7854: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7855: method="post" name="parameterlog">');
1.446 bisitz 7856:
1.311 albertel 7857: my %saveable_parameters = ('show' => 'scalar',);
7858: &Apache::loncommon::store_course_settings('parameter_log',
7859: \%saveable_parameters);
7860: &Apache::loncommon::restore_course_settings('parameter_log',
7861: \%saveable_parameters);
1.522 raeburn 7862: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7863: '<input type="submit" value="'.&mt('Display').'" />'.
7864: '</form></fieldset></div><br clear="all" />');
1.301 www 7865:
1.568 raeburn 7866: my $readonly = 1;
7867: if ($parm_permission->{'edit'}) {
7868: undef($readonly);
7869: }
1.531 raeburn 7870: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7871: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7872: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7873: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7874: unless ($readonly) {
7875: $r->print('<th>'.&mt('Announce').'</th>');
7876: }
7877: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7878: my $shown=0;
1.349 www 7879: my $folder='';
7880: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7881: my $last='';
7882: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7883: &GDBM_READER(),0640)) {
7884: $last=$hash{'last_known'};
7885: untie(%hash);
7886: }
7887: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7888: }
1.595 raeburn 7889: my $numgroups = 0;
7890: my @groups;
7891: if ($env{'request.course.groups'} ne '') {
7892: @groups = split(/:/,$env{'request.course.groups'});
7893: $numgroups = scalar(@groups);
7894: }
1.560 damieng 7895: foreach my $id (sort {
7896: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7897: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7898: }
7899: my $aid = (split('00000',$a))[-1];
7900: my $bid = (split('00000',$b))[-1];
7901: return $bid<=>$aid;
1.473 amueller 7902: } (keys(%parmlog))) {
1.294 www 7903: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7904: my $count = 0;
7905: my $time =
7906: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7907: my $plainname =
7908: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7909: $parmlog{$id}{'exe_udom'});
7910: my $about_me_link =
7911: &Apache::loncommon::aboutmewrapper($plainname,
7912: $parmlog{$id}{'exe_uname'},
7913: $parmlog{$id}{'exe_udom'});
7914: my $send_msg_link='';
1.568 raeburn 7915: if ((!$readonly) &&
7916: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7917: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7918: $send_msg_link ='<br />'.
7919: &Apache::loncommon::messagewrapper(&mt('Send message'),
7920: $parmlog{$id}{'exe_uname'},
7921: $parmlog{$id}{'exe_udom'});
7922: }
7923: my $row_start=&Apache::loncommon::start_data_table_row();
7924: my $makenewrow=0;
7925: my %istype=();
7926: my $output;
7927: foreach my $changed (reverse(sort(@changes))) {
7928: my $value=$parmlog{$id}{'logentry'}{$changed};
7929: my $typeflag = ($changed =~/\.type$/ &&
7930: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7931: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7932: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7933: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7934: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7935: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7936: if ($uname ne '') {
7937: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7938: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7939: }
7940: }
7941: if ($env{'form.displayfilter'} eq 'currentfolder') {
7942: if ($folder) {
7943: if ($middle!~/^\Q$folder\E/) { next; }
7944: }
7945: }
7946: if ($typeflag) {
7947: $istype{$parmname}=$value;
7948: if (!$env{'form.includetypes'}) { next; }
7949: }
7950: $count++;
7951: if ($makenewrow) {
7952: $output .= $row_start;
7953: } else {
7954: $makenewrow=1;
7955: }
1.470 raeburn 7956: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7957: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7958: &mt($parmitem).'</td><td>'.
7959: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7960: my $stillactive=0;
7961: if ($parmlog{$id}{'delflag'}) {
7962: $output .= &mt('Deleted');
7963: } else {
7964: if ($typeflag) {
1.470 raeburn 7965: my $parmitem = &standard_parameter_names($value);
7966: $parmitem = &mt($parmitem);
1.560 damieng 7967: $output .= &mt('Type: [_1]',$parmitem);
7968: } else {
1.584 raeburn 7969: my $toolsymb;
7970: if ($middle =~ /ext\.tool$/) {
7971: $toolsymb = $middle;
7972: }
1.560 damieng 7973: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7974: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7975: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7976: my $showvalue = $value;
7977: if ($istype{$parmname} eq '') {
7978: my $type = &standard_parameter_types($parmname);
7979: if ($type ne '') {
7980: if (&isdateparm($type)) {
7981: $showvalue =
7982: &Apache::lonlocal::locallocaltime($value);
7983: }
7984: }
7985: } else {
1.560 damieng 7986: if (&isdateparm($istype{$parmname})) {
7987: $showvalue = &Apache::lonlocal::locallocaltime($value);
1.622 raeburn 7988: } elsif (($istype{$parmname} eq 'string_grace') ||
7989: ($istype{$parmname} eq 'string_ip')) {
7990: $showvalue =~ s/,/, /g;
1.560 damieng 7991: }
1.469 raeburn 7992: }
7993: $output .= $showvalue;
1.560 damieng 7994: if ($value ne $all[$level]) {
7995: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7996: } else {
7997: $stillactive=1;
7998: }
7999: }
1.473 amueller 8000: }
1.568 raeburn 8001: $output .= '</td>';
8002:
8003: unless ($readonly) {
8004: $output .= '<td>';
8005: if ($stillactive) {
8006: my $parmitem = &standard_parameter_names($parmname);
8007: $parmitem = &mt($parmitem);
8008: my $title=&mt('Changed [_1]',$parmitem);
8009: my $description=&mt('Changed [_1] for [_2] to [_3]',
8010: $parmitem,$realmdescription,
8011: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
8012: if (($uname) && ($udom)) {
8013: $output .=
8014: &Apache::loncommon::messagewrapper('Notify User',
8015: $uname,$udom,$title,
8016: $description);
8017: } else {
8018: $output .=
8019: &Apache::lonrss::course_blog_link($id,$title,
8020: $description);
8021: }
1.560 damieng 8022: }
1.568 raeburn 8023: $output .= '</td>';
1.560 damieng 8024: }
1.568 raeburn 8025: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 8026: }
1.560 damieng 8027: if ($env{'form.displayfilter'} eq 'containing') {
8028: my $wholeentry=$about_me_link.':'.
8029: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
8030: $output;
8031: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 8032: }
1.349 www 8033: if ($count) {
1.560 damieng 8034: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
8035: <td rowspan="'.$count.'">'.$about_me_link.
8036: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
8037: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
8038: $send_msg_link.'</td>'.$output);
8039: $shown++;
8040: }
8041: if (!($env{'form.show'} eq &mt('all')
8042: || $shown<=$env{'form.show'})) { last; }
1.286 www 8043: }
1.301 www 8044: $r->print(&Apache::loncommon::end_data_table());
1.507 www 8045: &endSettingsScreen($r);
1.284 www 8046: $r->print(&Apache::loncommon::end_page());
8047: }
8048:
1.560 damieng 8049: ##################################################
8050: # MISC !
8051: ##################################################
8052:
1.563 damieng 8053: # Stores slot information.
1.560 damieng 8054: # Used by table UI
1.563 damieng 8055: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
8056: #
8057: # @param {string} $slot_name - slot name
8058: # @param {string} $cdom - course domain
8059: # @param {string} $cnum - course number
8060: # @param {string} $symb - resource symb
8061: # @param {string} $uname - user name
8062: # @param {string} $udom - user domain
8063: # @returns {string} - 'ok' or error name
1.437 raeburn 8064: sub update_slots {
8065: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
8066: my %slot=&Apache::lonnet::get_slot($slot_name);
8067: if (!keys(%slot)) {
8068: return 'error: slot does not exist';
8069: }
8070: my $max=$slot{'maxspace'};
8071: if (!defined($max)) { $max=99999; }
8072:
8073: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
8074: "^$slot_name\0");
8075: my ($tmp)=%consumed;
8076: if ($tmp=~/^error: 2 / ) {
8077: return 'error: unable to determine current slot status';
8078: }
8079: my $last=0;
8080: foreach my $key (keys(%consumed)) {
8081: my $num=(split('\0',$key))[1];
8082: if ($num > $last) { $last=$num; }
8083: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
8084: return 'ok';
8085: }
8086: }
8087:
8088: if (scalar(keys(%consumed)) >= $max) {
8089: return 'error: no space left in slot';
8090: }
8091: my $wanted=$last+1;
8092:
8093: my %reservation=('name' => $uname.':'.$udom,
8094: 'timestamp' => time,
8095: 'symb' => $symb);
8096:
8097: my $success=&Apache::lonnet::newput('slot_reservations',
8098: {"$slot_name\0$wanted" =>
8099: \%reservation},
8100: $cdom, $cnum);
1.438 raeburn 8101: if ($success eq 'ok') {
8102: my %storehash = (
8103: symb => $symb,
8104: slot => $slot_name,
8105: action => 'reserve',
8106: context => 'parameter',
8107: );
1.526 raeburn 8108: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 8109: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 8110:
1.526 raeburn 8111: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 8112: '',$uname,$udom,$uname,$udom);
1.438 raeburn 8113: }
1.437 raeburn 8114: return $success;
8115: }
8116:
1.563 damieng 8117: # Deletes a slot reservation.
1.560 damieng 8118: # Used by table UI
1.563 damieng 8119: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
8120: #
8121: # @param {string} $slot_name - slot name
8122: # @param {string} $cdom - course domain
8123: # @param {string} $cnum - course number
8124: # @param {string} $uname - user name
8125: # @param {string} $udom - user domain
8126: # @param {string} $symb - resource symb
8127: # @returns {string} - 'ok' or error name
1.437 raeburn 8128: sub delete_slots {
8129: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
8130: my $delresult;
8131: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
8132: $cnum, "^$slot_name\0");
8133: if (&Apache::lonnet::error(%consumed)) {
8134: return 'error: unable to determine current slot status';
8135: }
8136: my ($tmp)=%consumed;
8137: if ($tmp=~/^error: 2 /) {
8138: return 'error: unable to determine current slot status';
8139: }
8140: foreach my $key (keys(%consumed)) {
8141: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
8142: my $num=(split('\0',$key))[1];
8143: my $entry = $slot_name.'\0'.$num;
8144: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
8145: $cdom,$cnum);
8146: if ($delresult eq 'ok') {
8147: my %storehash = (
8148: symb => $symb,
8149: slot => $slot_name,
8150: action => 'release',
8151: context => 'parameter',
8152: );
1.526 raeburn 8153: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 8154: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 8155: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 8156: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 8157: }
8158: }
8159: }
8160: return $delresult;
8161: }
8162:
1.563 damieng 8163: # Returns true if there is a current course.
1.560 damieng 8164: # Used by handler
1.563 damieng 8165: #
8166: # @returns {boolean}
1.355 albertel 8167: sub check_for_course_info {
8168: my $navmap = Apache::lonnavmaps::navmap->new();
8169: return 1 if ($navmap);
8170: return 0;
8171: }
8172:
1.563 damieng 8173: # Returns the current course host and host LON-CAPA version.
8174: #
8175: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 8176: sub parameter_release_vars {
1.504 raeburn 8177: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
8178: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
8179: my $chostname = &Apache::lonnet::hostname($chome);
8180: my ($cmajor,$cminor) =
8181: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
8182: return ($chostname,$cmajor,$cminor);
8183: }
8184:
1.563 damieng 8185: # Checks if the course host version can handle a parameter required version,
8186: # and if it does, stores the release needed for the course.
8187: #
8188: # @param {string} $name - parameter name
8189: # @param {string} $value - parameter value
8190: # @param {string} $valmatch - name of the test used for checking the value
8191: # @param {string} $namematch - name of the test used for checking the name
8192: # @param {string} $needsrelease - version needed by the parameter, major.minor
8193: # @param {integer} $cmajor - course major version number
8194: # @param {integer} $cminor - course minor version number
8195: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 8196: sub parameter_releasecheck {
1.557 raeburn 8197: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 8198: my $needsnewer;
8199: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
8200: if (($cmajor < $needsmajor) ||
8201: ($cmajor == $needsmajor && $cminor < $needsminor)) {
8202: $needsnewer = 1;
1.557 raeburn 8203: } elsif ($name) {
8204: if ($valmatch) {
8205: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
8206: } elsif ($value) {
8207: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
8208: }
8209: } elsif ($namematch) {
8210: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 8211: }
8212: return $needsnewer;
8213: }
8214:
1.568 raeburn 8215: sub get_permission {
8216: my %permission;
8217: my $allowed = 0;
8218: return (\%permission,$allowed) unless ($env{'request.course.id'});
8219: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
8220: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
8221: $env{'request.course.sec'}))) {
8222: %permission= (
8223: 'edit' => 1,
8224: 'set' => 1,
8225: 'setoverview' => 1,
8226: 'addmetadata' => 1,
8227: 'ordermetadata' => 1,
8228: 'setrestrictmeta' => 1,
8229: 'newoverview' => 1,
8230: 'setdefaults' => 1,
8231: 'settable' => 1,
8232: 'parameterchangelog' => 1,
8233: 'cleanparameters' => 1,
8234: 'dateshift1' => 1,
8235: 'dateshift2' => 1,
8236: 'helper' => 1,
8237: );
8238: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
8239: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
8240: $env{'request.course.sec'}))) {
8241: %permission = (
8242: 'set' => 1,
8243: 'settable' => 1,
8244: 'newoverview' => 1,
8245: 'setoverview' => 1,
8246: 'parameterchangelog' => 1,
8247: );
8248: }
8249: foreach my $perm (values(%permission)) {
8250: if ($perm) { $allowed=1; last; }
8251: }
8252: return (\%permission,$allowed);
8253: }
8254:
1.560 damieng 8255: ##################################################
8256: # HANDLER
8257: ##################################################
8258:
8259: # Main handler for lonparmset.
8260: # Sub called based on request parameters action and command:
8261: # no command or action: print_main_menu
8262: # command 'set': assessparms (direct access to table mode for a resource)
8263: # (this can also be accessed simply with the symb parameter)
8264: # action 'setoverview': overview (display all existing parameter settings)
8265: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
8266: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
8267: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
8268: # action 'newoverview': newoverview (overview mode)
8269: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
8270: # action 'settable': assessparms (table mode)
8271: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
8272: # blog postings, user notification changes)
8273: # action 'cleanparameters': clean_parameters (unused)
8274: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
8275: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 8276: sub handler {
1.43 albertel 8277: my $r=shift;
1.30 www 8278:
1.376 albertel 8279: &reset_caches();
8280:
1.414 droeschl 8281: &Apache::loncommon::content_type($r,'text/html');
8282: $r->send_http_header;
8283: return OK if $r->header_only;
8284:
1.193 albertel 8285: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 8286: ['action','state',
1.205 www 8287: 'pres_marker',
8288: 'pres_value',
1.206 www 8289: 'pres_type',
1.506 www 8290: 'filter','part',
1.390 www 8291: 'udom','uname','symb','serial','timebase']);
1.131 www 8292:
1.83 bowersj2 8293:
1.193 albertel 8294: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 8295: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 8296: text=>"Content and Problem Settings",
1.473 amueller 8297: faq=>10,
8298: bug=>'Instructor Interface',
1.442 droeschl 8299: help =>
8300: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 8301:
1.30 www 8302: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 8303: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 8304: my $exists = &check_for_course_info();
8305:
1.568 raeburn 8306: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 8307: #
8308: # Main switch on form.action and form.state, as appropriate
8309: #
8310: # Check first if coming from someone else headed directly for
8311: # the table mode
1.568 raeburn 8312: if (($parm_permission->{'set'}) &&
8313: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
8314: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
8315: &assessparms($r,$parm_permission);
1.193 albertel 8316: } elsif (! exists($env{'form.action'})) {
8317: &print_main_menu($r,$parm_permission);
1.568 raeburn 8318: } elsif (!$parm_permission->{$env{'form.action'}}) {
8319: &print_main_menu($r,$parm_permission);
1.414 droeschl 8320: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 8321: &overview($r,$parm_permission);
1.560 damieng 8322: } elsif ($env{'form.action'} eq 'addmetadata') {
8323: &addmetafield($r);
8324: } elsif ($env{'form.action'} eq 'ordermetadata') {
8325: &order_meta_fields($r);
1.414 droeschl 8326: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 8327: &setrestrictmeta($r);
1.414 droeschl 8328: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 8329: &newoverview($r,$parm_permission);
1.414 droeschl 8330: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 8331: &defaultsetter($r);
8332: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 8333: &assessparms($r,$parm_permission);
1.414 droeschl 8334: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 8335: &parm_change_log($r,$parm_permission);
1.414 droeschl 8336: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 8337: &clean_parameters($r);
1.414 droeschl 8338: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 8339: &date_shift_one($r);
1.414 droeschl 8340: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 8341: &date_shift_two($r);
1.446 bisitz 8342: }
1.43 albertel 8343: } else {
1.1 www 8344: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 8345: if ($exists) {
8346: $env{'user.error.msg'}=
8347: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
8348: } else {
8349: $env{'user.error.msg'}=
8350: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
8351: }
8352: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 8353: }
1.376 albertel 8354: &reset_caches();
8355:
1.43 albertel 8356: return OK;
1.1 www 8357: }
8358:
8359: 1;
8360: __END__
8361:
8362:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>