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