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