Annotation of loncom/interface/lonparmset.pm, revision 1.619
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to set parameters for assessments
3: #
1.619 ! raeburn 4: # $Id: lonparmset.pm,v 1.618 2023/04/03 15:39:10 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.617 raeburn 332: use Text::Wrap();
1.416 jms 333: use LONCAPA qw(:DEFAULT :match);
334:
335:
1.560 damieng 336: ##################################################
337: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
338: ##################################################
339:
340: # Page header
1.561 damieng 341: #
342: # @param {Apache2::RequestRec} $r - Apache request object
343: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
344: # @param {string} $crstype - course type ('Community' for community settings)
1.507 www 345: sub startSettingsScreen {
1.531 raeburn 346: my ($r,$mode,$crstype)=@_;
1.507 www 347:
1.531 raeburn 348: my $tabtext = &mt('Course Settings');
349: if ($crstype eq 'Community') {
350: $tabtext = &mt('Community Settings');
351: }
1.507 www 352: $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
353: $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b> '.
1.531 raeburn 354: $tabtext.
1.507 www 355: ' </b></a></li>');
356:
1.523 raeburn 357: $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507 www 358: &mt('Content and Problem Settings').'</b></a></li>');
359: $r->print("\n".'</ul>'."\n");
1.523 raeburn 360: $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 361: }
362:
1.560 damieng 363: # Page footer
1.507 www 364: sub endSettingsScreen {
365: my ($r)=@_;
366: $r->print('</div></div></div>');
367: }
368:
369:
370:
1.560 damieng 371: ##################################################
1.563 damieng 372: # (mostly) TABLE MODE
1.560 damieng 373: # (parmval is also used for the log of parameter changes)
374: ##################################################
375:
1.566 damieng 376: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561 damieng 377: #
378: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 379: # @param {string} $id - resource id or map pc
1.561 damieng 380: # @param {string} $def - the resource's default value for this parameter
381: # @param {string} $uname - user name
382: # @param {string} $udom - user domain
383: # @param {string} $csec - section name
384: # @param {string} $cgroup - group name
385: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
386: # @returns {Array}
1.2 www 387: sub parmval {
1.275 raeburn 388: my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
389: return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
390: $cgroup,$courseopt);
1.201 www 391: }
392:
1.561 damieng 393: # Returns an array containing
394: # - the most specific level that is defined for that parameter (integer)
395: # - an array with the level as index and the parameter value as value (when defined)
396: # (level 1 is the most specific and will have precedence)
397: #
398: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566 damieng 399: # @param {string} $symb - resource symb or map src
1.561 damieng 400: # @param {string} $def - the resource's default value for this parameter
401: # @param {string} $uname - user name
402: # @param {string} $udom - user domain
403: # @param {string} $csec - section name
404: # @param {string} $cgroup - group name
405: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
406: # @returns {Array}
1.201 www 407: sub parmval_by_symb {
1.275 raeburn 408: my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200 www 409:
1.352 albertel 410: my $useropt;
411: if ($uname ne '' && $udom ne '') {
1.561 damieng 412: $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352 albertel 413: }
1.200 www 414:
1.8 www 415: my $result='';
1.44 albertel 416: my @outpar=();
1.2 www 417: # ----------------------------------------------------- Cascading lookup scheme
1.446 bisitz 418: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 419: $map = &Apache::lonnet::deversion($map);
1.561 damieng 420:
421: # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
422: # any change should be reflected there.
423:
1.201 www 424: my $symbparm=$symb.'.'.$what;
1.556 raeburn 425: my $recurseparm=$map.'___(rec).'.$what;
1.201 www 426: my $mapparm=$map.'___(all).'.$what;
1.10 www 427:
1.269 raeburn 428: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
429: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 430: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 431: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
432:
1.190 albertel 433: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
434: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 435: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 436: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
437:
438: my $courselevel=$env{'request.course.id'}.'.'.$what;
439: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 440: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 441: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2 www 442:
1.11 www 443:
1.182 albertel 444: # --------------------------------------------------------- first, check course
1.11 www 445:
1.561 damieng 446: # 18 - General Course
1.200 www 447: if (defined($$courseopt{$courselevel})) {
1.556 raeburn 448: $outpar[18]=$$courseopt{$courselevel};
449: $result=18;
450: }
451:
1.561 damieng 452: # 17 - Map or Folder level in course (recursive)
1.556 raeburn 453: if (defined($$courseopt{$courseleveli})) {
454: $outpar[17]=$$courseopt{$courseleveli};
455: $result=17;
1.43 albertel 456: }
1.11 www 457:
1.561 damieng 458: # 16 - Map or Folder level in course (non-recursive)
1.200 www 459: if (defined($$courseopt{$courselevelm})) {
1.556 raeburn 460: $outpar[16]=$$courseopt{$courselevelm};
461: $result=16;
1.43 albertel 462: }
1.11 www 463:
1.182 albertel 464: # ------------------------------------------------------- second, check default
465:
1.561 damieng 466: # 15 - resource default
1.556 raeburn 467: if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182 albertel 468:
469: # ------------------------------------------------------ third, check map parms
470:
1.556 raeburn 471:
1.561 damieng 472: # 14 - map default
1.376 albertel 473: my $thisparm=&parmhash($symbparm);
1.556 raeburn 474: if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182 albertel 475:
1.561 damieng 476: # 13 - resource level in course
1.200 www 477: if (defined($$courseopt{$courselevelr})) {
1.556 raeburn 478: $outpar[13]=$$courseopt{$courselevelr};
479: $result=13;
1.43 albertel 480: }
1.11 www 481:
1.182 albertel 482: # ------------------------------------------------------ fourth, back to course
1.352 albertel 483: if ($csec ne '') {
1.561 damieng 484: # 12 - General for section
1.200 www 485: if (defined($$courseopt{$seclevel})) {
1.556 raeburn 486: $outpar[12]=$$courseopt{$seclevel};
487: $result=12;
488: }
1.561 damieng 489: # 11 - Map or Folder level for section (recursive)
1.556 raeburn 490: if (defined($$courseopt{$secleveli})) {
491: $outpar[11]=$$courseopt{$secleveli};
492: $result=11;
493: }
1.561 damieng 494: # 10 - Map or Folder level for section (non-recursive)
1.200 www 495: if (defined($$courseopt{$seclevelm})) {
1.556 raeburn 496: $outpar[10]=$$courseopt{$seclevelm};
497: $result=10;
498: }
1.561 damieng 499: # 9 - resource level in section
1.200 www 500: if (defined($$courseopt{$seclevelr})) {
1.556 raeburn 501: $outpar[9]=$$courseopt{$seclevelr};
502: $result=9;
503: }
1.43 albertel 504: }
1.275 raeburn 505: # ------------------------------------------------------ fifth, check course group
1.352 albertel 506: if ($cgroup ne '') {
1.561 damieng 507: # 8 - General for group
1.269 raeburn 508: if (defined($$courseopt{$grplevel})) {
1.556 raeburn 509: $outpar[8]=$$courseopt{$grplevel};
510: $result=8;
511: }
1.561 damieng 512: # 7 - Map or Folder level for group (recursive)
1.556 raeburn 513: if (defined($$courseopt{$grpleveli})) {
514: $outpar[7]=$$courseopt{$grpleveli};
515: $result=7;
1.269 raeburn 516: }
1.561 damieng 517: # 6 - Map or Folder level for group (non-recursive)
1.269 raeburn 518: if (defined($$courseopt{$grplevelm})) {
1.556 raeburn 519: $outpar[6]=$$courseopt{$grplevelm};
520: $result=6;
1.269 raeburn 521: }
1.561 damieng 522: # 5 - resource level in group
1.269 raeburn 523: if (defined($$courseopt{$grplevelr})) {
1.556 raeburn 524: $outpar[5]=$$courseopt{$grplevelr};
525: $result=5;
1.269 raeburn 526: }
527: }
1.11 www 528:
1.556 raeburn 529: # ---------------------------------------------------------- sixth, check user
1.11 www 530:
1.352 albertel 531: if ($uname ne '') {
1.561 damieng 532: # 4 - General for specific student
533: if (defined($$useropt{$courselevel})) {
534: $outpar[4]=$$useropt{$courselevel};
535: $result=4;
536: }
1.556 raeburn 537:
1.561 damieng 538: # 3 - Map or Folder level for specific student (recursive)
539: if (defined($$useropt{$courseleveli})) {
540: $outpar[3]=$$useropt{$courseleveli};
541: $result=3;
542: }
1.473 amueller 543:
1.561 damieng 544: # 2 - Map or Folder level for specific student (non-recursive)
545: if (defined($$useropt{$courselevelm})) {
546: $outpar[2]=$$useropt{$courselevelm};
547: $result=2;
548: }
1.473 amueller 549:
1.561 damieng 550: # 1 - resource level for specific student
551: if (defined($$useropt{$courselevelr})) {
552: $outpar[1]=$$useropt{$courselevelr};
553: $result=1;
554: }
1.43 albertel 555: }
1.44 albertel 556: return ($result,@outpar);
1.2 www 557: }
558:
1.198 www 559:
560:
1.376 albertel 561: # --- Caches local to lonparmset
562:
1.446 bisitz 563:
1.561 damieng 564: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376 albertel 565: sub reset_caches {
566: &resetparmhash();
567: &resetsymbcache();
568: &resetrulescache();
1.203 www 569: }
570:
1.561 damieng 571: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
572: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376 albertel 573: {
1.561 damieng 574: my $parmhashid; # course identifier, to initialize the cache only once for a course
575: my %parmhash; # the parameter cache
576: # reset map parameter hash
1.376 albertel 577: sub resetparmhash {
1.560 damieng 578: undef($parmhashid);
579: undef(%parmhash);
1.376 albertel 580: }
1.446 bisitz 581:
1.561 damieng 582: # dump the _parms.db database into %parmhash
1.376 albertel 583: sub cacheparmhash {
1.560 damieng 584: if ($parmhashid eq $env{'request.course.fn'}) { return; }
585: my %parmhashfile;
586: if (tie(%parmhashfile,'GDBM_File',
587: $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
588: %parmhash=%parmhashfile;
589: untie(%parmhashfile);
590: $parmhashid=$env{'request.course.fn'};
591: }
1.201 www 592: }
1.446 bisitz 593:
1.561 damieng 594: # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376 albertel 595: sub parmhash {
1.560 damieng 596: my ($id) = @_;
597: &cacheparmhash();
598: return $parmhash{$id};
1.376 albertel 599: }
1.560 damieng 600: }
1.376 albertel 601:
1.566 damieng 602: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446 bisitz 603: {
1.561 damieng 604: my $symbsid; # course identifier, to initialize the cache only once for a course
605: my %symbs; # hash id->symb
606: # reset the id->symb cache
1.376 albertel 607: sub resetsymbcache {
1.560 damieng 608: undef($symbsid);
609: undef(%symbs);
1.376 albertel 610: }
1.446 bisitz 611:
1.566 damieng 612: # returns the resource symb or map src corresponding to a resource id or map pc
613: # (using lonnavmaps and a cache)
1.376 albertel 614: sub symbcache {
1.560 damieng 615: my $id=shift;
616: if ($symbsid ne $env{'request.course.id'}) {
617: undef(%symbs);
618: }
619: if (!$symbs{$id}) {
620: my $navmap = Apache::lonnavmaps::navmap->new();
621: if ($id=~/\./) {
622: my $resource=$navmap->getById($id);
623: $symbs{$id}=$resource->symb();
624: } else {
625: my $resource=$navmap->getByMapPc($id);
626: $symbs{$id}=&Apache::lonnet::declutter($resource->src());
627: }
628: $symbsid=$env{'request.course.id'};
1.473 amueller 629: }
1.560 damieng 630: return $symbs{$id};
1.473 amueller 631: }
1.560 damieng 632: }
1.201 www 633:
1.561 damieng 634: # cache for parameter default actions (stored in parmdefactions.db)
1.446 bisitz 635: {
1.561 damieng 636: my $rulesid; # course identifier, to initialize the cache only once for a course
637: my %rules; # parameter default actions hash
1.376 albertel 638: sub resetrulescache {
1.560 damieng 639: undef($rulesid);
640: undef(%rules);
1.376 albertel 641: }
1.446 bisitz 642:
1.561 damieng 643: # returns the value for a given key in the parameter default action hash
1.376 albertel 644: sub rulescache {
1.560 damieng 645: my $id=shift;
646: if ($rulesid ne $env{'request.course.id'}
647: && !defined($rules{$id})) {
648: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
649: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
650: %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
651: $rulesid=$env{'request.course.id'};
652: }
653: return $rules{$id};
1.221 www 654: }
655: }
656:
1.416 jms 657:
1.561 damieng 658: # Returns the values of the parameter type default action
659: # "default value when manually setting".
660: # If none is defined, ('','','','','') is returned.
661: #
662: # @param {string} $type - parameter type
663: # @returns {Array<string>} - (hours, min, sec, value)
1.229 www 664: sub preset_defaults {
665: my $type=shift;
666: if (&rulescache($type.'_action') eq 'default') {
1.560 damieng 667: # yes, there is something
668: return (&rulescache($type.'_hours'),
669: &rulescache($type.'_min'),
670: &rulescache($type.'_sec'),
671: &rulescache($type.'_value'));
1.229 www 672: } else {
1.560 damieng 673: # nothing there or something else
674: return ('','','','','');
1.229 www 675: }
676: }
677:
1.416 jms 678:
1.561 damieng 679: # Checks that a date is after enrollment start date and before
680: # enrollment end date.
681: # Returns HTML with a warning if it is not, or the empty string otherwise.
682: # This is used by both overview and table modes.
683: #
684: # @param {integer} $checkdate - the date to check.
685: # @returns {string} - HTML possibly containing a localized warning message.
1.277 www 686: sub date_sanity_info {
687: my $checkdate=shift;
688: unless ($checkdate) { return ''; }
689: my $result='';
690: my $crsprefix='course.'.$env{'request.course.id'}.'.';
691: if ($env{$crsprefix.'default_enrollment_end_date'}) {
692: if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413 bisitz 693: $result.='<div class="LC_warning">'
694: .&mt('After course enrollment end!')
695: .'</div>';
1.277 www 696: }
697: }
698: if ($env{$crsprefix.'default_enrollment_start_date'}) {
699: if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413 bisitz 700: $result.='<div class="LC_warning">'
701: .&mt('Before course enrollment start!')
702: .'</div>';
1.277 www 703: }
704: }
1.413 bisitz 705: # Preparation for additional warnings about dates in the past/future.
706: # An improved, more context sensitive version is recommended,
707: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
708: # if ($checkdate<time) {
709: # $result.='<div class="LC_info">'
710: # .'('.&mt('in the past').')'
711: # .'</div>';
712: # }
713: # if ($checkdate>time) {
714: # $result.='<div class="LC_info">'
715: # .'('.&mt('in the future').')'
716: # .'</div>';
717: # }
1.277 www 718: return $result;
719: }
1.561 damieng 720:
721:
722: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186 www 723: #
1.566 damieng 724: # @param {string} $sresid - resource id or map pc
1.565 damieng 725: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 726: # @param {integer} $snum - level
727: # @param {string} $nval - new value
728: # @param {string} $ntype - new type
729: # @param {string} $uname - username
730: # @param {string} $udom - userdomain
731: # @param {string} $csec - section name
732: # @param {string} $cgroup - group name
1.186 www 733: sub storeparm {
1.269 raeburn 734: my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275 raeburn 735: &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197 www 736: }
737:
1.561 damieng 738: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
739:
740: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
741: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
742: #
1.566 damieng 743: # @param {string} $symb - resource symb or map src
1.565 damieng 744: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561 damieng 745: # @param {integer} $snum - level
746: # @param {string} $nval - new value
747: # @param {string} $ntype - new type
748: # @param {string} $uname - username
749: # @param {string} $udom - userdomain
750: # @param {string} $csec - section name
751: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
752: # @param {string} $cgroup - group name
1.197 www 753: sub storeparm_by_symb {
1.275 raeburn 754: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226 www 755: unless ($recflag) {
1.560 damieng 756: # first time call
757: %recstack=();
758: $recflag=1;
1.226 www 759: }
1.560 damieng 760: # store parameter
1.226 www 761: &storeparm_by_symb_inner
1.473 amueller 762: ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560 damieng 763: # don't do anything if parameter was reset
1.266 www 764: unless ($nval) { return; }
1.226 www 765: my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560 damieng 766: # remember that this was set
1.226 www 767: $recstack{$parm}=1;
1.560 damieng 768: # what does this trigger?
1.226 www 769: foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560 damieng 770: # don't backfire
771: unless ((!$triggered) || ($recstack{$triggered})) {
772: my $action=&rulescache($triggered.'_action');
773: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
774: # set triggered parameter on same level
775: my $newspnam=$prefix.$triggered;
776: my $newvalue='';
777: my $active=1;
778: if ($action=~/^when\_setting/) {
779: # are there restrictions?
780: if (&rulescache($triggered.'_triggervalue')=~/\w/) {
781: $active=0;
1.565 damieng 782: foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560 damieng 783: if (lc($possiblevalue) eq lc($nval)) { $active=1; }
784: }
785: }
786: $newvalue=&rulescache($triggered.'_value');
787: } else {
788: my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
789: if ($action=~/^later\_than/) {
790: $newvalue=$nval+$totalsecs;
791: } else {
792: $newvalue=$nval-$totalsecs;
793: }
794: }
795: if ($active) {
796: &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
797: $uname,$udom,$csec,$recflag,$cgroup);
798: }
799: }
1.226 www 800: }
801: return '';
802: }
803:
1.561 damieng 804: # Adds all given arguments to the course parameter log.
805: # @returns {string} - the answer to the lonnet query.
1.293 www 806: sub log_parmset {
1.525 raeburn 807: return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284 www 808: }
809:
1.561 damieng 810: # Store a parameter value and type by symb, without using the parameter default actions.
811: # Expire related sheets.
812: #
1.566 damieng 813: # @param {string} $symb - resource symb or map src
1.561 damieng 814: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
815: # @param {integer} $snum - level
816: # @param {string} $nval - new value
817: # @param {string} $ntype - new type
818: # @param {string} $uname - username
819: # @param {string} $udom - userdomain
820: # @param {string} $csec - section name
821: # @param {string} $cgroup - group name
822: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226 www 823: sub storeparm_by_symb_inner {
1.197 www 824: # ---------------------------------------------------------- Get symb, map, etc
1.269 raeburn 825: my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197 www 826: # ---------------------------------------------------------- Construct prefixes
1.186 www 827: $spnam=~s/\_([^\_]+)$/\.$1/;
1.446 bisitz 828: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305 albertel 829: $map = &Apache::lonnet::deversion($map);
830:
1.197 www 831: my $symbparm=$symb.'.'.$spnam;
1.556 raeburn 832: my $recurseparm=$map.'___(rec).'.$spnam;
1.197 www 833: my $mapparm=$map.'___(all).'.$spnam;
834:
1.269 raeburn 835: my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
836: my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556 raeburn 837: my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269 raeburn 838: my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
839:
1.190 albertel 840: my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
841: my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556 raeburn 842: my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190 albertel 843: my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446 bisitz 844:
1.190 albertel 845: my $courselevel=$env{'request.course.id'}.'.'.$spnam;
846: my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556 raeburn 847: my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190 albertel 848: my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446 bisitz 849:
1.186 www 850: my $storeunder='';
1.578 raeburn 851: my $possreplace='';
1.556 raeburn 852: if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578 raeburn 853: if (($snum==17) || ($snum==3)) {
854: $storeunder=$courseleveli;
855: $possreplace=$courselevelm;
856: }
857: if (($snum==16) || ($snum==2)) {
858: $storeunder=$courselevelm;
859: $possreplace=$courseleveli;
860: }
1.556 raeburn 861: if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
862: if ($snum==12) { $storeunder=$seclevel; }
1.578 raeburn 863: if ($snum==11) {
864: $storeunder=$secleveli;
865: $possreplace=$seclevelm;
866: }
867: if ($snum==10) {
868: $storeunder=$seclevelm;
869: $possreplace=$secleveli;
870: }
1.556 raeburn 871: if ($snum==9) { $storeunder=$seclevelr; }
872: if ($snum==8) { $storeunder=$grplevel; }
1.578 raeburn 873: if ($snum==7) {
874: $storeunder=$grpleveli;
875: $possreplace=$grplevelm;
876: }
877: if ($snum==6) {
878: $storeunder=$grplevelm;
879: $possreplace=$grpleveli;
880: }
1.556 raeburn 881: if ($snum==5) { $storeunder=$grplevelr; }
1.269 raeburn 882:
1.446 bisitz 883:
1.186 www 884: my $delete;
885: if ($nval eq '') { $delete=1;}
886: my %storecontent = ($storeunder => $nval,
1.473 amueller 887: $storeunder.'.type' => $ntype);
1.186 www 888: my $reply='';
1.560 damieng 889:
1.556 raeburn 890: if ($snum>4) {
1.186 www 891: # ---------------------------------------------------------------- Store Course
892: #
1.560 damieng 893: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
894: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
895: # Expire sheets
896: &Apache::lonnet::expirespread('','','studentcalc');
897: if (($snum==13) || ($snum==9) || ($snum==5)) {
898: &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578 raeburn 899: } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560 damieng 900: &Apache::lonnet::expirespread('','','assesscalc',$map);
901: } else {
902: &Apache::lonnet::expirespread('','','assesscalc');
903: }
904: # Store parameter
905: if ($delete) {
906: $reply=&Apache::lonnet::del
907: ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
908: &log_parmset(\%storecontent,1);
909: } else {
910: $reply=&Apache::lonnet::cput
911: ('resourcedata',\%storecontent,$cdom,$cnum);
912: &log_parmset(\%storecontent);
1.578 raeburn 913: if ($possreplace) {
914: my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
915: if (ref($resdata) eq 'HASH') {
916: if (exists($resdata->{$possreplace})) {
917: if (&Apache::lonnet::del
918: ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
919: &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);
920: }
921: }
922: }
923: }
1.560 damieng 924: }
925: &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186 www 926: } else {
927: # ------------------------------------------------------------------ Store User
928: #
1.560 damieng 929: # Expire sheets
930: &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
931: if ($snum==1) {
932: &Apache::lonnet::expirespread
933: ($uname,$udom,'assesscalc',$symb);
1.578 raeburn 934: } elsif (($snum==2) || ($snum==3)) {
1.560 damieng 935: &Apache::lonnet::expirespread
936: ($uname,$udom,'assesscalc',$map);
937: } else {
938: &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
939: }
940: # Store parameter
941: if ($delete) {
942: $reply=&Apache::lonnet::del
943: ('resourcedata',[keys(%storecontent)],$udom,$uname);
944: &log_parmset(\%storecontent,1,$uname,$udom);
945: } else {
946: $reply=&Apache::lonnet::cput
947: ('resourcedata',\%storecontent,$udom,$uname);
948: &log_parmset(\%storecontent,0,$uname,$udom);
1.578 raeburn 949: if ($possreplace) {
950: my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
951: if (ref($resdata) eq 'HASH') {
952: if (exists($resdata->{$possreplace})) {
953: if (&Apache::lonnet::del
954: ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
955: &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
956: $uname,$udom);
957: }
958: }
959: }
960: }
1.560 damieng 961: }
962: &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186 www 963: }
1.446 bisitz 964:
1.186 www 965: if ($reply=~/^error\:(.*)/) {
1.560 damieng 966: return "<span class=\"LC_error\">Write Error: $1</span>";
1.186 www 967: }
968: return '';
969: }
970:
1.9 www 971:
1.561 damieng 972: # Returns HTML with the value of the given parameter,
973: # using a readable format for dates, and
974: # a warning if there is a problem with a date.
975: # Used by table mode.
976: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
977: #
978: # @param {string} $value - the parameter value
979: # @param {string} $type - the parameter type
980: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9 www 981: sub valout {
1.600 raeburn 982: my ($value,$type,$editable)=@_;
1.59 matthew 983: my $result = '';
984: # Values of zero are valid.
985: if (! $value && $value ne '0') {
1.528 bisitz 986: if ($editable) {
987: $result =
988: '<img src="/res/adm/pages/editmap.png"'
989: .' alt="'.&mt('Change').'"'
1.539 raeburn 990: .' title="'.&mt('Change').'" style="border:0;" />';
1.528 bisitz 991: } else {
992: $result=' ';
993: }
1.59 matthew 994: } else {
1.66 www 995: if ($type eq 'date_interval') {
1.559 raeburn 996: my ($totalsecs,$donesuffix) = split(/_/,$value,2);
997: my ($usesdone,$donebuttontext,$proctor,$secretkey);
998: if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
999: $donebuttontext = $1;
1000: (undef,$proctor,$secretkey) = split(/_/,$2);
1001: $usesdone = 'done';
1002: } elsif ($donesuffix =~ /^done(|_.+)$/) {
1003: $donebuttontext = &mt('Done');
1004: ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
1005: }
1.554 raeburn 1006: my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413 bisitz 1007: my @timer;
1.66 www 1008: $year=$year-70;
1009: $mday--;
1010: if ($year) {
1.413 bisitz 1011: # $result.=&mt('[quant,_1,yr]',$year).' ';
1012: push(@timer,&mt('[quant,_1,yr]',$year));
1.66 www 1013: }
1014: if ($mon) {
1.413 bisitz 1015: # $result.=&mt('[quant,_1,mth]',$mon).' ';
1016: push(@timer,&mt('[quant,_1,mth]',$mon));
1.66 www 1017: }
1018: if ($mday) {
1.413 bisitz 1019: # $result.=&mt('[quant,_1,day]',$mday).' ';
1020: push(@timer,&mt('[quant,_1,day]',$mday));
1.66 www 1021: }
1022: if ($hour) {
1.413 bisitz 1023: # $result.=&mt('[quant,_1,hr]',$hour).' ';
1024: push(@timer,&mt('[quant,_1,hr]',$hour));
1.66 www 1025: }
1026: if ($min) {
1.413 bisitz 1027: # $result.=&mt('[quant,_1,min]',$min).' ';
1028: push(@timer,&mt('[quant,_1,min]',$min));
1.66 www 1029: }
1030: if ($sec) {
1.413 bisitz 1031: # $result.=&mt('[quant,_1,sec]',$sec).' ';
1032: push(@timer,&mt('[quant,_1,sec]',$sec));
1.66 www 1033: }
1.413 bisitz 1034: # $result=~s/\s+$//;
1035: if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
1036: push(@timer,&mt('[quant,_1,sec]',0));
1037: }
1038: $result.=join(", ",@timer);
1.559 raeburn 1039: if ($usesdone eq 'done') {
1.558 raeburn 1040: if ($secretkey) {
1.559 raeburn 1041: $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);
1.558 raeburn 1042: } else {
1.559 raeburn 1043: $result .= ' + "'.$donebuttontext.'"';
1044: }
1.554 raeburn 1045: }
1.213 www 1046: } elsif (&isdateparm($type)) {
1.361 albertel 1047: $result = &Apache::lonlocal::locallocaltime($value).
1.560 damieng 1048: &date_sanity_info($value);
1.59 matthew 1049: } else {
1050: $result = $value;
1.517 www 1051: $result=~s/\,/\, /gs;
1.560 damieng 1052: $result = &HTML::Entities::encode($result,'"<>&');
1.59 matthew 1053: }
1054: }
1055: return $result;
1.9 www 1056: }
1057:
1.59 matthew 1058:
1.561 damieng 1059: # Returns HTML containing a link on a parameter value, for table mode.
1060: # The link uses the javascript function 'pjump'.
1061: #
1062: # @param {string} $type - parameter type
1063: # @param {string} $dis - dialog title for editing the parameter value and type
1064: # @param {string} $value - parameter value
1065: # @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.
1066: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
1067: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588 raeburn 1068: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
1069: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5 www 1070: sub plink {
1.588 raeburn 1071: my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23 www 1072: my $winvalue=$value;
1073: unless ($winvalue) {
1.592 raeburn 1074: if (&isdateparm($type) || (&is_specialstring($type))) {
1.190 albertel 1075: $winvalue=$env{'form.recent_'.$type};
1.591 raeburn 1076: } elsif ($type eq 'string_yesno') {
1077: if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
1078: $winvalue=$env{'form.recent_string'};
1079: }
1.23 www 1080: } else {
1.190 albertel 1081: $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23 www 1082: }
1083: }
1.229 www 1084: my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
1085: my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
1086: unless (defined($winvalue)) { $winvalue=$val; }
1.593 raeburn 1087: my $valout = &valout($value,$type,1);
1.429 raeburn 1088: my $unencmarker = $marker;
1.378 albertel 1089: foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588 raeburn 1090: \$hour, \$min, \$sec, \$extra) {
1.560 damieng 1091: $$item = &HTML::Entities::encode($$item,'"<>&');
1092: $$item =~ s/\'/\\\'/g;
1.378 albertel 1093: }
1.429 raeburn 1094: return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473 amueller 1095: '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588 raeburn 1096: .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578 raeburn 1097: $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
1098: &mt('recursive').'</td></tr>' : '').'</table>';
1099:
1.5 www 1100: }
1101:
1.561 damieng 1102: # Javascript for table mode.
1.280 albertel 1103: sub page_js {
1104:
1.81 www 1105: my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88 matthew 1106: my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280 albertel 1107:
1108: return(<<ENDJS);
1109: <script type="text/javascript">
1.454 bisitz 1110: // <![CDATA[
1.44 albertel 1111:
1.88 matthew 1112: $pjump_def
1.44 albertel 1113:
1114: function psub() {
1.591 raeburn 1115: var specstring = /^string_!(yesno|any)/i;
1.44 albertel 1116: if (document.parmform.pres_marker.value!='') {
1117: document.parmform.action+='#'+document.parmform.pres_marker.value;
1118: var typedef=new Array();
1119: typedef=document.parmform.pres_type.value.split('_');
1.562 damieng 1120: if (document.parmform.pres_type.value!='') {
1.589 raeburn 1121: if ((typedef[0]=='date') ||
1.591 raeburn 1122: (specstring.test(document.parmform.pres_type.value))) {
1.562 damieng 1123: eval('document.parmform.recent_'+
1124: document.parmform.pres_type.value+
1125: '.value=document.parmform.pres_value.value;');
1126: } else {
1127: eval('document.parmform.recent_'+typedef[0]+
1128: '.value=document.parmform.pres_value.value;');
1129: }
1.44 albertel 1130: }
1131: document.parmform.submit();
1132: } else {
1133: document.parmform.pres_value.value='';
1134: document.parmform.pres_marker.value='';
1135: }
1136: }
1137:
1.57 albertel 1138: function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
1139: var options = "width=" + w + ",height=" + h + ",";
1140: options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
1141: options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
1142: var newWin = window.open(url, wdwName, options);
1143: newWin.focus();
1144: }
1.523 raeburn 1145:
1.454 bisitz 1146: // ]]>
1.523 raeburn 1147:
1.44 albertel 1148: </script>
1.81 www 1149: $selscript
1.280 albertel 1150: ENDJS
1151:
1152: }
1.507 www 1153:
1.561 damieng 1154: # Javascript to show or hide the map selection (function showHide_courseContent),
1155: # for table and overview modes.
1.523 raeburn 1156: sub showhide_js {
1157: return <<"COURSECONTENTSCRIPT";
1158:
1159: function showHide_courseContent() {
1160: var parmlevValue=document.getElementById("parmlev").value;
1161: if (parmlevValue == 'general') {
1162: document.getElementById('mapmenu').style.display="none";
1163: } else {
1164: if ((parmlevValue == "full") || (parmlevValue == "map")) {
1165: document.getElementById('mapmenu').style.display ="";
1166: } else {
1167: document.getElementById('mapmenu').style.display="none";
1168: }
1169: }
1170: return;
1171: }
1172:
1173: COURSECONTENTSCRIPT
1174: }
1175:
1.561 damieng 1176: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549 raeburn 1177: sub toggleparmtextbox_js {
1178: return <<"ENDSCRIPT";
1179:
1180: if (!document.getElementsByClassName) {
1181: function getElementsByClassName(node, classname) {
1182: var a = [];
1183: var re = new RegExp('(^| )'+classname+'( |$)');
1184: var els = node.getElementsByTagName("*");
1185: for(var i=0,j=els.length; i<j; i++)
1186: if(re.test(els[i].className))a.push(els[i]);
1187: return a;
1188: }
1189: }
1190:
1191: function showHideLenient() {
1192: var lenients;
1193: var setRegExp = /^set_/;
1194: if (document.getElementsByClassName) {
1195: lenients = document.getElementsByClassName('LC_lenient_radio');
1196: } else {
1197: lenients = getElementsByClassName(document.body,'LC_lenient_radio');
1198: }
1199: if (lenients != 'undefined') {
1200: for (var i=0; i<lenients.length; i++) {
1201: if (lenients[i].checked) {
1202: if (lenients[i].value == 'weighted') {
1203: if (setRegExp.test(lenients[i].name)) {
1204: var identifier = lenients[i].name.replace(setRegExp,'');
1205: toggleParmTextbox(document.parmform,identifier);
1206: }
1207: }
1208: }
1209: }
1210: }
1211: return;
1212: }
1213:
1214: function toggleParmTextbox(form,key) {
1215: var divfortext = document.getElementById('LC_parmtext_'+key);
1216: if (divfortext) {
1217: var caller = form.elements['set_'+key];
1218: if (caller.length) {
1219: for (i=0; i<caller.length; i++) {
1220: if (caller[i].checked) {
1221: if (caller[i].value == 'weighted') {
1222: divfortext.style.display = 'inline';
1223: } else {
1224: divfortext.style.display = 'none';
1225: }
1226: }
1227: }
1228: }
1229: }
1230: return;
1231: }
1232:
1233: ENDSCRIPT
1234: }
1235:
1.561 damieng 1236: # Javascript function validateParms, for overview mode
1.549 raeburn 1237: sub validateparms_js {
1238: return <<'ENDSCRIPT';
1239:
1240: function validateParms() {
1241: var textRegExp = /^settext_/;
1242: var tailLenient = /\.lenient$/;
1243: var patternRelWeight = /^\-?[\d.]+$/;
1244: var patternLenientStd = /^(yes|no|default)$/;
1.597 raeburn 1245: var ipRegExp = /^setip/;
1.549 raeburn 1246: var ipallowRegExp = /^setipallow_/;
1247: var ipdenyRegExp = /^setipdeny_/;
1.597 raeburn 1248: var deeplinkRegExp = /^deeplink_/;
1.601 raeburn 1249: var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/;
1250: var dlLinkProtectRegExp = /^deeplink_protect_/;
1251: var dlLtidRegExp = /^deeplink_ltid_/;
1252: var dlLticRegExp = /^deeplink_ltic_/;
1.597 raeburn 1253: var dlKeyRegExp = /^deeplink_key_/;
1254: var dlMenusRegExp = /^deeplink_menus_/;
1255: var dlCollsRegExp = /^deeplink_colls_/;
1.613 raeburn 1256: var dlTargetRegExp = /^deeplink_target_/;
1.616 raeburn 1257: var dlExitRegExp = /^deeplink_exit_/;
1258: var dlExitTextRegExp = /^deeplink_exittext_/;
1.549 raeburn 1259: var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1.616 raeburn 1260: var numelements = document.parmform.elements.length;
1261: if ((typeof(numelements) != 'undefined') && (numelements != null)) {
1262: if (numelements) {
1263: for (i=0; i<numelements; i++) {
1.549 raeburn 1264: var name=document.parmform.elements[i].name;
1.588 raeburn 1265: if (textRegExp.test(name)) {
1.549 raeburn 1266: var identifier = name.replace(textRegExp,'');
1267: if (tailLenient.test(identifier)) {
1268: if (document.parmform.elements['set_'+identifier].length) {
1269: for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
1270: if (document.parmform.elements['set_'+identifier][j].checked) {
1271: if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
1272: var relweight = document.parmform.elements[i].value;
1273: relweight = relweight.replace(/^\s+|\s+$/g,'');
1274: if (!patternRelWeight.test(relweight)) {
1275: relweight = '0.0';
1276: }
1277: if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
1278: document.parmform.elements['set_'+identifier][j].value = relweight;
1279: } else {
1280: document.parmform.elements['set_'+identifier][j].value += ','+relweight;
1281: }
1282: }
1283: break;
1284: }
1285: }
1286: }
1287: }
1.597 raeburn 1288: } else if (ipRegExp.test(name)) {
1289: if (ipallowRegExp.test(name)) {
1290: var identifier = name.replace(ipallowRegExp,'');
1291: var possallow = document.parmform.elements[i].value;
1292: possallow = possallow.replace(/^\s+|\s+$/g,'');
1293: if (patternIP.test(possallow)) {
1294: if (document.parmform.elements['set_'+identifier].value) {
1295: possallow = ','+possallow;
1296: }
1297: document.parmform.elements['set_'+identifier].value += possallow;
1298: }
1299: } else if (ipdenyRegExp.test(name)) {
1300: var identifier = name.replace(ipdenyRegExp,'');
1301: var possdeny = document.parmform.elements[i].value;
1302: possdeny = possdeny.replace(/^\s+|\s+$/g,'');
1303: if (patternIP.test(possdeny)) {
1304: possdeny = '!'+possdeny;
1305: if (document.parmform.elements['set_'+identifier].value) {
1306: possdeny = ','+possdeny;
1307: }
1308: document.parmform.elements['set_'+identifier].value += possdeny;
1.588 raeburn 1309: }
1310: }
1311: } else if (deeplinkRegExp.test(name)) {
1.597 raeburn 1312: if (dlListScopeRegExp.test(name)) {
1313: var identifier = name.replace(dlListScopeRegExp,'');
1314: var idx = document.parmform.elements[i].selectedIndex;
1315: if (idx > 0) {
1316: var possdeeplink = document.parmform.elements[i].options[idx].value
1317: possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
1318: if (document.parmform.elements['set_'+identifier].value) {
1319: possdeeplink = ','+possdeeplink;
1320: }
1321: document.parmform.elements['set_'+identifier].value += possdeeplink;
1322: }
1.601 raeburn 1323: } else if (dlLinkProtectRegExp.test(name)) {
1.597 raeburn 1324: if (document.parmform.elements[i].checked) {
1.601 raeburn 1325: var identifier = name.replace(dlLinkProtectRegExp,'');
1.597 raeburn 1326: var posslinkurl = document.parmform.elements[i].value;
1327: posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
1328: if (document.parmform.elements['set_'+identifier].value) {
1329: posslinkurl = ','+posslinkurl;
1330: }
1331: document.parmform.elements['set_'+identifier].value += posslinkurl;
1332: }
1.601 raeburn 1333: } else if (dlLtidRegExp.test(name)) {
1334: var identifier = name.replace(dlLtidRegExp,'');
1335: if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
1336: var possltid = document.parmform.elements[i].value;
1337: possltid = possltid.replace(/\D+/g,'');
1338: if (possltid.length) {
1.597 raeburn 1339: if (document.parmform.elements['set_'+identifier].value) {
1.601 raeburn 1340: possltid = ':'+possltid;
1.597 raeburn 1341: }
1.601 raeburn 1342: document.parmform.elements['set_'+identifier].value += possltid;
1.597 raeburn 1343: } else {
1344: document.parmform.elements['set_'+identifier].value = '';
1.601 raeburn 1345: 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 1346: return false;
1347: }
1348: }
1.601 raeburn 1349: } else if (dlLticRegExp.test(name)) {
1350: var identifier = name.replace(dlLticRegExp,'');
1351: if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
1352: var possltic = document.parmform.elements[i].value;
1353: possltic = possltic.replace(/\D+/g,'');
1354: if (possltic.length) {
1355: if (document.parmform.elements['set_'+identifier].value) {
1356: possltic = ':'+possltic;
1357: }
1358: document.parmform.elements['set_'+identifier].value += possltic;
1359: } else {
1360: document.parmform.elements['set_'+identifier].value = '';
1361: 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.");
1362: return false;
1363: }
1364: }
1.597 raeburn 1365: } else if (dlKeyRegExp.test(name)) {
1366: var identifier = name.replace(dlKeyRegExp,'');
1.601 raeburn 1367: if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597 raeburn 1368: var posskey = document.parmform.elements[i].value;
1369: posskey = posskey.replace(/^\s+|\s+$/g,'');
1370: var origlength = posskey.length;
1371: posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
1372: var newlength = posskey.length;
1373: if (newlength > 0) {
1374: var change = origlength - newlength;
1375: if (change) {
1376: alert(change+' disallowed character(s) removed from deeplink key');
1377: }
1378: if (document.parmform.elements['set_'+identifier].value) {
1379: posskey = ':'+posskey;
1380: }
1381: document.parmform.elements['set_'+identifier].value += posskey;
1382: } else {
1383: document.parmform.elements['set_'+identifier].value = '';
1384: if (newlength < origlength) {
1385: 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_.!@#$%^&*()+=-");
1386: } else {
1387: alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
1388: }
1389: return false;
1390: }
1391: }
1392: } else if (dlMenusRegExp.test(name)) {
1393: if (document.parmform.elements[i].checked) {
1394: var identifier = name.replace(dlMenusRegExp,'');
1395: var posslinkmenu = document.parmform.elements[i].value;
1396: posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
1397: if (posslinkmenu == 'std') {
1398: posslinkmenu = '0';
1399: if (document.parmform.elements['set_'+identifier].value) {
1400: posslinkmenu = ','+posslinkmenu;
1401: }
1402: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1403: }
1404: }
1405: } else if (dlCollsRegExp.test(name)) {
1406: var identifier = name.replace(dlCollsRegExp,'');
1407: if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
1408: var posslinkmenu = document.parmform.elements[i].value;
1409: if (document.parmform.elements['set_'+identifier].value) {
1410: posslinkmenu = ','+posslinkmenu;
1411: }
1412: document.parmform.elements['set_'+identifier].value += posslinkmenu;
1413: }
1.614 raeburn 1414: } else if (dlTargetRegExp.test(name)) {
1415: var identifier = name.replace(dlTargetRegExp,'');
1.613 raeburn 1416: var idx = document.parmform.elements[i].selectedIndex;
1417: if (idx > 0) {
1.616 raeburn 1418: var linktarget = document.parmform.elements[i].options[idx].value
1419: linktarget = linktarget.replace(/^\s+|\s+$/g,'');
1420: if (document.parmform.elements['set_'+identifier].value) {
1421: linktarget = ','+linktarget;
1422: }
1423: document.parmform.elements['set_'+identifier].value += linktarget;
1424: }
1425: } else if (dlExitRegExp.test(name)) {
1426: if (document.parmform.elements[i].checked) {
1427: var identifier = name.replace(dlExitRegExp,'');
1428: var posslinkexit = document.parmform.elements[i].value;
1429: posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');
1.613 raeburn 1430: if (document.parmform.elements['set_'+identifier].value) {
1.616 raeburn 1431: posslinkexit = ','+posslinkexit;
1432: }
1433: document.parmform.elements['set_'+identifier].value += posslinkexit;
1434: }
1435: } else if (dlExitTextRegExp.test(name)) {
1436: var identifier = name.replace(dlExitTextRegExp,'');
1437: if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
1438: (isRadioSet('deeplink_exit_'+identifier,'url'))) {
1439: var posstext = document.parmform.elements[i].value;
1440: posstext = posstext.replace(/^\s+|\s+$/g,'');
1441: var origlength = posstext.length;
1442: posstext = posstext.replace(/[:;'",]/g,'');
1443: var newlength = posstext.length;
1444: if (newlength > 0) {
1445: var change = origlength - newlength;
1446: if (change) {
1447: alert(change+' disallowed character(s) removed from Exit Button text');
1448: }
1449: if (posstext !== 'Exit Tool') {
1450: posstext = ':'+posstext;
1451: document.parmform.elements['set_'+identifier].value += posstext;
1452: }
1453: } else {
1454: document.parmform.elements['set_'+identifier].value = '';
1455: if (newlength < origlength) {
1456: alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");
1457: } else {
1458: alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");
1459: }
1460: return false;
1.613 raeburn 1461: }
1462: }
1.549 raeburn 1463: }
1464: }
1465: }
1466: }
1467: }
1468: return true;
1469: }
1470:
1.597 raeburn 1471: function isRadioSet(name,expected) {
1472: var menuitems = document.getElementsByName(name);
1473: var radioLength = menuitems.length;
1474: result = false;
1475: if (radioLength > 1) {
1476: for (var j=0; j<radioLength; j++) {
1477: if (menuitems[j].checked) {
1478: if (menuitems[j].value == expected) {
1479: result = true;
1480: break;
1481: }
1482: }
1483: }
1484: }
1485: return result;
1486: }
1487:
1.549 raeburn 1488: ENDSCRIPT
1489: }
1490:
1.561 damieng 1491: # Javascript initialization, for overview mode
1.549 raeburn 1492: sub ipacc_boxes_js {
1493: my $remove = &mt('Remove');
1494: return <<"END";
1495: \$(document).ready(function() {
1496: var wrapper = \$(".LC_string_ipacc_wrap");
1497: var add_button = \$(".LC_add_ipacc_button");
1498: var ipaccRegExp = /^LC_string_ipacc_/;
1499:
1500: \$(add_button).click(function(e){
1501: e.preventDefault();
1502: var identifier = \$(this).closest("div").attr("id");
1503: identifier = identifier.replace(ipaccRegExp,'');
1.551 raeburn 1504: \$(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 1505: });
1506:
1507: \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
1508: e.preventDefault(); \$(this).closest("div").remove();
1509: })
1510: });
1511:
1512:
1513: END
1514: }
1515:
1.561 damieng 1516: # Javascript function toggleSecret, for overview mode.
1.558 raeburn 1517: sub done_proctor_js {
1.611 raeburn 1518: my $defaultdone = &mt('Done');
1519: &js_escape(\$defaultdone);
1.558 raeburn 1520: return <<"END";
1521: function toggleSecret(form,radio,key) {
1522: var radios = form[radio+key];
1523: if (radios.length) {
1524: for (var i=0; i<radios.length; i++) {
1525: if (radios[i].checked) {
1526: if (radios[i].value == '_done_proctor') {
1527: if (document.getElementById('done_'+key+'_proctorkey')) {
1528: document.getElementById('done_'+key+'_proctorkey').type='text';
1529: }
1530: } else {
1531: if (document.getElementById('done_'+key+'_proctorkey')) {
1532: document.getElementById('done_'+key+'_proctorkey').type='hidden';
1533: document.getElementById('done_'+key+'_proctorkey').value='';
1534: }
1535: }
1.611 raeburn 1536: if (document.getElementById('done_'+key+'_buttontext')) {
1537: if (radios[i].value == '') {
1538: document.getElementById('done_'+key+'_buttontext').value = '';
1539: } else {
1540: if (document.getElementById('done_'+key+'_buttontext').value == '') {
1541: document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
1542: }
1543: }
1544: }
1.558 raeburn 1545: }
1546: }
1547: }
1548: }
1549: END
1550:
1551: }
1552:
1.588 raeburn 1553: # Javascript function toggle
1554: sub deeplink_js {
1555: return <<"END";
1556: function toggleDeepLink(form,item,key) {
1557: var radios = form['deeplink_'+item+'_'+key];
1558: if (radios.length) {
1559: var keybox;
1560: if (document.getElementById('deeplink_key_'+item+'_'+key)) {
1561: keybox = document.getElementById('deeplink_key_'+item+'_'+key);
1562: }
1.601 raeburn 1563: var divoptions = new Array();
1564: if (item == 'protect') {
1565: divoptions = ['ltic','ltid'];
1.597 raeburn 1566: } else {
1567: if (item == 'menus') {
1.601 raeburn 1568: divoptions = ['colls'];
1.597 raeburn 1569: }
1570: }
1.601 raeburn 1571: var seldivs = new Array();
1572: if ((item == 'protect') || (item == 'menus')) {
1573: for (var i=0; i<divoptions.length; i++) {
1574: if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
1575: seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
1576: } else {
1577: seldivs[i] = '';
1578: }
1579: }
1.588 raeburn 1580: }
1581: for (var i=0; i<radios.length; i++) {
1582: if (radios[i].checked) {
1.601 raeburn 1583: if ((item == 'protect') || (item == 'menus')) {
1584: for (var j=0; j<seldivs.length; j++) {
1585: if (radios[i].value == divoptions[j]) {
1586: if (seldivs[j] != '') {
1587: seldivs[j].style.display = 'inline-block';
1588: }
1589: if (item == 'protect') {
1590: keybox.type = 'hidden';
1591: keybox.value = '';
1592: }
1593: } else {
1594: if (seldivs[j] != '') {
1595: seldivs[j].style.display = 'none';
1596: form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
1597: }
1598: }
1.597 raeburn 1599: }
1.601 raeburn 1600: if (item == 'protect') {
1.597 raeburn 1601: if (radios[i].value == 'key') {
1602: keybox.type = 'text';
1603: } else {
1604: keybox.type = 'hidden';
1605: }
1.588 raeburn 1606: }
1.616 raeburn 1607: } else if (item == 'exit') {
1608: if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
1609: if (radios[i].value == 'no') {
1610: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';
1611: if (document.getElementById('deeplink_exittext_'+key)) {
1612: if (document.getElementById('deeplink_exittext_'+key).value != '') {
1613: document.getElementById('deeplink_exittext_'+key).value = '';
1614: }
1615: }
1616: } else {
1617: document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
1618: if (document.getElementById('deeplink_exittext_'+key)) {
1619: if (document.getElementById('deeplink_exittext_'+key).value == '') {
1620: document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
1621: }
1622: }
1623: }
1624: }
1.588 raeburn 1625: }
1626: }
1627: }
1628: }
1629: }
1630: END
1631:
1632: }
1633:
1.561 damieng 1634: # Prints HTML page start for table mode.
1635: # @param {Apache2::RequestRec} $r - the Apache request
1636: # @param {string} $psymb - resource symb
1637: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280 albertel 1638: sub startpage {
1.531 raeburn 1639: my ($r,$psymb,$crstype) = @_;
1.281 albertel 1640:
1.515 raeburn 1641: my %loaditems = (
1642: 'onload' => "group_or_section('cgroup')",
1643: );
1644: if (!$psymb) {
1.523 raeburn 1645: $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515 raeburn 1646: }
1.280 albertel 1647:
1.560 damieng 1648: if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
1649: (!$env{'form.dis'})) || ($env{'form.symb'})) {
1650: &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
1651: text=>"Problem Parameters"});
1.414 droeschl 1652: } else {
1.560 damieng 1653: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1654: text=>"Table Mode",
1655: help => 'Course_Setting_Parameters'});
1.414 droeschl 1656: }
1.523 raeburn 1657: my $js = &page_js().'
1658: <script type="text/javascript">
1659: // <![CDATA[
1660: '.
1661: &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
1662: // ]]>
1663: </script>
1664: ';
1.446 bisitz 1665: my $start_page =
1.523 raeburn 1666: &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
1667: {'add_entries' => \%loaditems,});
1.446 bisitz 1668: my $breadcrumbs =
1.473 amueller 1669: &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506 www 1670: my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
1671: my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507 www 1672: $r->print($start_page.$breadcrumbs);
1.531 raeburn 1673: &startSettingsScreen($r,'parmset',$crstype);
1.280 albertel 1674: $r->print(<<ENDHEAD);
1.193 albertel 1675: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419 bisitz 1676: <input type="hidden" value="" name="pres_value" />
1677: <input type="hidden" value="" name="pres_type" />
1678: <input type="hidden" value="" name="pres_marker" />
1679: <input type="hidden" value="1" name="prevvisit" />
1.506 www 1680: <input type="hidden" value="$escfilter" name="filter" />
1681: <input type="hidden" value="$escpart" name="part" />
1.44 albertel 1682: ENDHEAD
1683: }
1684:
1.209 www 1685:
1.561 damieng 1686: # Prints a row for table mode (except for the tr start).
1687: # Every time a hash reference is passed, a single entry is used, so print_row
1688: # could just use these values, but why make it simple when it can be complicated ?
1689: #
1690: # @param {Apache2::RequestRec} $r - the Apache request
1691: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
1692: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
1693: # @param {hash reference} $name - parameter key -> parameter name
1.566 damieng 1694: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561 damieng 1695: # @param {string} $rid - resource id
1696: # @param {hash reference} $default - parameter key -> resource parameter default value
1697: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
1698: # @param {hash reference} $display - parameter key -> full title for the parameter
1699: # @param {string} $defbgone - user level and other levels background color
1700: # @param {string} $defbgtwo - section level background color, also used for part number
1701: # @param {string} $defbgthree - group level background color
1702: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1703: # @param {string} $uname - user name
1704: # @param {string} $udom - user domain
1705: # @param {string} $csec - section name
1706: # @param {string} $cgroup - group name
1707: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
1708: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582 raeburn 1709: # @param {boolean} $readonly - true if no editing allowed.
1710: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
1711: # @param {hash reference} - $maptitles - - hash map id or src -> map title
1712: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
1713: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set
1.44 albertel 1714: sub print_row {
1.201 www 1715: my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568 raeburn 1716: $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582 raeburn 1717: $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275 raeburn 1718: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1719: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1720: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582 raeburn 1721: my $numlinks = 0;
1.553 raeburn 1722:
1.560 damieng 1723: # get the values for the parameter in cascading order
1724: # empty levels will remain empty
1.44 albertel 1725: my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473 amueller 1726: $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1727: # get the type for the parameters
1728: # problem: these may not be set for all levels
1.66 www 1729: my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275 raeburn 1730: $$name{$which}.'.type',$rid,
1.473 amueller 1731: $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560 damieng 1732: # cascade down manually
1.182 albertel 1733: my $cascadetype=$$defaulttype{$which};
1.556 raeburn 1734: for (my $i=18;$i>0;$i--) {
1.560 damieng 1735: if ($typeoutpar[$i]) {
1.66 www 1736: $cascadetype=$typeoutpar[$i];
1.560 damieng 1737: } else {
1.66 www 1738: $typeoutpar[$i]=$cascadetype;
1739: }
1740: }
1.57 albertel 1741: my $parm=$$display{$which};
1742:
1.203 www 1743: if ($parmlev eq 'full') {
1.419 bisitz 1744: $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506 www 1745: .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433 raeburn 1746: } else {
1.57 albertel 1747: $parm=~s|\[.*\]\s||g;
1748: }
1.231 www 1749: my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
1750: if ($automatic) {
1.560 damieng 1751: $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231 www 1752: }
1.619 ! raeburn 1753: my $advice;
! 1754: if ((ref($name) eq 'HASH') && ($name->{$which} eq 'mapalias') &&
! 1755: (ref($symbp) eq 'HASH') && ($parmlev eq 'full')) {
! 1756: if ($symbp->{$rid} =~ m{^uploaded/}) {
! 1757: if ($result == 14) {
! 1758: $advice = &mt('Use Course Editor to modify this.');
! 1759: } else {
! 1760: $advice = &mt('Use Course Editor to set this.');
! 1761: }
! 1762: } else {
! 1763: if ($result == 14) {
! 1764: $advice = &mt('Use Resource Assembly Tool to modify this.');
! 1765: } else {
! 1766: $advice = &mt('Use Resource Assembly Tool to set this.');
! 1767: }
! 1768: }
! 1769: $parm .= '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
! 1770: }
1.427 bisitz 1771: $r->print('<td>'.$parm.'</td>');
1.446 bisitz 1772:
1.44 albertel 1773: my $thismarker=$which;
1774: $thismarker=~s/^parameter\_//;
1775: my $mprefix=$rid.'&'.$thismarker.'&';
1.582 raeburn 1776: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1777: my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588 raeburn 1778: $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582 raeburn 1779: if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
1780: if ($result eq '') {
1781: $recurse_check = 1;
1782: } elsif (($uname ne '') && ($result > 3)) {
1783: $recurse_check = 1;
1784: } elsif (($cgroup ne '') && ($result > 7)) {
1785: $recurse_check = 1;
1786: } elsif (($csec ne '') && ($result > 11)) {
1787: $recurse_check = 1;
1788: } elsif ($result > 17) {
1789: $recurse_check = 1;
1790: }
1791: if ($recurse_check) {
1792: my $what = $$part{$which}.'.'.$$name{$which};
1793: my $prefix;
1794: if (($uname ne '') && ($udom ne '')) {
1795: my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1796: $prefix = $env{'request.course.id'};
1797: $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
1798: if (ref($recursinfo) eq 'ARRAY') {
1799: $effparm_rec = 1;
1800: $effparm_level = &mt('user: [_1]',$uname);
1801: }
1802: }
1803: if (($cgroup ne '') && (!$effparm_rec)) {
1804: $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
1805: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1806: if (ref($recursinfo) eq 'ARRAY') {
1807: $effparm_rec = 1;
1808: $effparm_level = &mt('group: [_1]',$cgroup);
1809: }
1810: }
1811: if (($csec ne '') && (!$effparm_rec)) {
1812: $prefix = $env{'request.course.id'}.'.['.$csec.']';
1813: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1814: if (ref($recursinfo) eq 'ARRAY') {
1815: $effparm_rec = 1;
1816: $effparm_level = &mt('section: [_1]',$csec);
1817: }
1818: }
1819: if (!$effparm_rec) {
1820: $prefix = $env{'request.course.id'};
1821: $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
1822: if (ref($recursinfo) eq 'ARRAY') {
1823: $effparm_rec = 1;
1824: }
1825: }
1826: }
1827: }
1828: if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
1829: $effparm_rec = 1;
1830: }
1831: if ((!$effparm_rec) &&
1832: (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) &&
1833: ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578 raeburn 1834: $effparm_rec = 1;
1835: }
1.588 raeburn 1836: if ($parmname eq 'deeplink') {
1.601 raeburn 1837: my ($domltistr,$crsltistr);
1.588 raeburn 1838: my %lti =
1839: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 1840: 'linkprot');
1.601 raeburn 1841: if (keys(%lti)) {
1842: foreach my $item (sort { $a <=> $b } (keys(%lti))) {
1.604 raeburn 1843: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
1844: $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588 raeburn 1845: }
1846: }
1.601 raeburn 1847: $domltistr =~ s/,$//;
1848: if ($domltistr) {
1849: $extra = 'ltid_'.$domltistr;
1850: }
1.588 raeburn 1851: }
1.601 raeburn 1852: my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
1853: if (keys(%courselti)) {
1854: foreach my $item (sort { $a <=> $b } keys(%courselti)) {
1855: if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
1856: $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
1857: }
1858: }
1859: $crsltistr =~ s/,$//;
1860: if ($crsltistr) {
1861: if ($extra) {
1862: $extra .= '&';
1863: }
1864: $extra .= 'ltic_'.$crsltistr;
1.588 raeburn 1865: }
1866: }
1.597 raeburn 1867: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
1868: my @colls;
1869: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
1870: my ($num,$value) = split(/\%/,$item);
1871: if ($num =~ /^\d+$/) {
1872: push(@colls,$num);
1873: }
1874: }
1875: if (@colls) {
1876: if ($extra) {
1877: $extra .= '&';
1878: }
1879: $extra .= 'menus_'.join(',',@colls);
1880: }
1881: }
1.588 raeburn 1882: }
1.57 albertel 1883: if ($parmlev eq 'general') {
1884: if ($uname) {
1.588 raeburn 1885: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269 raeburn 1886: } elsif ($cgroup) {
1.588 raeburn 1887: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57 albertel 1888: } elsif ($csec) {
1.588 raeburn 1889: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1890: } else {
1.588 raeburn 1891: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57 albertel 1892: }
1893: } elsif ($parmlev eq 'map') {
1894: if ($uname) {
1.588 raeburn 1895: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269 raeburn 1896: } elsif ($cgroup) {
1.588 raeburn 1897: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57 albertel 1898: } elsif ($csec) {
1.588 raeburn 1899: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1900: } else {
1.588 raeburn 1901: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57 albertel 1902: }
1903: } else {
1.275 raeburn 1904: if ($uname) {
1905: if (@{$usersgroups} > 1) {
1.582 raeburn 1906: (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580 raeburn 1907: &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275 raeburn 1908: $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582 raeburn 1909: if (($coursereply) && ($result > 4)) {
1.275 raeburn 1910: if (defined($controlgrp)) {
1911: if ($cgroup ne $controlgrp) {
1.582 raeburn 1912: $eff_groupparm = $grp_parm;
1913: undef($result);
1914: undef($effparm_rec);
1915: if ($grp_is_rec) {
1916: $effparm_rec = 1;
1917: }
1.275 raeburn 1918: }
1919: }
1920: }
1921: }
1922: }
1.57 albertel 1923:
1.588 raeburn 1924: &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1925: &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1926: &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1927: &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1928: &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1929:
1930: if ($csec) {
1.588 raeburn 1931: &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1932: &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1933: &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1934: }
1.269 raeburn 1935:
1936: if ($cgroup) {
1.588 raeburn 1937: &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1938: &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1939: &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269 raeburn 1940: }
1.446 bisitz 1941:
1.548 raeburn 1942: if ($uname) {
1.275 raeburn 1943: if ($othergrp) {
1944: $r->print($othergrp);
1945: }
1.588 raeburn 1946: &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1947: &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1948: &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548 raeburn 1949: }
1.57 albertel 1950: } # end of $parmlev if/else
1.582 raeburn 1951: if (ref($recursinfo) eq 'ARRAY') {
1952: my $rectitle = &mt('recursive');
1953: if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
1954: if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
1955: $rectitle = &mt('set in: [_1]','"'.
1956: '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
1957: "'$parmname','$$part{$which}'".');">'.
1958: $maptitles->{$recursinfo->[2]}.'</a>"');
1959:
1960: $numlinks ++;
1961: }
1962: }
1963: my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593 raeburn 1964: $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582 raeburn 1965: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1966: '<br /><span class="LC_parm_recursive">'.$rectitle.' '.
1967: $effparm_level.'</span></td>');
1968: } else {
1969: if ($result) {
1.593 raeburn 1970: $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582 raeburn 1971: }
1972: if ($eff_groupparm) {
1973: $effective_parm = $eff_groupparm;
1974: }
1975: $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
1976: ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
1977: '</span>':'').'</td>');
1978: }
1.203 www 1979: if ($parmlev eq 'full') {
1.136 albertel 1980: my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201 www 1981: '.'.$$name{$which},$$symbp{$rid});
1.136 albertel 1982: my $sessionvaltype=$typeoutpar[$result];
1.560 damieng 1983: if (!defined($sessionvaltype)) {
1984: $sessionvaltype=$$defaulttype{$which};
1985: }
1.419 bisitz 1986: $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593 raeburn 1987: &valout($sessionval,$sessionvaltype).' '.
1.57 albertel 1988: '</font></td>');
1.136 albertel 1989: }
1.44 albertel 1990: $r->print('</tr>');
1.57 albertel 1991: $r->print("\n");
1.582 raeburn 1992: if (($numlinks) && (ref($reclinks))) {
1993: $$reclinks = $numlinks;
1994: }
1.44 albertel 1995: }
1.59 matthew 1996:
1.561 damieng 1997: # Prints a cell for table mode.
1998: #
1999: # FIXME: some of these parameter names are uninspired ($which and $value)
2000: # Also, it would make more sense to pass the display for this cell rather
2001: # than the full display hash and the key to use.
2002: #
2003: # @param {Apache2::RequestRec} $r - the Apache request
2004: # @param {integer} $which - level
2005: # @param {string} $defbg - cell background color
2006: # @param {integer} $result - the most specific level that is defined for that parameter
2007: # @param {array reference} $outpar - array level -> parameter value (when defined)
2008: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
2009: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
2010: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
2011: # @param {hash reference} $display - parameter key -> full title for the parameter
2012: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568 raeburn 2013: # @param {boolean} $readonly -true if editing not allowed.
1.588 raeburn 2014: # @param {boolean} $ismaplevel - true if level is for a map.
1.597 raeburn 2015: # @param {string} $extra - extra information to pass to plink.
1.44 albertel 2016: sub print_td {
1.578 raeburn 2017: my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588 raeburn 2018: $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578 raeburn 2019: my ($ineffect,$recursive,$currval,$currtype,$currlevel);
2020: $ineffect = 0;
2021: $currval = $$outpar[$which];
2022: $currtype = $$typeoutpar[$which];
2023: $currlevel = $which;
2024: if (($result) && ($result == $which)) {
2025: $ineffect = 1;
2026: }
2027: if ($ismaplevel) {
2028: if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
2029: if (($result) && ($result == $which)) {
2030: $recursive = 1;
2031: }
2032: } elsif ($$outpar[$which+1] ne '') {
2033: $recursive = 1;
2034: $currlevel = $which+1;
2035: $currval = $$outpar[$currlevel];
2036: $currtype = $$typeoutpar[$currlevel];
2037: if (($result) && ($result == $currlevel)) {
2038: $ineffect = 1;
2039: }
2040: }
2041: }
2042: $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419 bisitz 2043: ';" align="center">');
1.437 raeburn 2044: my $nolink = 0;
1.568 raeburn 2045: if ($readonly) {
1.552 raeburn 2046: $nolink = 1;
1.568 raeburn 2047: } else {
1.578 raeburn 2048: if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553 raeburn 2049: $nolink = 1;
1.568 raeburn 2050: } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533 raeburn 2051: $nolink = 1;
1.568 raeburn 2052: } elsif ($which == 5 || $which == 6 || $which == 7 || $which == 8) {
2053: if ($noeditgrp) {
2054: $nolink = 1;
2055: }
2056: } elsif ($mprefix =~ /availablestudent\&$/) {
1.599 raeburn 2057: $nolink = 1;
1.568 raeburn 2058: } elsif ($mprefix =~ /examcode\&$/) {
2059: unless ($which == 2) {
2060: $nolink = 1;
2061: }
1.533 raeburn 2062: }
1.437 raeburn 2063: }
2064: if ($nolink) {
1.577 raeburn 2065: my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593 raeburn 2066: $r->print(&valout($currval,$currtype));
1.114 www 2067: } else {
1.578 raeburn 2068: $r->print(&plink($currtype,
2069: $$display{$value},$currval,
1.588 raeburn 2070: $mprefix.$currlevel,'parmform.pres','psub',$recursive,
2071: $extra));
1.114 www 2072: }
2073: $r->print('</td>'."\n");
1.57 albertel 2074: }
2075:
1.561 damieng 2076: # Returns HTML and other info for the cell added when a user is selected
2077: # and that user is in several groups. This is the cell with the title "Control by other group".
2078: #
2079: # @param {string} $what - parameter part.'.'.parameter name
2080: # @param {string} $rid - resource id
2081: # @param {string} $cgroup - group name
2082: # @param {string} $defbg - cell background color
2083: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2084: # @param {integer} $result - level
2085: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582 raeburn 2086: # @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 2087: sub check_other_groups {
2088: my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275 raeburn 2089: my $courseid = $env{'request.course.id'};
2090: my $output;
2091: my $symb = &symbcache($rid);
2092: my $symbparm=$symb.'.'.$what;
2093: my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556 raeburn 2094: my $recurseparm=$map.'___(rec).'.$what;
1.275 raeburn 2095: my $mapparm=$map.'___(all).'.$what;
2096: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556 raeburn 2097: &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
2098: $recurseparm,$what,$courseopt);
1.275 raeburn 2099: my $bgcolor = $defbg;
1.582 raeburn 2100: my ($grp_parm,$grp_is_rec);
1.446 bisitz 2101: if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582 raeburn 2102: my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275 raeburn 2103: if ($result > 3) {
1.419 bisitz 2104: $bgcolor = '#AAFFAA';
1.275 raeburn 2105: }
1.593 raeburn 2106: $grp_parm = &valout($coursereply,$resulttype);
1.419 bisitz 2107: $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275 raeburn 2108: if ($resultgroup && $resultlevel) {
1.582 raeburn 2109: if ($resultlevel eq 'recursive') {
2110: $resultlevel = 'map/folder';
2111: $grp_is_rec = 1;
2112: }
2113: $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
2114: ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
2115:
1.275 raeburn 2116: } else {
2117: $output .= ' ';
2118: }
2119: $output .= '</td>';
2120: } else {
1.419 bisitz 2121: $output .= '<td style="background-color:'.$bgcolor.';"> </td>';
1.275 raeburn 2122: }
1.582 raeburn 2123: return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275 raeburn 2124: }
2125:
1.561 damieng 2126: # Looks for a group with a defined parameter for given user and parameter.
1.580 raeburn 2127: # Used by check_other_groups.
1.561 damieng 2128: #
2129: # @param {string} $courseid - the course id
2130: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2131: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
2132: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
2133: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
2134: # @param {string} $what - parameter part.'.'.parameter name
2135: # @param {hash reference} $courseopt - course parameters hash
2136: # @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 2137: sub parm_control_group {
1.556 raeburn 2138: my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275 raeburn 2139: my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2140: my $grpfound = 0;
1.556 raeburn 2141: my @levels = ($symbparm,$mapparm,$recurseparm,$what);
2142: my @levelnames = ('resource','map/folder','recursive','general');
1.275 raeburn 2143: foreach my $group (@{$usersgroups}) {
2144: if ($grpfound) { last; }
2145: for (my $i=0; $i<@levels; $i++) {
2146: my $item = $courseid.'.['.$group.'].'.$levels[$i];
2147: if (defined($$courseopt{$item})) {
2148: $coursereply = $$courseopt{$item};
2149: $resultitem = $item;
2150: $resultgroup = $group;
2151: $resultlevel = $levelnames[$i];
2152: $resulttype = $$courseopt{$item.'.type'};
2153: $grpfound = 1;
2154: last;
2155: }
2156: }
2157: }
2158: return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
2159: }
1.201 www 2160:
1.63 bowersj2 2161:
2162:
1.562 damieng 2163: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
2164: # All the parameters are references and are filled by the sub.
2165: #
1.566 damieng 2166: # @param {array reference} $ids - resource and map ids
2167: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
2168: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562 damieng 2169: # @param {hash reference} $allparms - hash parameter name -> parameter title
2170: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566 damieng 2171: # @param {hash reference} $allmaps - hash map pc -> map src
2172: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
2173: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
2174: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
2175: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562 damieng 2176: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
2177: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608 raeburn 2178: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63 bowersj2 2179: sub extractResourceInformation {
2180: my $ids = shift;
2181: my $typep = shift;
2182: my $keyp = shift;
2183: my $allparms = shift;
2184: my $allparts = shift;
2185: my $allmaps = shift;
2186: my $mapp = shift;
2187: my $symbp = shift;
1.82 www 2188: my $maptitles=shift;
1.196 www 2189: my $uris=shift;
1.210 www 2190: my $keyorder=shift;
1.211 www 2191: my $defkeytype=shift;
1.603 raeburn 2192: my $pssymb=shift;
1.196 www 2193:
1.210 www 2194: my $keyordercnt=100;
1.63 bowersj2 2195:
1.196 www 2196: my $navmap = Apache::lonnavmaps::navmap->new();
1.603 raeburn 2197: return unless(ref($navmap));
2198: my @allres;
2199: if ($pssymb ne '') {
2200: my $res = $navmap->getBySymb($pssymb);
2201: if (ref($res)) {
2202: @allres = ($res);
2203: }
2204: }
2205: if (!@allres) {
2206: @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
2207: }
1.196 www 2208: foreach my $resource (@allres) {
1.480 amueller 2209: my $id=$resource->id();
1.196 www 2210: my ($mapid,$resid)=split(/\./,$id);
1.480 amueller 2211: if ($mapid eq '0') { next; }
2212: $$ids[$#$ids+1]=$id;
2213: my $srcf=$resource->src();
2214: $srcf=~/\.(\w+)$/;
2215: $$typep{$id}=$1;
1.584 raeburn 2216: my $toolsymb;
2217: if ($srcf =~ /ext\.tool$/) {
2218: $toolsymb = $resource->symb();
2219: }
1.480 amueller 2220: $$keyp{$id}='';
1.196 www 2221: $$uris{$id}=$srcf;
1.512 foxr 2222:
1.584 raeburn 2223: foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480 amueller 2224: next if ($key!~/^parameter_/);
1.363 albertel 2225:
1.209 www 2226: # Hidden parameters
1.584 raeburn 2227: next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209 www 2228: #
2229: # allparms is a hash of parameter names
2230: #
1.584 raeburn 2231: my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480 amueller 2232: if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
2233: my ($display,$parmdis);
2234: $display = &standard_parameter_names($name);
2235: if ($display eq '') {
1.584 raeburn 2236: $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480 amueller 2237: $parmdis = $display;
2238: $parmdis =~ s/\s*\[Part.*$//g;
2239: } else {
2240: $parmdis = &mt($display);
2241: }
2242: $$allparms{$name}=$parmdis;
2243: if (ref($defkeytype)) {
2244: $$defkeytype{$name}=
1.584 raeburn 2245: &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480 amueller 2246: }
2247: }
1.363 albertel 2248:
1.209 www 2249: #
2250: # allparts is a hash of all parts
2251: #
1.584 raeburn 2252: my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480 amueller 2253: $$allparts{$part} = &mt('Part: [_1]',$part);
1.209 www 2254: #
2255: # Remember all keys going with this resource
2256: #
1.480 amueller 2257: if ($$keyp{$id}) {
2258: $$keyp{$id}.=','.$key;
2259: } else {
2260: $$keyp{$id}=$key;
2261: }
1.210 www 2262: #
2263: # Put in order
1.446 bisitz 2264: #
1.480 amueller 2265: unless ($$keyorder{$key}) {
2266: $$keyorder{$key}=$keyordercnt;
2267: $keyordercnt++;
2268: }
1.473 amueller 2269: }
2270:
2271:
1.480 amueller 2272: if (!exists($$mapp{$mapid})) {
2273: $$mapp{$id}=
2274: &Apache::lonnet::declutter($resource->enclosing_map_src());
2275: $$mapp{$mapid}=$$mapp{$id};
2276: $$allmaps{$mapid}=$$mapp{$id};
2277: if ($mapid eq '1') {
1.532 raeburn 2278: $$maptitles{$mapid}=&mt('Main Content');
1.480 amueller 2279: } else {
2280: $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
2281: }
2282: $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556 raeburn 2283: $$symbp{$mapid}=$$mapp{$id}.'___(all)'; # Added in rev. 1.57, but seems not to be used.
2284: # Lines 1038 and 1114 which use $symbp{$mapid}
2285: # are commented out in rev. 1.57
1.473 amueller 2286: } else {
1.480 amueller 2287: $$mapp{$id} = $$mapp{$mapid};
1.473 amueller 2288: }
1.480 amueller 2289: $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63 bowersj2 2290: }
2291: }
2292:
1.582 raeburn 2293: sub get_recursive {
2294: my ($recurseup,$resdata,$what,$prefix) = @_;
2295: if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
2296: foreach my $item (@{$recurseup}) {
2297: my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
2298: if (defined($resdata->{$norecursechk})) {
2299: if ($what =~ /\.(encrypturl|hiddenresource)$/) {
2300: my $type = $resdata->{$norecursechk.'.type'};
2301: return [$resdata->{$norecursechk},$type,$item];
2302: } else {
2303: last;
2304: }
2305: }
2306: my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
2307: if (defined($resdata->{$recursechk})) {
2308: my $type = $resdata->{$recursechk.'.type'};
2309: return [$resdata->{$recursechk},$type,$item];
2310: }
2311: }
2312: }
2313: return;
2314: }
2315:
1.208 www 2316:
1.562 damieng 2317: # Tells if a parameter type is a date.
2318: #
2319: # @param {string} type - parameter type
2320: # @returns{boolean} - true if it is a date
1.213 www 2321: sub isdateparm {
2322: my $type=shift;
2323: return (($type=~/^date/) && (!($type eq 'date_interval')));
2324: }
2325:
1.589 raeburn 2326: # Determine if parameter type is specialized string type (i.e.,
2327: # not just string or string_yesno.
2328:
2329: sub is_specialstring {
2330: my $type=shift;
1.603 raeburn 2331: return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589 raeburn 2332: }
2333:
1.562 damieng 2334: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468 amueller 2335: #
1.581 raeburn 2336: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 2337: sub parmmenu {
1.581 raeburn 2338: my ($r)=@_;
1.208 www 2339: $r->print(<<ENDSCRIPT);
2340: <script type="text/javascript">
1.454 bisitz 2341: // <![CDATA[
1.208 www 2342: function checkall(value, checkName) {
1.453 schualex 2343:
2344: var li = "_li";
2345: var displayOverview = "";
2346:
2347: if (value == false) {
2348: displayOverview = "none"
2349: }
2350:
1.562 damieng 2351: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208 www 2352: ele = document.forms.parmform.elements[i];
2353: if (ele.name == checkName) {
2354: document.forms.parmform.elements[i].checked=value;
2355: }
2356: }
2357: }
1.210 www 2358:
2359: function checkthis(thisvalue, checkName) {
1.562 damieng 2360: for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210 www 2361: ele = document.forms.parmform.elements[i];
2362: if (ele.name == checkName) {
1.562 damieng 2363: if (ele.value == thisvalue) {
2364: document.forms.parmform.elements[i].checked=true;
2365: }
1.210 www 2366: }
2367: }
2368: }
2369:
2370: function checkdates() {
1.562 damieng 2371: checkthis('duedate','pscat');
2372: checkthis('opendate','pscat');
2373: checkthis('answerdate','pscat');
1.218 www 2374: }
2375:
2376: function checkdisset() {
1.562 damieng 2377: checkthis('discussend','pscat');
2378: checkthis('discusshide','pscat');
2379: checkthis('discussvote','pscat');
1.218 www 2380: }
2381:
2382: function checkcontdates() {
1.562 damieng 2383: checkthis('contentopen','pscat');
2384: checkthis('contentclose','pscat');
1.218 www 2385: }
1.446 bisitz 2386:
1.210 www 2387: function checkvisi() {
1.562 damieng 2388: checkthis('hiddenresource','pscat');
2389: checkthis('encrypturl','pscat');
2390: checkthis('problemstatus','pscat');
2391: checkthis('contentopen','pscat');
2392: checkthis('opendate','pscat');
1.210 www 2393: }
2394:
2395: function checkparts() {
1.562 damieng 2396: checkthis('hiddenparts','pscat');
2397: checkthis('display','pscat');
2398: checkthis('ordered','pscat');
1.210 www 2399: }
2400:
2401: function checkstandard() {
2402: checkall(false,'pscat');
1.562 damieng 2403: checkdates();
2404: checkthis('weight','pscat');
2405: checkthis('maxtries','pscat');
2406: checkthis('type','pscat');
2407: checkthis('problemstatus','pscat');
1.210 www 2408: }
2409:
1.454 bisitz 2410: // ]]>
1.208 www 2411: </script>
2412: ENDSCRIPT
1.453 schualex 2413:
1.491 bisitz 2414: $r->print('<hr />');
1.581 raeburn 2415: &shortCuts($r);
1.491 bisitz 2416: $r->print('<hr />');
1.453 schualex 2417: }
1.562 damieng 2418:
2419: # Returns parameter categories.
2420: #
2421: # @returns {hash} - category name -> title in English
1.465 amueller 2422: sub categories {
2423: return ('time_settings' => 'Time Settings',
2424: 'grading' => 'Grading',
2425: 'tries' => 'Tries',
2426: 'problem_appearance' => 'Problem Appearance',
2427: 'behaviour_of_input_fields' => 'Behaviour of Input Fields',
2428: 'hiding' => 'Hiding',
2429: 'high_level_randomization' => 'High Level Randomization',
2430: 'slots' => 'Slots',
2431: 'file_submission' => 'File Submission',
2432: 'misc' => 'Miscellaneous' );
2433: }
2434:
1.562 damieng 2435: # Returns the category for each parameter.
2436: #
2437: # @returns {hash} - parameter name -> category name
1.465 amueller 2438: sub lookUpTableParameter {
2439:
2440: return (
2441: 'opendate' => 'time_settings',
2442: 'duedate' => 'time_settings',
2443: 'answerdate' => 'time_settings',
2444: 'interval' => 'time_settings',
2445: 'contentopen' => 'time_settings',
2446: 'contentclose' => 'time_settings',
2447: 'discussend' => 'time_settings',
1.560 damieng 2448: 'printstartdate' => 'time_settings',
2449: 'printenddate' => 'time_settings',
1.465 amueller 2450: 'weight' => 'grading',
2451: 'handgrade' => 'grading',
2452: 'maxtries' => 'tries',
2453: 'hinttries' => 'tries',
1.503 raeburn 2454: 'randomizeontries' => 'tries',
1.465 amueller 2455: 'type' => 'problem_appearance',
2456: 'problemstatus' => 'problem_appearance',
2457: 'display' => 'problem_appearance',
2458: 'ordered' => 'problem_appearance',
2459: 'numbubbles' => 'problem_appearance',
2460: 'tol' => 'behaviour_of_input_fields',
2461: 'sig' => 'behaviour_of_input_fields',
2462: 'turnoffunit' => 'behaviour_of_input_fields',
2463: 'hiddenresource' => 'hiding',
2464: 'hiddenparts' => 'hiding',
2465: 'discusshide' => 'hiding',
2466: 'buttonshide' => 'hiding',
2467: 'turnoffeditor' => 'hiding',
2468: 'encrypturl' => 'hiding',
1.587 raeburn 2469: 'deeplink' => 'hiding',
1.465 amueller 2470: 'randomorder' => 'high_level_randomization',
2471: 'randompick' => 'high_level_randomization',
2472: 'available' => 'slots',
2473: 'useslots' => 'slots',
2474: 'availablestudent' => 'slots',
2475: 'uploadedfiletypes' => 'file_submission',
2476: 'maxfilesize' => 'file_submission',
2477: 'cssfile' => 'misc',
2478: 'mapalias' => 'misc',
2479: 'acc' => 'misc',
2480: 'maxcollaborators' => 'misc',
2481: 'scoreformat' => 'misc',
1.514 raeburn 2482: 'lenient' => 'grading',
1.519 raeburn 2483: 'retrypartial' => 'tries',
1.521 raeburn 2484: 'discussvote' => 'misc',
1.584 raeburn 2485: 'examcode' => 'high_level_randomization',
1.575 raeburn 2486: );
1.465 amueller 2487: }
2488:
1.562 damieng 2489: # Adds the given parameter name to an array of arrays listing all parameters for each category.
2490: #
2491: # @param {string} $name - parameter name
2492: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465 amueller 2493: sub whatIsMyCategory {
2494: my $name = shift;
2495: my $catList = shift;
2496: my @list;
2497: my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
2498: my $cat = $lookUpList{$name};
2499: if (defined($cat)) {
2500: if (!defined($$catList{$cat})){
2501: push @list, ($name);
2502: $$catList{$cat} = \@list;
2503: } else {
2504: push @{${$catList}{$cat}}, ($name);
2505: }
2506: } else {
2507: if (!defined($$catList{'misc'})){
2508: push @list, ($name);
2509: $$catList{'misc'} = \@list;
2510: } else {
2511: push @{${$catList}{'misc'}}, ($name);
2512: }
2513: }
2514: }
2515:
1.562 damieng 2516: # Sorts parameter names based on appearance order.
2517: #
2518: # @param {array reference} name - array reference of parameter names
2519: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2520: # @returns {Array} - array of parameter names
1.465 amueller 2521: sub keysindisplayorderCategory {
2522: my ($name,$keyorder)=@_;
2523: return sort {
1.473 amueller 2524: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.465 amueller 2525: } ( @{$name});
2526: }
2527:
1.562 damieng 2528: # Returns a hash category name -> order, starting at 1 (integer)
2529: #
2530: # @returns {hash}
1.467 amueller 2531: sub category_order {
2532: return (
2533: 'time_settings' => 1,
2534: 'grading' => 2,
2535: 'tries' => 3,
2536: 'problem_appearance' => 4,
2537: 'hiding' => 5,
2538: 'behaviour_of_input_fields' => 6,
2539: 'high_level_randomization' => 7,
2540: 'slots' => 8,
2541: 'file_submission' => 9,
2542: 'misc' => 10
2543: );
2544:
2545: }
1.453 schualex 2546:
1.562 damieng 2547: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
2548: #
2549: # @param {Apache2::RequestRec} $r - the Apache request
2550: # @param {hash reference} $allparms - hash parameter name -> parameter title
2551: # @param {array reference} $pscat - list of selected parameter names
2552: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453 schualex 2553: sub parmboxes {
2554: my ($r,$allparms,$pscat,$keyorder)=@_;
1.548 raeburn 2555: my %categories = &categories();
1.467 amueller 2556: my %category_order = &category_order();
1.465 amueller 2557: my %categoryList = (
2558: 'time_settings' => [],
2559: 'grading' => [],
2560: 'tries' => [],
2561: 'problem_appearance' => [],
2562: 'behaviour_of_input_fields' => [],
2563: 'hiding' => [],
2564: 'high_level_randomization' => [],
2565: 'slots' => [],
2566: 'file_submission' => [],
2567: 'misc' => [],
1.489 bisitz 2568: );
1.510 www 2569:
1.548 raeburn 2570: foreach my $tempparameter (keys(%$allparms)) {
1.465 amueller 2571: &whatIsMyCategory($tempparameter, \%categoryList);
2572: }
1.453 schualex 2573: #part to print the parm-list
1.618 raeburn 2574: $Text::Wrap::columns=60;
2575: $Text::Wrap::separator='<br />';
1.536 raeburn 2576: foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
2577: next if (@{$categoryList{$key}} == 0);
2578: next if ($key eq '');
2579: $r->print('<div class="LC_Box LC_400Box">'
2580: .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
2581: foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575 raeburn 2582: next if ($tempkey eq '');
1.536 raeburn 2583: $r->print('<span class="LC_nobreak">'
2584: .'<label><input type="checkbox" name="pscat" '
2585: .'value="'.$tempkey.'" ');
2586: if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
2587: $r->print( ' checked="checked"');
2588: }
1.617 raeburn 2589: $r->print(' />'.($$allparms{$tempkey}=~/\S/ ?
2590: Text::Wrap::wrap('',' 'x4,$$allparms{$tempkey})
2591: : $tempkey)
1.536 raeburn 2592: .'</label></span><br />'."\n");
1.465 amueller 2593: }
1.536 raeburn 2594: $r->print('</div>');
1.465 amueller 2595: }
1.536 raeburn 2596: $r->print("\n");
1.453 schualex 2597: }
1.562 damieng 2598:
2599: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468 amueller 2600: #
1.562 damieng 2601: # @param {Apache2::RequestRec} $r - the Apache request
1.453 schualex 2602: sub shortCuts {
1.581 raeburn 2603: my ($r)=@_;
1.453 schualex 2604:
1.491 bisitz 2605: # Parameter Selection
2606: $r->print(
2607: &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
2608: .&Apache::lonhtmlcommon::add_item_funclist(
2609: '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
2610: .&Apache::lonhtmlcommon::add_item_funclist(
2611: '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
2612: .&Apache::lonhtmlcommon::add_item_funclist(
2613: '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
2614: .&Apache::lonhtmlcommon::end_funclist()
2615: );
2616:
2617: # Add Selection for...
2618: $r->print(
2619: &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
2620: .&Apache::lonhtmlcommon::add_item_funclist(
2621: '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
2622: .&Apache::lonhtmlcommon::add_item_funclist(
2623: '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
2624: .&Apache::lonhtmlcommon::add_item_funclist(
2625: '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
2626: .&Apache::lonhtmlcommon::add_item_funclist(
2627: '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
2628: .&Apache::lonhtmlcommon::add_item_funclist(
2629: '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
2630: .&Apache::lonhtmlcommon::end_funclist()
2631: );
1.208 www 2632: }
2633:
1.562 damieng 2634: # Prints HTML to select parts to view (except for the title).
2635: # Used by table and overview modes.
2636: #
2637: # @param {Apache2::RequestRec} $r - the Apache request
2638: # @param {hash reference} $allparts - hash parameter part -> part title
2639: # @param {array reference} $psprt - list of selected parameter parts
1.209 www 2640: sub partmenu {
1.446 bisitz 2641: my ($r,$allparts,$psprt)=@_;
1.523 raeburn 2642: my $selsize = 1+scalar(keys(%{$allparts}));
2643: if ($selsize > 8) {
2644: $selsize = 8;
2645: }
1.446 bisitz 2646:
1.523 raeburn 2647: $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208 www 2648: $r->print('<option value="all"');
1.562 damieng 2649: $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208 www 2650: $r->print('>'.&mt('All Parts').'</option>');
2651: my %temphash=();
2652: foreach (@{$psprt}) { $temphash{$_}=1; }
1.234 albertel 2653: foreach my $tempkey (sort {
1.560 damieng 2654: if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
2655: } keys(%{$allparts})) {
2656: unless ($tempkey =~ /\./) {
2657: $r->print('<option value="'.$tempkey.'"');
2658: if ($$psprt[0] eq "all" || $temphash{$tempkey}) {
2659: $r->print(' selected="selected"');
2660: }
2661: $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473 amueller 2662: }
1.208 www 2663: }
1.446 bisitz 2664: $r->print('</select>');
1.209 www 2665: }
2666:
1.562 damieng 2667: # Prints HTML to select a user and/or a group.
2668: # Used by table mode.
2669: #
2670: # @param {Apache2::RequestRec} $r - the Apache request
2671: # @param {string} $uname - selected user name
2672: # @param {string} $id - selected Student/Employee ID
2673: # @param {string} $udom - selected user domain
2674: # @param {string} $csec - selected section name
2675: # @param {string} $cgroup - selected group name
2676: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
2677: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
2678: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209 www 2679: sub usermenu {
1.553 raeburn 2680: my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209 www 2681: my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596 raeburn 2682: &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
2683: &Apache::lonhtmlcommon::scripttag(<<ENDJS);
2684: function setCourseadv(form,caller) {
2685: if (caller.value == 'st') {
2686: form.courseadv.value = 'none';
2687: } else {
2688: form.courseadv.value = '';
2689: }
2690: return;
2691: }
2692: ENDJS
1.412 bisitz 2693:
1.596 raeburn 2694: my (%chkroles,$stuonly,$courseadv);
2695: if ($env{'form.userroles'} eq 'any') {
2696: $chkroles{'any'} = ' checked="checked"';
2697: } else {
2698: $chkroles{'st'} = ' checked="checked"';
2699: $courseadv = 'none';
2700: }
2701: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
2702: if ($crstype eq 'Community') {
2703: $stuonly = &mt('member only');
2704: } else {
2705: $stuonly = &mt('student only');
2706: }
2707: $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
2708: &mt("User's role").': '.
2709: '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
2710: $stuonly.'</label> '.
2711: '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
2712: &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209 www 2713: my $sections='';
1.300 albertel 2714: my %sectionhash = &Apache::loncommon::get_sections();
2715:
1.269 raeburn 2716: my $groups;
1.553 raeburn 2717: my %grouphash;
2718: if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
2719: %grouphash = &Apache::longroup::coursegroups();
2720: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 2721: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 2722: }
1.299 albertel 2723:
1.412 bisitz 2724: my $g_s_header='';
2725: my $g_s_footer='';
1.446 bisitz 2726:
1.552 raeburn 2727: my $currsec = $env{'request.course.sec'};
2728: if ($currsec) {
2729: $sections=&mt('Section:').' '.$currsec;
2730: if (%grouphash) {
2731: $sections .= ';'.(' ' x2);
2732: }
2733: } elsif (%sectionhash && $currsec eq '') {
1.412 bisitz 2734: $sections=&mt('Section:').' <select name="csec"';
1.299 albertel 2735: if (%grouphash && $parmlev ne 'full') {
1.269 raeburn 2736: $sections .= qq| onchange="group_or_section('csec')" |;
2737: }
2738: $sections .= '>';
1.548 raeburn 2739: foreach my $section ('',sort(keys(%sectionhash))) {
1.473 amueller 2740: $sections.='<option value="'.$section.'" '.
2741: ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275 raeburn 2742: '</option>';
1.209 www 2743: }
2744: $sections.='</select>';
1.269 raeburn 2745: }
1.412 bisitz 2746:
1.552 raeburn 2747: if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412 bisitz 2748: $sections .= ' '.&mt('or').' ';
1.269 raeburn 2749: $sections .= qq|
2750: <script type="text/javascript">
1.454 bisitz 2751: // <![CDATA[
1.269 raeburn 2752: function group_or_section(caller) {
2753: if (caller == "cgroup") {
2754: if (document.parmform.cgroup.selectedIndex != 0) {
2755: document.parmform.csec.selectedIndex = 0;
2756: }
2757: } else {
2758: if (document.parmform.csec.selectedIndex != 0) {
2759: document.parmform.cgroup.selectedIndex = 0;
2760: }
2761: }
2762: }
1.454 bisitz 2763: // ]]>
1.269 raeburn 2764: </script>
2765: |;
1.554 raeburn 2766: } else {
1.269 raeburn 2767: $sections .= qq|
2768: <script type="text/javascript">
1.454 bisitz 2769: // <![CDATA[
1.269 raeburn 2770: function group_or_section(caller) {
2771: return;
2772: }
1.454 bisitz 2773: // ]]>
1.269 raeburn 2774: </script>
2775: |;
1.446 bisitz 2776: }
1.299 albertel 2777:
2778: if (%grouphash) {
1.597 raeburn 2779: $groups=&mt('Group').': <select name="cgroup"';
1.552 raeburn 2780: if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269 raeburn 2781: $groups .= qq| onchange="group_or_section('cgroup')" |;
2782: }
2783: $groups .= '>';
1.548 raeburn 2784: foreach my $grp ('',sort(keys(%grouphash))) {
1.275 raeburn 2785: $groups.='<option value="'.$grp.'" ';
2786: if ($grp eq $cgroup) {
2787: unless ((defined($uname)) && ($grp eq '')) {
2788: $groups .= 'selected="selected" ';
2789: }
2790: } elsif (!defined($cgroup)) {
2791: if (@{$usersgroups} == 1) {
2792: if ($grp eq $$usersgroups[0]) {
2793: $groups .= 'selected="selected" ';
2794: }
2795: }
2796: }
2797: $groups .= '>'.$grp.'</option>';
1.269 raeburn 2798: }
2799: $groups.='</select>';
2800: }
1.412 bisitz 2801:
1.445 neumanie 2802: if (%sectionhash || %grouphash) {
1.446 bisitz 2803: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
2804: $r->print($sections.$groups);
1.448 bisitz 2805: $r->print(&Apache::lonhtmlcommon::row_closure());
1.554 raeburn 2806: } else {
2807: $r->print($sections);
1.445 neumanie 2808: }
1.446 bisitz 2809:
2810: $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443 neumanie 2811: $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412 bisitz 2812: ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
2813: ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446 bisitz 2814: ,$chooseopt));
1.209 www 2815: }
2816:
1.562 damieng 2817: # Prints HTML to select parameters from a list of all parameters.
2818: # Uses parmmenu and parmboxes.
2819: # Used by table and overview modes.
1.468 amueller 2820: #
1.562 damieng 2821: # @param {Apache2::RequestRec} $r - the Apache request
2822: # @param {hash reference} $allparms - hash parameter name -> parameter title
2823: # @param {array reference} $pscat - list of selected parameter names
2824: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
2825: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209 www 2826: sub displaymenu {
1.581 raeburn 2827: my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510 www 2828:
1.445 neumanie 2829: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510 www 2830: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
2831:
1.581 raeburn 2832: &parmmenu($r);
1.536 raeburn 2833: $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510 www 2834: &parmboxes($r,$allparms,$pscat,$keyorder);
2835: $r->print(&Apache::loncommon::end_scrollbox());
2836:
2837: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453 schualex 2838: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510 www 2839:
1.209 www 2840: }
2841:
1.562 damieng 2842: # Prints HTML to select a map.
2843: # Used by table mode and overview mode.
2844: #
2845: # @param {Apache2::RequestRec} $r - the Apache request
1.566 damieng 2846: # @param {hash reference} $allmaps - hash map pc -> map src
2847: # @param {string} $pschp - selected map pc, or 'all'
1.562 damieng 2848: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566 damieng 2849: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610 raeburn 2850: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445 neumanie 2851: sub mapmenu {
1.610 raeburn 2852: my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468 amueller 2853: my %allmaps_inverted = reverse %$allmaps;
1.461 neumanie 2854: my $navmap = Apache::lonnavmaps::navmap->new();
2855: my $tree=[];
2856: my $treeinfo={};
2857: if (defined($navmap)) {
1.499 raeburn 2858: my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461 neumanie 2859: my $curRes;
2860: my $depth = 0;
1.468 amueller 2861: my %parent = ();
2862: my $startcount = 5;
2863: my $lastcontainer = $startcount;
2864: # preparing what is to show ...
1.461 neumanie 2865: while ($curRes = $it->next()) {
2866: if ($curRes == $it->BEGIN_MAP()) {
2867: $depth++;
1.468 amueller 2868: $parent{$depth}= $lastcontainer;
1.461 neumanie 2869: }
2870: if ($curRes == $it->END_MAP()) {
2871: $depth--;
1.468 amueller 2872: $lastcontainer = $parent{$depth};
1.461 neumanie 2873: }
2874: if (ref($curRes)) {
1.468 amueller 2875: my $symb = $curRes->symb();
2876: my $ressymb = $symb;
1.461 neumanie 2877: if (($curRes->is_sequence()) || ($curRes->is_page())) {
2878: my $type = 'sequence';
2879: if ($curRes->is_page()) {
2880: $type = 'page';
2881: }
2882: my $id= $curRes->id();
1.468 amueller 2883: my $srcf = $curRes->src();
2884: my $resource_name = &Apache::lonnet::gettitle($srcf);
2885: if(!exists($treeinfo->{$id})) {
2886: push(@$tree,$id);
1.473 amueller 2887: my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());
1.468 amueller 2888: $treeinfo->{$id} = {
1.461 neumanie 2889: depth => $depth,
2890: type => $type,
1.468 amueller 2891: name => $resource_name,
2892: enclosing_map_folder => $enclosing_map_folder,
1.461 neumanie 2893: };
1.462 neumanie 2894: }
1.461 neumanie 2895: }
2896: }
2897: }
1.462 neumanie 2898: }
1.473 amueller 2899: # Show it ...
1.610 raeburn 2900: my $rowattr = ' id="mapmenu"';
2901: if ($parmlev eq 'general') {
2902: $rowattr .= ' style="display:none"';
2903: }
2904: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461 neumanie 2905: if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
2906: my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497 bisitz 2907: my $whitespace =
2908: '<img src="'
2909: .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
2910: .'" alt="" />';
2911:
1.498 bisitz 2912: # Info about selectable folders/maps
2913: $r->print(
2914: '<div class="LC_info">'
1.508 www 2915: .&mt('You can only select maps and folders which have modifiable settings.')
2916: .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder')
1.498 bisitz 2917: .'</div>'
2918: );
2919:
1.536 raeburn 2920: $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523 raeburn 2921: $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497 bisitz 2922:
1.498 bisitz 2923: # Display row: "All Maps or Folders"
2924: $r->print(
1.523 raeburn 2925: &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498 bisitz 2926: .'<td>'
2927: .'<label>'
2928: .'<input type="radio" name="pschp"'
1.497 bisitz 2929: );
2930: $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498 bisitz 2931: $r->print(
2932: ' value="all" /> '.$icon.' '
2933: .&mt('All Maps or Folders')
2934: .'</label>'
2935: .'<hr /></td>'
2936: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2937: );
1.497 bisitz 2938:
1.532 raeburn 2939: # Display row: "Main Content"
1.468 amueller 2940: if (exists($$allmaps{1})) {
1.498 bisitz 2941: $r->print(
2942: &Apache::loncommon::start_data_table_row()
2943: .'<td>'
2944: .'<label>'
2945: .'<input type="radio" name="pschp" value="1"'
1.468 amueller 2946: );
1.497 bisitz 2947: $r->print(' checked="checked"') if ($pschp eq '1');
1.498 bisitz 2948: $r->print(
2949: '/> '.$icon.' '
2950: .$$maptitles{1}
2951: .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
2952: .'</label>'
2953: .'</td>'
2954: .&Apache::loncommon::end_data_table_row()
1.468 amueller 2955: );
2956: }
1.497 bisitz 2957:
2958: # Display rows for all course maps and folders
1.468 amueller 2959: foreach my $id (@{$tree}) {
2960: my ($mapid,$resid)=split(/\./,$id);
1.464 bisitz 2961: # Indentation
1.468 amueller 2962: my $depth = $treeinfo->{$id}->{'depth'};
1.464 bisitz 2963: my $indent;
2964: for (my $i = 0; $i < $depth; $i++) {
2965: $indent.= $whitespace;
2966: }
1.461 neumanie 2967: $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468 amueller 2968: if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461 neumanie 2969: $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
2970: }
1.468 amueller 2971: my $symb_name = $$symbp{$id};
2972: my ($front, $tail) = split (/___${resid}___/, $symb_name);
2973: $symb_name = $tail;
1.498 bisitz 2974: $r->print(
2975: &Apache::loncommon::start_data_table_row()
2976: .'<td>'
2977: .'<label>'
1.463 bisitz 2978: );
1.498 bisitz 2979: # Only offer radio button for folders/maps which can be parameterized
2980: if ($allmaps_inverted{$symb_name}) {
2981: $r->print(
2982: '<input type ="radio" name="pschp"'
2983: .' value="'.$allmaps_inverted{$symb_name}.'"'
2984: );
2985: $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
2986: $r->print('/>');
2987: } else {
2988: $r->print($whitespace);
1.461 neumanie 2989: }
1.498 bisitz 2990: $r->print(
2991: $indent.$icon.' '
2992: .$treeinfo->{$id}->{name}
2993: .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
2994: .'</label>'
2995: .'</td>'
2996: .&Apache::loncommon::end_data_table_row()
1.463 bisitz 2997: );
1.461 neumanie 2998: }
1.497 bisitz 2999:
1.523 raeburn 3000: $r->print(&Apache::loncommon::end_data_table().
3001: '<br style="line-height:2px;" />'.
3002: &Apache::loncommon::end_scrollbox());
1.209 www 3003: }
3004: }
3005:
1.563 damieng 3006: # Prints HTML to select the parameter level (resource, map/folder or course).
3007: # Used by table and overview modes.
3008: #
3009: # @param {Apache2::RequestRec} $r - the Apache request
3010: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
3011: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209 www 3012: sub levelmenu {
1.446 bisitz 3013: my ($r,$alllevs,$parmlev)=@_;
3014:
1.548 raeburn 3015: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
3016: &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474 amueller 3017: $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548 raeburn 3018: foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
3019: $r->print('<option value="'.$$alllevs{$lev}.'"');
3020: if ($parmlev eq $$alllevs{$lev}) {
3021: $r->print(' selected="selected"');
3022: }
3023: $r->print('>'.&mt($lev).'</option>');
1.208 www 3024: }
1.446 bisitz 3025: $r->print("</select>");
1.208 www 3026: }
3027:
1.211 www 3028:
1.563 damieng 3029: # Returns HTML to select a section (with a select HTML element).
3030: # Used by overview mode.
3031: #
3032: # @param {array reference} $selectedsections - list of selected section ids
3033: # @returns {string}
1.211 www 3034: sub sectionmenu {
1.553 raeburn 3035: my ($selectedsections)=@_;
1.300 albertel 3036: my %sectionhash = &Apache::loncommon::get_sections();
1.553 raeburn 3037: return '' if (!%sectionhash);
1.300 albertel 3038:
1.552 raeburn 3039: my (@possibles,$disabled);
3040: if ($env{'request.course.sec'} ne '') {
3041: @possibles = ($env{'request.course.sec'});
3042: $selectedsections = [$env{'request.course.sec'}];
3043: $disabled = ' disabled="disabled"';
3044: } else {
3045: @possibles = ('all',sort(keys(%sectionhash)));
3046: }
1.553 raeburn 3047: my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552 raeburn 3048: foreach my $s (@possibles) {
1.553 raeburn 3049: $output .= ' <option value="'.$s.'"';
3050: if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {
3051: $output .= ' selected="selected"';
1.473 amueller 3052: }
1.553 raeburn 3053: $output .= '>'."$s</option>\n";
1.300 albertel 3054: }
1.553 raeburn 3055: $output .= "</select>\n";
3056: return $output;
1.269 raeburn 3057: }
3058:
1.563 damieng 3059: # Returns HTML to select a group (with a select HTML element).
3060: # Used by overview mode.
3061: #
3062: # @param {array reference} $selectedgroups - list of selected group names
3063: # @returns {string}
1.269 raeburn 3064: sub groupmenu {
1.553 raeburn 3065: my ($selectedgroups)=@_;
3066: my %grouphash;
3067: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3068: %grouphash = &Apache::longroup::coursegroups();
3069: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 3070: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 3071: }
3072: return '' if (!%grouphash);
1.299 albertel 3073:
1.553 raeburn 3074: my $output = '<select name="Group" multiple="multiple" size="8">';
1.299 albertel 3075: foreach my $group (sort(keys(%grouphash))) {
1.553 raeburn 3076: $output .= ' <option value="'.$group.'"';
3077: if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
3078: $output .= ' selected="selected"';
1.473 amueller 3079: }
1.553 raeburn 3080: $output .= '>'."$group</option>\n";
1.211 www 3081: }
1.553 raeburn 3082: $output .= "</select>\n";
3083: return $output;
1.211 www 3084: }
3085:
1.563 damieng 3086: # Returns an array with the given parameter split by comma.
3087: # Used by assessparms (table mode).
3088: #
3089: # @param {string} $keyp - the string to split
3090: # @returns {Array<string>}
1.210 www 3091: sub keysplit {
3092: my $keyp=shift;
3093: return (split(/\,/,$keyp));
3094: }
3095:
1.563 damieng 3096: # Returns the keys in $name, sorted using $keyorder.
3097: # Parameters are sorted by key, which means they are sorted by part first, then by name.
3098: # Used by assessparms (table mode) for resource level.
3099: #
3100: # @param {hash reference} $name - parameter key -> parameter name
3101: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3102: # @returns {Array<string>}
1.210 www 3103: sub keysinorder {
3104: my ($name,$keyorder)=@_;
3105: return sort {
1.560 damieng 3106: $$keyorder{$a} <=> $$keyorder{$b};
1.548 raeburn 3107: } (keys(%{$name}));
1.210 www 3108: }
3109:
1.563 damieng 3110: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
3111: # Used by assessparms (table mode) for map and general levels.
3112: #
3113: # @param {hash reference} $name - parameter key -> parameter name
3114: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3115: # @returns {Array<string>}
1.236 albertel 3116: sub keysinorder_bytype {
3117: my ($name,$keyorder)=@_;
3118: return sort {
1.563 damieng 3119: my $ta=(split('_',$a))[-1]; # parameter name
1.560 damieng 3120: my $tb=(split('_',$b))[-1];
3121: if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
3122: return ($a cmp $b);
3123: }
3124: $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548 raeburn 3125: } (keys(%{$name}));
1.236 albertel 3126: }
3127:
1.563 damieng 3128: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
3129: # Used by defaultsetter (parameter settings default actions).
3130: #
3131: # @param {hash reference} $name - hash parameter name -> parameter title
3132: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
3133: # @returns {Array<string>}
1.211 www 3134: sub keysindisplayorder {
3135: my ($name,$keyorder)=@_;
3136: return sort {
1.560 damieng 3137: $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548 raeburn 3138: } (keys(%{$name}));
1.211 www 3139: }
3140:
1.563 damieng 3141: # Prints HTML with a choice to sort results by realm or student first.
3142: # Used by overview mode.
3143: #
3144: # @param {Apache2::RequestRec} $r - the Apache request
3145: # @param {string} $sortorder - realmstudent|studentrealm
1.608 raeburn 3146: # @param {string} $context - newoverview|overview
1.214 www 3147: sub sortmenu {
1.608 raeburn 3148: my ($r,$sortorder,$context)=@_;
3149: my %text;
3150: if ($context eq 'newoverview') {
3151: %text = &Apache::lonlocal::texthash (
3152: realmstudent => 'Sort by location in course first, then student (group/section)',
3153: studentrealm => 'Sort by student (group/section) first, then location in course',
3154: );
3155: } else {
3156: %text = &Apache::lonlocal::texthash (
3157: realmstudent => 'Sort by realm first, then student (group/section)',
3158: studentrealm => 'Sort by student (group/section) first, then realm',
3159: );
1.214 www 3160: }
1.608 raeburn 3161: my %sortchecked = (
3162: realmstudent => ' checked="checked"',
3163: studentrealm => '',
3164: );
1.214 www 3165: if ($sortorder eq 'studentrealm') {
1.608 raeburn 3166: $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
3167: $sortchecked{'realmstudent'} = '';
3168: }
3169: foreach my $sorttype ('realmstudent','studentrealm') {
3170: $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
3171: $text{$sorttype}.'</label>');
1.214 www 3172: }
3173: }
3174:
1.563 damieng 3175: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
3176: #
3177: # @returns {hash}
1.211 www 3178: sub standardkeyorder {
3179: return ('parameter_0_opendate' => 1,
1.473 amueller 3180: 'parameter_0_duedate' => 2,
3181: 'parameter_0_answerdate' => 3,
3182: 'parameter_0_interval' => 4,
3183: 'parameter_0_weight' => 5,
3184: 'parameter_0_maxtries' => 6,
3185: 'parameter_0_hinttries' => 7,
3186: 'parameter_0_contentopen' => 8,
3187: 'parameter_0_contentclose' => 9,
3188: 'parameter_0_type' => 10,
3189: 'parameter_0_problemstatus' => 11,
3190: 'parameter_0_hiddenresource' => 12,
3191: 'parameter_0_hiddenparts' => 13,
3192: 'parameter_0_display' => 14,
3193: 'parameter_0_ordered' => 15,
3194: 'parameter_0_tol' => 16,
3195: 'parameter_0_sig' => 17,
3196: 'parameter_0_turnoffunit' => 18,
1.521 raeburn 3197: 'parameter_0_discussend' => 19,
3198: 'parameter_0_discusshide' => 20,
3199: 'parameter_0_discussvote' => 21,
1.560 damieng 3200: 'parameter_0_printstartdate' => 22,
3201: 'parameter_0_printenddate' => 23);
1.211 www 3202: }
3203:
1.59 matthew 3204:
1.560 damieng 3205: # Table mode UI.
1.563 damieng 3206: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
3207: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
3208: #
3209: # Parameters used from the request:
3210: # action - handler action (see handler), usermenu is checking for value 'settable'
3211: # cgroup - selected group
3212: # command - 'set': direct access to table mode for a resource
3213: # csec - selected section
3214: # dis - set when the "Update Display" button was used, used only to discard command 'set'
3215: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
3216: # id - student/employee ID
3217: # parmlev - selected level (full|map|general)
3218: # part - selected part (unused ?)
3219: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
3220: # pres_type - &&&-separated parameter types
3221: # pres_value - &&&-separated parameter values
3222: # prevvisit - '1' if the user has submitted the form before
3223: # pscat (multiple values) - selected parameter names
1.566 damieng 3224: # pschp - selected map pc, or 'all'
1.563 damieng 3225: # psprt (multiple values) - list of selected parameter parts
3226: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
3227: # recent_* (* = parameter type) - recent values entered by the user for parameter types
3228: # symb - resource symb (when a single resource is selected)
3229: # udom - selected user domain
3230: # uname - selected user name
3231: # url - used only with command 'set', the resource url
3232: #
3233: # @param {Apache2::RequestRec} $r - the Apache request
1.568 raeburn 3234: # @param $parm_permission - ref to hash of permissions
3235: # if $parm_permission->{'edit'} is true, editing is allowed.
1.30 www 3236: sub assessparms {
1.1 www 3237:
1.568 raeburn 3238: my ($r,$parm_permission) = @_;
1.201 www 3239:
1.512 foxr 3240:
3241: # -------------------------------------------------------- Variable declaration
1.566 damieng 3242: my @ids=(); # resource and map ids
3243: my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
3244: my %mapp=(); # hash map pc or resource/map id -> enclosing map src
3245: my %typep=(); # hash resource/map id -> resource type (file extension)
3246: my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
3247: my %uris=(); # hash resource/map id -> resource src
3248: my %maptitles=(); # hash map pc or src -> map title
3249: my %allmaps=(); # hash map pc -> map src
1.582 raeburn 3250: my %allmaps_inverted=(); # hash map src -> map pc
1.563 damieng 3251: my %alllevs=(); # hash English level title -> value
3252:
3253: my $uname; # selected user name
3254: my $udom; # selected user domain
3255: my $uhome; # server with the user's files, or 'no_host'
3256: my $csec; # selected section name
3257: my $cgroup; # selected group name
3258: my @usersgroups = (); # list of the user groups
1.582 raeburn 3259: my $numreclinks = 0;
1.446 bisitz 3260:
1.190 albertel 3261: my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187 www 3262:
1.57 albertel 3263: $alllevs{'Resource Level'}='full';
1.215 www 3264: $alllevs{'Map/Folder Level'}='map';
1.57 albertel 3265: $alllevs{'Course Level'}='general';
3266:
1.563 damieng 3267: my %allparms; # hash parameter name -> parameter title
3268: my %allparts; # hash parameter part -> part title
1.512 foxr 3269: # ------------------------------------------------------------------------------
3270:
1.210 www 3271: #
3272: # Order in which these parameters will be displayed
3273: #
1.211 www 3274: my %keyorder=&standardkeyorder();
3275:
1.512 foxr 3276: # @ids=();
3277: # %symbp=(); # These seem defined above already.
3278: # %typep=();
1.43 albertel 3279:
3280: my $message='';
3281:
1.190 albertel 3282: $csec=$env{'form.csec'};
1.552 raeburn 3283: if ($env{'request.course.sec'} ne '') {
3284: $csec = $env{'request.course.sec'};
3285: }
3286:
1.553 raeburn 3287: # Check group privs.
1.269 raeburn 3288: $cgroup=$env{'form.cgroup'};
1.553 raeburn 3289: my $noeditgrp;
3290: if ($cgroup ne '') {
3291: unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
3292: if (($env{'request.course.groups'} eq '') ||
1.585 raeburn 3293: (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553 raeburn 3294: $noeditgrp = 1;
3295: }
3296: }
3297: }
1.188 www 3298:
1.190 albertel 3299: if ($udom=$env{'form.udom'}) {
3300: } elsif ($udom=$env{'request.role.domain'}) {
3301: } elsif ($udom=$env{'user.domain'}) {
1.172 albertel 3302: } else {
1.473 amueller 3303: $udom=$r->dir_config('lonDefDomain');
1.172 albertel 3304: }
1.468 amueller 3305:
1.43 albertel 3306:
1.134 albertel 3307: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190 albertel 3308: my $pschp=$env{'form.pschp'};
1.506 www 3309:
3310:
1.134 albertel 3311: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 3312: if (!@psprt) { $psprt[0]='all'; }
1.506 www 3313: if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57 albertel 3314:
1.43 albertel 3315: my $pssymb='';
1.57 albertel 3316: my $parmlev='';
1.446 bisitz 3317:
1.190 albertel 3318: unless ($env{'form.parmlev'}) {
1.57 albertel 3319: $parmlev = 'map';
3320: } else {
1.190 albertel 3321: $parmlev = $env{'form.parmlev'};
1.57 albertel 3322: }
1.26 www 3323:
1.29 www 3324: # ----------------------------------------------- Was this started from grades?
3325:
1.560 damieng 3326: if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
3327: (!$env{'form.dis'})) {
1.473 amueller 3328: my $url=$env{'form.url'};
3329: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
3330: $pssymb=&Apache::lonnet::symbread($url);
3331: if (!@pscat) { @pscat=('all'); }
3332: $pschp='';
1.57 albertel 3333: $parmlev = 'full';
1.190 albertel 3334: } elsif ($env{'form.symb'}) {
1.473 amueller 3335: $pssymb=$env{'form.symb'};
3336: if (!@pscat) { @pscat=('all'); }
3337: $pschp='';
1.57 albertel 3338: $parmlev = 'full';
1.43 albertel 3339: } else {
1.473 amueller 3340: $env{'form.url'}='';
1.43 albertel 3341: }
3342:
1.190 albertel 3343: my $id=$env{'form.id'};
1.43 albertel 3344: if (($id) && ($udom)) {
1.555 raeburn 3345: $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473 amueller 3346: if ($uname) {
3347: $id='';
3348: } else {
3349: $message=
1.540 bisitz 3350: '<p class="LC_warning">'.
3351: &mt('Unknown ID [_1] at domain [_2]',
3352: "'".$id."'","'".$udom."'").
3353: '</p>';
1.473 amueller 3354: }
1.43 albertel 3355: } else {
1.473 amueller 3356: $uname=$env{'form.uname'};
1.43 albertel 3357: }
3358: unless ($udom) { $uname=''; }
3359: $uhome='';
3360: if ($uname) {
1.473 amueller 3361: $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43 albertel 3362: if ($uhome eq 'no_host') {
1.473 amueller 3363: $message=
1.540 bisitz 3364: '<p class="LC_warning">'.
3365: &mt('Unknown user [_1] at domain [_2]',
3366: "'".$uname."'","'".$udom."'").
3367: '</p>';
1.473 amueller 3368: $uname='';
1.12 www 3369: } else {
1.473 amueller 3370: $csec=&Apache::lonnet::getsection($udom,$uname,
3371: $env{'request.course.id'});
3372: if ($csec eq '-1') {
1.596 raeburn 3373: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
3374: if ($env{'form.userroles'} eq 'any') {
3375: if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
3376: $csec = $env{'request.course.sec'};
3377: $message = '<span class="LC_info">';
3378: if ($crstype eq 'Community') {
3379: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3380: $uname,$udom);
3381: } else {
3382: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3383: $uname,$udom);
3384: }
3385: $message .= '</span>';
3386: } else {
3387: my @possroles = ('in','ep','ta','cr');
3388: if ($crstype eq 'Community') {
3389: unshift(@possroles,'co');
3390: } else {
3391: unshift(@possroles,'cc');
3392: }
3393: my %not_student_roles =
3394: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
3395: \@possroles,[$udom],1,1);
3396: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3397: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
3398: my %sections_by_role;
3399: foreach my $role (keys(%not_student_roles)) {
3400: if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
3401: my ($rolename,$sec) = ($1,$2);
3402: if ($rolename =~ m{^cr/}) {
3403: $rolename = 'cr';
3404: }
3405: push(@{$sections_by_role{$rolename}},$sec);
3406: }
3407: }
3408: my $numroles = scalar(keys(%sections_by_role));
3409: if ($numroles) {
3410: foreach my $role (@possroles) {
3411: if (ref($sections_by_role{$role}) eq 'ARRAY') {
3412: my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
3413: $csec = $secs[0];
3414: last;
3415: }
3416: }
3417: }
3418: if ($csec eq '-1') {
3419: $message = '<span class="LC_warning">';
3420: if ($crstype eq 'Community') {
3421: $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
3422: $uname,$udom);
3423: } else {
3424: $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
3425: $uname,$udom);
3426: }
3427: $message .= '</span>';
3428: $uname='';
3429: if ($env{'request.course.sec'} ne '') {
3430: $csec=$env{'request.course.sec'};
3431: } else {
3432: $csec=$env{'form.csec'};
3433: }
3434: $cgroup=$env{'form.cgroup'};
3435: } else {
3436: $message = '<span class="LC_info">';
3437: if ($crstype eq 'Community') {
3438: $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
3439: $uname,$udom);
3440: } else {
3441: $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
3442: $uname,$udom);
3443: }
3444: $message .= '</span>';
3445: }
3446: }
1.594 raeburn 3447: } else {
1.596 raeburn 3448: $message = '<span class="LC_warning">';
3449: if ($crstype eq 'Community') {
3450: $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
3451: $uname,$udom);
3452: } else {
3453: $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
3454: $uname,$udom);
3455: }
3456: $message .= '</span>';
3457: $uname='';
3458: if ($env{'request.course.sec'} ne '') {
3459: $csec=$env{'request.course.sec'};
3460: } else {
3461: $csec=$env{'form.csec'};
3462: }
3463: $cgroup=$env{'form.cgroup'};
1.594 raeburn 3464: }
3465: } elsif ($env{'request.course.sec'} ne '') {
3466: if ($csec ne $env{'request.course.sec'}) {
1.596 raeburn 3467: $message='<span class="LC_warning">'.
1.594 raeburn 3468: &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
3469: $uname,$udom,$env{'request.course.sec'}).
3470: '</span>';
3471: $uname='';
3472: $csec=$env{'request.course.sec'};
3473: }
1.269 raeburn 3474: $cgroup=$env{'form.cgroup'};
1.596 raeburn 3475: }
3476: if ($uname ne '') {
1.473 amueller 3477: my %name=&Apache::lonnet::userenvironment($udom,$uname,
3478: ('firstname','middlename','lastname','generation','id'));
1.596 raeburn 3479: $message .= "\n<p>\n".&mt('Full Name').': '
3480: .$name{'firstname'}.' '.$name{'middlename'}.' '
3481: .$name{'lastname'}.' '.$name{'generation'}
3482: ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
3483: @usersgroups = &Apache::lonnet::get_users_groups(
3484: $udom,$uname,$env{'request.course.id'});
3485: if (@usersgroups > 0) {
3486: unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
3487: $cgroup = $usersgroups[0];
3488: }
3489: } else {
3490: $cgroup = '';
1.297 raeburn 3491: }
1.269 raeburn 3492: }
1.12 www 3493: }
1.43 albertel 3494: }
1.2 www 3495:
1.43 albertel 3496: unless ($csec) { $csec=''; }
1.269 raeburn 3497: unless ($cgroup) { $cgroup=''; }
1.12 www 3498:
1.14 www 3499: # --------------------------------------------------------- Get all assessments
1.446 bisitz 3500: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 3501: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 3502: \%keyorder,undef,$pssymb);
1.63 bowersj2 3503:
1.582 raeburn 3504: %allmaps_inverted = reverse(%allmaps);
3505:
1.57 albertel 3506: $mapp{'0.0'} = '';
3507: $symbp{'0.0'} = '';
1.99 albertel 3508:
1.14 www 3509: # ---------------------------------------------------------- Anything to store?
1.568 raeburn 3510: if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205 www 3511: my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
3512: my @values=split(/\&\&\&/,$env{'form.pres_value'});
3513: my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500 raeburn 3514: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3515: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504 raeburn 3516: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
3517: my ($got_chostname,$chostname,$cmajor,$cminor);
3518: my $totalstored = 0;
1.605 raeburn 3519: my $totalskippeduser = 0;
1.546 raeburn 3520: my $now = time;
1.473 amueller 3521: for (my $i=0;$i<=$#markers;$i++) {
1.557 raeburn 3522: my ($needsrelease,$needsnewer,$name,$namematch);
1.556 raeburn 3523: if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552 raeburn 3524: next if ($csec ne $env{'request.course.sec'});
3525: }
1.556 raeburn 3526: if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553 raeburn 3527: next if ($noeditgrp);
1.605 raeburn 3528: } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
3529: if ($uname eq '') {
3530: $totalskippeduser ++;
3531: next;
3532: }
1.557 raeburn 3533: }
3534: if ($markers[$i] =~ /\&(17|11|7|3)$/) {
3535: $namematch = 'maplevelrecurse';
3536: }
1.556 raeburn 3537: if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437 raeburn 3538: my (@ok_slots,@fail_slots,@del_slots);
3539: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
3540: my ($level,@all) =
3541: &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
3542: $csec,$cgroup,$courseopt);
3543: foreach my $slot_name (split(/:/,$values[$i])) {
3544: next if ($slot_name eq '');
3545: if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
3546: push(@ok_slots,$slot_name);
3547:
3548: } else {
3549: push(@fail_slots,$slot_name);
3550: }
3551: }
3552: if (@ok_slots) {
3553: $values[$i] = join(':',@ok_slots);
3554: } else {
3555: $values[$i] = '';
3556: }
3557: if ($all[$level] ne '') {
3558: my @existing = split(/:/,$all[$level]);
3559: foreach my $slot_name (@existing) {
3560: if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
3561: if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
3562: push(@del_slots,$slot_name);
3563: }
3564: }
3565: }
3566: }
1.554 raeburn 3567: } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514 raeburn 3568: $name = $1;
1.533 raeburn 3569: my $val = $values[$i];
1.549 raeburn 3570: my $valmatch = '';
1.533 raeburn 3571: if ($name eq 'examcode') {
1.544 raeburn 3572: if (&Apache::lonnet::validCODE($values[$i])) {
3573: $val = 'valid';
3574: }
1.546 raeburn 3575: } elsif ($name eq 'printstartdate') {
3576: if ($val =~ /^\d+$/) {
3577: if ($val > $now) {
3578: $val = 'future';
3579: }
3580: }
3581: } elsif ($name eq 'printenddate') {
3582: if ($val =~ /^\d+$/) {
3583: if ($val < $now) {
3584: $val = 'past';
3585: }
3586: }
1.549 raeburn 3587: } elsif (($name eq 'lenient') || ($name eq 'acc')) {
3588: my $stringtype = &get_stringtype($name);
3589: my $stringmatch = &standard_string_matches($stringtype);
3590: if (ref($stringmatch) eq 'ARRAY') {
3591: foreach my $item (@{$stringmatch}) {
3592: if (ref($item) eq 'ARRAY') {
3593: my ($regexpname,$pattern) = @{$item};
3594: if ($pattern ne '') {
3595: if ($val =~ /$pattern/) {
3596: $valmatch = $regexpname;
3597: $val = '';
3598: last;
3599: }
3600: }
3601: }
3602: }
3603: }
1.554 raeburn 3604: } elsif ($name eq 'interval') {
3605: my $intervaltype = &get_intervaltype($name);
3606: my $intervalmatch = &standard_interval_matches($intervaltype);
3607: if (ref($intervalmatch) eq 'ARRAY') {
3608: foreach my $item (@{$intervalmatch}) {
3609: if (ref($item) eq 'ARRAY') {
3610: my ($regexpname,$pattern) = @{$item};
3611: if ($pattern ne '') {
3612: if ($val =~ /$pattern/) {
3613: $valmatch = $regexpname;
3614: $val = '';
3615: last;
3616: }
3617: }
3618: }
3619: }
3620: }
1.533 raeburn 3621: }
1.504 raeburn 3622: $needsrelease =
1.557 raeburn 3623: $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504 raeburn 3624: if ($needsrelease) {
1.505 raeburn 3625: unless ($got_chostname) {
1.514 raeburn 3626: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
1.504 raeburn 3627: $got_chostname = 1;
1.546 raeburn 3628: }
1.557 raeburn 3629: $needsnewer = ¶meter_releasecheck($name,$val,$valmatch,undef,
1.514 raeburn 3630: $needsrelease,
3631: $cmajor,$cminor);
1.500 raeburn 3632: }
1.437 raeburn 3633: }
1.504 raeburn 3634: if ($needsnewer) {
1.557 raeburn 3635: undef($namematch);
3636: } else {
3637: my $currneeded;
3638: if ($needsrelease) {
3639: $currneeded = $needsrelease;
3640: }
3641: if ($namematch) {
3642: $needsrelease =
3643: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
3644: if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
3645: unless ($got_chostname) {
3646: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
3647: $got_chostname = 1;
3648: }
3649: $needsnewer = ¶meter_releasecheck(undef,undef,undef,$namematch,
3650: $needsrelease,
3651: $cmajor,$cminor);
3652: } else {
3653: undef($namematch);
3654: }
3655: }
3656: }
3657: if ($needsnewer) {
3658: $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504 raeburn 3659: $cminor,$needsrelease);
3660: } else {
3661: $message.=&storeparm(split(/\&/,$markers[$i]),
3662: $values[$i],
3663: $types[$i],
3664: $uname,$udom,$csec,$cgroup);
3665: $totalstored ++;
3666: }
1.473 amueller 3667: }
1.68 www 3668: # ---------------------------------------------------------------- Done storing
1.504 raeburn 3669: if ($totalstored) {
3670: $message.='<p class="LC_warning">'
1.605 raeburn 3671: .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
3672: .'<br />'
1.504 raeburn 3673: .&mt('Changes can take up to 10 minutes before being active for all students.')
3674: .&Apache::loncommon::help_open_topic('Caching')
3675: .'</p>';
1.605 raeburn 3676: } else {
3677: $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
3678: }
3679: if ($totalskippeduser) {
3680: $message .= '<p class="LC_warning">';
3681: if ($uhome eq 'no_host') {
3682: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
3683: $totalskippeduser);
3684: } elsif ($env{'form.userroles'} eq 'any') {
3685: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
3686: $totalskippeduser);
3687: } else {
3688: $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
3689: $totalskippeduser);
3690: }
3691: $message .= '</p>';
1.504 raeburn 3692: }
1.68 www 3693: }
1.584 raeburn 3694:
1.57 albertel 3695: #----------------------------------------------- if all selected, fill in array
1.563 damieng 3696: if ($pscat[0] eq "all") {
3697: @pscat = (keys(%allparms));
3698: }
3699: if (!@pscat) {
3700: @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
3701: };
3702: if ($psprt[0] eq "all" || !@psprt) {
3703: @psprt = (keys(%allparts));
3704: }
1.2 www 3705: # ------------------------------------------------------------------ Start page
1.63 bowersj2 3706:
1.531 raeburn 3707: my $crstype = &Apache::loncommon::course_type();
3708: &startpage($r,$pssymb,$crstype);
1.57 albertel 3709:
1.548 raeburn 3710: foreach my $item ('tolerance','date_default','date_start','date_end',
1.589 raeburn 3711: 'date_interval','int','float','string','string_lenient',
3712: 'string_examcode','string_deeplink','string_discussvote',
3713: 'string_useslots','string_problemstatus','string_ip',
3714: 'string_questiontype') {
1.473 amueller 3715: $r->print('<input type="hidden" value="'.
1.563 damieng 3716: &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
3717: '" name="recent_'.$item.'" />');
1.44 albertel 3718: }
1.446 bisitz 3719:
1.459 bisitz 3720: # ----- Start Parameter Selection
3721:
1.606 raeburn 3722: # Hide parm selection and possibly table?
3723: my ($tablejs,$tabledivsty);
3724: if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
3725: ($env{'form.dis'}) && ($pssymb eq '')) {
3726: $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
3727: $tabledivsty = ' style="display:none"';
3728: }
1.459 bisitz 3729: $r->print(<<ENDPARMSELSCRIPT);
3730: <script type="text/javascript">
3731: // <![CDATA[
3732: function parmsel_show() {
1.562 damieng 3733: document.getElementById('parmsel').style.display = "";
3734: document.getElementById('parmsellink').style.display = "none";
1.606 raeburn 3735: $tablejs
1.459 bisitz 3736: }
3737: // ]]>
3738: </script>
3739: ENDPARMSELSCRIPT
1.474 amueller 3740:
1.445 neumanie 3741: if (!$pssymb) {
1.563 damieng 3742: # No single resource selected, print forms to select things (hidden after first selection)
1.486 www 3743: my $parmselhiddenstyle=' style="display:none"';
3744: if($env{'form.hideparmsel'} eq 'hidden') {
3745: $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
3746: } else {
3747: $r->print('<div id="parmsel">');
3748: }
3749:
1.491 bisitz 3750: # Step 1
1.523 raeburn 3751: $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
3752: $r->print('
1.474 amueller 3753: <script type="text/javascript">
1.523 raeburn 3754: // <![CDATA['.
3755: &showhide_js().'
1.474 amueller 3756: // ]]>
3757: </script>
1.523 raeburn 3758: ');
3759: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209 www 3760: &levelmenu($r,\%alllevs,$parmlev);
1.491 bisitz 3761: $r->print(&Apache::lonhtmlcommon::row_closure());
1.610 raeburn 3762: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491 bisitz 3763: $r->print(&Apache::lonhtmlcommon::row_closure());
3764: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
3765: &partmenu($r,\%allparts,\@psprt);
1.474 amueller 3766: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3767: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3768:
3769: # Step 2
1.523 raeburn 3770: $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581 raeburn 3771: &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491 bisitz 3772:
3773: # Step 3
1.523 raeburn 3774: $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486 www 3775: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3776: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3777: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3778: $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491 bisitz 3779:
3780: # Update Display Button
1.486 www 3781: $r->print('<p>'
3782: .'<input type="submit" name="dis"'
1.511 www 3783: .' value="'.&mt('Update Display').'" />'
1.486 www 3784: .'<input type="hidden" name="hideparmsel" value="hidden" />'
3785: .'</p>');
3786: $r->print('</div>');
1.491 bisitz 3787:
1.486 www 3788: # Offer link to display parameter selection again
3789: $r->print('<p id="parmsellink"');
3790: if ($env{'form.hideparmsel'} ne 'hidden') {
3791: $r->print($parmselhiddenstyle);
3792: }
3793: $r->print('>'
3794: .'<a href="javascript:parmsel_show()">'
3795: .&mt('Change Parameter Selection')
3796: .'</a>'
3797: .'</p>');
1.44 albertel 3798: } else {
1.478 amueller 3799: # parameter screen for a single resource.
1.486 www 3800: my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473 amueller 3801: my $title = &Apache::lonnet::gettitle($pssymb);
1.501 bisitz 3802: $r->print(&mt('Specific Resource: [_1] ([_2])',
3803: $title,'<span class="LC_filename">'.$resource.'</span>').
1.472 amueller 3804: '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486 www 3805: '<br />');
3806: $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
3807: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553 raeburn 3808: &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486 www 3809: $r->print(&Apache::lonhtmlcommon::row_closure(1));
3810: $r->print(&Apache::lonhtmlcommon::end_pick_box());
3811: $r->print('<p>'
1.459 bisitz 3812: .'<input type="submit" name="dis"'
1.511 www 3813: .' value="'.&mt('Update Display').'" />'
1.459 bisitz 3814: .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486 www 3815: .'</p>');
1.459 bisitz 3816: }
1.478 amueller 3817:
1.486 www 3818: # ----- End Parameter Selection
1.57 albertel 3819:
1.459 bisitz 3820: # Display Messages
3821: $r->print('<div>'.$message.'</div>');
1.210 www 3822:
1.57 albertel 3823:
3824: my @temp_pscat;
3825: map {
3826: my $cat = $_;
3827: push(@temp_pscat, map { $_.'.'.$cat } @psprt);
3828: } @pscat;
3829:
3830: @pscat = @temp_pscat;
3831:
1.548 raeburn 3832:
1.209 www 3833: if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10 www 3834: # ----------------------------------------------------------------- Start Table
1.57 albertel 3835: my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190 albertel 3836: my $csuname=$env{'user.name'};
3837: my $csudom=$env{'user.domain'};
1.568 raeburn 3838: my $readonly = 1;
3839: if ($parm_permission->{'edit'}) {
3840: undef($readonly);
3841: }
1.606 raeburn 3842: $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57 albertel 3843:
1.203 www 3844: if ($parmlev eq 'full') {
1.506 www 3845: #
3846: # This produces the cascading table output of parameters
3847: #
1.578 raeburn 3848: my $coursespan=$csec?8:5;
3849: my $userspan=3;
1.560 damieng 3850: if ($cgroup ne '') {
1.578 raeburn 3851: $coursespan += 3;
1.560 damieng 3852: }
1.473 amueller 3853:
1.560 damieng 3854: $r->print(&Apache::loncommon::start_data_table());
3855: #
3856: # This produces the headers
3857: #
3858: $r->print('<tr><td colspan="5"></td>');
3859: $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
3860: if ($uname) {
1.473 amueller 3861: if (@usersgroups > 1) {
1.560 damieng 3862: $userspan ++;
3863: }
3864: $r->print('<th colspan="'.$userspan.'" rowspan="2">');
3865: $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
3866: }
3867: my %lt=&Apache::lonlocal::texthash(
1.473 amueller 3868: 'pie' => "Parameter in Effect",
3869: 'csv' => "Current Session Value",
1.472 amueller 3870: 'rl' => "Resource Level",
1.473 amueller 3871: 'ic' => 'in Course',
3872: 'aut' => "Assessment URL and Title",
3873: 'type' => 'Type',
3874: 'emof' => "Enclosing Map or Folder",
3875: 'part' => 'Part',
1.472 amueller 3876: 'pn' => 'Parameter Name',
1.473 amueller 3877: 'def' => 'default',
3878: 'femof' => 'from Enclosing Map or Folder',
3879: 'gen' => 'general',
3880: 'foremf' => 'for Enclosing Map or Folder',
3881: 'fr' => 'for Resource'
3882: );
1.560 damieng 3883: $r->print(<<ENDTABLETWO);
1.419 bisitz 3884: <th rowspan="3">$lt{'pie'}</th>
1.501 bisitz 3885: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578 raeburn 3886: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419 bisitz 3887: <th colspan="1">$lt{'ic'}</th>
1.182 albertel 3888:
1.10 www 3889: ENDTABLETWO
1.560 damieng 3890: if ($csec) {
1.578 raeburn 3891: $r->print('<th colspan="3">'.
1.560 damieng 3892: &mt("in Section")." $csec</th>");
3893: }
3894: if ($cgroup) {
1.578 raeburn 3895: $r->print('<th colspan="3">'.
1.472 amueller 3896: &mt("in Group")." $cgroup</th>");
1.560 damieng 3897: }
3898: $r->print(<<ENDTABLEHEADFOUR);
1.133 www 3899: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
3900: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578 raeburn 3901: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192 albertel 3902: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10 www 3903: ENDTABLEHEADFOUR
1.57 albertel 3904:
1.560 damieng 3905: if ($csec) {
1.578 raeburn 3906: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3907: }
1.473 amueller 3908:
1.560 damieng 3909: if ($cgroup) {
1.578 raeburn 3910: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3911: }
3912:
3913: if ($uname) {
3914: if (@usersgroups > 1) {
3915: $r->print('<th>'.&mt('Control by other group?').'</th>');
3916: }
1.578 raeburn 3917: $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560 damieng 3918: }
3919:
3920: $r->print('</tr>');
1.506 www 3921: #
3922: # Done with the headers
3923: #
1.560 damieng 3924: my $defbgone='';
3925: my $defbgtwo='';
3926: my $defbgthree = '';
1.57 albertel 3927:
1.560 damieng 3928: foreach my $rid (@ids) {
1.57 albertel 3929:
3930: my ($inmapid)=($rid=~/\.(\d+)$/);
1.446 bisitz 3931: if ((!$pssymb &&
1.560 damieng 3932: (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
3933: ||
3934: ($pssymb && $pssymb eq $symbp{$rid})) {
1.4 www 3935: # ------------------------------------------------------ Entry for one resource
1.473 amueller 3936: if ($defbgone eq '#E0E099') {
3937: $defbgone='#E0E0DD';
1.57 albertel 3938: } else {
1.419 bisitz 3939: $defbgone='#E0E099';
1.57 albertel 3940: }
1.419 bisitz 3941: if ($defbgtwo eq '#FFFF99') {
1.473 amueller 3942: $defbgtwo='#FFFFDD';
1.57 albertel 3943: } else {
1.473 amueller 3944: $defbgtwo='#FFFF99';
1.57 albertel 3945: }
1.419 bisitz 3946: if ($defbgthree eq '#FFBB99') {
3947: $defbgthree='#FFBBDD';
1.269 raeburn 3948: } else {
1.419 bisitz 3949: $defbgthree='#FFBB99';
1.269 raeburn 3950: }
3951:
1.57 albertel 3952: my $thistitle='';
3953: my %name= ();
3954: undef %name;
3955: my %part= ();
3956: my %display=();
3957: my %type= ();
3958: my %default=();
1.196 www 3959: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 3960: my $toolsymb;
3961: if ($uri =~ /ext\.tool$/) {
3962: $toolsymb = $symbp{$rid};
3963: }
1.57 albertel 3964:
1.506 www 3965: my $filter=$env{'form.filter'};
1.548 raeburn 3966: foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57 albertel 3967: if (grep $_ eq $tempkeyp, @catmarker) {
1.584 raeburn 3968: my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560 damieng 3969: # We may only want certain parameters listed
3970: if ($filter) {
3971: unless ($filter=~/\Q$parmname\E/) { next; }
3972: }
3973: $name{$tempkeyp}=$parmname;
1.584 raeburn 3974: $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560 damieng 3975:
1.584 raeburn 3976: my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560 damieng 3977: if ($allparms{$name{$tempkeyp}} ne '') {
3978: my $identifier;
3979: if ($parmdis =~ /(\s*\[Part.*)$/) {
3980: $identifier = $1;
3981: }
3982: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
3983: } else {
3984: $display{$tempkeyp} = $parmdis;
3985: }
3986: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
3987: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584 raeburn 3988: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
3989: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
3990: $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57 albertel 3991: }
3992: }
1.548 raeburn 3993: my $totalparms=scalar(keys(%name));
1.57 albertel 3994: if ($totalparms>0) {
1.560 damieng 3995: my $firstrow=1;
1.473 amueller 3996: my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582 raeburn 3997: my $navmap = Apache::lonnavmaps::navmap->new();
3998: my @recurseup;
3999: if (ref($navmap) && $mapp{$rid}) {
4000: @recurseup = $navmap->recurseup_maps($mapp{$rid});
4001: }
1.419 bisitz 4002: $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57 albertel 4003: ' rowspan='.$totalparms.
1.419 bisitz 4004: '><tt><font size="-1">'.
1.57 albertel 4005: join(' / ',split(/\//,$uri)).
4006: '</font></tt><p><b>'.
1.154 albertel 4007: "<a href=\"javascript:openWindow('".
1.473 amueller 4008: &Apache::lonnet::clutter($uri).'?symb='.
4009: &escape($symbp{$rid}).
1.336 albertel 4010: "', 'metadatafile', '450', '500', 'no', 'yes');\"".
4011: " target=\"_self\">$title");
1.57 albertel 4012:
4013: if ($thistitle) {
1.473 amueller 4014: $r->print(' ('.$thistitle.')');
1.57 albertel 4015: }
4016: $r->print('</a></b></td>');
1.419 bisitz 4017: $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57 albertel 4018: ' rowspan='.$totalparms.'>'.$typep{$rid}.
4019: '</td>');
4020:
1.419 bisitz 4021: $r->print('<td style="background-color:'.$defbgone.';"'.
1.57 albertel 4022: ' rowspan='.$totalparms.
1.238 www 4023: '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548 raeburn 4024: foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57 albertel 4025: unless ($firstrow) {
4026: $r->print('<tr>');
4027: } else {
4028: undef $firstrow;
4029: }
1.548 raeburn 4030: &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57 albertel 4031: \%type,\%display,$defbgone,$defbgtwo,
1.269 raeburn 4032: $defbgthree,$parmlev,$uname,$udom,$csec,
1.582 raeburn 4033: $cgroup,\@usersgroups,$noeditgrp,$readonly,
4034: \@recurseup,\%maptitles,\%allmaps_inverted,
4035: \$numreclinks);
1.57 albertel 4036: }
4037: }
4038: }
4039: } # end foreach ids
1.43 albertel 4040: # -------------------------------------------------- End entry for one resource
1.517 www 4041: $r->print(&Apache::loncommon::end_data_table);
1.203 www 4042: } # end of full
1.57 albertel 4043: #--------------------------------------------------- Entry for parm level map
4044: if ($parmlev eq 'map') {
1.419 bisitz 4045: my $defbgone = '#E0E099';
4046: my $defbgtwo = '#FFFF99';
4047: my $defbgthree = '#FFBB99';
1.57 albertel 4048:
4049: my %maplist;
4050:
4051: if ($pschp eq 'all') {
1.446 bisitz 4052: %maplist = %allmaps;
1.57 albertel 4053: } else {
4054: %maplist = ($pschp => $mapp{$pschp});
4055: }
4056:
4057: #-------------------------------------------- for each map, gather information
4058: my $mapid;
1.607 raeburn 4059: foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60 albertel 4060: my $maptitle = $maplist{$mapid};
1.57 albertel 4061:
4062: #----------------------- loop through ids and get all parameter types for map
4063: #----------------------------------------- and associated information
4064: my %name = ();
4065: my %part = ();
4066: my %display = ();
4067: my %type = ();
4068: my %default = ();
4069: my $map = 0;
4070:
1.473 amueller 4071: # $r->print("Catmarker: @catmarker<br />\n");
1.446 bisitz 4072:
1.548 raeburn 4073: foreach my $id (@ids) {
4074: ($map)=($id =~ /([\d]*?)\./);
4075: my $rid = $id;
1.446 bisitz 4076:
1.57 albertel 4077: # $r->print("$mapid:$map: $rid <br /> \n");
4078:
1.560 damieng 4079: if ($map eq $mapid) {
1.473 amueller 4080: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4081: my $toolsymb;
4082: if ($uri =~ /ext\.tool$/) {
4083: $toolsymb = $symbp{$rid};
4084: }
1.582 raeburn 4085:
1.57 albertel 4086: # $r->print("Keys: $keyp{$rid} <br />\n");
4087:
4088: #--------------------------------------------------------------------
4089: # @catmarker contains list of all possible parameters including part #s
4090: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4091: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4092: # When storing information, store as part 0
4093: # When requesting information, request from full part
4094: #-------------------------------------------------------------------
1.548 raeburn 4095: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4096: my $tempkeyp = $fullkeyp;
4097: $tempkeyp =~ s/_\w+_/_0_/;
1.473 amueller 4098:
1.548 raeburn 4099: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4100: $part{$tempkeyp}="0";
1.584 raeburn 4101: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4102: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4103: if ($allparms{$name{$tempkeyp}} ne '') {
4104: my $identifier;
4105: if ($parmdis =~ /(\s*\[Part.*)$/) {
4106: $identifier = $1;
4107: }
4108: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4109: } else {
4110: $display{$tempkeyp} = $parmdis;
4111: }
4112: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4113: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4114: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4115: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4116: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473 amueller 4117: }
4118: } # end loop through keys
1.560 damieng 4119: }
1.57 albertel 4120: } # end loop through ids
1.446 bisitz 4121:
1.57 albertel 4122: #---------------------------------------------------- print header information
1.133 www 4123: my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82 www 4124: my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401 bisitz 4125: my $tmp="";
1.57 albertel 4126: if ($uname) {
1.473 amueller 4127: my $person=&Apache::loncommon::plainname($uname,$udom);
1.401 bisitz 4128: $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
4129: &mt('in')." \n";
1.57 albertel 4130: } else {
1.401 bisitz 4131: $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57 albertel 4132: }
1.269 raeburn 4133: if ($cgroup) {
1.401 bisitz 4134: $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
4135: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4136: $csec = '';
4137: } elsif ($csec) {
1.401 bisitz 4138: $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
4139: "</i></font> ".&mt('of')." \n";
1.269 raeburn 4140: }
1.401 bisitz 4141: $r->print('<div align="center"><h4>'
4142: .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404 bisitz 4143: ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401 bisitz 4144: ,$tmp
4145: ,'<font color="red"><i>'.$coursename.'</i></font>'
4146: )
4147: ."<br /></h4>\n"
1.422 bisitz 4148: );
1.57 albertel 4149: #---------------------------------------------------------------- print table
1.419 bisitz 4150: $r->print('<p>'.&Apache::loncommon::start_data_table()
4151: .&Apache::loncommon::start_data_table_header_row()
4152: .'<th>'.&mt('Parameter Name').'</th>'
1.578 raeburn 4153: .'<th>'.&mt('Value').'</th>'
1.419 bisitz 4154: .'<th>'.&mt('Parameter in Effect').'</th>'
4155: .&Apache::loncommon::end_data_table_header_row()
4156: );
1.57 albertel 4157:
1.582 raeburn 4158: my $navmap = Apache::lonnavmaps::navmap->new();
4159: my @recurseup;
4160: if (ref($navmap)) {
4161: my $mapres = $navmap->getByMapPc($mapid);
4162: if (ref($mapres)) {
4163: @recurseup = $navmap->recurseup_maps($mapres->src());
4164: }
4165: }
4166:
4167:
1.548 raeburn 4168: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473 amueller 4169: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4170: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269 raeburn 4171: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568 raeburn 4172: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582 raeburn 4173: $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
4174: \$numreclinks);
1.57 albertel 4175: }
1.422 bisitz 4176: $r->print(&Apache::loncommon::end_data_table().'</p>'
4177: .'</div>'
4178: );
1.57 albertel 4179: } # end each map
4180: } # end of $parmlev eq map
4181: #--------------------------------- Entry for parm level general (Course level)
4182: if ($parmlev eq 'general') {
1.473 amueller 4183: my $defbgone = '#E0E099';
1.419 bisitz 4184: my $defbgtwo = '#FFFF99';
4185: my $defbgthree = '#FFBB99';
1.57 albertel 4186:
4187: #-------------------------------------------- for each map, gather information
4188: my $mapid="0.0";
4189: #----------------------- loop through ids and get all parameter types for map
4190: #----------------------------------------- and associated information
4191: my %name = ();
4192: my %part = ();
4193: my %display = ();
4194: my %type = ();
4195: my %default = ();
1.446 bisitz 4196:
1.548 raeburn 4197: foreach $id (@ids) {
4198: my $rid = $id;
1.446 bisitz 4199:
1.196 www 4200: my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584 raeburn 4201: my $toolsymb;
4202: if ($uri =~ /ext\.tool$/) {
4203: $toolsymb = $symbp{$rid};
4204: }
1.57 albertel 4205:
4206: #--------------------------------------------------------------------
4207: # @catmarker contains list of all possible parameters including part #s
4208: # $fullkeyp contains the full part/id # for the extraction of proper parameters
4209: # $tempkeyp contains part 0 only (no ids - ie, subparts)
4210: # When storing information, store as part 0
4211: # When requesting information, request from full part
4212: #-------------------------------------------------------------------
1.548 raeburn 4213: foreach my $fullkeyp (&keysplit($keyp{$rid})) {
4214: my $tempkeyp = $fullkeyp;
4215: $tempkeyp =~ s/_\w+_/_0_/;
4216: if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473 amueller 4217: $part{$tempkeyp}="0";
1.584 raeburn 4218: $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
4219: my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473 amueller 4220: if ($allparms{$name{$tempkeyp}} ne '') {
4221: my $identifier;
4222: if ($parmdis =~ /(\s*\[Part.*)$/) {
4223: $identifier = $1;
4224: }
4225: $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
4226: } else {
4227: $display{$tempkeyp} = $parmdis;
4228: }
4229: unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
4230: $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
4231: $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584 raeburn 4232: $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
4233: $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560 damieng 4234: }
1.57 albertel 4235: } # end loop through keys
4236: } # end loop through ids
1.446 bisitz 4237:
1.57 albertel 4238: #---------------------------------------------------- print header information
1.473 amueller 4239: my $setdef=&mt("Set Defaults for All Resources in Course");
1.57 albertel 4240: $r->print(<<ENDMAPONE);
1.419 bisitz 4241: <center>
4242: <h4>$setdef
1.135 albertel 4243: <font color="red"><i>$coursename</i></font><br />
1.57 albertel 4244: ENDMAPONE
4245: if ($uname) {
1.473 amueller 4246: my $person=&Apache::loncommon::plainname($uname,$udom);
1.135 albertel 4247: $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57 albertel 4248: } else {
1.135 albertel 4249: $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57 albertel 4250: }
1.446 bisitz 4251:
1.135 albertel 4252: if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306 albertel 4253: if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135 albertel 4254: $r->print("</h4>\n");
1.57 albertel 4255: #---------------------------------------------------------------- print table
1.419 bisitz 4256: $r->print('<p>'.&Apache::loncommon::start_data_table()
4257: .&Apache::loncommon::start_data_table_header_row()
4258: .'<th>'.&mt('Parameter Name').'</th>'
4259: .'<th>'.&mt('Default Value').'</th>'
4260: .'<th>'.&mt('Parameter in Effect').'</th>'
4261: .&Apache::loncommon::end_data_table_header_row()
4262: );
1.57 albertel 4263:
1.548 raeburn 4264: foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419 bisitz 4265: $r->print(&Apache::loncommon::start_data_table_row());
1.548 raeburn 4266: &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568 raeburn 4267: \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
4268: $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
4269: $readonly);
1.57 albertel 4270: }
1.419 bisitz 4271: $r->print(&Apache::loncommon::end_data_table()
4272: .'</p>'
4273: .'</center>'
4274: );
1.57 albertel 4275: } # end of $parmlev eq general
1.606 raeburn 4276: $r->print('</div>');
1.43 albertel 4277: }
1.507 www 4278: $r->print('</form>');
1.582 raeburn 4279: if ($numreclinks) {
4280: $r->print(<<"END");
4281: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
4282: <input type="hidden" name="pschp" />
4283: <input type="hidden" name="pscat" />
4284: <input type="hidden" name="psprt" />
4285: <input type="hidden" name="hideparmsel" value="hidden" />
4286: </form>
4287: <script type="text/javascript">
4288: function pjumprec(rid,name,part) {
4289: document.forms.recurseform.pschp.value = rid;
4290: document.forms.recurseform.pscat.value = name;
4291: document.forms.recurseform.psprt.value = part;
4292: document.forms.recurseform.submit();
4293: return false;
4294: }
4295: </script>
4296: END
4297: }
1.507 www 4298: &endSettingsScreen($r);
4299: $r->print(&Apache::loncommon::end_page());
1.57 albertel 4300: } # end sub assessparms
1.30 www 4301:
1.560 damieng 4302:
4303:
1.120 www 4304: ##################################################
1.560 damieng 4305: # OVERVIEW MODE
1.207 www 4306: ##################################################
1.124 www 4307:
1.563 damieng 4308: my $tableopen; # boolean, true if HTML table is already opened
4309:
4310: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
4311: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
4312: # @returns {string}
1.124 www 4313: sub tablestart {
1.576 raeburn 4314: my ($readonly,$is_map) = @_;
1.124 www 4315: if ($tableopen) {
1.552 raeburn 4316: return '';
1.124 www 4317: } else {
1.552 raeburn 4318: $tableopen=1;
4319: my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
4320: if ($readonly) {
4321: $output .= '<th>'.&mt('Current value').'</th>';
4322: } else {
1.576 raeburn 4323: $output .= '<th>'.&mt('Delete').'</th>'.
4324: '<th>'.&mt('Set to ...').'</th>';
4325: if ($is_map) {
4326: $output .= '<th>'.&mt('Recursive?').'</th>';
4327: }
1.552 raeburn 4328: }
4329: $output .= '</tr>';
4330: return $output;
1.124 www 4331: }
4332: }
4333:
1.563 damieng 4334: # Returns HTML with the HTML table end tag, unless the table is not opened.
4335: # @returns {string}
1.124 www 4336: sub tableend {
4337: if ($tableopen) {
1.560 damieng 4338: $tableopen=0;
4339: return &Apache::loncommon::end_data_table();
1.124 www 4340: } else {
1.560 damieng 4341: return'';
1.124 www 4342: }
4343: }
4344:
1.563 damieng 4345: # Reads course and user information.
4346: # 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).
4347: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
4348: # If the context is looking for a list, returns a list with the scalar data and the class list.
4349: # @param {string} $crs - course number
4350: # @param {string} $dom - course domain
4351: # @returns {hash reference|Array}
1.207 www 4352: sub readdata {
4353: my ($crs,$dom)=@_;
4354: # Read coursedata
4355: my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
4356: # Read userdata
4357:
4358: my $classlist=&Apache::loncoursedata::get_classlist();
1.548 raeburn 4359: foreach my $user (keys(%$classlist)) {
4360: if ($user=~/^($match_username)\:($match_domain)$/) {
4361: my ($tuname,$tudom)=($1,$2);
4362: my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
4363: foreach my $userkey (keys(%{$useropt})) {
4364: if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207 www 4365: my $newkey=$userkey;
1.548 raeburn 4366: $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
4367: $$resourcedata{$newkey}=$$useropt{$userkey};
4368: }
4369: }
1.473 amueller 4370: }
4371: }
1.552 raeburn 4372: if (wantarray) {
4373: return ($resourcedata,$classlist);
4374: } else {
4375: return $resourcedata;
4376: }
1.207 www 4377: }
4378:
4379:
1.563 damieng 4380: # Stores parameter data, using form parameters directly.
4381: #
4382: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.588 raeburn 4383: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563 damieng 4384: # del_* - remove a parameter
4385: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
4386: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
4387: # key_* - date values
4388: # days_* - for date intervals
4389: # hours_* - for date intervals
4390: # minutes_* - for date intervals
4391: # seconds_* - for date intervals
4392: # done_* - for date intervals
4393: # typeof_* - parameter type
4394: #
4395: # @param {Apache2::RequestRec} $r - the Apache request
4396: # @param {string} $crs - course number
4397: # @param {string} $dom - course domain
1.208 www 4398: sub storedata {
4399: my ($r,$crs,$dom)=@_;
1.207 www 4400: # Set userlevel immediately
4401: # Do an intermediate store of course level
4402: my $olddata=&readdata($crs,$dom);
1.124 www 4403: my %newdata=();
4404: undef %newdata;
4405: my @deldata=();
1.576 raeburn 4406: my @delrec=();
4407: my @delnonrec=();
1.124 www 4408: undef @deldata;
1.504 raeburn 4409: my ($got_chostname,$chostname,$cmajor,$cminor);
1.546 raeburn 4410: my $now = time;
1.560 damieng 4411: foreach my $key (keys(%env)) {
4412: if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
4413: my $cmd=$1;
4414: my $thiskey=$2;
1.576 raeburn 4415: my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588 raeburn 4416: next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576 raeburn 4417: if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) &&
4418: ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
4419: unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
4420: $altkey = $thiskey;
4421: $altkey =~ s/\Q___(all)\E/___(rec)/;
4422: if ($env{'form.rec_'.$thiskey}) {
4423: $recursive = 1;
4424: }
4425: }
4426: }
1.560 damieng 4427: my ($tuname,$tudom)=&extractuser($thiskey);
1.473 amueller 4428: if ($tuname) {
1.576 raeburn 4429: $tkey=$thiskey;
1.560 damieng 4430: $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576 raeburn 4431: if ($altkey) {
4432: $tkeynonrec = $tkey;
4433: $tkeyrec = $altkey;
4434: $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
4435: }
1.560 damieng 4436: }
4437: if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563 damieng 4438: my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
4439: if ($cmd eq 'set') {
4440: $data=$env{$key};
4441: $valmatch = '';
4442: $valchk = $data;
4443: $typeof=$env{'form.typeof_'.$thiskey};
4444: $text = &mt('Saved modified parameter for');
4445: if ($typeof eq 'string_questiontype') {
4446: $name = 'type';
1.588 raeburn 4447: } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
4448: ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563 damieng 4449: my $stringmatch = &standard_string_matches($typeof);
4450: if (ref($stringmatch) eq 'ARRAY') {
4451: foreach my $item (@{$stringmatch}) {
4452: if (ref($item) eq 'ARRAY') {
4453: my ($regexpname,$pattern) = @{$item};
4454: if ($pattern ne '') {
4455: if ($data =~ /$pattern/) {
4456: $valmatch = $regexpname;
4457: $valchk = '';
4458: last;
4459: }
1.560 damieng 4460: }
1.549 raeburn 4461: }
4462: }
4463: }
1.563 damieng 4464: } elsif ($typeof eq 'string_discussvote') {
4465: $name = 'discussvote';
4466: } elsif ($typeof eq 'string_examcode') {
4467: $name = 'examcode';
4468: if (&Apache::lonnet::validCODE($data)) {
4469: $valchk = 'valid';
4470: }
4471: } elsif ($typeof eq 'string_yesno') {
4472: if ($thiskey =~ /\.retrypartial$/) {
4473: $name = 'retrypartial';
4474: }
1.549 raeburn 4475: }
1.563 damieng 4476: } elsif ($cmd eq 'datepointer') {
4477: $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
4478: $typeof=$env{'form.typeof_'.$thiskey};
4479: $text = &mt('Saved modified date for');
4480: if ($typeof eq 'date_start') {
4481: if ($thiskey =~ /\.printstartdate$/) {
4482: $name = 'printstartdate';
4483: if (($data) && ($data > $now)) {
4484: $valchk = 'future';
4485: }
1.560 damieng 4486: }
1.563 damieng 4487: } elsif ($typeof eq 'date_end') {
4488: if ($thiskey =~ /\.printenddate$/) {
4489: $name = 'printenddate';
4490: if (($data) && ($data < $now)) {
4491: $valchk = 'past';
4492: }
1.560 damieng 4493: }
1.504 raeburn 4494: }
1.563 damieng 4495: } elsif ($cmd eq 'dateinterval') {
4496: $data=&get_date_interval_from_form($thiskey);
4497: if ($thiskey =~ /\.interval$/) {
4498: $name = 'interval';
4499: my $intervaltype = &get_intervaltype($name);
4500: my $intervalmatch = &standard_interval_matches($intervaltype);
4501: if (ref($intervalmatch) eq 'ARRAY') {
4502: foreach my $item (@{$intervalmatch}) {
4503: if (ref($item) eq 'ARRAY') {
4504: my ($regexpname,$pattern) = @{$item};
4505: if ($pattern ne '') {
4506: if ($data =~ /$pattern/) {
4507: $valmatch = $regexpname;
4508: $valchk = '';
4509: last;
4510: }
1.560 damieng 4511: }
1.554 raeburn 4512: }
4513: }
4514: }
4515: }
1.563 damieng 4516: $typeof=$env{'form.typeof_'.$thiskey};
4517: $text = &mt('Saved modified date for');
1.554 raeburn 4518: }
1.576 raeburn 4519: if ($recursive) {
1.563 damieng 4520: $namematch = 'maplevelrecurse';
1.560 damieng 4521: }
1.563 damieng 4522: if (($name ne '') || ($namematch ne '')) {
4523: my ($needsrelease,$needsnewer);
4524: if ($name ne '') {
4525: $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560 damieng 4526: if ($needsrelease) {
4527: unless ($got_chostname) {
1.563 damieng 4528: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.560 damieng 4529: $got_chostname = 1;
4530: }
1.563 damieng 4531: $needsnewer = ¶meter_releasecheck($name,$valchk,$valmatch,undef,
4532: $needsrelease,
4533: $cmajor,$cminor);
4534: }
4535: }
4536: if ($namematch ne '') {
4537: if ($needsnewer) {
4538: undef($namematch);
1.560 damieng 4539: } else {
1.563 damieng 4540: my $currneeded;
4541: if ($needsrelease) {
4542: $currneeded = $needsrelease;
4543: }
4544: $needsrelease =
4545: $Apache::lonnet::needsrelease{"parameter::::$namematch"};
4546: if (($needsrelease) &&
4547: (($currneeded eq '') || ($needsrelease < $currneeded))) {
4548: unless ($got_chostname) {
4549: ($chostname,$cmajor,$cminor) = ¶meter_release_vars();
4550: $got_chostname = 1;
4551: }
4552: $needsnewer = ¶meter_releasecheck(undef,$valchk,$valmatch,
4553: $namematch, $needsrelease,$cmajor,$cminor);
4554: } else {
4555: undef($namematch);
4556: }
1.560 damieng 4557: }
1.557 raeburn 4558: }
1.563 damieng 4559: if ($needsnewer) {
4560: $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
4561: $chostname,$cmajor,
4562: $cminor,$needsrelease));
4563: next;
4564: }
1.504 raeburn 4565: }
1.576 raeburn 4566: my ($reconlychg,$haschange,$storekey);
4567: if ($tuname) {
4568: my $ustorekey;
4569: if ($altkey) {
4570: if ($recursive) {
4571: if (exists($$olddata{$thiskey})) {
4572: if ($$olddata{$thiskey} eq $data) {
4573: $reconlychg = 1;
4574: }
4575: &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
4576: }
4577: if (exists($$olddata{$altkey})) {
4578: if (defined($data) && $$olddata{$altkey} ne $data) {
4579: $haschange = 1;
4580: }
4581: } elsif ((!$reconlychg) && ($data ne '')) {
4582: $haschange = 1;
4583: }
4584: $ustorekey = $tkeyrec;
4585: } else {
4586: if (exists($$olddata{$altkey})) {
4587: if ($$olddata{$altkey} eq $data) {
4588: $reconlychg = 1;
4589: }
4590: &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
4591: }
4592: if (exists($$olddata{$thiskey})) {
4593: if (defined($data) && $$olddata{$thiskey} ne $data) {
4594: $haschange = 1;
4595: }
4596: } elsif ((!$reconlychg) && ($data ne '')) {
4597: $haschange = 1;
4598: }
4599: $ustorekey = $tkeynonrec;
4600: }
4601: } else {
4602: if (exists($$olddata{$tkey})) {
4603: if (defined($data) && $$olddata{$tkey} ne $data) {
4604: $haschange = 1;
4605: }
4606: $ustorekey = $tkey;
4607: }
4608: }
4609: if ($haschange || $reconlychg) {
4610: unless ($env{'form.del_'.$thiskey}) {
4611: if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
4612: $ustorekey.'.type' => $typeof},
4613: $tudom,$tuname) eq 'ok') {
4614: &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
4615: $r->print('<br />'.$text.' '.
4616: &Apache::loncommon::plainname($tuname,$tudom));
4617: } else {
4618: $r->print('<div class="LC_error">'.
4619: &mt('Error saving parameters').'</div>');
4620: }
4621: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4622: }
4623: }
4624: } else {
4625: if ($altkey) {
4626: if ($recursive) {
4627: if (exists($$olddata{$thiskey})) {
4628: if ($$olddata{$thiskey} eq $data) {
4629: $reconlychg = 1;
4630: }
4631: push(@delnonrec,($thiskey,$thiskey.'.type'));
4632: }
4633: if (exists($$olddata{$altkey})) {
4634: if (defined($data) && $$olddata{$altkey} ne $data) {
4635: $haschange = 1;
4636: }
4637: } elsif (($data ne '') && (!$reconlychg)) {
4638: $haschange = 1;
4639: }
4640: $storekey = $altkey;
1.563 damieng 4641: } else {
1.576 raeburn 4642: if (exists($$olddata{$altkey})) {
4643: if ($$olddata{$altkey} eq $data) {
4644: $reconlychg = 1;
4645: }
4646: push(@delrec,($altkey,$altkey.'.type'));
4647: }
4648: if (exists($$olddata{$thiskey})) {
4649: if (defined($data) && $$olddata{$thiskey} ne $data) {
4650: $haschange = 1;
4651: }
4652: } elsif (($data ne '') && (!$reconlychg)) {
4653: $haschange = 1;
4654: }
4655: $storekey = $thiskey;
1.563 damieng 4656: }
1.560 damieng 4657: } else {
1.576 raeburn 4658: if (defined($data) && $$olddata{$thiskey} ne $data) {
4659: $haschange = 1;
4660: $storekey = $thiskey;
4661: }
4662: }
4663: }
4664: if ($reconlychg || $haschange) {
4665: unless ($env{'form.del_'.$thiskey}) {
4666: $newdata{$storekey}=$data;
4667: $newdata{$storekey.'.type'}=$typeof;
1.560 damieng 4668: }
4669: }
4670: } elsif ($cmd eq 'del') {
4671: if ($tuname) {
1.576 raeburn 4672: my $error;
4673: if ($altkey) {
4674: if (exists($$olddata{$altkey})) {
4675: if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
4676: &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
4677: if ($recursive) {
4678: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4679: }
4680: } elsif ($recursive) {
4681: $error = 1;
4682: }
4683: }
4684: if (exists($$olddata{$thiskey})) {
4685: if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
4686: &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
4687: unless ($recursive) {
4688: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4689: }
4690: } elsif (!$recursive) {
4691: $error = 1;
4692: }
4693: }
1.560 damieng 4694: } else {
1.576 raeburn 4695: if (exists($$olddata{$thiskey})) {
4696: if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
4697: &log_parmset({$tkey=>''},1,$tuname,$tudom);
4698: $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
4699: } else {
4700: $error = 1;
4701: }
4702: }
4703: }
4704: if ($error) {
1.560 damieng 4705: $r->print('<div class="LC_error">'.
4706: &mt('Error deleting parameters').'</div>');
4707: }
4708: &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
4709: } else {
1.576 raeburn 4710: if ($altkey) {
4711: if (exists($$olddata{$altkey})) {
4712: unless (grep(/^\Q$altkey\E$/,@delrec)) {
4713: push(@deldata,($altkey,$altkey.'.type'));
4714: }
4715: }
4716: if (exists($$olddata{$thiskey})) {
4717: unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
4718: push(@deldata,($thiskey,$thiskey.'.type'));
4719: }
4720: }
4721: } elsif (exists($$olddata{$thiskey})) {
4722: push(@deldata,($thiskey,$thiskey.'.type'));
4723: }
1.560 damieng 4724: }
1.473 amueller 4725: }
4726: }
4727: }
1.207 www 4728: # Store all course level
1.144 www 4729: my $delentries=$#deldata+1;
1.576 raeburn 4730: my @alldels;
4731: if (@delrec) {
4732: push(@alldels,@delrec);
4733: }
4734: if (@delnonrec) {
4735: push(@alldels,@delnonrec);
4736: }
4737: if (@deldata) {
4738: push(@alldels,@deldata);
4739: }
1.548 raeburn 4740: my @newdatakeys=keys(%newdata);
1.144 www 4741: my $putentries=$#newdatakeys+1;
1.576 raeburn 4742: my ($delresult,$devalidate);
4743: if (@alldels) {
4744: if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
4745: my %loghash=map { $_ => '' } @alldels;
1.560 damieng 4746: &log_parmset(\%loghash,1);
1.576 raeburn 4747: if ($delentries) {
4748: $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
4749: }
4750: } elsif ($delentries) {
1.560 damieng 4751: $r->print('<div class="LC_error">'.
4752: &mt('Error deleting parameters').'</div>');
4753: }
1.576 raeburn 4754: $devalidate = 1;
1.144 www 4755: }
4756: if ($putentries) {
1.560 damieng 4757: if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
4758: &log_parmset(\%newdata,0);
4759: $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
4760: } else {
4761: $r->print('<div class="LC_error">'.
4762: &mt('Error saving parameters').'</div>');
4763: }
1.576 raeburn 4764: $devalidate = 1;
4765: }
4766: if ($devalidate) {
1.560 damieng 4767: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144 www 4768: }
1.208 www 4769: }
1.207 www 4770:
1.563 damieng 4771: # Returns the username and domain from a key created in readdata from a resourcedata key.
4772: #
4773: # @param {string} $key - the key
4774: # @returns {Array}
1.208 www 4775: sub extractuser {
4776: my $key=shift;
1.350 albertel 4777: return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208 www 4778: }
1.206 www 4779:
1.563 damieng 4780: # Parses a parameter key and returns the components.
4781: #
4782: # @param {string} $key -
4783: # @param {hash reference} $listdata -
4784: # @return {Array} - (student, resource, part, parameter)
1.381 albertel 4785: sub parse_listdata_key {
4786: my ($key,$listdata) = @_;
4787: # split into student/section affected, and
4788: # the realm (folder/resource part and parameter
1.446 bisitz 4789: my ($student,$realm) =
1.473 amueller 4790: ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381 albertel 4791: # if course wide student would be undefined
4792: if (!defined($student)) {
1.560 damieng 4793: ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381 albertel 4794: }
4795: # strip off the .type if it's not the Question type parameter
4796: if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560 damieng 4797: $realm=~s/\.type//;
1.381 albertel 4798: }
4799: # split into resource+part and parameter name
1.388 albertel 4800: my ($res, $parm) = ($realm=~/^(.*)\.(.*)$/);
4801: ($res, my $part) = ($res =~/^(.*)\.(.*)$/);
1.381 albertel 4802: return ($student,$res,$part,$parm);
4803: }
4804:
1.563 damieng 4805: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
4806: #
4807: # @param {Apache2::RequestRec} $r - the Apache request
4808: # @param {hash reference} $resourcedata - parameter data returned by readdata
4809: # @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
4810: # @param {string} $sortorder - realmstudent|studentrealm
4811: # @param {string} $caller - name of the calling sub (overview|newoverview)
4812: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568 raeburn 4813: # @param {boolean} $readonly - true if editing not allowed
1.608 raeburn 4814: # @param {string} $parmlev - full|map
4815: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order
4816: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 4817: # @returns{integer} - number of $listdata parameters processed
1.208 www 4818: sub listdata {
1.608 raeburn 4819: my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552 raeburn 4820:
1.207 www 4821: # Start list output
1.206 www 4822:
1.122 www 4823: my $oldsection='';
4824: my $oldrealm='';
4825: my $oldpart='';
1.123 www 4826: my $pointer=0;
1.124 www 4827: $tableopen=0;
1.145 www 4828: my $foundkeys=0;
1.248 albertel 4829: my %keyorder=&standardkeyorder();
1.594 raeburn 4830: my $readonlyall = $readonly;
1.381 albertel 4831:
1.552 raeburn 4832: my ($secidx,%grouphash);
4833: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4834: $secidx = &Apache::loncoursedata::CL_SECTION();
1.553 raeburn 4835: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4836: %grouphash = &Apache::longroup::coursegroups();
4837: } elsif ($env{'request.course.groups'} ne '') {
1.585 raeburn 4838: map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553 raeburn 4839: }
1.552 raeburn 4840: }
4841:
1.576 raeburn 4842: foreach my $key (sort {
1.560 damieng 4843: my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
4844: my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608 raeburn 4845: my ($aid,$bid);
4846: if ($caller eq 'newoverview') {
4847: if (ref($hash_for_realm) eq 'HASH') {
4848: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4849: my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4850: my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
4851: $aid = $hash_for_realm->{$aurl};
4852: $bid = $hash_for_realm->{$burl};
4853: } elsif ($parmlev eq 'full') {
4854: $aid = $hash_for_realm->{$ares};
4855: $bid = $hash_for_realm->{$bres};
4856: }
4857: }
4858: }
1.381 albertel 4859:
1.560 damieng 4860: # get the numerical order for the param
4861: $aparm=$keyorder{'parameter_0_'.$aparm};
4862: $bparm=$keyorder{'parameter_0_'.$bparm};
1.381 albertel 4863:
1.560 damieng 4864: my $result=0;
1.381 albertel 4865:
1.560 damieng 4866: if ($sortorder eq 'realmstudent') {
1.381 albertel 4867: if ($ares ne $bres ) {
1.608 raeburn 4868: if ($caller eq 'newoverview') {
4869: if (ref($hash_for_realm) eq 'HASH') {
4870: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4871: $result = ($aid <=> $bid);
4872: } elsif ($parmlev eq 'full') {
4873: $result = ($aid <=> $bid);
4874: } else {
4875: $result = ($ares cmp $bres);
4876: }
4877: } else {
4878: $result = ($ares cmp $bres);
4879: }
4880: } else {
4881: $result = ($ares cmp $bres);
4882: }
1.446 bisitz 4883: } elsif ($astudent ne $bstudent) {
1.560 damieng 4884: $result = ($astudent cmp $bstudent);
4885: } elsif ($apart ne $bpart ) {
4886: $result = ($apart cmp $bpart);
4887: }
4888: } else {
4889: if ($astudent ne $bstudent) {
4890: $result = ($astudent cmp $bstudent);
4891: } elsif ($ares ne $bres ) {
1.608 raeburn 4892: if ($caller eq 'newoverview') {
4893: if (ref($hash_for_realm) eq 'HASH') {
4894: if (($parmlev eq 'map') && ($pschp eq 'all')) {
4895: $result = ($aid <=> $bid);
4896: } elsif ($parmlev eq 'full') {
4897: $result = ($aid <=> $bid);
4898: } else {
4899: $result = ($ares cmp $bres);
4900: }
4901: } else {
4902: $result = ($ares cmp $bres);
4903: }
4904: } else {
4905: $result = ($ares cmp $bres);
4906: }
1.560 damieng 4907: } elsif ($apart ne $bpart ) {
4908: $result = ($apart cmp $bpart);
4909: }
1.473 amueller 4910: }
1.446 bisitz 4911:
1.560 damieng 4912: if (!$result) {
1.381 albertel 4913: if (defined($aparm) && defined($bparm)) {
1.560 damieng 4914: $result = ($aparm <=> $bparm);
1.381 albertel 4915: } elsif (defined($aparm)) {
1.560 damieng 4916: $result = -1;
1.381 albertel 4917: } elsif (defined($bparm)) {
1.560 damieng 4918: $result = 1;
4919: }
1.473 amueller 4920: }
1.381 albertel 4921:
1.560 damieng 4922: $result;
4923:
1.576 raeburn 4924: } keys(%{$listdata})) { # foreach my $key
4925: my $thiskey = $key;
1.560 damieng 4926: if ($$listdata{$thiskey.'.type'}) {
4927: my $thistype=$$listdata{$thiskey.'.type'};
4928: if ($$resourcedata{$thiskey.'.type'}) {
4929: $thistype=$$resourcedata{$thiskey.'.type'};
4930: }
4931: my ($middle,$part,$name)=
1.572 damieng 4932: ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560 damieng 4933: my $section=&mt('All Students');
1.594 raeburn 4934: $readonly = $readonlyall;
1.599 raeburn 4935: my $userscope;
1.576 raeburn 4936: my $showval = $$resourcedata{$thiskey};
1.560 damieng 4937: if ($middle=~/^\[(.*)\]/) {
4938: my $issection=$1;
4939: if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
4940: my ($stuname,$studom) = ($1,$2);
4941: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4942: if (ref($classlist) eq 'HASH') {
4943: if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
4944: next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'});
4945: }
4946: }
4947: }
4948: $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599 raeburn 4949: $userscope = 1;
1.560 damieng 4950: } else {
4951: if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4952: if (exists($grouphash{$issection})) {
4953: $section=&mt('Group').': '.$issection;
4954: } elsif ($issection eq $env{'request.course.sec'}) {
4955: $section = &mt('Section').': '.$issection;
4956: } else {
4957: next;
1.552 raeburn 4958: }
1.560 damieng 4959: } else {
4960: $section=&mt('Group/Section').': '.$issection;
1.552 raeburn 4961: }
4962: }
1.560 damieng 4963: $middle=~s/^\[(.*)\]//;
4964: } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
4965: $readonly = 1;
4966: }
4967: $middle=~s/\.+$//;
4968: $middle=~s/^\.+//;
4969: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576 raeburn 4970: my ($is_map,$is_recursive,$mapurl,$maplevel);
4971: if ($caller eq 'overview') {
4972: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
4973: $mapurl = $1;
4974: $maplevel = $2;
4975: $is_map = 1;
4976: }
4977: } elsif ($caller eq 'newoverview') {
4978: if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
4979: $mapurl = $1;
4980: $maplevel = $2;
4981: $is_map = 1;
4982: }
4983: }
4984: if ($is_map) {
1.560 damieng 4985: my $leveltitle = &mt('Folder/Map');
1.615 raeburn 4986: my $title = &Apache::lonnet::gettitle($mapurl);
1.608 raeburn 4987: if (ref($hash_for_realm) eq 'HASH') {
4988: if ($hash_for_realm->{$mapurl} eq '1') {
4989: $title = &mt('Main Content');
4990: }
4991: }
1.576 raeburn 4992: unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {
4993: if ($caller eq 'newoverview') {
4994: my $altkey = $thiskey;
4995: $altkey =~ s/\Q___(all)\E/___(rec)/;
4996: if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
4997: $is_recursive = 1;
4998: if ($$resourcedata{$altkey.'.type'}) {
4999: $thistype=$$resourcedata{$altkey.'.type'};
5000: }
5001: $showval = $$resourcedata{$altkey};
5002: }
5003: } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
5004: $thiskey =~ s/\Q___(rec)\E/___(all)/;
5005: $is_recursive = 1;
5006: }
1.560 damieng 5007: }
1.608 raeburn 5008: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560 damieng 5009: } elsif ($middle) {
5010: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609 raeburn 5011: next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560 damieng 5012: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
5013: ': '.&Apache::lonnet::gettitle($middle).
5014: ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
5015: $id.')</span></span>';
5016: }
5017: if ($sortorder eq 'realmstudent') {
5018: if ($realm ne $oldrealm) {
5019: $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
5020: $oldrealm=$realm;
5021: $oldsection='';
5022: }
5023: if ($section ne $oldsection) {
5024: $r->print(&tableend()."\n<h2>$section</h2>");
5025: $oldsection=$section;
5026: $oldpart='';
5027: }
1.552 raeburn 5028: } else {
1.560 damieng 5029: if ($section ne $oldsection) {
5030: $r->print(&tableend()."\n<hr /><h1>$section</h1>");
5031: $oldsection=$section;
5032: $oldrealm='';
5033: }
5034: if ($realm ne $oldrealm) {
5035: $r->print(&tableend()."\n<h2>$realm</h2>");
5036: $oldrealm=$realm;
5037: $oldpart='';
1.552 raeburn 5038: }
5039: }
1.560 damieng 5040: if ($part ne $oldpart) {
5041: $r->print(&tableend().
5042: "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
5043: $oldpart=$part;
1.556 raeburn 5044: }
1.560 damieng 5045: #
5046: # Ready to print
5047: #
1.470 raeburn 5048: my $parmitem = &standard_parameter_names($name);
1.619 ! raeburn 5049: my $advice;
! 5050: if (($name eq 'mapalias') && ($middle) && (!$is_map)) {
! 5051: if ($middle =~ m{^uploaded/}) {
! 5052: $advice = &mt('Use Course Editor to set this.');
! 5053: } else {
! 5054: $advice = &mt('Use Resource Assembly Tool to set this.');
! 5055: }
! 5056: $advice = '<br /><span class="LC_fontsize_small LC_cusr_emph">'.$advice.'</span>';
! 5057: }
1.576 raeburn 5058: $r->print(&tablestart($readonly,$is_map).
1.560 damieng 5059: &Apache::loncommon::start_data_table_row().
5060: '<td><b>'.&mt($parmitem).
1.619 ! raeburn 5061: '</b>'.$advice.'</td>');
1.560 damieng 5062: unless ($readonly) {
1.599 raeburn 5063: my $disabled;
5064: if (($name eq 'availablestudent') &&
5065: (($showval eq '') || ($userscope))) {
5066: $disabled = ' disabled="disabled"';
1.619 ! raeburn 5067: } elsif (($name eq 'mapalias') && ($showval eq '')) {
! 5068: $disabled = ' disabled="disabled"';
1.599 raeburn 5069: }
1.560 damieng 5070: $r->print('<td><input type="checkbox" name="del_'.
1.599 raeburn 5071: $thiskey.'"'.$disabled.' /></td>');
1.560 damieng 5072: }
5073: $r->print('<td>');
5074: $foundkeys++;
5075: if (&isdateparm($thistype)) {
5076: my $jskey='key_'.$pointer;
5077: my $state;
5078: $pointer++;
5079: if ($readonly) {
5080: $state = 'disabled';
5081: }
5082: $r->print(
5083: &Apache::lonhtmlcommon::date_setter('parmform',
5084: $jskey,
1.576 raeburn 5085: $showval,
1.560 damieng 5086: '',1,$state));
5087: unless ($readonly) {
5088: $r->print(
5089: '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576 raeburn 5090: (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560 damieng 5091: &mt('Shift all dates based on this date').'</a></span>':'').
1.576 raeburn 5092: &date_sanity_info($showval)
1.560 damieng 5093: );
5094: }
5095: } elsif ($thistype eq 'date_interval') {
5096: $r->print(&date_interval_selector($thiskey,$name,
1.576 raeburn 5097: $showval,$readonly));
1.560 damieng 5098: } elsif ($thistype =~ m/^string/) {
1.599 raeburn 5099: if ($name eq 'availablestudent') {
5100: $readonly = 1;
1.619 ! raeburn 5101: } elsif (($name eq 'mapalias') && ($showval eq '')) {
! 5102: $readonly = 1;
1.599 raeburn 5103: }
1.560 damieng 5104: $r->print(&string_selector($thistype,$thiskey,
1.576 raeburn 5105: $showval,$name,$readonly));
1.560 damieng 5106: } else {
1.576 raeburn 5107: $r->print(&default_selector($thiskey,$showval,$readonly));
1.552 raeburn 5108: }
1.560 damieng 5109: unless ($readonly) {
5110: $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
5111: $thistype.'" />');
1.552 raeburn 5112: }
1.576 raeburn 5113: $r->print('</td>');
5114: if ($is_map) {
5115: if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
5116: $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
5117: } else {
5118: my ($disabled,$recon,$recoff);
5119: if ($readonly) {
5120: $disabled = ' disabled="disabled"';
5121: }
5122: if ($is_recursive) {
5123: $recon = ' checked="checked"';
5124: } else {
5125: $recoff = ' checked="checked"';
5126: }
5127: $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
5128: '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
5129: }
5130: }
5131: $r->print(&Apache::loncommon::end_data_table_row());
1.473 amueller 5132: }
1.121 www 5133: }
1.208 www 5134: return $foundkeys;
5135: }
5136:
1.563 damieng 5137: # Returns a string representing the interval, directly using form data matching the given key.
5138: # The returned string may also include information related to proctored exams.
5139: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
5140: #
5141: # @param {string} $key - suffix for form fields related to the interval
5142: # @returns {string}
1.385 albertel 5143: sub get_date_interval_from_form {
5144: my ($key) = @_;
5145: my $seconds = 0;
1.611 raeburn 5146: my $numnotnull = 0;
1.385 albertel 5147: foreach my $which (['days', 86400],
1.473 amueller 5148: ['hours', 3600],
5149: ['minutes', 60],
5150: ['seconds', 1]) {
1.560 damieng 5151: my ($name, $factor) = @{ $which };
5152: if (defined($env{'form.'.$name.'_'.$key})) {
1.611 raeburn 5153: unless ($env{'form.'.$name.'_'.$key} eq '') {
5154: $numnotnull ++;
5155: $seconds += $env{'form.'.$name.'_'.$key} * $factor;
5156: }
1.560 damieng 5157: }
1.473 amueller 5158: }
1.560 damieng 5159: if (($key =~ /\.interval$/) &&
5160: (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559 raeburn 5161: if ($env{'form.done_'.$key.'_buttontext'}) {
5162: $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
5163: $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
5164: if ($env{'form.done_'.$key} eq '_done_proctor') {
5165: $seconds .= '_proctor';
5166: }
5167: } else {
5168: $seconds .= $env{'form.done_'.$key};
5169: }
5170: if (($env{'form.done_'.$key} eq '_done_proctor') &&
1.560 damieng 5171: ($env{'form.done_'.$key.'_proctorkey'})) {
1.558 raeburn 5172: $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
5173: }
1.554 raeburn 5174: }
1.611 raeburn 5175: return if (!$numnotnull);
1.385 albertel 5176: return $seconds;
5177: }
5178:
5179:
1.563 damieng 5180: # Returns HTML to enter a text value for a parameter.
5181: #
5182: # @param {string} $thiskey - parameter key
5183: # @param {string} $showval - the current value
5184: # @param {boolean} $readonly - true if the field should not be made editable
5185: # @returns {string}
1.383 albertel 5186: sub default_selector {
1.552 raeburn 5187: my ($thiskey, $showval, $readonly) = @_;
5188: my $disabled;
5189: if ($readonly) {
5190: $disabled = ' disabled="disabled"';
5191: }
5192: return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383 albertel 5193: }
5194:
1.563 damieng 5195: # Returns HTML to enter allow/deny rules related to IP addresses.
5196: #
5197: # @param {string} $thiskey - parameter key
5198: # @param {string} $showval - the current value
5199: # @param {boolean} $readonly - true if the fields should not be made editable
5200: # @returns {string}
1.549 raeburn 5201: sub string_ip_selector {
1.552 raeburn 5202: my ($thiskey, $showval, $readonly) = @_;
1.549 raeburn 5203: my %access = (
5204: allow => [],
5205: deny => [],
5206: );
5207: if ($showval ne '') {
5208: my @current;
5209: if ($showval =~ /,/) {
5210: @current = split(/,/,$showval);
5211: } else {
5212: @current = ($showval);
5213: }
5214: foreach my $item (@current) {
5215: if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
5216: push(@{$access{'deny'}},$1);
5217: } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
5218: push(@{$access{'allow'}},$item);
5219: }
5220: }
5221: }
5222: if (!@{$access{'allow'}}) {
5223: @{$access{'allow'}} = ('');
5224: }
5225: if (!@{$access{'deny'}}) {
5226: @{$access{'deny'}} = ('');
5227: }
1.552 raeburn 5228: my ($disabled,$addmore);
1.567 raeburn 5229: if ($readonly) {
1.552 raeburn 5230: $disabled=' disabled="disabled"';
5231: } else {
5232: $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
5233: }
1.549 raeburn 5234: my $output = '<input type="hidden" name="set_'.$thiskey.'" />
5235: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
5236: foreach my $acctype ('allow','deny') {
5237: $output .= '
5238: <td valign="top">
5239: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
5240: <div class="LC_string_ipacc_inner">'."\n";
5241: my $num = 0;
5242: foreach my $curr (@{$access{$acctype}}) {
1.552 raeburn 5243: $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549 raeburn 5244: if ($num > 0) {
5245: $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>';
5246: }
5247: $output .= '</div>'."\n";
5248: $num ++;
5249: }
5250: $output .= '
1.552 raeburn 5251: </div>'.$addmore.'
1.549 raeburn 5252: </div>
5253: </td>';
5254: }
5255: $output .= '
5256: </tr>
5257: </table>'."\n";
5258: return $output;
5259: }
5260:
1.588 raeburn 5261: sub string_deeplink_selector {
5262: my ($thiskey, $showval, $readonly) = @_;
1.616 raeburn 5263: my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
5264: %selectnull,%domlti,%crslti,@possmenus,%components);
5265: @tables = ('upper','lower');
5266: %components = (
5267: upper => ['state','others','listing','scope'],
5268: lower => ['protect','menus','target','exit'],
5269: );
1.588 raeburn 5270: %titles = &Apache::lonlocal::texthash (
1.601 raeburn 5271: state => 'Access status',
5272: others => 'Hide other resources',
1.588 raeburn 5273: listing => 'In Contents and/or Gradebook',
5274: scope => 'Access scope for link',
1.601 raeburn 5275: protect => 'Link protection',
1.597 raeburn 5276: menus => 'Menu Items Displayed',
1.613 raeburn 5277: target => 'Embedded?',
1.616 raeburn 5278: exit => 'Exit Tool Button?',
1.588 raeburn 5279: );
5280: %options = (
1.601 raeburn 5281: state => ['only','off','both'],
5282: others => ['hide','unhide'],
1.588 raeburn 5283: listing => ['full','absent','grades','details','datestatus'],
5284: scope => ['res','map','rec'],
1.601 raeburn 5285: protect => ['none','key','ltid','ltic'],
1.597 raeburn 5286: menus => ['std','colls'],
1.613 raeburn 5287: target => ['_self','_top'],
1.616 raeburn 5288: exit => ['no','yes','url'],
1.588 raeburn 5289: );
5290: %optiontext = &Apache::lonlocal::texthash (
1.601 raeburn 5291: only => 'deep only',
5292: off => 'deeplink off',
5293: both => 'regular + deep',
5294: hide => 'Hidden',
5295: unhide => 'Unhidden',
1.588 raeburn 5296: full => 'Listed (linked) in both',
5297: absent => 'Not listed',
5298: grades => 'Listed in grades only',
5299: details => 'Listed (unlinked) in both',
5300: datestatus => 'Listed (unlinked) inc. status in both',
5301: res => 'resource only',
5302: map => 'enclosing map/folder',
5303: rec => 'recursive map/folder',
1.601 raeburn 5304: none => 'not in use',
5305: key => 'key access',
5306: ltic => 'LTI access (course)',
5307: ltid => 'LTI access (domain)' ,
1.597 raeburn 5308: std => 'Standard (all menus)',
5309: colls => 'Numbered collection',
1.614 raeburn 5310: _self => 'Embedded',
1.613 raeburn 5311: _top => 'Not embedded',
1.616 raeburn 5312: no => 'Not in use',
5313: yes => 'In use, no URL redirect',
5314: url => 'In use, redirect to URL',
1.597 raeburn 5315: );
5316: %selectnull = &Apache::lonlocal::texthash (
1.601 raeburn 5317: ltic => 'Select Launcher',
5318: ltid => 'Select Launcher',
1.597 raeburn 5319: colls => 'Select',
1.588 raeburn 5320: );
5321: if ($showval =~ /,/) {
1.597 raeburn 5322: %values=();
1.588 raeburn 5323: @current = split(/,/,$showval);
1.601 raeburn 5324: ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
5325: ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
5326: ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
5327: ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
5328: ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
5329: ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613 raeburn 5330: ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616 raeburn 5331: ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588 raeburn 5332: } else {
1.601 raeburn 5333: $defaults{'state'} = 'off',
5334: $defaults{'others'} = 'unhide',
1.588 raeburn 5335: $defaults{'listing'} = 'full';
5336: $defaults{'scope'} = 'res';
1.601 raeburn 5337: $defaults{'protect'} = 'none';
1.597 raeburn 5338: $defaults{'menus'} = '0';
1.613 raeburn 5339: $defaults{'target'} = '_top';
1.616 raeburn 5340: $defaults{'exit'} = 'yes';
1.588 raeburn 5341: }
5342: my $disabled;
5343: if ($readonly) {
5344: $disabled=' disabled="disabled"';
5345: }
1.601 raeburn 5346: my %courselti =
5347: &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
5348: $env{'course.'.$env{'request.course.id'}.'.domain'});
5349: foreach my $item (keys(%courselti)) {
5350: if (ref($courselti{$item}) eq 'HASH') {
5351: $crslti{$item} = $courselti{$item}{'name'};
5352: }
5353: }
5354: my %lti =
1.588 raeburn 5355: &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604 raeburn 5356: 'linkprot');
1.588 raeburn 5357: foreach my $item (keys(%lti)) {
1.604 raeburn 5358: if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
5359: $domlti{$item} = $lti{$item}{'name'};
1.588 raeburn 5360: }
5361: }
1.597 raeburn 5362: if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
5363: foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
5364: my ($num,$value) = split(/\%/,$item);
5365: if ($num =~ /^\d+$/) {
5366: push(@possmenus,$num);
5367: }
5368: }
5369: }
5370:
1.616 raeburn 5371: my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
5372: foreach my $table ('upper','lower') {
5373: next unless (ref($components{$table}) eq 'ARRAY');
5374: $output .= '<table width="100%"><tr>';
5375: foreach my $item (@{$components{$table}}) {
5376: $output .= '<th>'.$titles{$item}.'</th>';
5377: }
5378: $output .= '</tr><tr>';
5379: foreach my $item (@{$components{$table}}) {
5380: $output .= '<td>';
5381: if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
5382: my $selected = $values{$item};
5383: foreach my $option (@{$options{$item}}) {
5384: if ($item eq 'protect') {
5385: if ($option eq 'ltid') {
5386: next unless (keys(%domlti));
5387: } elsif ($option eq 'ltic') {
5388: next unless (keys(%crslti));
5389: }
5390: } elsif (($item eq 'menus') && ($option eq 'colls')) {
5391: next unless (@possmenus);
5392: }
5393: my $checked;
5394: if ($item eq 'menus') {
5395: if (($selected =~ /^\d+$/) && (@possmenus) &&
5396: (grep(/^\Q$selected\E$/,@possmenus))) {
5397: if ($option eq 'colls') {
5398: $checked = ' checked="checked"';
5399: }
5400: } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597 raeburn 5401: $checked = ' checked="checked"';
5402: }
1.616 raeburn 5403: } elsif ($selected =~ /^\Q$option\E/) {
1.597 raeburn 5404: $checked = ' checked="checked"';
5405: }
1.616 raeburn 5406: my $onclick;
5407: unless ($readonly) {
5408: my $esc_key = &js_escape($thiskey);
5409: $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
5410: }
5411: $output .= '<span class="LC_nobreak"><label>'.
5412: '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
5413: $optiontext{$option}.'</label>';
5414: if (($item eq 'protect') && ($option eq 'key')) {
5415: my $visibility="hidden";
5416: my $currkey;
5417: if ($checked) {
5418: $visibility = "text";
5419: $currkey = (split(/\:/,$values{$item}))[1];
5420: }
5421: $output .= ' '.
5422: '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
5423: } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
5424: my $display="none";
5425: my ($current,$blankcheck,@possibles);
5426: if ($checked) {
5427: $display = 'inline-block';
5428: if (($option eq 'ltic') || ($option eq 'ltid')) {
5429: $current = (split(/\:/,$selected))[1];
5430: } else {
5431: $current = $selected;
5432: }
1.597 raeburn 5433: } else {
1.616 raeburn 5434: $blankcheck = ' selected="selected"';
1.597 raeburn 5435: }
1.601 raeburn 5436: if ($option eq 'ltid') {
1.616 raeburn 5437: @possibles = keys(%domlti);
1.601 raeburn 5438: } elsif ($option eq 'ltic') {
1.616 raeburn 5439: @possibles = keys(%crslti);
5440: } else {
5441: @possibles = @possmenus;
5442: }
5443: $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
5444: ' style="display: '.$display.'"> <select name="'.
5445: 'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
5446: if (@possibles > 1) {
5447: $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
5448: '</option>'."\n";
5449: }
5450: foreach my $poss (sort { $a <=> $b } @possibles) {
5451: my $selected;
5452: if (($poss == $current) || (scalar(@possibles) ==1)) {
5453: $selected = ' selected="selected"';
5454: }
5455: my $shown = $poss;
5456: if ($option eq 'ltid') {
5457: $shown = $domlti{$poss};
5458: } elsif ($option eq 'ltic') {
5459: $shown = $crslti{$poss};
5460: }
5461: $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
5462: }
5463: $output .= '</select></div>';
5464: }
5465: $output .= '</span> ';
5466: }
5467: if ($item eq 'exit') {
5468: my $exitsty = 'none';
5469: my $displayval;
5470: if ($values{$item} =~ /^(yes|url)/) {
5471: $exitsty = 'inline-block';
5472: my $currval = (split(/\:/,$values{$item}))[1];
5473: if ($currval eq '') {
5474: $displayval = 'Exit Tool';
5475: } else {
5476: $displayval = $currval;
1.597 raeburn 5477: }
1.588 raeburn 5478: }
1.616 raeburn 5479: $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
5480: ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
5481: '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
5482: ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
5483: ' size="10"'.$disabled.' /></div>';
1.588 raeburn 5484: }
1.616 raeburn 5485: } else {
5486: my $selected = $values{$item};
5487: my $defsel;
5488: if ($selected eq '') {
5489: $defsel = ' selected="selected"';
5490: }
5491: $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
5492: '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
5493: foreach my $option (@{$options{$item}}) {
5494: $output .= '<option value="'.$option.'"';
5495: if ($option eq $selected) {
5496: $output .= ' selected="selected"';
5497: }
5498: $output .= '>'.$optiontext{$option}.'</option>';
1.588 raeburn 5499: }
1.616 raeburn 5500: $output .= '</select>';
1.588 raeburn 5501: }
1.616 raeburn 5502: $output .= '</td>';
5503: }
5504: $output .= '</tr></table>'."\n";
5505: if ($table eq 'upper') {
5506: $output .= '<br />';
1.588 raeburn 5507: }
5508: }
5509: return $output;
5510: }
5511:
1.560 damieng 5512:
5513: { # block using some constants related to parameter types (overview mode)
5514:
1.446 bisitz 5515: my %strings =
1.383 albertel 5516: (
5517: 'string_yesno'
5518: => [[ 'yes', 'Yes' ],
1.560 damieng 5519: [ 'no', 'No' ]],
1.383 albertel 5520: 'string_problemstatus'
5521: => [[ 'yes', 'Yes' ],
1.473 amueller 5522: [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
5523: [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
5524: [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504 raeburn 5525: 'string_questiontype'
5526: => [[ 'problem', 'Standard Problem'],
5527: [ 'survey', 'Survey'],
5528: [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530 bisitz 5529: [ 'exam', 'Bubblesheet Exam'],
1.504 raeburn 5530: [ 'anonsurvey', 'Anonymous Survey'],
5531: [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
5532: [ 'practice', 'Practice'],
5533: [ 'surveycred', 'Survey (credit for submission)']],
1.514 raeburn 5534: 'string_lenient'
5535: => [['yes', 'Yes' ],
5536: [ 'no', 'No' ],
1.549 raeburn 5537: [ 'default', 'Default - only bubblesheet grading is lenient' ],
5538: [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521 raeburn 5539: 'string_discussvote'
5540: => [['yes','Yes'],
5541: ['notended','Yes, unless discussion ended'],
5542: ['no','No']],
1.549 raeburn 5543: 'string_ip'
5544: => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587 raeburn 5545: ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']],
5546: 'string_deeplink'
1.616 raeburn 5547: => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.587 raeburn 5548: );
5549:
1.383 albertel 5550:
1.549 raeburn 5551: my %stringmatches = (
5552: 'string_lenient'
5553: => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
5554: 'string_ip'
5555: => [['_allowfrom_','[^\!]+'],
5556: ['_denyfrom_','\!']],
1.588 raeburn 5557: 'string_deeplink'
1.616 raeburn 5558: => [['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.549 raeburn 5559: );
5560:
5561: my %stringtypes = (
5562: type => 'string_questiontype',
5563: lenient => 'string_lenient',
5564: retrypartial => 'string_yesno',
5565: discussvote => 'string_discussvote',
5566: examcode => 'string_examcode',
5567: acc => 'string_ip',
1.587 raeburn 5568: deeplink => 'string_deeplink',
1.549 raeburn 5569: );
5570:
1.563 damieng 5571: # Returns the possible values and titles for a given string type, or undef if there are none.
5572: # Used by courseprefs.
5573: #
5574: # @param {string} $string_type - a parameter type for strings
5575: # @returns {array reference} - 2D array, containing values and English titles
1.505 raeburn 5576: sub standard_string_options {
5577: my ($string_type) = @_;
5578: if (ref($strings{$string_type}) eq 'ARRAY') {
5579: return $strings{$string_type};
5580: }
5581: return;
5582: }
1.383 albertel 5583:
1.563 damieng 5584: # Returns regular expressions to match kinds of string types, or undef if there are none.
5585: #
5586: # @param {string} $string_type - a parameter type for strings
5587: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.549 raeburn 5588: sub standard_string_matches {
5589: my ($string_type) = @_;
5590: if (ref($stringmatches{$string_type}) eq 'ARRAY') {
5591: return $stringmatches{$string_type};
5592: }
5593: return;
5594: }
5595:
1.563 damieng 5596: # Returns a parameter type for a given parameter with a string type, or undef if not known.
5597: #
5598: # @param {string} $name - parameter name
5599: # @returns {string}
1.549 raeburn 5600: sub get_stringtype {
5601: my ($name) = @_;
5602: if (exists($stringtypes{$name})) {
5603: return $stringtypes{$name};
5604: }
5605: return;
5606: }
5607:
1.563 damieng 5608: # Returns HTML to edit a string parameter.
5609: #
5610: # @param {string} $thistype - parameter type
5611: # @param {string} $thiskey - parameter key
5612: # @param {string} $showval - parameter current value
5613: # @param {string} $name - parameter name
5614: # @param {boolean} $readonly - true if the values should not be made editable
5615: # @returns {string}
1.383 albertel 5616: sub string_selector {
1.552 raeburn 5617: my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446 bisitz 5618:
1.383 albertel 5619: if (!exists($strings{$thistype})) {
1.552 raeburn 5620: return &default_selector($thiskey,$showval,$readonly);
1.383 albertel 5621: }
5622:
1.504 raeburn 5623: my %skiptype;
1.514 raeburn 5624: if (($thistype eq 'string_questiontype') ||
1.560 damieng 5625: ($thistype eq 'string_lenient') ||
5626: ($thistype eq 'string_discussvote') ||
5627: ($thistype eq 'string_ip') ||
1.588 raeburn 5628: ($thistype eq 'string_deeplink') ||
1.560 damieng 5629: ($name eq 'retrypartial')) {
1.504 raeburn 5630: my ($got_chostname,$chostname,$cmajor,$cminor);
5631: foreach my $possibilities (@{ $strings{$thistype} }) {
5632: next unless (ref($possibilities) eq 'ARRAY');
1.514 raeburn 5633: my ($parmval, $description) = @{ $possibilities };
1.549 raeburn 5634: my $parmmatch;
5635: if (ref($stringmatches{$thistype}) eq 'ARRAY') {
5636: foreach my $item (@{$stringmatches{$thistype}}) {
5637: if (ref($item) eq 'ARRAY') {
5638: if ($parmval eq $item->[0]) {
5639: $parmmatch = $parmval;
5640: $parmval = '';
5641: last;
5642: }
5643: }
5644: }
5645: }
5646: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
1.504 raeburn 5647: if ($needsrelease) {
5648: unless ($got_chostname) {
1.514 raeburn 5649: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
1.504 raeburn 5650: $got_chostname = 1;
5651: }
1.557 raeburn 5652: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.549 raeburn 5653: $needsrelease,$cmajor,$cminor);
1.504 raeburn 5654: if ($needsnewer) {
1.549 raeburn 5655: if ($parmmatch ne '') {
5656: $skiptype{$parmmatch} = 1;
5657: } elsif ($parmval ne '') {
5658: $skiptype{$parmval} = 1;
5659: }
1.504 raeburn 5660: }
5661: }
5662: }
5663: }
1.549 raeburn 5664:
5665: if ($thistype eq 'string_ip') {
1.552 raeburn 5666: return &string_ip_selector($thiskey,$showval,$readonly);
1.588 raeburn 5667: } elsif ($thistype eq 'string_deeplink') {
5668: return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549 raeburn 5669: }
1.504 raeburn 5670:
1.552 raeburn 5671: my ($result,$disabled);
5672:
5673: if ($readonly) {
5674: $disabled = ' disabled="disabled"';
5675: }
1.504 raeburn 5676: my $numinrow = 3;
5677: if ($thistype eq 'string_problemstatus') {
5678: $numinrow = 2;
5679: } elsif ($thistype eq 'string_questiontype') {
5680: if (keys(%skiptype) > 0) {
5681: $numinrow = 4;
5682: }
5683: }
5684: my $rem;
5685: if (ref($strings{$thistype}) eq 'ARRAY') {
5686: my $i=0;
5687: foreach my $possibilities (@{ $strings{$thistype} }) {
5688: next unless (ref($possibilities) eq 'ARRAY');
5689: my ($name, $description) = @{ $possibilities };
1.549 raeburn 5690: next if ($skiptype{$name});
1.504 raeburn 5691: $rem = $i%($numinrow);
5692: if ($rem == 0) {
5693: if ($i > 0) {
5694: $result .= '</tr>';
5695: }
5696: $result .= '<tr>';
5697: }
1.549 raeburn 5698: my $colspan;
5699: if ($i == @{ $strings{$thistype} }-1) {
5700: $rem = @{ $strings{$thistype} }%($numinrow);
5701: if ($rem) {
5702: my $colsleft = $numinrow - $rem;
5703: if ($colsleft) {
5704: $colspan = $colsleft+1;
5705: $colspan = ' colspan="'.$colspan.'"';
5706: }
5707: }
5708: }
5709: my ($add,$onchange,$css_class);
5710: if ($thistype eq 'string_lenient') {
5711: if ($name eq 'weighted') {
5712: my $display;
5713: my %relatives = &Apache::lonlocal::texthash(
5714: corrchkd => 'Correct (checked)',
5715: corrunchkd => 'Correct (unchecked)',
5716: incorrchkd => 'Incorrect (checked)',
5717: incorrunchkd => 'Incorrect (unchecked)',
5718: );
5719: my %textval = (
5720: corrchkd => '1.0',
5721: corrunchkd => '1.0',
5722: incorrchkd => '0.0',
5723: incorrunchkd => '0.0',
5724: );
5725: if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
5726: $textval{'corrchkd'} = $1;
5727: $textval{'corrunchkd'} = $2;
5728: $textval{'incorrchkd'} = $3;
5729: $textval{'incorrunchkd'} = $4;
5730: $display = 'inline';
5731: $showval = $name;
5732: } else {
5733: $display = 'none';
5734: }
5735: $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
5736: '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';
5737: foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
5738: $add .= '<tr><td> </td><td>'.$relatives{$reltype}.'</td>'."\n".
5739: '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552 raeburn 5740: ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549 raeburn 5741: '</td></tr>';
5742: }
5743: $add .= '</table></div>'."\n";
5744: }
5745: $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
5746: $css_class = ' class="LC_lenient_radio"';
5747: }
5748: $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504 raeburn 5749: '<span class="LC_nobreak"><label>'.
5750: '<input type="radio" name="set_'.$thiskey.
1.552 raeburn 5751: '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504 raeburn 5752: if ($showval eq $name) {
5753: $result .= ' checked="checked"';
5754: }
1.549 raeburn 5755: $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504 raeburn 5756: $i++;
5757: }
5758: $result .= '</tr>';
1.473 amueller 5759: }
1.504 raeburn 5760: if ($result) {
5761: $result = '<table border="0">'.$result.'</table>';
1.383 albertel 5762: }
5763: return $result;
5764: }
5765:
1.554 raeburn 5766: my %intervals =
5767: (
5768: 'date_interval'
5769: => [[ 'done', 'Yes' ],
1.558 raeburn 5770: [ 'done_proctor', 'Yes, with proctor key'],
1.554 raeburn 5771: [ '', 'No' ]],
5772: );
5773:
5774: my %intervalmatches = (
5775: 'date_interval'
1.559 raeburn 5776: => [['done','\d+_done(|\:[^\:]+\:)$'],
5777: ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554 raeburn 5778: );
5779:
5780: my %intervaltypes = (
5781: interval => 'date_interval',
5782: );
5783:
1.563 damieng 5784: # Returns regular expressions to match kinds of interval type, or undef if there are none.
5785: #
5786: # @param {string} $interval_type - a parameter type for intervals
5787: # @returns {array reference} - 2D array, containing regular expression names and regular expressions
1.554 raeburn 5788: sub standard_interval_matches {
5789: my ($interval_type) = @_;
5790: if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
5791: return $intervalmatches{$interval_type};
5792: }
5793: return;
5794: }
5795:
1.563 damieng 5796: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
5797: #
5798: # @param {string} $name - parameter name
5799: # @returns {string}
1.554 raeburn 5800: sub get_intervaltype {
5801: my ($name) = @_;
5802: if (exists($intervaltypes{$name})) {
5803: return $intervaltypes{$name};
5804: }
5805: return;
5806: }
5807:
1.563 damieng 5808: # Returns the possible values and titles for a given interval type, or undef if there are none.
5809: # Used by courseprefs.
5810: #
5811: # @param {string} $interval_type - a parameter type for intervals
5812: # @returns {array reference} - 2D array, containing values and English titles
1.554 raeburn 5813: sub standard_interval_options {
5814: my ($interval_type) = @_;
5815: if (ref($intervals{$interval_type}) eq 'ARRAY') {
5816: return $intervals{$interval_type};
5817: }
5818: return;
5819: }
5820:
1.563 damieng 5821: # Returns HTML to edit a date interval parameter.
5822: #
5823: # @param {string} $thiskey - parameter key
5824: # @param {string} $name - parameter name
5825: # @param {string} $showval - parameter current value
5826: # @param {boolean} $readonly - true if the values should not be made editable
5827: # @returns {string}
1.554 raeburn 5828: sub date_interval_selector {
5829: my ($thiskey, $name, $showval, $readonly) = @_;
5830: my ($result,%skipval);
5831: if ($name eq 'interval') {
5832: my $intervaltype = &get_intervaltype($name);
5833: my ($got_chostname,$chostname,$cmajor,$cminor);
5834: foreach my $possibilities (@{ $intervals{$intervaltype} }) {
5835: next unless (ref($possibilities) eq 'ARRAY');
5836: my ($parmval, $description) = @{ $possibilities };
5837: my $parmmatch;
5838: if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
5839: foreach my $item (@{$intervalmatches{$intervaltype}}) {
5840: if (ref($item) eq 'ARRAY') {
5841: if ($parmval eq $item->[0]) {
5842: $parmmatch = $parmval;
5843: $parmval = '';
5844: last;
5845: }
5846: }
5847: }
5848: }
5849: my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
5850: if ($needsrelease) {
5851: unless ($got_chostname) {
5852: ($chostname,$cmajor,$cminor)=¶meter_release_vars();
5853: $got_chostname = 1;
5854: }
1.557 raeburn 5855: my $needsnewer=¶meter_releasecheck($name,$parmval,$parmmatch,undef,
1.554 raeburn 5856: $needsrelease,$cmajor,$cminor);
5857: if ($needsnewer) {
5858: if ($parmmatch ne '') {
5859: $skipval{$parmmatch} = 1;
5860: } elsif ($parmval ne '') {
5861: $skipval{$parmval} = 1;
5862: }
5863: }
5864: }
5865: }
5866: }
5867:
5868: my $currval = $showval;
5869: foreach my $which (['days', 86400, 31],
5870: ['hours', 3600, 23],
5871: ['minutes', 60, 59],
5872: ['seconds', 1, 59]) {
1.560 damieng 5873: my ($name, $factor, $max) = @{ $which };
5874: my $amount = int($showval/$factor);
5875: $showval %= $factor;
5876: my %select = ((map {$_ => $_} (0..$max)),
5877: 'select_form_order' => [0..$max]);
1.611 raeburn 5878: if ($currval eq '') {
5879: unshift(@{$select{'select_form_order'}},'');
5880: $select{''} = '';
5881: $amount = '';
5882: }
1.560 damieng 5883: $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
5884: \%select,'',$readonly);
5885: $result .= ' '.&mt($name);
1.554 raeburn 5886: }
5887: if ($name eq 'interval') {
5888: unless ($skipval{'done'}) {
5889: my $checkedon = '';
1.611 raeburn 5890: my $checkedoff = '';
1.558 raeburn 5891: my $checkedproc = '';
5892: my $currproctorkey = '';
5893: my $currprocdisplay = 'hidden';
1.559 raeburn 5894: my $currdonetext = &mt('Done');
5895: if ($currval =~ /^(?:\d+)_done$/) {
5896: $checkedon = ' checked="checked"';
5897: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
5898: $currdonetext = $1;
1.554 raeburn 5899: $checkedon = ' checked="checked"';
1.558 raeburn 5900: } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
5901: $currproctorkey = $1;
5902: $checkedproc = ' checked="checked"';
5903: $currprocdisplay = 'text';
1.559 raeburn 5904: } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
5905: $currdonetext = $1;
5906: $currproctorkey = $2;
5907: $checkedproc = ' checked="checked"';
5908: $currprocdisplay = 'text';
1.611 raeburn 5909: } elsif ($currval ne '') {
5910: $checkedoff = ' checked="checked"';
5911: } else {
5912: $currdonetext = '';
1.554 raeburn 5913: }
1.558 raeburn 5914: my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567 raeburn 5915: my $disabled;
5916: if ($readonly) {
5917: $disabled = ' disabled="disabled"';
5918: }
1.558 raeburn 5919: $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567 raeburn 5920: '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558 raeburn 5921: &mt('No').'</label>'.(' 'x2).
1.567 raeburn 5922: '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558 raeburn 5923: &mt('Yes').'</label>'.(' 'x2).
1.567 raeburn 5924: '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558 raeburn 5925: &mt('Yes, with proctor key').'</label>'.
5926: '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567 raeburn 5927: 'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559 raeburn 5928: '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611 raeburn 5929: '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
5930: &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554 raeburn 5931: }
5932: }
5933: unless ($readonly) {
5934: $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
5935: }
5936: return $result;
5937: }
5938:
1.563 damieng 5939: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
5940: #
5941: # @param {string} $name - parameter name
5942: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
5943: # @param {string} $value - parameter value
5944: # @param {string} $chostname - course server name
5945: # @param {integer} $cmajor - major version number
5946: # @param {integer} $cminor - minor version number
5947: # @param {string} $needsrelease - release version needed (major.minor)
5948: # @returns {string}
1.549 raeburn 5949: sub oldversion_warning {
1.557 raeburn 5950: my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
5951: my $standard_name = &standard_parameter_names($name);
5952: if ($namematch) {
5953: my $level = &standard_parameter_levels($namematch);
5954: my $msg = '';
5955: if ($level) {
5956: $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
5957: $standard_name,'<b>','</b>','"'.$level.'"');
5958: } else {
5959: $msg = &mt('[_1] was [_2]not[_3] set.',
5960: $standard_name,'<b>','</b>');
5961: }
5962: return '<p class="LC_warning">'.$msg.'<br />'.
5963: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
5964: $cmajor.'.'.$cminor,$chostname,
5965: $needsrelease).
5966: '</p>';
5967: }
1.549 raeburn 5968: my $desc;
5969: my $stringtype = &get_stringtype($name);
5970: if ($stringtype ne '') {
5971: if ($name eq 'examcode') {
5972: $desc = $value;
5973: } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
5974: foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
5975: next unless (ref($possibilities) eq 'ARRAY');
5976: my ($parmval, $description) = @{ $possibilities };
5977: my $parmmatch;
5978: if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
5979: foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
5980: if (ref($item) eq 'ARRAY') {
5981: my ($regexpname,$pattern) = @{$item};
5982: if ($parmval eq $regexpname) {
5983: if ($value =~ /$pattern/) {
5984: $desc = $description;
5985: $parmmatch = 1;
5986: last;
5987: }
5988: }
5989: }
5990: }
5991: last if ($parmmatch);
5992: } elsif ($parmval eq $value) {
5993: $desc = $description;
5994: last;
5995: }
5996: }
5997: }
5998: } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
5999: my $now = time;
6000: if ($value =~ /^\d+$/) {
6001: if ($name eq 'printstartdate') {
6002: if ($value > $now) {
6003: $desc = &Apache::lonlocal::locallocaltime($value);
6004: }
6005: } elsif ($name eq 'printenddate') {
6006: if ($value < $now) {
6007: $desc = &Apache::lonlocal::locallocaltime($value);
6008: }
6009: }
6010: }
6011: }
6012: return '<p class="LC_warning">'.
1.557 raeburn 6013: &mt('[_1] was [_2]not[_3] set to [_4].',
6014: $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
6015: &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
6016: $cmajor.'.'.$cminor,$chostname,
6017: $needsrelease).
6018: '</p>';
1.549 raeburn 6019: }
6020:
1.560 damieng 6021: } # end of block using some constants related to parameter types
6022:
1.549 raeburn 6023:
1.563 damieng 6024:
6025: # Shifts all start and end dates in the current course by $shift.
1.389 www 6026: #
1.563 damieng 6027: # @param {integer} $shift - time to shift, in seconds
6028: # @returns {string} - error name or 'ok'
1.389 www 6029: sub dateshift {
1.594 raeburn 6030: my ($shift,$numchanges)=@_;
1.389 www 6031: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6032: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6033: my $sec = $env{'request.course.sec'};
1.595 raeburn 6034: my $secgrpregex;
6035: if ($sec ne '') {
6036: my @groups;
6037: if ($env{'request.course.groups'} ne '') {
6038: @groups = split(/:/,$env{'request.course.groups'});
6039: }
6040: if (@groups) {
6041: $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
6042: } else {
6043: $secgrpregex = $sec;
6044: }
6045: }
1.389 www 6046: my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
6047: # ugly retro fix for broken version of types
1.548 raeburn 6048: foreach my $key (keys(%data)) {
1.389 www 6049: if ($key=~/\wtype$/) {
6050: my $newkey=$key;
6051: $newkey=~s/type$/\.type/;
6052: $data{$newkey}=$data{$key};
6053: delete $data{$key};
6054: }
6055: }
1.391 www 6056: my %storecontent=();
1.389 www 6057: # go through all parameters and look for dates
1.548 raeburn 6058: foreach my $key (keys(%data)) {
1.389 www 6059: if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594 raeburn 6060: if ($sec ne '') {
1.595 raeburn 6061: next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594 raeburn 6062: }
1.389 www 6063: my $newdate=$data{$key}+$shift;
1.594 raeburn 6064: $$numchanges ++;
1.391 www 6065: $storecontent{$key}=$newdate;
1.389 www 6066: }
6067: }
1.391 www 6068: my $reply=&Apache::lonnet::cput
6069: ('resourcedata',\%storecontent,$dom,$crs);
6070: if ($reply eq 'ok') {
6071: &log_parmset(\%storecontent);
6072: }
6073: &Apache::lonnet::devalidatecourseresdata($crs,$dom);
6074: return $reply;
1.389 www 6075: }
6076:
1.563 damieng 6077: # Overview mode UI to edit course parameters.
6078: #
6079: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6080: sub newoverview {
1.568 raeburn 6081: my ($r,$parm_permission) = @_;
1.280 albertel 6082:
1.208 www 6083: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6084: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6085: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6086: my $readonly = 1;
6087: if ($parm_permission->{'edit'}) {
6088: undef($readonly);
6089: }
1.414 droeschl 6090: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6091: text=>"Overview Mode"});
1.523 raeburn 6092:
6093: my %loaditems = (
1.549 raeburn 6094: 'onload' => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523 raeburn 6095: );
6096: my $js = '
6097: <script type="text/javascript">
6098: // <![CDATA[
6099: '.
6100: &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
6101: &showhide_js()."\n".
1.549 raeburn 6102: &toggleparmtextbox_js()."\n".
6103: &validateparms_js()."\n".
6104: &ipacc_boxes_js()."\n".
1.558 raeburn 6105: &done_proctor_js()."\n".
1.588 raeburn 6106: &deeplink_js()."\n".
1.523 raeburn 6107: '// ]]>
6108: </script>
6109: ';
1.549 raeburn 6110:
1.523 raeburn 6111: my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
6112: {'add_entries' => \%loaditems,});
1.298 albertel 6113: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6114: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6115: &startSettingsScreen($r,'parmset',$crstype);
1.208 www 6116: $r->print(<<ENDOVER);
1.549 raeburn 6117: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208 www 6118: ENDOVER
1.211 www 6119: my @ids=();
6120: my %typep=();
6121: my %keyp=();
6122: my %allparms=();
6123: my %allparts=();
6124: my %allmaps=();
6125: my %mapp=();
6126: my %symbp=();
6127: my %maptitles=();
6128: my %uris=();
6129: my %keyorder=&standardkeyorder();
6130: my %defkeytype=();
6131:
6132: my %alllevs=();
6133: $alllevs{'Resource Level'}='full';
1.215 www 6134: $alllevs{'Map/Folder Level'}='map';
1.211 www 6135: $alllevs{'Course Level'}='general';
6136:
6137: my $csec=$env{'form.csec'};
1.269 raeburn 6138: my $cgroup=$env{'form.cgroup'};
1.211 www 6139:
6140: my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
6141: my $pschp=$env{'form.pschp'};
1.506 www 6142:
1.211 www 6143: my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516 www 6144: if (!@psprt) { $psprt[0]='all'; }
1.211 www 6145:
1.446 bisitz 6146: my @selected_sections =
1.473 amueller 6147: &Apache::loncommon::get_env_multiple('form.Section');
1.211 www 6148: @selected_sections = ('all') if (! @selected_sections);
1.374 albertel 6149: foreach my $sec (@selected_sections) {
6150: if ($sec eq 'all') {
1.211 www 6151: @selected_sections = ('all');
6152: }
6153: }
1.552 raeburn 6154: if ($env{'request.course.sec'} ne '') {
6155: @selected_sections = ($env{'request.course.sec'});
6156: }
1.269 raeburn 6157: my @selected_groups =
6158: &Apache::loncommon::get_env_multiple('form.Group');
1.211 www 6159:
6160: my $pssymb='';
6161: my $parmlev='';
1.446 bisitz 6162:
1.211 www 6163: unless ($env{'form.parmlev'}) {
6164: $parmlev = 'map';
6165: } else {
6166: $parmlev = $env{'form.parmlev'};
6167: }
6168:
1.446 bisitz 6169: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 6170: \%mapp, \%symbp,\%maptitles,\%uris,
1.603 raeburn 6171: \%keyorder,\%defkeytype,$pssymb);
1.211 www 6172:
1.374 albertel 6173: if (grep {$_ eq 'all'} (@psprt)) {
1.481 amueller 6174: @psprt = keys(%allparts);
1.374 albertel 6175: }
1.211 www 6176: # Menu to select levels, etc
6177:
1.456 bisitz 6178: $r->print('<div class="LC_Box">');
1.445 neumanie 6179: #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452 bisitz 6180: $r->print('<div>');
1.523 raeburn 6181: $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211 www 6182: &levelmenu($r,\%alllevs,$parmlev);
1.610 raeburn 6183: $r->print(&Apache::lonhtmlcommon::row_closure());
6184: &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447 bisitz 6185: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6186: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6187: $r->print('</div></div>');
1.446 bisitz 6188:
1.456 bisitz 6189: $r->print('<div class="LC_Box">');
1.452 bisitz 6190: $r->print('<div>');
1.581 raeburn 6191: &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453 schualex 6192: $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446 bisitz 6193: $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553 raeburn 6194: my $sectionselector = §ionmenu(\@selected_sections);
6195: my $groupselector = &groupmenu(\@selected_groups);
1.481 amueller 6196: $r->print('<table>'.
1.553 raeburn 6197: '<tr><th>'.&mt('Parts').'</th>');
6198: if ($sectionselector) {
6199: $r->print('<th>'.&mt('Section(s)').'</th>');
6200: }
6201: if ($groupselector) {
6202: $r->print('<th>'.&mt('Group(s)').'</th>');
6203: }
6204: $r->print('</tr><tr><td>');
1.211 www 6205: &partmenu($r,\%allparts,\@psprt);
1.553 raeburn 6206: $r->print('</td>');
6207: if ($sectionselector) {
6208: $r->print('<td>'.$sectionselector.'</td>');
6209: }
6210: if ($groupselector) {
6211: $r->print('<td>'.$groupselector.'</td>');
6212: }
6213: $r->print('</tr></table>');
1.447 bisitz 6214: $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445 neumanie 6215: $r->print(&Apache::lonhtmlcommon::end_pick_box());
6216: $r->print('</div></div>');
6217:
1.456 bisitz 6218: $r->print('<div class="LC_Box">');
1.452 bisitz 6219: $r->print('<div>');
1.214 www 6220: my $sortorder=$env{'form.sortorder'};
6221: unless ($sortorder) { $sortorder='realmstudent'; }
1.612 raeburn 6222: &sortmenu($r,$sortorder,'newoverview');
1.445 neumanie 6223: $r->print('</div></div>');
1.446 bisitz 6224:
1.214 www 6225: $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446 bisitz 6226:
1.211 www 6227: # Build the list data hash from the specified parms
6228:
6229: my $listdata;
6230: %{$listdata}=();
6231:
6232: foreach my $cat (@pscat) {
1.269 raeburn 6233: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
6234: &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211 www 6235: }
6236:
1.212 www 6237: if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211 www 6238:
1.481 amueller 6239: if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211 www 6240:
6241: # Read modified data
6242:
1.481 amueller 6243: my $resourcedata=&readdata($crs,$dom);
1.211 www 6244:
6245: # List data
6246:
1.608 raeburn 6247: my $hash_for_realm;
6248: if (($parmlev eq 'map') && (keys(%allmaps))) {
6249: %{$hash_for_realm} = reverse(%allmaps);
6250: } elsif (($parmlev eq 'full') && (keys(%symbp))) {
6251: for (my $i=0; $i<@ids; $i++) {
6252: $hash_for_realm->{$symbp{$ids[$i]}} = $i;
6253: }
6254: }
6255: &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568 raeburn 6256: }
6257: $r->print(&tableend());
6258: unless ($readonly) {
6259: $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211 www 6260: }
1.568 raeburn 6261: $r->print('</form>');
1.507 www 6262: &endSettingsScreen($r);
6263: $r->print(&Apache::loncommon::end_page());
1.208 www 6264: }
6265:
1.563 damieng 6266: # Fills $listdata with parameter information.
6267: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
6268: # The non-type value is always 1.
6269: #
6270: # @param {string} $cat - parameter name
1.566 damieng 6271: # @param {string} $pschp - selected map pc, or 'all'
1.563 damieng 6272: # @param {string} $parmlev - selected level value (full|map|general), or ''
6273: # @param {hash reference} $listdata - the parameter data that will be modified
6274: # @param {array reference} $psprt - selected parts
6275: # @param {array reference} $selections - selected sections
6276: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566 damieng 6277: # @param {hash reference} $allmaps - hash map pc -> map src
6278: # @param {array reference} $ids - resource and map ids
6279: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269 raeburn 6280: sub secgroup_lister {
6281: my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
6282: foreach my $item (@{$selections}) {
6283: foreach my $part (@{$psprt}) {
6284: my $rootparmkey=$env{'request.course.id'};
6285: if (($item ne 'all') && ($item ne 'none') && ($item)) {
6286: $rootparmkey.='.['.$item.']';
6287: }
6288: if ($parmlev eq 'general') {
6289: # course-level parameter
6290: my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
6291: $$listdata{$newparmkey}=1;
6292: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6293: } elsif ($parmlev eq 'map') {
6294: # map-level parameter
1.548 raeburn 6295: foreach my $mapid (keys(%{$allmaps})) {
1.269 raeburn 6296: if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
6297: my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
6298: $$listdata{$newparmkey}=1;
6299: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6300: }
6301: } else {
6302: # resource-level parameter
6303: foreach my $rid (@{$ids}) {
6304: my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
6305: if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
6306: my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
6307: $$listdata{$newparmkey}=1;
6308: $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
6309: }
6310: }
6311: }
6312: }
6313: }
6314:
1.563 damieng 6315: # UI to edit parameter settings starting with a list of all existing parameters.
6316: # (called by setoverview action)
6317: #
6318: # @param {Apache2::RequestRec} $r - the Apache request
1.208 www 6319: sub overview {
1.568 raeburn 6320: my ($r,$parm_permission) = @_;
1.208 www 6321: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6322: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6323: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568 raeburn 6324: my $readonly = 1;
6325: if ($parm_permission->{'edit'}) {
6326: undef($readonly);
6327: }
1.549 raeburn 6328: my $js = '<script type="text/javascript">'."\n".
6329: '// <![CDATA['."\n".
6330: &toggleparmtextbox_js()."\n".
6331: &validateparms_js()."\n".
6332: &ipacc_boxes_js()."\n".
1.558 raeburn 6333: &done_proctor_js()."\n".
1.588 raeburn 6334: &deeplink_js()."\n".
1.549 raeburn 6335: '// ]]>'."\n".
6336: '</script>'."\n";
1.414 droeschl 6337: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473 amueller 6338: text=>"Overview Mode"});
1.549 raeburn 6339: my %loaditems = (
6340: 'onload' => "showHideLenient();",
6341: );
6342:
6343: my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298 albertel 6344: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507 www 6345: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6346: &startSettingsScreen($r,'parmset',$crstype);
1.549 raeburn 6347: $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507 www 6348:
1.208 www 6349: # Store modified
6350:
1.568 raeburn 6351: unless ($readonly) {
6352: &storedata($r,$crs,$dom);
6353: }
1.208 www 6354:
6355: # Read modified data
6356:
1.552 raeburn 6357: my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208 www 6358:
1.214 www 6359:
6360: my $sortorder=$env{'form.sortorder'};
6361: unless ($sortorder) { $sortorder='realmstudent'; }
1.608 raeburn 6362: &sortmenu($r,$sortorder,'overview');
1.214 www 6363:
1.568 raeburn 6364: my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
6365:
6366: if ($readonly) {
6367: $r->print('<p>'.$submitbutton.'</p>');
6368: }
6369:
1.208 www 6370: # List data
6371:
1.568 raeburn 6372: my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
6373: $r->print(&tableend().'<p>');
6374: if ($foundkeys) {
6375: unless ($readonly) {
6376: $r->print('<p>'.$submitbutton.'</p>');
6377: }
6378: } else {
6379: $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
6380: }
6381: $r->print('</form>'.&Apache::loncommon::end_page());
1.120 www 6382: }
1.121 www 6383:
1.560 damieng 6384: # Unused sub.
1.563 damieng 6385: #
6386: # @param {Apache2::RequestRec} $r - the Apache request
1.333 albertel 6387: sub clean_parameters {
6388: my ($r) = @_;
6389: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6390: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
6391:
1.414 droeschl 6392: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473 amueller 6393: text=>"Clean Parameters"});
1.333 albertel 6394: my $start_page=&Apache::loncommon::start_page('Clean Parameters');
6395: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
6396: $r->print(<<ENDOVER);
6397: $start_page
6398: $breadcrumbs
6399: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
6400: ENDOVER
6401: # Store modified
6402:
6403: &storedata($r,$crs,$dom);
6404:
6405: # Read modified data
6406:
6407: my $resourcedata=&readdata($crs,$dom);
6408:
6409: # List data
6410:
6411: $r->print('<h3>'.
1.473 amueller 6412: &mt('These parameters refer to resources that do not exist.').
6413: '</h3>'.
6414: '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
6415: '<br />');
1.333 albertel 6416: $r->print(&Apache::loncommon::start_data_table().
1.473 amueller 6417: '<tr>'.
6418: '<th>'.&mt('Delete').'</th>'.
6419: '<th>'.&mt('Parameter').'</th>'.
6420: '</tr>');
1.333 albertel 6421: foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560 damieng 6422: next if (!exists($resourcedata->{$thiskey.'.type'})
6423: && $thiskey=~/\.type$/);
6424: my %data = &parse_key($thiskey);
6425: if (1) { #exists($data{'realm_exists'})
6426: #&& !$data{'realm_exists'}) {
6427: $r->print(&Apache::loncommon::start_data_table_row().
6428: '<tr>'.
6429: '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>' );
6430:
6431: $r->print('<td>');
6432: my $display_value = $resourcedata->{$thiskey};
6433: if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
6434: $display_value =
6435: &Apache::lonlocal::locallocaltime($display_value);
6436: }
1.470 raeburn 6437: my $parmitem = &standard_parameter_names($data{'parameter_name'});
6438: $parmitem = &mt($parmitem);
1.560 damieng 6439: $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
6440: $parmitem,$resourcedata->{$thiskey}));
6441: $r->print('<br />');
6442: if ($data{'scope_type'} eq 'all') {
6443: $r->print(&mt('All users'));
6444: } elsif ($data{'scope_type'} eq 'user') {
6445: $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581 raeburn 6446: } elsif ($data{'scope_type'} eq 'secgroup') {
6447: $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560 damieng 6448: }
6449: $r->print('<br />');
6450: if ($data{'realm_type'} eq 'all') {
6451: $r->print(&mt('All Resources'));
6452: } elsif ($data{'realm_type'} eq 'folder') {
6453: $r->print(&mt('Folder: [_1]'),$data{'realm'});
6454: } elsif ($data{'realm_type'} eq 'symb') {
6455: my ($map,$resid,$url) =
6456: &Apache::lonnet::decode_symb($data{'realm'});
6457: $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
6458: $url.' <br /> ',
6459: $resid.' <br /> ',$map));
6460: }
6461: $r->print(' <br /> '.&mt('Part: [_1]',$data{'parameter_part'}));
6462: $r->print('</td></tr>');
6463:
1.473 amueller 6464: }
1.333 albertel 6465: }
6466: $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473 amueller 6467: '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507 www 6468: '</p></form>');
6469: &endSettingsScreen($r);
6470: $r->print(&Apache::loncommon::end_page());
1.333 albertel 6471: }
6472:
1.563 damieng 6473: # UI to shift all dates (called by dateshift1 action).
6474: # Used by overview mode.
6475: #
6476: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6477: sub date_shift_one {
6478: my ($r) = @_;
6479: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6480: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6481: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594 raeburn 6482: my $sec = $env{'request.course.sec'};
1.414 droeschl 6483: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6484: text=>"Shifting Dates"});
1.594 raeburn 6485: my $submit_text = &mt('Shift all dates accordingly');
6486: if ($sec ne '') {
1.595 raeburn 6487: my @groups;
6488: if ($env{'request.course.groups'} ne '') {
6489: @groups = split(/:/,$env{'request.course.groups'});
6490: }
6491: if (@groups) {
6492: $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
6493: } else {
6494: $submit_text = &mt("Shift dates set just for your section, accordingly");
6495: }
1.594 raeburn 6496: }
1.390 www 6497: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6498: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6499: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6500: &startSettingsScreen($r,'parmset',$crstype);
1.538 bisitz 6501: $r->print('<form name="shiftform" method="post" action="">'.
1.390 www 6502: '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
6503: &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
6504: '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541 bisitz 6505: &Apache::lonhtmlcommon::date_setter('shiftform',
1.390 www 6506: 'timeshifted',
6507: $env{'form.timebase'},,
6508: '').
6509: '</td></tr></table>'.
6510: '<input type="hidden" name="action" value="dateshift2" />'.
6511: '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594 raeburn 6512: '<input type="submit" value="'.$submit_text.'" /></form>');
1.507 www 6513: &endSettingsScreen($r);
1.390 www 6514: $r->print(&Apache::loncommon::end_page());
6515: }
6516:
1.563 damieng 6517: # UI to shift all dates (second form).
6518: #
6519: # @param {Apache2::RequestRec} $r - the Apache request
1.390 www 6520: sub date_shift_two {
6521: my ($r) = @_;
6522: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6523: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594 raeburn 6524: my $sec = $env{'request.course.sec'};
1.531 raeburn 6525: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 6526: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473 amueller 6527: text=>"Shifting Dates"});
1.390 www 6528: my $start_page=&Apache::loncommon::start_page('Shift Dates');
6529: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507 www 6530: $r->print($start_page.$breadcrumbs);
1.531 raeburn 6531: &startSettingsScreen($r,'parmset',$crstype);
1.390 www 6532: my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594 raeburn 6533: $r->print('<h2>'.&mt('Shift Dates').'</h2>');
6534: if ($sec ne '') {
1.595 raeburn 6535: my @groups;
6536: if ($env{'request.course.groups'} ne '') {
6537: @groups = split(/:/,$env{'request.course.groups'});
6538: }
6539: if (@groups) {
6540: $r->print('<p>'.
6541: &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
6542: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6543: &Apache::lonlocal::locallocaltime($timeshifted)).
6544: '</p>');
6545: } else {
6546: $r->print('<p>'.
6547: &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
6548: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6549: &Apache::lonlocal::locallocaltime($timeshifted)).
6550: '</p>');
6551: }
1.594 raeburn 6552: } else {
6553: $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
6554: &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
6555: &Apache::lonlocal::locallocaltime($timeshifted)).
6556: '</p>');
6557: }
1.390 www 6558: my $delta=$timeshifted-$env{'form.timebase'};
1.594 raeburn 6559: my $numchanges = 0;
6560: my $result = &dateshift($delta,\$numchanges);
6561: if ($result eq 'ok') {
6562: $r->print(
6563: &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
6564: $numchanges)));
6565: } elsif ($result eq 'con_delayed') {
6566: $r->print(
6567: &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
6568: $numchanges)));
6569: } else {
6570: $r->print(
6571: &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
6572: }
1.543 bisitz 6573: $r->print(
6574: '<br /><br />'.
6575: &Apache::lonhtmlcommon::actionbox(
6576: ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507 www 6577: &endSettingsScreen($r);
1.390 www 6578: $r->print(&Apache::loncommon::end_page());
6579: }
6580:
1.563 damieng 6581: # Returns the different components of a resourcedata key.
6582: # Keys: scope_type, scope, realm_type, realm, realm_title,
6583: # realm_exists, parameter_part, parameter_name.
6584: # Was used by clean_parameters (which is unused).
6585: #
6586: # @param {string} $key - the parameter key
6587: # @returns {hash}
1.333 albertel 6588: sub parse_key {
6589: my ($key) = @_;
6590: my %data;
6591: my ($middle,$part,$name)=
1.572 damieng 6592: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333 albertel 6593: $data{'scope_type'} = 'all';
6594: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 6595: $data{'scope'} = $1;
6596: if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
6597: $data{'scope_type'} = 'user';
6598: $data{'scope'} = [$1,$2];
6599: } else {
1.581 raeburn 6600: $data{'scope_type'} = 'secgroup';
1.560 damieng 6601: }
6602: $middle=~s/^\[(.*)\]//;
1.333 albertel 6603: }
6604: $middle=~s/\.+$//;
6605: $middle=~s/^\.+//;
6606: $data{'realm_type'}='all';
6607: if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560 damieng 6608: $data{'realm'} = $1;
6609: $data{'realm_type'} = 'folder';
6610: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6611: ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333 albertel 6612: } elsif ($middle) {
1.560 damieng 6613: $data{'realm'} = $middle;
6614: $data{'realm_type'} = 'symb';
6615: $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
6616: my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
6617: $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333 albertel 6618: }
1.446 bisitz 6619:
1.333 albertel 6620: $data{'parameter_part'} = $part;
6621: $data{'parameter_name'} = $name;
6622:
6623: return %data;
6624: }
6625:
1.239 raeburn 6626:
1.563 damieng 6627: # Calls loncommon::start_page with the "Settings" title.
1.416 jms 6628: sub header {
1.507 www 6629: return &Apache::loncommon::start_page('Settings');
1.416 jms 6630: }
1.193 albertel 6631:
6632:
6633:
1.560 damieng 6634: ##################################################
6635: # MAIN MENU
6636: ##################################################
6637:
1.563 damieng 6638: # Content and problem settings main menu.
6639: #
6640: # @param {Apache2::RequestRec} $r - the Apache request
6641: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193 albertel 6642: sub print_main_menu {
6643: my ($r,$parm_permission)=@_;
6644: #
1.414 droeschl 6645: $r->print(&header());
1.507 www 6646: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531 raeburn 6647: my $crstype = &Apache::loncommon::course_type();
6648: my $lc_crstype = lc($crstype);
6649:
6650: &startSettingsScreen($r,'parmset',$crstype);
1.193 albertel 6651: $r->print(<<ENDMAINFORMHEAD);
6652: <form method="post" enctype="multipart/form-data"
6653: action="/adm/parmset" name="studentform">
6654: ENDMAINFORMHEAD
6655: #
1.195 albertel 6656: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6657: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268 albertel 6658: my $vgr = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366 albertel 6659: my $mgr = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520 raeburn 6660: my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568 raeburn 6661: my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
6662: my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520 raeburn 6663: if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
6664: $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
6665: '/'.$env{'request.course.sec'});
6666: }
1.568 raeburn 6667: if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
6668: $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
6669: '/'.$env{'request.course.sec'});
6670: }
6671: my (%linktext,%linktitle,%url);
6672: if ($parm_permission->{'edit'}) {
6673: %linktext = (
6674: newoverview => 'Edit Resource Parameters - Overview Mode',
6675: settable => 'Edit Resource Parameters - Table Mode',
6676: setoverview => 'Modify Resource Parameters - Overview Mode',
6677: );
6678: %linktitle = (
6679: newoverview => 'Set/Modify resource parameters in overview mode.',
6680: settable => 'Set/Modify resource parameters in table mode.',
6681: setoverview => 'Set/Modify existing resource parameters in overview mode.',
6682: );
6683: } else {
6684: %linktext = (
6685: newoverview => 'View Resource Parameters - Overview Mode',
6686: settable => 'View Resource Parameters - Table Mode',
6687: setoverview => 'View Resource Parameters - Overview Mode',
6688: );
6689: %linktitle = (
6690: newoverview => 'Display resource parameters in overview mode.',
6691: settable => 'Display resource parameters in table mode.',
6692: setoverview => 'Display existing resource parameters in overview mode.',
6693: );
6694: }
6695: if ($mgr) {
6696: $linktext{'resettimes'} = 'Reset Student Access Times';
6697: $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
6698: $url{'resettimes'} = '/adm/helper/resettimes.helper';
6699: } elsif ($vgr) {
6700: $linktext{'resettimes'} = 'Display Student Access Times',
6701: $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
6702: $url{'resettimes'} = '/adm/accesstimes';
6703: }
1.193 albertel 6704: my @menu =
1.507 www 6705: ( { categorytitle=>"Content Settings for this $crstype",
1.473 amueller 6706: items => [
6707: { linktext => 'Portfolio Metadata',
6708: url => '/adm/parmset?action=setrestrictmeta',
1.568 raeburn 6709: permission => $parm_permission->{'setrestrictmeta'},
1.477 raeburn 6710: linktitle => "Restrict metadata for this $lc_crstype." ,
1.473 amueller 6711: icon =>'contact-new.png' ,
6712: },
1.568 raeburn 6713: { linktext => $linktext{'resettimes'},
6714: url => $url{'resettimes'},
6715: permission => ($vgr || $mgr),
6716: linktitle => $linktitle{'resettimes'},
6717: icon => 'start-here.png',
1.473 amueller 6718: },
1.520 raeburn 6719: { linktext => 'Blocking Communication/Resource Access',
6720: url => '/adm/setblock',
1.568 raeburn 6721: permission => ($vcb || $dcm),
1.520 raeburn 6722: linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
6723: icon => 'comblock.png',
6724: },
1.473 amueller 6725: { linktext => 'Set Parameter Setting Default Actions',
6726: url => '/adm/parmset?action=setdefaults',
1.568 raeburn 6727: permission => $parm_permission->{'setdefaults'},
1.473 amueller 6728: linktitle =>'Set default actions for parameters.' ,
6729: icon => 'folder-new.png' ,
6730: }]},
6731: { categorytitle => 'New and Existing Parameter Settings for Resources',
6732: items => [
6733: { linktext => 'Edit Resource Parameters - Helper Mode',
6734: url => '/adm/helper/parameter.helper',
1.568 raeburn 6735: permission => $parm_permission->{'helper'},
1.473 amueller 6736: linktitle =>'Set/Modify resource parameters in helper mode.' ,
6737: icon => 'dialog-information.png' ,
6738: #help => 'Parameter_Helper',
6739: },
1.568 raeburn 6740: { linktext => $linktext{'newoverview'},
1.473 amueller 6741: url => '/adm/parmset?action=newoverview',
1.568 raeburn 6742: permission => $parm_permission->{'newoverview'},
6743: linktitle => $linktitle{'newoverview'},
6744: icon => 'edit-find.png',
1.473 amueller 6745: #help => 'Parameter_Overview',
6746: },
1.568 raeburn 6747: { linktext => $linktext{'settable'},
1.473 amueller 6748: url => '/adm/parmset?action=settable',
1.568 raeburn 6749: permission => $parm_permission->{'settable'},
6750: linktitle => $linktitle{'settable'},
6751: icon => 'edit-copy.png',
1.473 amueller 6752: #help => 'Table_Mode',
6753: }]},
1.417 droeschl 6754: { categorytitle => 'Existing Parameter Settings for Resources',
1.473 amueller 6755: items => [
1.570 raeburn 6756: { linktext => $linktext{'setoverview'},
1.473 amueller 6757: url => '/adm/parmset?action=setoverview',
1.568 raeburn 6758: permission => $parm_permission->{'setoverview'},
6759: linktitle => $linktitle{'setoverview'},
6760: icon => 'preferences-desktop-wallpaper.png',
1.473 amueller 6761: #help => 'Parameter_Overview',
6762: },
6763: { linktext => 'Change Log',
6764: url => '/adm/parmset?action=parameterchangelog',
1.568 raeburn 6765: permission => $parm_permission->{'parameterchangelog'},
1.477 raeburn 6766: linktitle =>"View parameter and $lc_crstype blog posting/user notification change log." ,
1.487 wenzelju 6767: icon => 'document-properties.png',
1.473 amueller 6768: }]}
1.193 albertel 6769: );
1.414 droeschl 6770: $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539 raeburn 6771: $r->print('</form>');
1.507 www 6772: &endSettingsScreen($r);
1.539 raeburn 6773: $r->print(&Apache::loncommon::end_page());
1.193 albertel 6774: return;
6775: }
1.414 droeschl 6776:
1.416 jms 6777:
6778:
1.560 damieng 6779: ##################################################
6780: # PORTFOLIO METADATA
6781: ##################################################
6782:
1.563 damieng 6783: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
6784: # It looks like field titles are not localized.
6785: #
6786: # @param {Apache2::RequestRec} $r - the Apache request
6787: # @param {string} $field_name - metadata field name
6788: # @param {string} $field_text - metadata field title, in English unless manually added
6789: # @param {boolean} $added_flag - true if the field was manually added
1.252 banghart 6790: sub output_row {
1.347 banghart 6791: my ($r, $field_name, $field_text, $added_flag) = @_;
1.252 banghart 6792: my $output;
1.263 banghart 6793: my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
6794: my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337 banghart 6795: if (!defined($options)) {
1.254 banghart 6796: $options = 'active,stuadd';
1.261 banghart 6797: $values = '';
1.252 banghart 6798: }
1.337 banghart 6799: if (!($options =~ /deleted/)) {
6800: my @options= ( ['active', 'Show to student'],
1.418 schafran 6801: ['stuadd', 'Provide text area for students to type metadata'],
1.351 banghart 6802: ['choices','Provide choices for students to select from']);
1.473 amueller 6803: # ['onlyone','Student may select only one choice']);
1.337 banghart 6804: if ($added_flag) {
6805: push @options,['deleted', 'Delete Metadata Field'];
6806: }
1.351 banghart 6807: $output = &Apache::loncommon::start_data_table_row();
1.451 bisitz 6808: $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351 banghart 6809: $output .= &Apache::loncommon::end_data_table_row();
1.337 banghart 6810: foreach my $opt (@options) {
1.560 damieng 6811: my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
6812: $output .= &Apache::loncommon::continue_data_table_row();
6813: $output .= '<td>'.(' ' x 5).'<label>
6814: <input type="checkbox" name="'.
6815: $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
6816: &mt($opt->[1]).'</label></td>';
6817: $output .= &Apache::loncommon::end_data_table_row();
6818: }
1.351 banghart 6819: $output .= &Apache::loncommon::continue_data_table_row();
1.451 bisitz 6820: $output .= '<td>'.(' ' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351 banghart 6821: $output .= &Apache::loncommon::end_data_table_row();
6822: my $multiple_checked;
6823: my $single_checked;
6824: if ($options =~ m/onlyone/) {
1.422 bisitz 6825: $multiple_checked = '';
1.423 bisitz 6826: $single_checked = ' checked="checked"';
1.351 banghart 6827: } else {
1.423 bisitz 6828: $multiple_checked = ' checked="checked"';
1.422 bisitz 6829: $single_checked = '';
1.351 banghart 6830: }
1.560 damieng 6831: $output .= &Apache::loncommon::continue_data_table_row();
6832: $output .= '<td>'.(' ' x 10).'
6833: <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
6834: '.&mt('Student may select multiple choices from list').'</td>';
6835: $output .= &Apache::loncommon::end_data_table_row();
6836: $output .= &Apache::loncommon::continue_data_table_row();
6837: $output .= '<td>'.(' ' x 10).'
6838: <input type="radio" name="'.$field_name.'_onlyone" value="single"'.$single_checked.' />
6839: '.&mt('Student may select only one choice from list').'</td>';
6840: $output .= &Apache::loncommon::end_data_table_row();
1.252 banghart 6841: }
6842: return ($output);
6843: }
1.416 jms 6844:
6845:
1.560 damieng 6846: # UI to order portfolio metadata fields.
1.563 damieng 6847: # Currently useless because addmetafield does not work.
6848: #
6849: # @param {Apache2::RequestRec} $r - the Apache request
1.340 banghart 6850: sub order_meta_fields {
6851: my ($r)=@_;
6852: my $idx = 1;
6853: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6854: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6855: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341 banghart 6856: $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560 damieng 6857: &Apache::lonhtmlcommon::add_breadcrumb(
6858: {href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6859: text=>"Add Metadata Field"});
1.560 damieng 6860: &Apache::lonhtmlcommon::add_breadcrumb(
6861: {href=>"/adm/parmset?action=setrestrictmeta",
6862: text=>"Restrict Metadata"},
6863: {text=>"Order Metadata"});
1.345 banghart 6864: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531 raeburn 6865: &startSettingsScreen($r,'parmset',$crstype);
1.340 banghart 6866: if ($env{'form.storeorder'}) {
6867: my $newpos = $env{'form.newpos'} - 1;
6868: my $currentpos = $env{'form.currentpos'} - 1;
6869: my @neworder = ();
1.548 raeburn 6870: my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6871: my $i;
1.341 banghart 6872: if ($newpos > $currentpos) {
1.340 banghart 6873: # moving stuff up
6874: for ($i=0;$i<$currentpos;$i++) {
1.560 damieng 6875: $neworder[$i]=$oldorder[$i];
1.340 banghart 6876: }
6877: for ($i=$currentpos;$i<$newpos;$i++) {
1.560 damieng 6878: $neworder[$i]=$oldorder[$i+1];
1.340 banghart 6879: }
6880: $neworder[$newpos]=$oldorder[$currentpos];
6881: for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560 damieng 6882: $neworder[$i]=$oldorder[$i];
1.340 banghart 6883: }
6884: } else {
6885: # moving stuff down
1.473 amueller 6886: for ($i=0;$i<$newpos;$i++) {
6887: $neworder[$i]=$oldorder[$i];
6888: }
6889: $neworder[$newpos]=$oldorder[$currentpos];
6890: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
6891: $neworder[$i]=$oldorder[$i-1];
6892: }
6893: for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
6894: $neworder[$i]=$oldorder[$i];
6895: }
1.340 banghart 6896: }
1.560 damieng 6897: my $ordered_fields = join ",", @neworder;
1.343 banghart 6898: my $put_result = &Apache::lonnet::put('environment',
1.560 damieng 6899: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6900: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340 banghart 6901: }
1.357 raeburn 6902: my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341 banghart 6903: my $ordered_fields;
1.548 raeburn 6904: my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340 banghart 6905: if (!@fields_in_order) {
6906: # no order found, pick sorted order then create metadata.addedorder key.
1.548 raeburn 6907: foreach my $key (sort(keys(%$fields))) {
1.340 banghart 6908: push @fields_in_order, $key;
1.341 banghart 6909: $ordered_fields = join ",", @fields_in_order;
1.340 banghart 6910: }
1.341 banghart 6911: my $put_result = &Apache::lonnet::put('environment',
1.446 bisitz 6912: {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
6913: }
1.340 banghart 6914: $r->print('<table>');
6915: my $num_fields = scalar(@fields_in_order);
6916: foreach my $key (@fields_in_order) {
6917: $r->print('<tr><td>');
6918: $r->print('<form method="post" action="">');
1.537 bisitz 6919: $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340 banghart 6920: for (my $i = 1;$i le $num_fields;$i ++) {
6921: if ($i eq $idx) {
6922: $r->print('<option value="'.$i.'" SELECTED>('.$i.')</option>');
6923: } else {
6924: $r->print('<option value="'.$i.'">'.$i.'</option>');
6925: }
6926: }
6927: $r->print('</select></td><td>');
6928: $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
6929: $r->print('<input type="hidden" name="storeorder" value="true" />');
6930: $r->print('</form>');
6931: $r->print($$fields{$key}.'</td></tr>');
6932: $idx ++;
6933: }
6934: $r->print('</table>');
1.507 www 6935: &endSettingsScreen($r);
1.340 banghart 6936: return 'ok';
6937: }
1.416 jms 6938:
6939:
1.563 damieng 6940: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
6941: # @returns {string}
1.359 banghart 6942: sub continue {
6943: my $output;
6944: $output .= '<form action="" method="post">';
6945: $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586 raeburn 6946: $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359 banghart 6947: return ($output);
6948: }
1.416 jms 6949:
6950:
1.563 damieng 6951: # UI to add a metadata field.
6952: # Currenly does not work because of an HTML error (the field is not visible).
6953: #
6954: # @param {Apache2::RequestRec} $r - the Apache request
1.334 banghart 6955: sub addmetafield {
6956: my ($r)=@_;
1.414 droeschl 6957: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473 amueller 6958: text=>"Add Metadata Field"});
1.334 banghart 6959: $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
6960: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335 banghart 6961: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6962: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 6963: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
6964: &startSettingsScreen($r,'parmset',$crstype);
1.339 banghart 6965: if (exists($env{'form.undelete'})) {
1.358 banghart 6966: my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339 banghart 6967: foreach my $meta_field(@meta_fields) {
6968: my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
6969: $options =~ s/deleted//;
6970: $options =~ s/,,/,/;
6971: my $put_result = &Apache::lonnet::put('environment',
6972: {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446 bisitz 6973:
1.586 raeburn 6974: $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
6975: '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
6976: '</strong>',$put_result).
6977: '<br />');
1.339 banghart 6978: }
1.359 banghart 6979: $r->print(&continue());
1.339 banghart 6980: } elsif (exists($env{'form.fieldname'})) {
1.335 banghart 6981: my $meta_field = $env{'form.fieldname'};
6982: my $display_field = $env{'form.fieldname'};
6983: $meta_field =~ s/\W/_/g;
1.338 banghart 6984: $meta_field =~ tr/A-Z/a-z/;
1.335 banghart 6985: my $put_result = &Apache::lonnet::put('environment',
6986: {'metadata.'.$meta_field.'.values'=>"",
6987: 'metadata.'.$meta_field.'.added'=>"$display_field",
6988: 'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586 raeburn 6989: $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
6990: '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
6991: '<br />');
1.359 banghart 6992: $r->print(&continue());
1.335 banghart 6993: } else {
1.357 raeburn 6994: my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339 banghart 6995: if ($fields) {
1.586 raeburn 6996: $r->print(&mt('You may undelete previously deleted fields.').
6997: '<br />'.
6998: &mt('Check those you wish to undelete and click Undelete.').
6999: '<br />');
1.339 banghart 7000: $r->print('<form method="post" action="">');
7001: foreach my $key(keys(%$fields)) {
1.581 raeburn 7002: $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339 banghart 7003: }
1.586 raeburn 7004: $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339 banghart 7005: $r->print('</form>');
7006: }
1.586 raeburn 7007: $r->print('<hr />'.
7008: &mt('[_1]Or[_2] you may enter a new metadata field name.',
7009: '<strong>','</strong>').
1.581 raeburn 7010: '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335 banghart 7011: $r->print('<input type="text" name="fieldname" /><br />');
1.586 raeburn 7012: $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581 raeburn 7013: $r->print('</form>');
1.334 banghart 7014: }
1.507 www 7015: &endSettingsScreen($r);
1.334 banghart 7016: }
1.416 jms 7017:
7018:
7019:
1.560 damieng 7020: # Display or save portfolio metadata.
1.563 damieng 7021: #
7022: # @param {Apache2::RequestRec} $r - the Apache request
1.259 banghart 7023: sub setrestrictmeta {
1.240 banghart 7024: my ($r)=@_;
1.242 banghart 7025: my $next_meta;
1.244 banghart 7026: my $output;
1.245 banghart 7027: my $item_num;
1.246 banghart 7028: my $put_result;
1.414 droeschl 7029: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473 amueller 7030: text=>"Restrict Metadata"});
1.280 albertel 7031: $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298 albertel 7032: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240 banghart 7033: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7034: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531 raeburn 7035: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
7036: &startSettingsScreen($r,'parmset',$crstype);
1.259 banghart 7037: my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252 banghart 7038: my $save_field = '';
1.586 raeburn 7039: my %lt = &Apache::lonlocal::texthash(
7040: addm => 'Add Metadata Field',
7041: ordm => 'Order Metadata Fields',
7042: save => 'Save',
7043: );
1.259 banghart 7044: if ($env{'form.restrictmeta'}) {
1.254 banghart 7045: foreach my $field (sort(keys(%env))) {
1.252 banghart 7046: if ($field=~m/^form.(.+)_(.+)$/) {
1.254 banghart 7047: my $options;
1.252 banghart 7048: my $meta_field = $1;
7049: my $meta_key = $2;
1.253 banghart 7050: if ($save_field ne $meta_field) {
1.252 banghart 7051: $save_field = $meta_field;
1.473 amueller 7052: if ($env{'form.'.$meta_field.'_stuadd'}) {
7053: $options.='stuadd,';
7054: }
7055: if ($env{'form.'.$meta_field.'_choices'}) {
7056: $options.='choices,';
7057: }
7058: if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
7059: $options.='onlyone,';
7060: }
7061: if ($env{'form.'.$meta_field.'_active'}) {
7062: $options.='active,';
7063: }
7064: if ($env{'form.'.$meta_field.'_deleted'}) {
7065: $options.='deleted,';
7066: }
1.259 banghart 7067: my $name = $save_field;
1.560 damieng 7068: $put_result = &Apache::lonnet::put('environment',
7069: {'metadata.'.$meta_field.'.options'=>$options,
7070: 'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
7071: },$dom,$crs);
1.252 banghart 7072: }
7073: }
7074: }
7075: }
1.296 albertel 7076: &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473 amueller 7077: {'freshen_cache' => 1});
1.335 banghart 7078: # Get the default metadata fields
1.258 albertel 7079: my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335 banghart 7080: # Now get possible added metadata fields
1.357 raeburn 7081: my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347 banghart 7082: $output .= &Apache::loncommon::start_data_table();
1.258 albertel 7083: foreach my $field (sort(keys(%metadata_fields))) {
1.265 banghart 7084: if ($field ne 'courserestricted') {
1.586 raeburn 7085: $output.= &output_row($r,$field,$metadata_fields{$field});
1.560 damieng 7086: }
1.255 banghart 7087: }
1.351 banghart 7088: my $buttons = (<<ENDButtons);
1.586 raeburn 7089: <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351 banghart 7090: </form><br />
7091: <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586 raeburn 7092: <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351 banghart 7093: </form>
7094: <br />
7095: <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586 raeburn 7096: <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351 banghart 7097: ENDButtons
1.337 banghart 7098: my $added_flag = 1;
1.335 banghart 7099: foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586 raeburn 7100: $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335 banghart 7101: }
1.347 banghart 7102: $output .= &Apache::loncommon::end_data_table();
1.446 bisitz 7103: $r->print(<<ENDenv);
1.259 banghart 7104: <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244 banghart 7105: $output
1.351 banghart 7106: $buttons
1.340 banghart 7107: </form>
1.244 banghart 7108: ENDenv
1.507 www 7109: &endSettingsScreen($r);
1.280 albertel 7110: $r->print(&Apache::loncommon::end_page());
1.240 banghart 7111: return 'ok';
7112: }
1.416 jms 7113:
7114:
1.563 damieng 7115: # Returns metadata fields that have been manually added.
7116: #
7117: # @param {string} $cid - course id
7118: # @returns {hash reference} - hash field name -> field title (not localized)
1.335 banghart 7119: sub get_added_meta_fieldnames {
1.357 raeburn 7120: my ($cid) = @_;
1.335 banghart 7121: my %fields;
7122: foreach my $key(%env) {
1.357 raeburn 7123: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335 banghart 7124: my $field_name = $1;
7125: my ($display_field_name) = $env{$key};
7126: $fields{$field_name} = $display_field_name;
7127: }
7128: }
7129: return \%fields;
7130: }
1.416 jms 7131:
7132:
1.563 damieng 7133: # Returns metadata fields that have been manually added and deleted.
7134: #
7135: # @param {string} $cid - course id
7136: # @returns {hash reference} - hash field name -> field title (not localized)
1.339 banghart 7137: sub get_deleted_meta_fieldnames {
1.357 raeburn 7138: my ($cid) = @_;
1.339 banghart 7139: my %fields;
7140: foreach my $key(%env) {
1.357 raeburn 7141: if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339 banghart 7142: my $field_name = $1;
7143: if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
7144: my ($display_field_name) = $env{$key};
7145: $fields{$field_name} = $display_field_name;
7146: }
7147: }
7148: }
7149: return \%fields;
7150: }
1.560 damieng 7151:
7152:
7153: ##################################################
7154: # PARAMETER SETTINGS DEFAULT ACTIONS
7155: ##################################################
7156:
7157: # UI to change parameter setting default actions
1.563 damieng 7158: #
7159: # @param {Apache2::RequestRec} $r - the Apache request
1.220 www 7160: sub defaultsetter {
1.280 albertel 7161: my ($r) = @_;
7162:
1.414 droeschl 7163: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473 amueller 7164: text=>"Set Defaults"});
1.531 raeburn 7165: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7166: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
7167: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446 bisitz 7168: my $start_page =
1.531 raeburn 7169: &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298 albertel 7170: my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507 www 7171: $r->print($start_page.$breadcrumbs);
1.531 raeburn 7172: &startSettingsScreen($r,'parmset',$crstype);
1.507 www 7173: $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280 albertel 7174:
1.221 www 7175: my @ids=();
7176: my %typep=();
7177: my %keyp=();
7178: my %allparms=();
7179: my %allparts=();
7180: my %allmaps=();
7181: my %mapp=();
7182: my %symbp=();
7183: my %maptitles=();
7184: my %uris=();
7185: my %keyorder=&standardkeyorder();
7186: my %defkeytype=();
7187:
1.446 bisitz 7188: &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473 amueller 7189: \%mapp, \%symbp,\%maptitles,\%uris,
7190: \%keyorder,\%defkeytype);
1.224 www 7191: if ($env{'form.storerules'}) {
1.560 damieng 7192: my %newrules=();
7193: my @delrules=();
7194: my %triggers=();
7195: foreach my $key (keys(%env)) {
1.225 albertel 7196: if ($key=~/^form\.(\w+)\_action$/) {
1.560 damieng 7197: my $tempkey=$1;
7198: my $action=$env{$key};
1.226 www 7199: if ($action) {
1.560 damieng 7200: $newrules{$tempkey.'_action'}=$action;
7201: if ($action ne 'default') {
7202: my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
7203: $triggers{$whichparm}.=$tempkey.':';
7204: }
7205: $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
7206: if (&isdateparm($defkeytype{$tempkey})) {
7207: $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
7208: $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
7209: $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
7210: $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
7211: } else {
7212: $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
7213: $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
7214: }
7215: } else {
7216: push(@delrules,$tempkey.'_action');
7217: push(@delrules,$tempkey.'_type');
7218: push(@delrules,$tempkey.'_hours');
7219: push(@delrules,$tempkey.'_min');
7220: push(@delrules,$tempkey.'_sec');
7221: push(@delrules,$tempkey.'_value');
7222: }
1.473 amueller 7223: }
7224: }
1.560 damieng 7225: foreach my $key (keys(%allparms)) {
7226: $newrules{$key.'_triggers'}=$triggers{$key};
1.473 amueller 7227: }
1.560 damieng 7228: &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
7229: &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
7230: &resetrulescache();
1.224 www 7231: }
1.227 www 7232: my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473 amueller 7233: 'hours' => 'Hours',
7234: 'min' => 'Minutes',
7235: 'sec' => 'Seconds',
7236: 'yes' => 'Yes',
7237: 'no' => 'No');
1.222 www 7238: my @standardoptions=('','default');
7239: my @standarddisplay=('',&mt('Default value when manually setting'));
7240: my @dateoptions=('','default');
7241: my @datedisplay=('',&mt('Default value when manually setting'));
7242: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7243: unless ($tempkey) { next; }
7244: push @standardoptions,'when_setting_'.$tempkey;
7245: push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
7246: if (&isdateparm($defkeytype{$tempkey})) {
7247: push @dateoptions,'later_than_'.$tempkey;
7248: push @datedisplay,&mt('Automatically set later than ').$tempkey;
7249: push @dateoptions,'earlier_than_'.$tempkey;
7250: push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
7251: }
1.222 www 7252: }
1.563 damieng 7253: $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
7254: &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318 albertel 7255: $r->print("\n".&Apache::loncommon::start_data_table().
1.473 amueller 7256: &Apache::loncommon::start_data_table_header_row().
7257: "<th>".&mt('Rule for parameter').'</th><th>'.
7258: &mt('Action').'</th><th>'.&mt('Value').'</th>'.
7259: &Apache::loncommon::end_data_table_header_row());
1.221 www 7260: foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560 damieng 7261: unless ($tempkey) { next; }
7262: $r->print("\n".&Apache::loncommon::start_data_table_row().
7263: "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
7264: my $action=&rulescache($tempkey.'_action');
7265: $r->print('<select name="'.$tempkey.'_action">');
7266: if (&isdateparm($defkeytype{$tempkey})) {
7267: for (my $i=0;$i<=$#dateoptions;$i++) {
7268: if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
7269: $r->print("\n<option value='$dateoptions[$i]'".
7270: ($dateoptions[$i] eq $action?' selected="selected"':'').
7271: ">$datedisplay[$i]</option>");
7272: }
7273: } else {
7274: for (my $i=0;$i<=$#standardoptions;$i++) {
7275: if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
7276: $r->print("\n<option value='$standardoptions[$i]'".
7277: ($standardoptions[$i] eq $action?' selected="selected"':'').
7278: ">$standarddisplay[$i]</option>");
7279: }
1.473 amueller 7280: }
1.560 damieng 7281: $r->print('</select>');
7282: unless (&isdateparm($defkeytype{$tempkey})) {
7283: $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
7284: '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473 amueller 7285: }
1.560 damieng 7286: $r->print("\n</td><td>\n");
1.222 www 7287:
1.221 www 7288: if (&isdateparm($defkeytype{$tempkey})) {
1.560 damieng 7289: my $days=&rulescache($tempkey.'_days');
7290: my $hours=&rulescache($tempkey.'_hours');
7291: my $min=&rulescache($tempkey.'_min');
7292: my $sec=&rulescache($tempkey.'_sec');
7293: $r->print(<<ENDINPUTDATE);
7294: <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
7295: <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
7296: <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
7297: <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564 raeburn 7298: ENDINPUTDATE
1.560 damieng 7299: } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
7300: my $yeschecked='';
7301: my $nochecked='';
7302: if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
7303: if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
7304:
7305: $r->print(<<ENDYESNO);
7306: <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
7307: <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564 raeburn 7308: ENDYESNO
1.221 www 7309: } else {
1.560 damieng 7310: $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
7311: }
1.318 albertel 7312: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221 www 7313: }
1.318 albertel 7314: $r->print(&Apache::loncommon::end_data_table().
1.473 amueller 7315: "\n".'<input type="submit" name="storerules" value="'.
1.507 www 7316: &mt('Save').'" /></form>'."\n");
7317: &endSettingsScreen($r);
7318: $r->print(&Apache::loncommon::end_page());
1.220 www 7319: return;
7320: }
1.193 albertel 7321:
1.560 damieng 7322: ##################################################
7323: # PARAMETER CHANGES LOG
7324: ##################################################
7325:
1.563 damieng 7326: # Returns some info for a parameter log entry.
7327: # Returned entries:
7328: # $realm - HTML title for the parameter level and resource
7329: # $section - parameter section
7330: # $name - parameter name
7331: # $part - parameter part
7332: # $what - $part.'.'.$name
7333: # $middle - resource symb ?
7334: # $uname - user name (same as given)
7335: # $udom - user domain (same as given)
7336: # $issection - section or group name
7337: # $realmdescription - title for the parameter level and resource (without using HTML)
7338: #
7339: # @param {string} $key - parameter log key
7340: # @param {string} $uname - user name
7341: # @param {string} $udom - user domain
7342: # @param {boolean} $typeflag - .type log entry
7343: # @returns {Array}
1.290 www 7344: sub components {
1.581 raeburn 7345: my ($key,$uname,$udom,$typeflag)=@_;
1.330 albertel 7346:
7347: if ($typeflag) {
1.560 damieng 7348: $key=~s/\.type$//;
1.290 www 7349: }
1.330 albertel 7350:
7351: my ($middle,$part,$name)=
1.572 damieng 7352: ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291 www 7353: my $issection;
1.330 albertel 7354:
1.290 www 7355: my $section=&mt('All Students');
7356: if ($middle=~/^\[(.*)\]/) {
1.560 damieng 7357: $issection=$1;
7358: $section=&mt('Group/Section').': '.$issection;
7359: $middle=~s/^\[(.*)\]//;
1.290 www 7360: }
7361: $middle=~s/\.+$//;
7362: $middle=~s/^\.+//;
1.291 www 7363: if ($uname) {
1.560 damieng 7364: $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
7365: $issection='';
1.291 www 7366: }
1.316 albertel 7367: my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446 bisitz 7368: my $realmdescription=&mt('all resources');
1.556 raeburn 7369: if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
7370: my $mapurl = $1;
7371: my $maplevel = $2;
7372: my $leveltitle = &mt('Folder/Map');
7373: if ($maplevel eq 'rec') {
7374: $leveltitle = &mt('Recursive');
7375: }
1.560 damieng 7376: $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
7377: ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
7378: $mapurl.')</span></span>';
7379: $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
7380: } elsif ($middle) {
7381: my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
7382: $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
7383: ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
7384: ' in '.$map.' id: '.$id.')</span></span>';
7385: $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290 www 7386: }
1.291 www 7387: my $what=$part.'.'.$name;
1.330 albertel 7388: return ($realm,$section,$name,$part,
1.473 amueller 7389: $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290 www 7390: }
1.293 www 7391:
1.563 damieng 7392: my %standard_parms; # hash parameter name -> parameter title (not localized)
7393: my %standard_parms_types; # hash parameter name -> parameter type
1.416 jms 7394:
1.563 damieng 7395: # Reads parameter info from packages.tab into %standard_parms.
1.328 albertel 7396: sub load_parameter_names {
1.583 raeburn 7397: open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328 albertel 7398: while (my $configline=<$config>) {
1.560 damieng 7399: if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
7400: chomp($configline);
7401: my ($short,$plain)=split(/:/,$configline);
7402: my (undef,$name,$type)=split(/\&/,$short,3);
7403: if ($type eq 'display') {
7404: $standard_parms{$name} = $plain;
1.469 raeburn 7405: } elsif ($type eq 'type') {
1.560 damieng 7406: $standard_parms_types{$name} = $plain;
1.469 raeburn 7407: }
1.328 albertel 7408: }
7409: close($config);
7410: $standard_parms{'int_pos'} = 'Positive Integer';
7411: $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575 raeburn 7412: $standard_parms{'scoreformat'} = 'Format for display of score';
1.328 albertel 7413: }
7414:
1.563 damieng 7415: # Returns a parameter title for standard parameters, the name for others.
7416: #
7417: # @param {string} $name - parameter name
7418: # @returns {string}
1.292 www 7419: sub standard_parameter_names {
7420: my ($name)=@_;
1.328 albertel 7421: if (!%standard_parms) {
1.560 damieng 7422: &load_parameter_names();
1.328 albertel 7423: }
1.292 www 7424: if ($standard_parms{$name}) {
1.560 damieng 7425: return $standard_parms{$name};
1.446 bisitz 7426: } else {
1.560 damieng 7427: return $name;
1.292 www 7428: }
7429: }
1.290 www 7430:
1.563 damieng 7431: # Returns a parameter type for standard parameters, undef for others.
7432: #
7433: # @param {string} $name - parameter name
7434: # @returns {string}
1.469 raeburn 7435: sub standard_parameter_types {
7436: my ($name)=@_;
7437: if (!%standard_parms_types) {
7438: &load_parameter_names();
7439: }
7440: if ($standard_parms_types{$name}) {
7441: return $standard_parms_types{$name};
7442: }
7443: return;
7444: }
1.309 www 7445:
1.563 damieng 7446: # Returns a parameter level title (not localized) from the parameter level name.
7447: #
7448: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
7449: # @returns {string}
1.557 raeburn 7450: sub standard_parameter_levels {
7451: my ($name)=@_;
7452: my %levels = (
7453: 'resourcelevel' => 'a single resource',
7454: 'maplevel' => 'the enclosing map/folder',
7455: 'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
7456: 'courselevel' => 'the general (course) level',
7457: );
7458: if ($levels{$name}) {
7459: return $levels{$name};
7460: }
7461: return;
7462: }
7463:
1.560 damieng 7464: # Display log for parameter changes, blog postings, user notification changes.
1.563 damieng 7465: #
7466: # @param {Apache2::RequestRec} $r - the Apache request
1.285 albertel 7467: sub parm_change_log {
1.568 raeburn 7468: my ($r,$parm_permission)=@_;
1.531 raeburn 7469: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7470: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569 raeburn 7471: my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414 droeschl 7472: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473 amueller 7473: text=>"Parameter Change Log"});
1.522 raeburn 7474: my $js = '<script type="text/javascript">'."\n".
7475: '// <![CDATA['."\n".
7476: &Apache::loncommon::display_filter_js('parmslog')."\n".
7477: '// ]]>'."\n".
7478: '</script>'."\n";
7479: $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327 albertel 7480: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531 raeburn 7481: &startSettingsScreen($r,'parmset',$crstype);
7482: my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311 albertel 7483:
1.301 www 7484: if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311 albertel 7485:
1.522 raeburn 7486: $r->print('<div class="LC_left_float">'.
7487: '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
7488: '<form action="/adm/parmset?action=parameterchangelog"
1.327 albertel 7489: method="post" name="parameterlog">');
1.446 bisitz 7490:
1.311 albertel 7491: my %saveable_parameters = ('show' => 'scalar',);
7492: &Apache::loncommon::store_course_settings('parameter_log',
7493: \%saveable_parameters);
7494: &Apache::loncommon::restore_course_settings('parameter_log',
7495: \%saveable_parameters);
1.522 raeburn 7496: $r->print(&Apache::loncommon::display_filter('parmslog').' '."\n".
7497: '<input type="submit" value="'.&mt('Display').'" />'.
7498: '</form></fieldset></div><br clear="all" />');
1.301 www 7499:
1.568 raeburn 7500: my $readonly = 1;
7501: if ($parm_permission->{'edit'}) {
7502: undef($readonly);
7503: }
1.531 raeburn 7504: my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301 www 7505: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473 amueller 7506: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568 raeburn 7507: &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
7508: unless ($readonly) {
7509: $r->print('<th>'.&mt('Announce').'</th>');
7510: }
7511: $r->print(&Apache::loncommon::end_data_table_header_row());
1.309 www 7512: my $shown=0;
1.349 www 7513: my $folder='';
7514: if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560 damieng 7515: my $last='';
7516: if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
7517: &GDBM_READER(),0640)) {
7518: $last=$hash{'last_known'};
7519: untie(%hash);
7520: }
7521: if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
7522: }
1.595 raeburn 7523: my $numgroups = 0;
7524: my @groups;
7525: if ($env{'request.course.groups'} ne '') {
7526: @groups = split(/:/,$env{'request.course.groups'});
7527: $numgroups = scalar(@groups);
7528: }
1.560 damieng 7529: foreach my $id (sort {
7530: if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
7531: return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
7532: }
7533: my $aid = (split('00000',$a))[-1];
7534: my $bid = (split('00000',$b))[-1];
7535: return $bid<=>$aid;
1.473 amueller 7536: } (keys(%parmlog))) {
1.294 www 7537: my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560 damieng 7538: my $count = 0;
7539: my $time =
7540: &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
7541: my $plainname =
7542: &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
7543: $parmlog{$id}{'exe_udom'});
7544: my $about_me_link =
7545: &Apache::loncommon::aboutmewrapper($plainname,
7546: $parmlog{$id}{'exe_uname'},
7547: $parmlog{$id}{'exe_udom'});
7548: my $send_msg_link='';
1.568 raeburn 7549: if ((!$readonly) &&
7550: (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560 damieng 7551: || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
7552: $send_msg_link ='<br />'.
7553: &Apache::loncommon::messagewrapper(&mt('Send message'),
7554: $parmlog{$id}{'exe_uname'},
7555: $parmlog{$id}{'exe_udom'});
7556: }
7557: my $row_start=&Apache::loncommon::start_data_table_row();
7558: my $makenewrow=0;
7559: my %istype=();
7560: my $output;
7561: foreach my $changed (reverse(sort(@changes))) {
7562: my $value=$parmlog{$id}{'logentry'}{$changed};
7563: my $typeflag = ($changed =~/\.type$/ &&
7564: !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330 albertel 7565: my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581 raeburn 7566: &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560 damieng 7567: if ($env{'request.course.sec'} ne '') {
1.595 raeburn 7568: next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
7569: ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560 damieng 7570: if ($uname ne '') {
7571: my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
7572: next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'}));
7573: }
7574: }
7575: if ($env{'form.displayfilter'} eq 'currentfolder') {
7576: if ($folder) {
7577: if ($middle!~/^\Q$folder\E/) { next; }
7578: }
7579: }
7580: if ($typeflag) {
7581: $istype{$parmname}=$value;
7582: if (!$env{'form.includetypes'}) { next; }
7583: }
7584: $count++;
7585: if ($makenewrow) {
7586: $output .= $row_start;
7587: } else {
7588: $makenewrow=1;
7589: }
1.470 raeburn 7590: my $parmitem = &standard_parameter_names($parmname);
1.560 damieng 7591: $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
7592: &mt($parmitem).'</td><td>'.
7593: ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
7594: my $stillactive=0;
7595: if ($parmlog{$id}{'delflag'}) {
7596: $output .= &mt('Deleted');
7597: } else {
7598: if ($typeflag) {
1.470 raeburn 7599: my $parmitem = &standard_parameter_names($value);
7600: $parmitem = &mt($parmitem);
1.560 damieng 7601: $output .= &mt('Type: [_1]',$parmitem);
7602: } else {
1.584 raeburn 7603: my $toolsymb;
7604: if ($middle =~ /ext\.tool$/) {
7605: $toolsymb = $middle;
7606: }
1.560 damieng 7607: my ($level,@all)=&parmval_by_symb($what,$middle,
1.584 raeburn 7608: &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560 damieng 7609: $uname,$udom,$issection,$issection,$courseopt);
1.469 raeburn 7610: my $showvalue = $value;
7611: if ($istype{$parmname} eq '') {
7612: my $type = &standard_parameter_types($parmname);
7613: if ($type ne '') {
7614: if (&isdateparm($type)) {
7615: $showvalue =
7616: &Apache::lonlocal::locallocaltime($value);
7617: }
7618: }
7619: } else {
1.560 damieng 7620: if (&isdateparm($istype{$parmname})) {
7621: $showvalue = &Apache::lonlocal::locallocaltime($value);
7622: }
1.469 raeburn 7623: }
7624: $output .= $showvalue;
1.560 damieng 7625: if ($value ne $all[$level]) {
7626: $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
7627: } else {
7628: $stillactive=1;
7629: }
7630: }
1.473 amueller 7631: }
1.568 raeburn 7632: $output .= '</td>';
7633:
7634: unless ($readonly) {
7635: $output .= '<td>';
7636: if ($stillactive) {
7637: my $parmitem = &standard_parameter_names($parmname);
7638: $parmitem = &mt($parmitem);
7639: my $title=&mt('Changed [_1]',$parmitem);
7640: my $description=&mt('Changed [_1] for [_2] to [_3]',
7641: $parmitem,$realmdescription,
7642: (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
7643: if (($uname) && ($udom)) {
7644: $output .=
7645: &Apache::loncommon::messagewrapper('Notify User',
7646: $uname,$udom,$title,
7647: $description);
7648: } else {
7649: $output .=
7650: &Apache::lonrss::course_blog_link($id,$title,
7651: $description);
7652: }
1.560 damieng 7653: }
1.568 raeburn 7654: $output .= '</td>';
1.560 damieng 7655: }
1.568 raeburn 7656: $output .= &Apache::loncommon::end_data_table_row();
1.473 amueller 7657: }
1.560 damieng 7658: if ($env{'form.displayfilter'} eq 'containing') {
7659: my $wholeentry=$about_me_link.':'.
7660: $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
7661: $output;
7662: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473 amueller 7663: }
1.349 www 7664: if ($count) {
1.560 damieng 7665: $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
7666: <td rowspan="'.$count.'">'.$about_me_link.
7667: '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
7668: ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
7669: $send_msg_link.'</td>'.$output);
7670: $shown++;
7671: }
7672: if (!($env{'form.show'} eq &mt('all')
7673: || $shown<=$env{'form.show'})) { last; }
1.286 www 7674: }
1.301 www 7675: $r->print(&Apache::loncommon::end_data_table());
1.507 www 7676: &endSettingsScreen($r);
1.284 www 7677: $r->print(&Apache::loncommon::end_page());
7678: }
7679:
1.560 damieng 7680: ##################################################
7681: # MISC !
7682: ##################################################
7683:
1.563 damieng 7684: # Stores slot information.
1.560 damieng 7685: # Used by table UI
1.563 damieng 7686: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7687: #
7688: # @param {string} $slot_name - slot name
7689: # @param {string} $cdom - course domain
7690: # @param {string} $cnum - course number
7691: # @param {string} $symb - resource symb
7692: # @param {string} $uname - user name
7693: # @param {string} $udom - user domain
7694: # @returns {string} - 'ok' or error name
1.437 raeburn 7695: sub update_slots {
7696: my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
7697: my %slot=&Apache::lonnet::get_slot($slot_name);
7698: if (!keys(%slot)) {
7699: return 'error: slot does not exist';
7700: }
7701: my $max=$slot{'maxspace'};
7702: if (!defined($max)) { $max=99999; }
7703:
7704: my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
7705: "^$slot_name\0");
7706: my ($tmp)=%consumed;
7707: if ($tmp=~/^error: 2 / ) {
7708: return 'error: unable to determine current slot status';
7709: }
7710: my $last=0;
7711: foreach my $key (keys(%consumed)) {
7712: my $num=(split('\0',$key))[1];
7713: if ($num > $last) { $last=$num; }
7714: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7715: return 'ok';
7716: }
7717: }
7718:
7719: if (scalar(keys(%consumed)) >= $max) {
7720: return 'error: no space left in slot';
7721: }
7722: my $wanted=$last+1;
7723:
7724: my %reservation=('name' => $uname.':'.$udom,
7725: 'timestamp' => time,
7726: 'symb' => $symb);
7727:
7728: my $success=&Apache::lonnet::newput('slot_reservations',
7729: {"$slot_name\0$wanted" =>
7730: \%reservation},
7731: $cdom, $cnum);
1.438 raeburn 7732: if ($success eq 'ok') {
7733: my %storehash = (
7734: symb => $symb,
7735: slot => $slot_name,
7736: action => 'reserve',
7737: context => 'parameter',
7738: );
1.526 raeburn 7739: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7740: '',$uname,$udom,$cnum,$cdom);
1.438 raeburn 7741:
1.526 raeburn 7742: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7743: '',$uname,$udom,$uname,$udom);
1.438 raeburn 7744: }
1.437 raeburn 7745: return $success;
7746: }
7747:
1.563 damieng 7748: # Deletes a slot reservation.
1.560 damieng 7749: # Used by table UI
1.563 damieng 7750: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
7751: #
7752: # @param {string} $slot_name - slot name
7753: # @param {string} $cdom - course domain
7754: # @param {string} $cnum - course number
7755: # @param {string} $uname - user name
7756: # @param {string} $udom - user domain
7757: # @param {string} $symb - resource symb
7758: # @returns {string} - 'ok' or error name
1.437 raeburn 7759: sub delete_slots {
7760: my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
7761: my $delresult;
7762: my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
7763: $cnum, "^$slot_name\0");
7764: if (&Apache::lonnet::error(%consumed)) {
7765: return 'error: unable to determine current slot status';
7766: }
7767: my ($tmp)=%consumed;
7768: if ($tmp=~/^error: 2 /) {
7769: return 'error: unable to determine current slot status';
7770: }
7771: foreach my $key (keys(%consumed)) {
7772: if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
7773: my $num=(split('\0',$key))[1];
7774: my $entry = $slot_name.'\0'.$num;
7775: $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
7776: $cdom,$cnum);
7777: if ($delresult eq 'ok') {
7778: my %storehash = (
7779: symb => $symb,
7780: slot => $slot_name,
7781: action => 'release',
7782: context => 'parameter',
7783: );
1.526 raeburn 7784: &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524 raeburn 7785: 1,$uname,$udom,$cnum,$cdom);
1.526 raeburn 7786: &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524 raeburn 7787: 1,$uname,$udom,$uname,$udom);
1.437 raeburn 7788: }
7789: }
7790: }
7791: return $delresult;
7792: }
7793:
1.563 damieng 7794: # Returns true if there is a current course.
1.560 damieng 7795: # Used by handler
1.563 damieng 7796: #
7797: # @returns {boolean}
1.355 albertel 7798: sub check_for_course_info {
7799: my $navmap = Apache::lonnavmaps::navmap->new();
7800: return 1 if ($navmap);
7801: return 0;
7802: }
7803:
1.563 damieng 7804: # Returns the current course host and host LON-CAPA version.
7805: #
7806: # @returns {Array} - (course hostname, major version number, minor version number)
1.514 raeburn 7807: sub parameter_release_vars {
1.504 raeburn 7808: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
7809: my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
7810: my $chostname = &Apache::lonnet::hostname($chome);
7811: my ($cmajor,$cminor) =
7812: split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
7813: return ($chostname,$cmajor,$cminor);
7814: }
7815:
1.563 damieng 7816: # Checks if the course host version can handle a parameter required version,
7817: # and if it does, stores the release needed for the course.
7818: #
7819: # @param {string} $name - parameter name
7820: # @param {string} $value - parameter value
7821: # @param {string} $valmatch - name of the test used for checking the value
7822: # @param {string} $namematch - name of the test used for checking the name
7823: # @param {string} $needsrelease - version needed by the parameter, major.minor
7824: # @param {integer} $cmajor - course major version number
7825: # @param {integer} $cminor - course minor version number
7826: # @returns {boolean} - true if a newer version is needed
1.514 raeburn 7827: sub parameter_releasecheck {
1.557 raeburn 7828: my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504 raeburn 7829: my $needsnewer;
7830: my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
7831: if (($cmajor < $needsmajor) ||
7832: ($cmajor == $needsmajor && $cminor < $needsminor)) {
7833: $needsnewer = 1;
1.557 raeburn 7834: } elsif ($name) {
7835: if ($valmatch) {
7836: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
7837: } elsif ($value) {
7838: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
7839: }
7840: } elsif ($namematch) {
7841: &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504 raeburn 7842: }
7843: return $needsnewer;
7844: }
7845:
1.568 raeburn 7846: sub get_permission {
7847: my %permission;
7848: my $allowed = 0;
7849: return (\%permission,$allowed) unless ($env{'request.course.id'});
7850: if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
7851: (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
7852: $env{'request.course.sec'}))) {
7853: %permission= (
7854: 'edit' => 1,
7855: 'set' => 1,
7856: 'setoverview' => 1,
7857: 'addmetadata' => 1,
7858: 'ordermetadata' => 1,
7859: 'setrestrictmeta' => 1,
7860: 'newoverview' => 1,
7861: 'setdefaults' => 1,
7862: 'settable' => 1,
7863: 'parameterchangelog' => 1,
7864: 'cleanparameters' => 1,
7865: 'dateshift1' => 1,
7866: 'dateshift2' => 1,
7867: 'helper' => 1,
7868: );
7869: } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
7870: (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
7871: $env{'request.course.sec'}))) {
7872: %permission = (
7873: 'set' => 1,
7874: 'settable' => 1,
7875: 'newoverview' => 1,
7876: 'setoverview' => 1,
7877: 'parameterchangelog' => 1,
7878: );
7879: }
7880: foreach my $perm (values(%permission)) {
7881: if ($perm) { $allowed=1; last; }
7882: }
7883: return (\%permission,$allowed);
7884: }
7885:
1.560 damieng 7886: ##################################################
7887: # HANDLER
7888: ##################################################
7889:
7890: # Main handler for lonparmset.
7891: # Sub called based on request parameters action and command:
7892: # no command or action: print_main_menu
7893: # command 'set': assessparms (direct access to table mode for a resource)
7894: # (this can also be accessed simply with the symb parameter)
7895: # action 'setoverview': overview (display all existing parameter settings)
7896: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
7897: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
7898: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
7899: # action 'newoverview': newoverview (overview mode)
7900: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
7901: # action 'settable': assessparms (table mode)
7902: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
7903: # blog postings, user notification changes)
7904: # action 'cleanparameters': clean_parameters (unused)
7905: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
7906: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30 www 7907: sub handler {
1.43 albertel 7908: my $r=shift;
1.30 www 7909:
1.376 albertel 7910: &reset_caches();
7911:
1.414 droeschl 7912: &Apache::loncommon::content_type($r,'text/html');
7913: $r->send_http_header;
7914: return OK if $r->header_only;
7915:
1.193 albertel 7916: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473 amueller 7917: ['action','state',
1.205 www 7918: 'pres_marker',
7919: 'pres_value',
1.206 www 7920: 'pres_type',
1.506 www 7921: 'filter','part',
1.390 www 7922: 'udom','uname','symb','serial','timebase']);
1.131 www 7923:
1.83 bowersj2 7924:
1.193 albertel 7925: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194 albertel 7926: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507 www 7927: text=>"Content and Problem Settings",
1.473 amueller 7928: faq=>10,
7929: bug=>'Instructor Interface',
1.442 droeschl 7930: help =>
7931: 'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203 www 7932:
1.30 www 7933: # ----------------------------------------------------- Needs to be in a course
1.568 raeburn 7934: my ($parm_permission,$allowed) = &get_permission();
1.355 albertel 7935: my $exists = &check_for_course_info();
7936:
1.568 raeburn 7937: if ($env{'request.course.id'} && $allowed && $exists) {
1.193 albertel 7938: #
7939: # Main switch on form.action and form.state, as appropriate
7940: #
7941: # Check first if coming from someone else headed directly for
7942: # the table mode
1.568 raeburn 7943: if (($parm_permission->{'set'}) &&
7944: ((($env{'form.command'} eq 'set') && ($env{'form.url'})
7945: && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
7946: &assessparms($r,$parm_permission);
1.193 albertel 7947: } elsif (! exists($env{'form.action'})) {
7948: &print_main_menu($r,$parm_permission);
1.568 raeburn 7949: } elsif (!$parm_permission->{$env{'form.action'}}) {
7950: &print_main_menu($r,$parm_permission);
1.414 droeschl 7951: } elsif ($env{'form.action'} eq 'setoverview') {
1.568 raeburn 7952: &overview($r,$parm_permission);
1.560 damieng 7953: } elsif ($env{'form.action'} eq 'addmetadata') {
7954: &addmetafield($r);
7955: } elsif ($env{'form.action'} eq 'ordermetadata') {
7956: &order_meta_fields($r);
1.414 droeschl 7957: } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560 damieng 7958: &setrestrictmeta($r);
1.414 droeschl 7959: } elsif ($env{'form.action'} eq 'newoverview') {
1.568 raeburn 7960: &newoverview($r,$parm_permission);
1.414 droeschl 7961: } elsif ($env{'form.action'} eq 'setdefaults') {
1.560 damieng 7962: &defaultsetter($r);
7963: } elsif ($env{'form.action'} eq 'settable') {
1.568 raeburn 7964: &assessparms($r,$parm_permission);
1.414 droeschl 7965: } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568 raeburn 7966: &parm_change_log($r,$parm_permission);
1.414 droeschl 7967: } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560 damieng 7968: &clean_parameters($r);
1.414 droeschl 7969: } elsif ($env{'form.action'} eq 'dateshift1') {
1.390 www 7970: &date_shift_one($r);
1.414 droeschl 7971: } elsif ($env{'form.action'} eq 'dateshift2') {
1.390 www 7972: &date_shift_two($r);
1.446 bisitz 7973: }
1.43 albertel 7974: } else {
1.1 www 7975: # ----------------------------- Not in a course, or not allowed to modify parms
1.560 damieng 7976: if ($exists) {
7977: $env{'user.error.msg'}=
7978: "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
7979: } else {
7980: $env{'user.error.msg'}=
7981: "/adm/parmset::0:1:Course environment gone, reinitialize the course";
7982: }
7983: return HTTP_NOT_ACCEPTABLE;
1.43 albertel 7984: }
1.376 albertel 7985: &reset_caches();
7986:
1.43 albertel 7987: return OK;
1.1 www 7988: }
7989:
7990: 1;
7991: __END__
7992:
7993:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>