Annotation of loncom/interface/courseprefs.pm, revision 1.28.2.4
1.1 raeburn 1: # The LearningOnline Network with CAPA
1.2 raeburn 2: # Handler to set configuration settings for a course
1.1 raeburn 3: #
1.28.2.4! raeburn 4: # $Id: courseprefs.pm,v 1.28.2.3 2010/09/17 23:59:27 raeburn Exp $
1.1 raeburn 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: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: #
28: ###############################################################
29: ##############################################################
30:
1.23 raeburn 31: =pod
32:
33: =head1 NAME
34:
35: courseprefs- Handler to set/modify course configuration
36:
37: =head1 SYNOPSIS
38:
39: courseprefs provides an interface for setting general course configuration
40:
41: =head1 DESCRIPTION
42:
43: This module is used for configuration of a course
44:
45: =head1 INTERNAL SUBROUTINES
46:
47: =over
48:
49: =item get_allitems()
50:
51: =item print_config_box()
52:
53: =item process_changes()
54:
55: =item get_sec_str()
56:
57: =item check_clone()
58:
59: =item store_changes()
60:
61: =item update_env()
62:
63: =item display_disallowed()
64:
65: =item get_course()
66:
67: =item get_jscript()
68:
69: =item cloners_javascript()
70:
71: =item print_courseinfo()
72:
73: =item new_cloners_dom_row()
74:
75: =item can_modify_catsettings()
76:
77: =item assign_course_categories()
78:
79: =item print_localization()
80:
81: =item get_lang_choices()
82:
83: =item print_feedback()
84:
85: =item user_table()
86:
87: =item select_recipient()
88:
89: =item select_sections()
90:
91: =item print_discussion()
92:
93: =item role_checkboxes()
94:
95: =item print_classlists()
96:
97: =item print_appearance()
98:
99: =item print_grading()
100:
101: =item print_printouts()
102:
103: =item print_spreadsheet()
104:
105: =item print_bridgetasks()
106:
107: =item print_other()
108:
109: =item get_other_items()
110:
111: =item item_table_row_start()
112:
113: =item item_table_row_end()
114:
115: =item yes_no_radio()
116:
117: =item select_from_options()
118:
119: =item make_item_rows()
120:
121: Creates table used to display and set course configuration items.
122:
123: Inputs: $cdom,$items,$ordered,$settings,$rowtotal,$crstype
124: where $cdom is course's domain, $items is HASH ref for current config
125: item, $ordered is ARRAY ref of items to include in row in
126: display order, $settings is HASH ref of current values forrow,
127: $rowtotal is SCALAR ref used to accumulate row count, $crstype is
128: course type.
129:
130: Returns: $datatable
131: HTML mark-up of data table which accumulates individual rows.
132:
133: =item nothidepriv_row()
134:
135: Creates row containing form elements used to display and set
136: whether Domain coordinators who are currently included in
137: advanced course user .db file for a course are to be hidden (e.g.,
138: in syllabus, or from course user lists).
139:
140: Inputs: $cdom,$item,$settings,$crstype
141: where $cdom is course domain, item is nothideprivileged, $settings is
142: HASH ref of the current values for nothideprivileged, $crstype is
143: course type (Course or Community).
144:
145: Return: $datatable
146: HTML mark-up for Privileged users (Domain Coordinators) in staff listing.
147:
148: =item print_hdrfmt_row()
149:
150: Creates row containing form elements used to display and set
151: substitution items and text to be used in the header included
152: on printouts.
153:
154: Inputs: $item,$settings
155: where $item is print_header_format, and $settings is a HASH ref
156: of the current values stored for print_header_format.
157:
158: Returns: $output
159: HTML mark-up containing Javascript functions: reOrder() and getIndexByName()
160: used to dynamically update position selectboxes, and HTML table elements
161: for the "Print header format" row.
162:
163: =item position_selector()
164:
165: Creates a select box which can be used to reorder substitutions
166: and text included in a printout header.
167:
168: Inputs: $pos,$num,$maxnum
169: where $pos is current position, $num is the unique identifier,
170: and $maxnum is the total number of items (both substitutions
171: and text in the printout header.
172:
173: Returns: $output
174: HTML mark-up for the selectbox and a hidden form element containing
175: the current position.
176:
177: =item substitution_selector()
178:
179: Creates a combination of select box for choosing an item
180: (student name, course ID or assignment note) to substitute,
181: and a corresponding size limit in the header used for printouts.
182:
183: Inputs: $num,$subst,$limit,$crstype
184: where $num is the unique identifier, $subst is the current
185: substitution (n,c or a, for name, course or note respectively,
186: $limit is the current size limit (integer), and $crstype is
187: course type - course or community.
188:
189: Returns: $output
190: HTML mark-up for selectbox and textbox (separate table cells).
191:
192: =item change_clone()
193:
194: Modifies the list of courses a user can clone (stored
195: in the user's environment.db file), called when a
196: change is made to the list of users allowed to clone
197: a course.
198:
199: Inputs: $action,$cloner
200: where $action is add or drop, and $cloner is identity of
201: user for whom cloning ability is to be changed in course.
202:
203: Returns: nothing
204:
205: =back
206:
207: =cut
208:
209:
1.1 raeburn 210: package Apache::courseprefs;
211:
212: use strict;
213: use Apache::Constants qw(:common :http);
214: use Apache::lonnet;
215: use Apache::loncommon();
216: use Apache::lonhtmlcommon();
217: use Apache::lonconfigsettings;
218: use Apache::lonlocal;
219: use LONCAPA qw(:DEFAULT :match);
220:
221: sub handler {
222: my $r=shift;
223: if ($r->header_only) {
224: &Apache::loncommon::content_type($r,'text/html');
225: $r->send_http_header;
226: return OK;
227: }
228: my $context = 'course';
229: my $cid = $env{'request.course.id'};
230: my ($cnum,$cdom) = &get_course($cid);
231: my $crstype = &Apache::loncommon::course_type();
232: my $parm_permission = &Apache::lonnet::allowed('opa',$cid);
233: my $navmap = Apache::lonnavmaps::navmap->new();
234: if ($parm_permission && $navmap) {
235: &Apache::loncommon::content_type($r,'text/html');
236: $r->send_http_header;
237: } else {
238: if ($navmap) {
1.9 raeburn 239: if ($crstype eq 'Community') {
240: $env{'user.error.msg'}=
241: "/adm/courseprefs:opa:0:0:Cannot modify community settings";
242: } else {
243: $env{'user.error.msg'}=
244: "/adm/courseprefs:opa:0:0:Cannot modify course settings";
245: }
1.1 raeburn 246: } else {
1.9 raeburn 247: if ($crstype eq 'Community') {
248: $env{'user.error.msg'}=
249: "/adm/courseprefs::0:1:Course environment gone, reinitialize the community";
250: } else {
251: $env{'user.error.msg'}=
252: "/adm/courseprefs::0:1:Course environment gone, reinitialize the course";
253:
254: }
1.1 raeburn 255: }
256: return HTTP_NOT_ACCEPTABLE;
257: }
258:
1.4 raeburn 259: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
260: ['phase','actions','origin']);
1.1 raeburn 261: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.4 raeburn 262: if ($env{'form.origin'} eq 'params') {
263: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
264: text=>"Parameter Manager"});
265: }
1.9 raeburn 266: my ($brtext,$brtitle,$crsinfotext,$crsinfodesc,$crscateg,$crshide);
267: my %lt;
268: if ($crstype eq 'Community') {
269: %lt = (
270: conf => 'Community Configuration',
271: edit => 'Edit Community Configuration',
272: gens => 'General community settings',
273: idnu => 'Community ID or number',
274: desc => 'Community Description',
1.24 raeburn 275: ownr => 'Community Owner',
1.25 raeburn 276: cown => 'Community Co-owners',
1.9 raeburn 277: catg => 'Categorize community',
278: excc => 'Exclude from community catalog',
279: clon => 'Users allowed to clone community',
280: rept => 'Replacement titles for standard community roles',
281: time => 'Timezone where the community is located',
282: date => 'Locale used for community calendar',
283: coco => 'Community Content',
284: copo => 'Community Policy',
1.13 bisitz 285: priv => 'Domain Coordinators in community',
1.9 raeburn 286: defd => 'Default dates for member access',
287: stuv => 'Member-viewable membership list options',
288: stul => 'Member agreement needed to be listed',
289: clas => 'Membership and Facilitator Listing',
290: priv => 'Privileged users (Domain Coordinators) in facilitator listing',
291: defc => 'Default Community Spreadsheet',
292: defs => 'Default User Spreadsheet',
293: seme => 'Send message to member when clicking Done on Tasks'
294: );
295: } else {
296: %lt = (
297: conf => 'Course Configuration',
298: edit => 'Edit Course Configuration',
1.20 faziophi 299: gens => 'General course settings',
300: idnu => 'Course ID or number',
301: desc => 'Course Description',
1.24 raeburn 302: ownr => 'Course Owner',
1.25 raeburn 303: cown => 'Course Co-owners',
1.9 raeburn 304: catg => 'Categorize course',
305: excc => 'Exclude from course catalog',
306: clon => 'Users allowed to clone course',
307: rept => 'Replacement titles for standard course roles',
1.20 faziophi 308: time => 'Timezone in which the course takes place',
309: date => 'Locale used for course calendar',
1.9 raeburn 310: coco => 'Course Content',
311: copo => 'Course Policy',
1.13 bisitz 312: priv => 'Domain Coordinators in course',
1.9 raeburn 313: defd => 'Default dates for student access',
314: stuv => 'Student-viewable classlist options',
315: stul => 'Student agreement needed to be listed',
316: clas => 'Classlists and Staff Listing',
317: priv => 'Privileged users (Domain Coordinators) in staff listing',
318: defc => 'Default Course Spreadsheet',
319: defs => 'Default Student Spreadsheet',
320: seme => 'Send message to student when clicking Done on Tasks',
321: );
322: }
1.1 raeburn 323: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs',
1.9 raeburn 324: text=>$lt{'conf'}});
1.1 raeburn 325: my $breadcrumbs =
1.9 raeburn 326: &Apache::lonhtmlcommon::breadcrumbs($lt{'edit'});
1.1 raeburn 327:
328: my $phase = 'pickactions';
329: if ( exists($env{'form.phase'}) ) {
330: $phase = $env{'form.phase'};
331: }
332:
333: if ($phase eq 'categorizecourse') {
1.9 raeburn 334: &assign_course_categories($r,$crstype);
1.1 raeburn 335: return OK;
336: }
337:
338: my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
339: my @prefs_order = ('courseinfo','localization','feedback','discussion',
340: 'classlists','appearance','grading','printouts',
341: 'spreadsheet','bridgetasks','other');
342:
343: my %prefs = (
344: 'courseinfo' =>
1.9 raeburn 345: { text => $lt{'gens'},
1.1 raeburn 346: help => 'Course_Environment',
1.28.2.1 raeburn 347: header => [{col1 => 'Setting',
348: col2 => 'Value'}],
1.25 raeburn 349: ordered => ['owner','co-owners','description','courseid',
350: 'categories','hidefromcat','externalsyllabus',
1.28.2.1 raeburn 351: 'url','rolenames','cloners'],
1.3 raeburn 352: itemtext => {
1.25 raeburn 353: 'owner' => $lt{'ownr'},
354: 'co-owners' => $lt{'cown'},
355: 'description' => $lt{'desc'},
356: 'courseid' => $lt{'idnu'},
357: 'categories' => $lt{'catg'},
358: 'hidefromcat' => $lt{'excc'},
359: 'cloners' => $lt{'clon'},
360: 'externalsyllabus' => 'URL of Syllabus',
361: 'url' => 'Top Level Map',
362: 'rolenames' => $lt{'rept'},
1.3 raeburn 363: },
1.1 raeburn 364: },
365: 'localization' =>
1.27 raeburn 366: { text => 'Language and Time Localization',
1.1 raeburn 367: help => 'Course_Environment',
1.28.2.1 raeburn 368: header => [{col1 => 'Setting',
369: col2 => 'Value',}],
1.1 raeburn 370: ordered => ['languages','timezone','datelocale'],
1.3 raeburn 371: itemtext => {
1.20 faziophi 372: languages => 'Languages used',
1.9 raeburn 373: timezone => $lt{'time'},
374: datelocale => $lt{'date'},
1.3 raeburn 375: },
1.1 raeburn 376: },
377: 'feedback' =>
1.20 faziophi 378: { text => 'Feedback messages',
1.1 raeburn 379: help => 'Course_Environment',
380: header => [{col1 => 'Questions about:',
1.28.2.1 raeburn 381: col2 => 'Recipients'},
382: {col1 => 'Questions about:',
383: col2 => 'Custom Text'}],
1.3 raeburn 384: ordered => ['question.email','comment.email','policy.email'],
385: itemtext => {
386: 'question.email' => 'Resource Content',
1.9 raeburn 387: 'comment.email' => $lt{'coco'},
388: 'policy.email' => $lt{'copo'},
1.3 raeburn 389: },
1.1 raeburn 390: },
391: 'discussion' =>
392: { text => 'Discussion and Chat',
393: help => 'Course_Environment',
1.28.2.3 raeburn 394: ordered => ['pch.roles.denied','pch.users.denied',
395: 'plc.roles.denied','plc.users.denied',
1.1 raeburn 396: 'allow_limited_html_in_feedback',
397: 'allow_discussion_post_editing'],
1.3 raeburn 398: itemtext => {
1.28.2.3 raeburn 399: 'pch.roles.denied' => 'No Resource Discussion',
400: 'pch.users.denied' => 'No Resource Discussion',
401: 'plc.roles.denied' => 'No Chat room use',
402: 'plc.users.denied' => 'No Chat room use',
1.20 faziophi 403: allow_limited_html_in_feedback => 'Allow limited HTML in discussion',
404: allow_discussion_post_editing => 'Users can edit/delete own discussion posts',
1.3 raeburn 405: },
1.1 raeburn 406: },
407: 'classlists' =>
1.9 raeburn 408: { text => $lt{'clas'},
1.1 raeburn 409: help => 'Course_Environment',
410: header => [{col1 => 'Type',
1.9 raeburn 411: col2 => $lt{'defd'}},
1.1 raeburn 412: {col1 => 'Setting',
1.9 raeburn 413: col2 => $lt{'priv'}},
1.1 raeburn 414: {col1 => 'Setting',
1.9 raeburn 415: col2 => $lt{'stuv'}}],
1.1 raeburn 416: ordered => ['default_enrollment_start_date',
417: 'default_enrollment_end_date',
418: 'nothideprivileged','student_classlist_view',
1.26 raeburn 419: 'student_classlist_opt_in','student_classlist_portfiles'],
1.3 raeburn 420: itemtext => {
421: default_enrollment_start_date => 'Start date',
422: default_enrollment_end_date => 'End date',
1.9 raeburn 423: nothideprivileged => $lt{'priv'},
424: student_classlist_view => $lt{'stuv'},
1.26 raeburn 425: student_classlist_opt_in => $lt{'stul'},
1.3 raeburn 426: student_classlist_portfiles => 'Include link to accessible portfolio files',
427: },
1.1 raeburn 428: },
429: 'appearance' =>
1.20 faziophi 430: { text => 'Display of resources ',
1.1 raeburn 431: help => 'Course_Environment',
1.28.2.1 raeburn 432: header => [{col1 => 'Setting',
433: col2 => 'Value',}],
1.1 raeburn 434: ordered => ['default_xml_style','pageseparators',
435: 'disable_receipt_display','texengine',
436: 'tthoptions'],
1.3 raeburn 437: itemtext => {
1.17 faziophi 438: default_xml_style => 'Default XML style file',
1.20 faziophi 439: pageseparators => 'Visibly Separate Items on Pages',
440: disable_receipt_display => 'Disable display of problem receipts',
441: texengine => 'Force use of a specific math rendering engine',
1.3 raeburn 442: tthoptions => 'Default set of options to pass to tth/m when converting TeX',
443: },
1.1 raeburn 444: },
445: 'grading' =>
446: { text => 'Grading',
447: help => 'Course_Environment',
1.28.2.1 raeburn 448: header => [{col1 => 'Setting',
449: col2 => 'Value',}],
1.1 raeburn 450: ordered => ['grading','rndseed',
451: 'receiptalg','disablesigfigs'],
1.3 raeburn 452: itemtext => {
1.20 faziophi 453: grading => 'Grading',
454: rndseed => 'Randomization algorithm used',
455: receiptalg => 'Receipt algorithm used',
456: disablesigfigs => 'Disable checking of Significant Figures',
1.3 raeburn 457: },
458:
1.1 raeburn 459: },
460: 'printouts' =>
1.20 faziophi 461: { text => 'Printout generation',
1.1 raeburn 462: help => 'Course_Environment',
1.28.2.1 raeburn 463: header => [{col1 => 'Setting',
464: col2 => 'Value',}],
1.1 raeburn 465: ordered => ['problem_stream_switch','suppress_tries',
466: 'default_paper_size','print_header_format',
1.14 raeburn 467: 'disableexampointprint','canuse_pdfforms'],
1.3 raeburn 468: itemtext => {
469: problem_stream_switch => 'Allow problems to be split over pages',
470: suppress_tries => 'Suppress number of tries in printing',
471: default_paper_size => 'Default paper type',
472: print_header_format => 'Print header format',
473: disableexampointprint => 'Disable automatically printing point values on exams',
1.14 raeburn 474: canuse_pdfforms => 'Users can print problems as PDF forms and upload later for grading',
1.3 raeburn 475: },
1.1 raeburn 476: },
477: 'spreadsheet' =>
478: { text => 'Spreadsheets',
479: help => 'Course_Environment',
1.28.2.1 raeburn 480: header => [{col1 => 'Setting',
481: col2 => 'Value'}],
1.1 raeburn 482: ordered => ['spreadsheet_default_classcalc',
483: 'spreadsheet_default_studentcalc',
484: 'spreadsheet_default_assesscalc','hideemptyrows'],
1.3 raeburn 485: itemtext => {
1.9 raeburn 486: spreadsheet_default_classcalc => $lt{'defc'},
487: spreadsheet_default_studentcalc => $lt{'defs'},
1.3 raeburn 488: spreadsheet_default_assesscalc => 'Default Assessment Spreadsheet',
489: hideemptyrows => 'Hide Empty Rows in Spreadsheets',
490: },
1.1 raeburn 491: },
492: 'bridgetasks' =>
493: { text => 'Bridge tasks',
494: help => 'Course_Environment',
1.28.2.1 raeburn 495: header => [{col1 => 'Setting',
496: col2 => 'Value'}],
1.1 raeburn 497: ordered => ['task_messages','task_grading',
498: 'suppress_embed_prompt'],
1.3 raeburn 499: itemtext => {
1.9 raeburn 500: task_messages => $lt{'seme'},
1.3 raeburn 501: task_grading => 'Bridge Task grading by instructors and TAs in sections' ,
1.5 raeburn 502: suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio',
1.3 raeburn 503: },
1.1 raeburn 504: },
505: 'other' =>
506: { text => 'Other settings',
507: help => 'Course_Environment',
508: header => [ {col1 => 'Item',
509: col2 => 'Value',
510: }],
511: },
512: );
513: if ($phase eq 'process') {
1.3 raeburn 514: my @allitems = &get_allitems(%prefs);
1.1 raeburn 515: &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context,
1.3 raeburn 516: \@prefs_order,\%prefs,\%values,
517: $cnum,undef,\@allitems);
1.1 raeburn 518: } elsif ($phase eq 'display') {
1.12 raeburn 519: my $jscript = &get_jscript($cdom,$phase,$crstype);
1.3 raeburn 520: my @allitems = &get_allitems(%prefs);
1.1 raeburn 521: &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,
1.9 raeburn 522: \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype);
1.1 raeburn 523: } else {
524: &Apache::lonconfigsettings::display_choices($r,$phase,$context,
525: \@prefs_order,\%prefs);
526: }
527: return OK;
528: }
529:
1.3 raeburn 530: sub get_allitems {
531: my (%prefs) = @_;
532: my @allitems;
533: foreach my $item (keys(%prefs)) {
534: if (ref($prefs{$item}) eq 'HASH') {
535: if (ref($prefs{$item}{'ordered'}) eq 'ARRAY') {
536: push(@allitems,@{$prefs{$item}{'ordered'}});
537: if ($item eq 'feedback') {
538: push(@allitems,(map { $_.'.text'; } @{$prefs{$item}{'ordered'}}));
539: }
540: }
541: }
542: }
543: return @allitems;
544: }
545:
1.1 raeburn 546: sub print_config_box {
1.9 raeburn 547: my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype) = @_;
1.1 raeburn 548: my $ordered = $item->{'ordered'};
1.3 raeburn 549: my $itemtext = $item->{'itemtext'};
1.1 raeburn 550: my $rowtotal = 0;
551: my $output =
1.28.2.1 raeburn 552: '<table class="LC_nested_outer">
553: <tr>
554: <th align="left" valign="middle"><span class="LC_nobreak" style="font-size: larger;" >'.
555: &mt($item->{text}).' '.
556: &Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".
557: '</tr>';
1.1 raeburn 558: if (($action eq 'feedback') || ($action eq 'classlists')) {
559: $output .= '
1.28.2.1 raeburn 560: <tr>
561: <td>
562: <table class="LC_nested">';
1.18 faziophi 563: if (exists $item->{'header'}->[0]->{'col1'} ||
564: exists $item->{'header'}->[0]->{'col2'}) {
565: $output .= '
566: <tr class="LC_info_row">
1.1 raeburn 567: <td class="LC_left_item">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
568: <td class="LC_right_item">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
1.18 faziophi 569: </tr>';
570: }
1.1 raeburn 571: $rowtotal ++;
572: if ($action eq 'feedback') {
1.3 raeburn 573: $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 574: } elsif ($action eq 'classlists') {
1.9 raeburn 575: $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 576: }
577: $output .= '
578: </table>
1.28.2.1 raeburn 579: </td>
580: </tr>
581: <tr>
582: <td>
1.1 raeburn 583: <table class="LC_nested">
584: <tr class="LC_info_row">
585: <td class="LC_left_item">'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';
586: $output .= '
587: <td class="LC_right_item">'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
588: </tr>';
589: if ($action eq 'classlists') {
1.9 raeburn 590: $output .= &print_classlists('middle',$cdom,$settings,$itemtext,\$rowtotal,$crstype).
1.1 raeburn 591: '
592: </table>
1.28.2.1 raeburn 593: </td>
594: </tr>
595: <tr>
596: <td>
1.18 faziophi 597: <table class="LC_nested">';
598: if (exists $item->{'header'}->[0]->{'col1'} ||
599: exists $item->{'header'}->[0]->{'col2'}) {
600: $output .= '
601: <tr class="LC_info_row">
602: <td class="LC_left_item">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
603: <td class="LC_right_item">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
604: </tr>';
1.28.2.1 raeburn 605: }
1.1 raeburn 606: }
607: } else {
608: $output .= '
1.28.2.1 raeburn 609: <tr>
610: <td>
1.18 faziophi 611: <table class="LC_nested">';
612: if (exists $item->{'header'}->[0]->{'col1'} ||
613: exists $item->{'header'}->[0]->{'col2'}) {
614: $output .= '
615: <tr class="LC_info_row">
1.1 raeburn 616: <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
617: <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
1.18 faziophi 618: </tr>';
619: }
1.1 raeburn 620: }
621: $rowtotal ++;
622: if ($action eq 'courseinfo') {
1.9 raeburn 623: $output .= &print_courseinfo($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 624: } elsif ($action eq 'localization') {
1.3 raeburn 625: $output .= &print_localization($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 626: } elsif ($action eq 'feedback') {
1.3 raeburn 627: $output .= &print_feedback('bottom',$cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 628: } elsif ($action eq 'discussion') {
1.3 raeburn 629: $output .= &print_discussion($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 630: } elsif ($action eq 'classlists') {
1.9 raeburn 631: $output .= &print_classlists('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 632: } elsif ($action eq 'appearance') {
1.9 raeburn 633: $output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 634: } elsif ($action eq 'grading') {
1.9 raeburn 635: $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 636: } elsif ($action eq 'printouts') {
1.9 raeburn 637: $output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 638: } elsif ($action eq 'spreadsheet') {
1.9 raeburn 639: $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 640: } elsif ($action eq 'bridgetasks') {
1.9 raeburn 641: $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype);
1.1 raeburn 642: } elsif ($action eq 'other') {
1.9 raeburn 643: $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype);
1.1 raeburn 644: }
645: $output .= '
646: </table>
1.28.2.1 raeburn 647: </td>
648: </tr>
649: </table><br />';
1.1 raeburn 650: return ($output,$rowtotal);
651: }
652:
653: sub process_changes {
1.9 raeburn 654: my ($cdom,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_;
1.3 raeburn 655: my %newvalues;
656: if (ref($item) eq 'HASH') {
657: if (ref($changes) eq 'HASH') {
658: my @ordered;
659: if ($action eq 'other') {
660: @ordered = &get_other_items($cdom,$values,$allitems);
661: if ($env{'form.newp_name'} ne '') {
662: my $newp = $env{'form.newp_name'};
663: if ($env{'form.newp_value'} ne '') {
664: if (ref($allitems) eq 'ARRAY') {
665: unless ((grep(/^\Q$newp\E$/,@ordered)) ||
666: (grep(/^\Q$newp\E$/,@{$allitems}))) {
667: $changes->{$newp} = $env{'form.newp_value'};
668: }
669: }
670: }
671: }
672: } elsif (ref($item->{'ordered'}) eq 'ARRAY') {
673: @ordered = @{$item->{'ordered'}};
674: }
675: if (@ordered > 0) {
676: if ($action eq 'feedback') {
677: foreach my $entry (@ordered) {
678: my $userstr = '';
679: my $total = $env{'form.'.$entry.'_total'};
680: if ($total) {
681: my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
682: for (my $i=0; $i<$total; $i++) {
683: unless (grep(/^$i$/,@deletes)) {
684: $userstr .= $env{'form.'.$entry.'_user_'.$i}.
685: &get_sec_str($entry,$i).',';
686: }
687: }
688: } else {
689: $total = 0;
690: }
691: if ($env{'form.'.$entry.'_uname_'.$total} ne '') {
692: my $uname = $env{'form.'.$entry.'_uname_'.$total};
693: my $udom = $env{'form.'.$entry.'_udom_'.$total};
694: if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') {
695: $userstr =~ s/,$//;
696: $disallowed->{'feedback'}{$entry} = $uname.':'.$udom;
697: } else {
698: $userstr .= $uname.':'.$udom.&get_sec_str($entry,$total);
699: }
700: } else {
701: $userstr =~ s/,$//;
702: }
703: $newvalues{$entry} = $userstr;
704: if ($newvalues{$entry} ne $values->{$entry}) {
705: $changes->{$entry} = $newvalues{$entry};
706: }
707: my $ext_entry = $entry.'.text';
708: $newvalues{$ext_entry} = $env{'form.'.$ext_entry};
709: if ($newvalues{$ext_entry} ne $values->{$ext_entry}) {
710: $changes->{$ext_entry} = $newvalues{$ext_entry};
711: }
712: }
713: } else {
714: foreach my $entry (@ordered) {
715: if ($entry eq 'cloners') {
716: if ($env{'form.cloners_all'}) {
717: $newvalues{$entry} = '*';
718: } else {
719: my @clonedoms;
720: if (exists($env{'form.cloners_activate'})) {
721: my $actnum = $env{'form.cloners_activate'};
722: if ($actnum ne '') {
1.28.2.4! raeburn 723: if ($env{'form.cloners_dom_'.$actnum} ne '') {
! 724: my $clonedom = $env{'form.cloners_dom_'.$actnum};
1.3 raeburn 725: if (&check_clone($clonedom,$disallowed) eq 'ok') {
726: $newvalues{$entry} = '*:'.$clonedom;
727: push(@clonedoms,$newvalues{$entry});
728: }
729: }
730: }
731: } else {
732: my $num = $env{'form.cloners_total'};
733: my @deletes =
734: &Apache::loncommon::get_env_multiple('form.cloners_delete');
735: for (my $i=0; $i<$num; $i++) {
736: if (!grep(/^$i$/,@deletes)) {
737: my $clonedom = $env{'form.cloners_dom_'.$i};
738: if (&check_clone($clonedom,$disallowed) eq 'ok') {
739: if (!grep(/^\*:\Q$clonedom\E$/,@clonedoms)) {
740: push (@clonedoms,'*:'.$clonedom);
741: }
742: }
743: }
744: }
745: if (@clonedoms) {
746: $newvalues{$entry}=join(',',@clonedoms);
747: }
748: }
749: if ($env{'form.cloners_newdom'} ne '') {
750: my $clonedom = $env{'form.cloners_newdom'};
751: if (&check_clone($clonedom,$disallowed) eq 'ok') {
752: my $newdom = '*:'.$env{'form.cloners_newdom'};
753: if (@clonedoms) {
754: if (!grep(/^\Q$newdom\E$/,@clonedoms)) {
755: $newvalues{$entry} .= ','.$newdom;
756: }
757: } else {
758: $newvalues{$entry} = $newdom;
759: }
760: }
761: }
762: if ($env{'form.'.$entry} ne '') {
763: my @cloners = split(',',$env{'form.'.$entry});
764: my @okcloners;
765: foreach my $cloner (@cloners) {
1.23 raeburn 766: $cloner =~ s/^\s+//;
767: $cloner =~ s/\s+$//;
768: unless ($cloner eq '') {
769: my ($uname,$udom) = split(':',$cloner);
770: if (&check_clone($udom,$disallowed,$uname) eq 'ok') {
771: if (!grep(/^\Q$cloner\E$/,@okcloners)) {
772: push(@okcloners,$cloner);
773: }
1.3 raeburn 774: }
775: }
776: }
777: if (@okcloners) {
778: my $okclonestr = join(',',@okcloners);
779: if ($newvalues{$entry} ne '') {
780: $newvalues{$entry} .= ','.$okclonestr;
781: } else {
782: $newvalues{$entry} = $okclonestr;
783: }
784: }
785: }
786: }
787: if (ref($disallowed) eq 'HASH') {
788: if (ref($disallowed->{'cloners'}) eq 'HASH') {
789: foreach my $key (keys(%{$disallowed->{'cloners'}})) {
790: $disallowed->{'cloners'}{$key} =~ s/,$//;
791: }
792: }
793: }
1.25 raeburn 794: } elsif ($entry eq 'co-owners') {
795: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
796: my $coowners = $values->{'internal.co-owners'};
797: my @currcoown;
798: if ($coowners) {
799: @currcoown = split(',',$coowners);
800: }
801: if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
802: my $autocoowner;
803: if (($crstype eq 'Course') &&
804: ($values->{'internal.coursecode'})) {
805: my %domconf =
806: &Apache::lonnet::get_dom('configuration',['autoenroll'],$cdom);
807: if (ref($domconf{'autoenroll'}) eq 'HASH') {
808: $autocoowner = $domconf{'autoenroll'}{'co-owners'};
809: }
810: }
811: unless ($autocoowner) {
812: my @keepcoowners = &Apache::loncommon::get_env_multiple('form.coowners');
813: my @pendingcoowners = &Apache::loncommon::get_env_multiple('form.pendingcoowners');
814: my @invitecoowners = &Apache::loncommon::get_env_multiple('form.invitecoowners');
815: if (@invitecoowners) {
816: push(@pendingcoowners,@invitecoowners);
817: }
818: $newvalues{'pendingco-owners'} = join(',',sort(@pendingcoowners));
819: $newvalues{'co-owners'} = join(',',sort(@keepcoowners));
820: if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) {
821: $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'};
822: push(@{$changes->{$entry}{'changed'}},'co-owners');
823: }
824: if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) {
825: $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'};
826: push(@{$changes->{$entry}{'changed'}},'pendingco-owners');
827: }
828: }
829: } else {
830: my (@newpending,@newcoown);
831: my $uname = $env{'user.name'};
832: my $udom = $env{'user.domain'};
833: my $pendingcoowners = $values->{'internal.pendingco-owners'};
834: my @pendingcoown = split(',',$pendingcoowners);
835: if ($env{'form.pending_coowoner'}) {
836: foreach my $item (@pendingcoown) {
837: unless ($item eq $uname.':'.$udom) {
838: push(@newpending,$item);
839: }
840: }
841: @newcoown = @currcoown;
842: if ($env{'form.pending_coowoner'} eq 'accept') {
843: unless (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {
844: push(@newcoown,$uname.':'.$udom);
845: }
846: }
847: } elsif ($env{'form.remove_coowoner'}) {
848: foreach my $item (@currcoown) {
849: unless ($item eq $uname.':'.$udom) {
850: push(@newcoown,$item);
851: }
852: }
853: if ($pendingcoowners ne '') {
854: @newpending = @pendingcoown;
855: }
856: }
857: $newvalues{'pendingco-owners'} = join(',',sort(@newpending));
858: $newvalues{'co-owners'} = join(',',sort(@newcoown));
859: if ($newvalues{'co-owners'} ne $values->{'internal.co-owners'}) {
860: $changes->{$entry}{'co-owners'} = $newvalues{'co-owners'};
861: push(@{$changes->{$entry}{'changed'}},'co-owners');
862: }
863: if ($newvalues{'pendingco-owners'} ne $values->{'internal.pendingco-owners'}) {
864: $changes->{$entry}{'pendingco-owners'} = $newvalues{'pendingco-owners'};
865: push(@{$changes->{$entry}{'changed'}},'pendingco-owners');
866: }
867: }
1.3 raeburn 868: } elsif ($entry =~ /^default_enrollment_(start|end)_date$/) {
869: $newvalues{$entry}=&Apache::lonhtmlcommon::get_date_from_form($entry);
870: } elsif ($entry eq 'rolenames') {
871: my %adv_roles =
872: &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
1.9 raeburn 873: my @stds;
874: if ($crstype eq 'Community') {
875: @stds = ('co');
876: } else {
877: @stds = ('cc');
878: }
879: push(@stds,('in','ta','ep','ad','st'));
1.3 raeburn 880: my (@replacements,@regulars);
881: foreach my $role (@stds) {
882: if ($values->{$role.'.plaintext'} ne '') {
1.9 raeburn 883: push(@replacements,$role);
1.3 raeburn 884: } else {
885: push(@regulars,$role);
886: }
1.9 raeburn 887: }
1.3 raeburn 888: foreach my $stdrole (@stds) {
889: my $ext_entry = $entry.'_'.$stdrole;
890: my $stdname = &Apache::lonnet::plaintext($stdrole,$crstype,
891: $env{'request.course.id'},1);
892: if ($env{'form.'.$ext_entry} eq $stdname) {
893: $newvalues{$ext_entry} = '';
894: } else {
895: $newvalues{$ext_entry} = $env{'form.'.$ext_entry};
896: }
897: if ($newvalues{$ext_entry} ne $values->{$stdrole.'.plaintext'}) {
898: my $dupname = 0;
899: if ($newvalues{$ext_entry} ne '') {
900: if (grep(/^\Q$newvalues{$ext_entry}\E$/,@replacements)) {
901: $dupname = 1;
902: push(@{$disallowed->{'rolenames'}{'replacements'}},$newvalues{$ext_entry});
903: }
904: if (!$dupname) {
905: if (grep(/^\Q$newvalues{$ext_entry}\E$/,@regulars)) {
906: $dupname = 1;
907: push(@{$disallowed->{rolenames}{'regulars'}},$newvalues{$ext_entry});
908: }
909: }
910: if (!$dupname) {
911: foreach my $role (keys(%adv_roles)) {
912: if ($role =~ m{^cr/$match_domain/$match_name/\Q$newvalues{$ext_entry}\E$}) {
913: $dupname = 1;
914: push(@{$disallowed->{rolenames}{'customrole'}},$newvalues{$ext_entry});
915: last;
916: }
917: }
918: }
919: }
920: if (!$dupname) {
921: $changes->{$ext_entry} = $newvalues{$ext_entry};
922: }
923: }
924: }
925: } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied')) {
926: my @denied = &Apache::loncommon::get_env_multiple('form.'.$entry);
927: @denied = sort(@denied);
928: my $deniedstr = '';
929: if (@denied > 0) {
930: $deniedstr = join(',',@denied);
931: }
932: $newvalues{$entry} = $deniedstr;
933: } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied')) {
934: my $total = $env{'form.'.$entry.'_total'};
935: my $userstr = '';
936: my @denied;
937: if ($total > 0) {
938: my @deletes =
939: &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
940: for (my $i=0; $i<$total; $i++) {
941: unless (grep(/^$i$/,@deletes)) {
942: $userstr .= $env{'form.'.$entry.'_user_'.$i}.',';
943: push(@denied,$env{'form.'.$entry.'_user_'.$i});
944: }
945: }
946: } else {
947: $total = 0;
948: }
949: if ($env{'form.'.$entry.'_uname_'.$total} ne '') {
950: my $uname = $env{'form.'.$entry.'_uname_'.$total};
951: my $udom = $env{'form.'.$entry.'_udom_'.$total};
952: if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') {
953: $userstr =~ s/,$//;
954: $disallowed->{'discussion'}{$entry} = $uname.':'.$udom;
955: } else {
956: my $newuser .= $uname.':'.$udom;
957: if (grep(/^\Q$newuser\E$/,@denied)) {
958: $userstr =~ s/,$//;
959: } else {
960: $userstr .= $newuser;
961: }
962: }
963: } else {
964: $userstr =~ s/,$//;
965: }
966: $newvalues{$entry} = $userstr;
967: } elsif ($entry eq 'allow_discussion_post_editing') {
968: my @canedit = &Apache::loncommon::get_env_multiple('form.'.$entry);
969: @canedit = sort(@canedit);
970: foreach my $role (@canedit) {
971: my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$role);
972: if ((grep(/^\s*$/,@secs)) || (@secs == 0)) {
973: $newvalues{$entry} .= $role.',';
974: } else {
975: foreach my $sec (@secs) {
976: $newvalues{$entry} .= $role.':'.$sec.',';
977: }
978: }
979: }
980: $newvalues{$entry} =~ s/,$//;
981: } elsif ($entry eq 'nothideprivileged') {
982: my @curr_nothide;
983: my @new_nothide;
984: if ($values->{$entry} ne '') {
985: foreach my $user (split(/\s*\,\s*/,$values->{$entry})) {
986: my $nothide;
987: if ($user !~ /:/) {
988: $nothide = join(':',split(/[\@]/,$user));
989: } else {
990: $nothide = $user;
991: }
992: if ((defined($nothide)) &&
993: (!grep(/^\Q$nothide\E$/,@curr_nothide))) {
994: push(@curr_nothide,$nothide);
995: }
996: }
997: }
998: foreach my $key (keys(%env)) {
999: if ($key =~ /^form\.\Q$entry\E_($match_username:$match_domain)$/) {
1.7 raeburn 1000: if ($env{$key}) {
1.3 raeburn 1001: my $nothide = $1;
1002: if (!grep(/^\Q$nothide\E$/,@new_nothide)) {
1003: push(@new_nothide,$nothide);
1004: }
1005: }
1006: }
1007: }
1008: @new_nothide = sort(@new_nothide);
1009: my @differences =
1010: &Apache::loncommon::compare_arrays(\@curr_nothide,
1011: \@new_nothide);
1012: if (@differences > 0) {
1013: if (@new_nothide > 0) {
1014: $newvalues{$entry} = join(',',@new_nothide);
1015: } else {
1016: $newvalues{$entry} = '';
1017: }
1018: } else {
1019: $newvalues{$entry} = $values->{$entry};
1020: }
1021: } elsif ($entry eq 'print_header_format') {
1022: my $maxnum = $env{'form.printfmthdr_maxnum'};
1023: my @newhdr;
1024: if ($maxnum > 2) {
1025: for (my $i=0; $i<$maxnum-2; $i++) {
1026: if ($env{'form.printfmthdr_del_'.$i}) {
1027: $newhdr[$env{'form.printfmthdr_pos_'.$i}] = '';
1028: } else {
1029: my $hdr;
1030: if ($env{'form.printfmthdr_sub_'.$i} =~ /^[nca]$/) {
1031: $hdr = '%';
1032: if ($env{'form.printfmthdr_limit_'.$i} =~ /^\d+$/) {
1033: $hdr .= $env{'form.printfmthdr_limit_'.$i};
1034: }
1035: $hdr .= $env{'form.printfmthdr_sub_'.$i};
1.28.2.2 raeburn 1036: } elsif ($env{'form.printfmthdr_text_'.$i} ne '') {
1037: $hdr = $env{'form.printfmthdr_text_'.$i};
1.3 raeburn 1038: }
1039: $newhdr[$env{'form.printfmthdr_pos_'.$i}] = $hdr;
1040: }
1041: }
1042: }
1043: my $newsub = $maxnum-2;
1044: if ($env{'form.printfmthdr_sub_'.$newsub} =~ /^[nca]$/) {
1045: my $hdr = '%';
1046: if ($env{'form.printfmthdr_limit_'.$newsub} =~ /^\d+$/) {
1047: $hdr .= $env{'form.printfmthdr_limit_'.$newsub};
1048: }
1049: $hdr .= $env{'form.printfmthdr_sub_'.$newsub};
1050: $newhdr[$env{'form.printfmthdr_pos_'.$newsub}] = $hdr;
1051: }
1052: my $newtext = $maxnum-1;
1053: $newhdr[$env{'form.printfmthdr_pos_'.$newtext}] = $env{'form.printfmthdr_text_'.$newtext};
1054: $newvalues{$entry} = join('',@newhdr);
1055: } elsif ($entry eq 'languages') {
1056: my $langstr;
1057: my $total = $env{'form.'.$entry.'_total'};
1058: if ($total) {
1059: my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
1060: for (my $i=0; $i<$total; $i++) {
1061: unless (grep(/^$i$/,@deletes)) {
1062: $langstr .= $env{'form.'.$entry.'_'.$i}.',';
1063: }
1064: }
1065: } else {
1066: $total = 0;
1067: }
1068: if ($env{'form.'.$entry.'_'.$total} ne '') {
1069: my $newlang = $env{'form.'.$entry.'_'.$total};
1070: my %langchoices = &get_lang_choices();
1071: if ($langchoices{$newlang}) {
1072: $langstr .= $newlang;
1073: } else {
1074: $langstr =~ s/,$//;
1075: $disallowed->{'localization'}{$entry} = $newlang;
1076: }
1077: } else {
1078: $langstr =~ s/,$//;
1079: }
1080: $newvalues{$entry} = $langstr;
1081: } else {
1082: $newvalues{$entry} = $env{'form.'.$entry};
1083: }
1.25 raeburn 1084: unless ($entry eq 'co-owners') {
1085: if ($newvalues{$entry} ne $values->{$entry}) {
1086: $changes->{$entry} = $newvalues{$entry};
1087: }
1.3 raeburn 1088: }
1089: }
1090: }
1091: }
1092: }
1093: }
1094: return;
1095: }
1096:
1097: sub get_sec_str {
1098: my ($entry,$num) = @_;
1099: my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$num);
1100: my $secstr;
1101: if (grep(/^\s*$/,@secs)) {
1102: $secstr = '';
1103: } elsif (@secs > 0) {
1104: $secstr = join(';',@secs);
1105: }
1106: if ($secstr ne '') {
1107: return '('.$secstr.')';
1108: }
1109: return;
1110: }
1111:
1112: sub check_clone {
1113: my ($clonedom,$disallowed,$clonename) = @_;
1114: return if (ref($disallowed) ne 'HASH');
1115: if ($clonedom !~ /^$match_domain$/) {
1116: $disallowed->{'cloners'}{'format'} .= $clonedom.',';
1117: return;
1118: } elsif (!&Apache::lonnet::domain($clonedom)) {
1119: $disallowed->{'cloners'}{'domain'} .= $clonedom.',';
1120: return;
1121: }
1122: if ($clonename ne '') {
1123: if ($clonename !~ /^$match_username$/) {
1124: $disallowed->{'cloners'}{'format'} .= $clonename.':'.$clonedom.',';
1125: return;
1126: } else {
1127: if (&Apache::lonnet::homeserver($clonename,$clonedom) eq 'no_host') {
1128: $disallowed->{'cloners'}{'newuser'} .= $clonename.':'.$clonedom.',';
1129: return;
1130: }
1131: }
1132: }
1133: return 'ok';
1134: }
1135:
1136: sub store_changes {
1.9 raeburn 1137: my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_;
1.3 raeburn 1138: my ($chome,$output);
1.23 raeburn 1139: my (%storehash,@delkeys,@need_env_update,@oldcloner);
1.3 raeburn 1140: if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {
1141: %storehash = %{$values};
1142: } else {
1.9 raeburn 1143: if ($crstype eq 'Community') {
1144: $output = &mt('No changes made to community settings.');
1145: } else {
1146: $output = &mt('No changes made to course settings.');
1147: }
1148: return $output;
1.3 raeburn 1149: }
1150: my %yesno = (
1151: hidefromcat => '1',
1152: problem_stream_switch => '1',
1153: suppress_tries => '1',
1154: disableexampointprint => '1',
1155: hideemptyrows => '1',
1156: suppress_embed_prompt => '1',
1157: );
1158: foreach my $item (@{$prefs_order}) {
1159: if (grep(/^\Q$item\E$/,@{$actions})) {
1160: $output .= '<h3>'.&mt($prefs->{$item}{'text'}).'</h3>';
1161: if (ref($changes->{$item}) eq 'HASH') {
1162: if (keys(%{$changes->{$item}}) > 0) {
1.22 wenzelju 1163: $output .= &mt('Changes made:').'<ul style="list-style:none;">';
1.3 raeburn 1164: if ($item eq 'other') {
1165: foreach my $key (sort(keys(%{$changes->{$item}}))) {
1166: $storehash{$key} = $changes->{$item}{$key};
1167: if ($changes->{$item}{$key} eq '') {
1168: push(@delkeys,$key);
1.22 wenzelju 1169: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]','<i>'.$key.'</i>')).'</li>';
1.3 raeburn 1170: } else {
1.22 wenzelju 1171: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]','<i>'.$key.'</i>',
1172: "'$storehash{$key}'")).'</li>';
1.3 raeburn 1173: }
1174: }
1175: } else {
1176: if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {
1177: my @settings = @{$prefs->{$item}->{'ordered'}};
1178: if ($item eq 'feedback') {
1179: push(@settings,(map { $_.'.text'; } @settings));
1180: }
1181: foreach my $key (@settings) {
1182: if ($key eq 'rolenames') {
1183: my $displayname = $prefs->{$item}->{'itemtext'}{$key};
1184: my $msg;
1.9 raeburn 1185: my @roles;
1186: if ($crstype eq 'Community') {
1187: @roles = ('co');
1188: } else {
1189: @roles = ('cc');
1190: }
1191: push(@roles,('in','ta','ep','ad','st'));
1192: foreach my $role (@roles) {
1.3 raeburn 1193: next if (!exists($changes->{$item}{$key.'_'.$role}));
1194: my $stdname = &Apache::lonnet::plaintext($role,$crstype,undef,1);
1195: my $newname = $changes->{$item}{$key.'_'.$role};
1196: $storehash{$role.'.plaintext'} = $newname;
1197: if ($newname eq '') {
1198: $newname = $stdname;
1199: }
1200: $msg .= '<li>'.&mt('[_1] set to [_2]','<i>'.$stdname.'</i>',
1201: "'<b>".$newname."</b>'").'</li>';
1202: }
1203: if ($msg ne '') {
1.22 wenzelju 1204: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt($displayname)).'<ul class="LC_success">'.$msg.'</ul></li>';
1.3 raeburn 1205: }
1206: } else {
1207: next if (!exists($changes->{$item}{$key}));
1208: my ($displayname,$text);
1209: $text = $prefs->{$item}->{'itemtext'}{$key};
1.25 raeburn 1210: my $displayval;
1211: unless ($key eq 'co-owners') {
1212: $displayval = $changes->{$item}{$key};
1213: }
1.3 raeburn 1214: if ($item eq 'feedback') {
1215: if ($key =~ /^(question|policy|comment)(\.email)\.text$/) {
1216: $text = $prefs->{$item}->{'itemtext'}{$1.$2};
1217: $displayname = &mt('Custom text for '.$text.' questions');
1218: } else {
1219: $displayname = &mt('Recipients of '.$text.' questions');
1220: }
1221: } elsif ($item eq 'discussion') {
1222: if ($key =~ /^p(lc|ch)\.roles\.denied/) {
1223: $displayname = &mt("$text (role-based)");
1224: if ($displayval ne '') {
1225: my @roles = split(',',$displayval);
1226: @roles = map { &Apache::lonnet::plaintext($_); } @roles;
1227: $displayval = join(', ',@roles);
1228: }
1229: } elsif ($key =~ /^p(lc|ch)\.users\.denied/) {
1230: $displayname = &mt("$text (specific user(s))");
1231: } else {
1232: if ($key eq 'allow_discussion_post_editing') {
1233: if ($displayval ne '') {
1234: my @roles = split(',',$displayval);
1235: my @longroles;
1236: foreach my $role (@roles) {
1237: my ($trole,$sec) = split(':',$role);
1238: my $rolename =
1239: &Apache::lonnet::plaintext($trole);
1240: if ($sec ne '') {
1241: $rolename .= ':'.$sec;
1242: }
1243: push(@longroles,$rolename);
1244: }
1245: $displayval = join(', ',@longroles);
1246: }
1247: }
1248: $displayname = &mt($text);
1249: }
1250: } elsif ($item eq 'spreadsheet') {
1251: if ($key =~ /^spreadsheet_default_(studentcalc|assesscalc)$/x) {
1252: my $sheettype = $1;
1253: if ($sheettype eq 'studentcalc') {
1254: &Apache::lonnet::expirespread('','','studentcalc');
1255: } else {
1256: &Apache::lonnet::expirespread('','','assesscalc');
1257: &Apache::lonnet::expirespread('','','studentcalc');
1258: }
1259: }
1260: $displayname = &mt($text);
1261: } else {
1262: $displayname = &mt($text);
1263: }
1264: if (defined($yesno{$key})) {
1.14 raeburn 1265: $displayval = &mt('No');
1.3 raeburn 1266: if ($changes->{$item}{$key} eq 'yes') {
1.14 raeburn 1267: $displayval = &mt('Yes');
1.3 raeburn 1268: }
1269: } elsif (($key =~ /^default_enrollment_(start|end)_date$/) && ($displayval)) {
1270: $displayval = &Apache::lonlocal::locallocaltime($displayval);
1271: } elsif ($key eq 'categories') {
1272: $displayval = $env{'form.categories_display'};
1.14 raeburn 1273: } elsif ($key eq 'canuse_pdfforms') {
1274: if ($changes->{$item}{$key} eq '1') {
1275: $displayval = &mt('Yes');
1276: } elsif ($changes->{$item}{$key} eq '0') {
1277: $displayval = &mt('No');
1278: }
1279: }
1.25 raeburn 1280: if ($key eq 'co-owners') {
1281: if (ref($changes->{$item}{$key}) eq 'HASH') {
1282: if (ref($changes->{$item}{$key}{'changed'}) eq 'ARRAY') {
1283: foreach my $type ('co-owners','pendingco-owners') {
1284: next unless (grep(/^\Q$type\E$/,@{$changes->{$item}{$key}{'changed'}}));
1285: if ($type eq 'pendingco-owners') {
1286: if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
1287: $displayname = &mt('Invited as co-owners, pending acceptance');
1288: }
1289: }
1290: if ($changes->{$item}{$key}{$type} eq '') {
1291: push(@delkeys,'internal.'.$type);
1292: if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
1293: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
1294: '<i>'.$displayname.'</i>')).'</li>';
1295: }
1296: } elsif (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
1297: $displayval = join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } split(',',$changes->{$item}{$key}{$type}));
1298: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
1299: '<i>'.$displayname.'</i>',
1300: "'<b>$displayval</b>'")).'</li>';
1301: }
1302: }
1303: }
1304: unless (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
1305: if ($env{'form.pending_coowoner'} eq 'accept') {
1306: $displayval = &mt('on');
1307: } elsif ($env{'form.pending_coowoner'} eq 'decline') {
1308: $displayval = '';
1309: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Invitation to be co-owner declined')).'</li>';
1310: } elsif ($env{'form.remove_coowoner'}) {
1311: $displayval = &mt('off');
1312: }
1313: if ($displayval) {
1314: $displayname = &mt('Your co-ownership status');
1315: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
1316: '<i>'.$displayname.'</i>',
1317: "'<b>$displayval</b>'")).'</li>';
1318: }
1319: }
1320: }
1321: } elsif ($changes->{$item}{$key} eq '') {
1.3 raeburn 1322: push(@delkeys,$key);
1.22 wenzelju 1323: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('Deleted setting for [_1]',
1324: '<i>'.$displayname.'</i>')).'</li>';
1.3 raeburn 1325: } else {
1.22 wenzelju 1326: $output .= '<li>'.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]',
1.3 raeburn 1327: '<i>'.$displayname.'</i>',
1.22 wenzelju 1328: "'<b>$displayval</b>'"));
1.3 raeburn 1329: if ($key eq 'url') {
1330: my $bkuptime=time;
1331: $output .= (' 'x2).&mt('(Previous URL backed up)').': '.
1.28.2.4! raeburn 1332: $storehash{'top level map backup '.$bkuptime} = $values->{$key};
1.3 raeburn 1333: }
1334: $output .= '</li>';
1335: }
1.25 raeburn 1336: if ($key eq 'co-owners') {
1337: if (ref($changes->{$item}{$key}) eq 'HASH') {
1338: if (ref($changes->{$item}{$key}{'changed'}) eq 'ARRAY') {
1339: foreach my $type ('co-owners','pendingco-owners') {
1340: next unless (grep(/^\Q$type\E$/,@{$changes->{$item}{$key}{'changed'}}));
1341: $storehash{'internal.'.$type} = $changes->{$item}{$key}{$type};
1342: }
1343: }
1344: }
1345: } else {
1346: $storehash{$key} = $changes->{$item}{$key};
1347: }
1.3 raeburn 1348: }
1.23 raeburn 1349: if ($key eq 'cloners') {
1350: # Get existing cloners
1351: my %clonenames =
1352: &Apache::lonnet::dump('environment',$cdom,$cnum,'cloners');
1353: if ($clonenames{'cloners'} =~ /,/) {
1354: @oldcloner = split(/\s*\,\s*/,$clonenames{'cloners'});
1355: } else {
1356: $oldcloner[0] = $clonenames{'cloners'};
1357: }
1358: }
1.3 raeburn 1359: if (($key eq 'description') || ($key eq 'cloners') ||
1.25 raeburn 1360: ($key eq 'hidefromcat') || ($key eq 'categories') ||
1361: ($key eq 'co-owners')) {
1.3 raeburn 1362: push(@need_env_update,$key);
1363: }
1364: }
1365: }
1366: }
1367: $output .= '</ul>';
1368: } else {
1.9 raeburn 1369: if ($crstype eq 'Community') {
1370: $output = &mt('No changes made to community settings.');
1371: } else {
1372: $output = &mt('No changes made to course settings.');
1373: }
1.3 raeburn 1374: }
1375: }
1376: }
1377: }
1378: if (&Apache::lonnet::put('environment',\%storehash,$cdom,$cnum) eq 'ok') {
1.23 raeburn 1379: if (ref($changes) eq 'HASH') {
1380: if (ref($changes->{'courseinfo'}) eq 'HASH') {
1381: if (exists($changes->{'courseinfo'}{'cloners'})) {
1382: &change_clone($cdom,$cnum,$changes->{'courseinfo'}{'cloners'},
1383: \@oldcloner);
1384: }
1385: }
1386: }
1.3 raeburn 1387: if (@delkeys) {
1388: if (&Apache::lonnet::del('environment',\@delkeys,$cdom,$cnum) ne 'ok') {
1.9 raeburn 1389: $output .= '<br /><span class="LC_error">';
1390: if ($crstype eq 'Community') {
1391: $output .= &mt('An error occurred when removing community settings which are no longer in use.');
1392: } else {
1393: $output .= &mt('An error occurred when removing course settings which are no longer in use.');
1394: }
1395: $output .= '</span>';
1.14 raeburn 1396: } else {
1397: foreach my $key (@delkeys) {
1398: &Apache::lonnet::delenv('course.'.$cdom.'_'.$cnum.'.'.$key);
1399: }
1.3 raeburn 1400: }
1401: }
1402: if (@need_env_update) {
1403: $chome = &Apache::lonnet::homeserver($cnum,$cdom);
1404: &update_env($cnum,$cdom,$chome,\@need_env_update,\%storehash);
1405: }
1406: &Apache::lonnet::coursedescription($env{'request.course.id'},
1407: {'freshen_cache' => 1});
1408: } else {
1.9 raeburn 1409: $output = '<span class="LC_error">';
1410: if ($crstype eq 'Community') {
1411: $output .= &mt('An error occurred when saving changes to community settings, which remain unchanged.');
1412: } else {
1413: $output .= &mt('An error occurred when saving changes to course settings, which remain unchanged.');
1414: }
1415: $output .= '</span>';
1.3 raeburn 1416: }
1417: return $output;
1418: }
1419:
1420: sub update_env {
1421: my ($cnum,$cdom,$chome,$need_env_update,$storehash) = @_;
1422: my $count = 0;
1423: if ((ref($need_env_update) eq 'ARRAY') && (ref($storehash) eq 'HASH')) {
1424: my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.');
1425: if (ref($crsinfo{$env{'request.course.id'}}) eq 'HASH') {
1426: foreach my $key (@{$need_env_update}) {
1427: if ($key eq 'description' && defined($storehash->{$key})) {
1428: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.description' => $storehash->{$key}});
1429: $crsinfo{$env{'request.course.id'}}{'description'} = $storehash->{$key};
1430: $count ++;
1431: } elsif (($key eq 'cloners') || ($key eq 'hidefromcat') || ($key eq 'categories')) {
1432: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash->{$key}});
1433: $crsinfo{$env{'request.course.id'}}{$key} = $storehash->{$key};
1434: $count ++;
1.25 raeburn 1435: } elsif ($key eq 'co-owners') {
1436: if ($storehash->{'internal.co-owners'} ne '') {
1437: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.co-owners' => $storehash->{'internal.co-owners'}});
1438: }
1439: if ($storehash->{'internal.pendingco-owners'} ne '') {
1440: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.internal.pendingco-owners' => $storehash->{'internal.pendingco-owners'}});
1441: }
1442: my @coowners = split(',',$storehash->{'internal.'.$key});
1443: $crsinfo{$env{'request.course.id'}}{'co-owners'} = \@coowners;
1444: $count ++;
1.3 raeburn 1445: }
1446: }
1447: if ($count) {
1448: my $putresult = &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime');
1449: }
1450: }
1451: }
1452: return;
1453: }
1454:
1455: sub display_disallowed {
1.9 raeburn 1456: my ($item,$disallowed,$prefs,$crstype) = @_;
1.3 raeburn 1457: my $output;
1458: if ((ref($disallowed) eq 'HASH') && (ref($prefs) eq 'HASH')) {
1459: if (keys(%{$disallowed})) {
1460: if ($item eq 'cloners') {
1461: my @fails;
1462: my %lt = &Apache::lonlocal::texthash (
1463: format => 'Invalid format',
1464: domain => 'Domain does not exist',
1465: newuser => 'LON-CAPA user(s) do(es) not exist.',
1466: );
1467: foreach my $error ('format','domain','newuser') {
1468: if (defined($disallowed->{$error})) {
1469: my $msg = '<b>'.$disallowed->{$error}.'</b>, '.&mt('reason').' - '.
1470: $lt{$error};
1471: if ($error eq 'newuser') {
1.9 raeburn 1472: $msg .= '<br />'.&mt("Please [_1]add the user(s)[_2] before returning to the [_3]$crstype Configuration[_2] to add as potential cloners.",'<a href="/adm/createuser">','</a>','<a href="/adm/courseprefs">');
1.3 raeburn 1473: }
1474: push(@fails,$msg);
1475: }
1476: }
1477: if (@fails) {
1478: $output .= '<span class="LC_warning">'.&mt('Unable to add to allowed cloners: ').
1479: '</span>'.join('; ',@fails).'.<br />';
1480: }
1481: } elsif ($item eq 'rolenames') {
1482: my %lt = &Apache::lonlocal::texthash (
1483: replacements => 'Name already used to replace a different standard role name',
1484: regulars => 'Name already used as a standard role name',
1485: customrole => 'Name already used as the name of a custom role',
1486: );
1487: my @fails;
1488: foreach my $error ('replacements','regulars','customrole') {
1489: if (ref($disallowed->{$error}) eq 'ARRAY') {
1490: push(@fails,'<b>'.join(', ',@{$disallowed->{$error}}).
1491: '</b>, '.&mt('reason').' - '.$lt{'error'});
1492: }
1493: }
1494: if (@fails) {
1495: $output .= '<span class="LC_warning">'.
1496: &mt('Unable to include amongst replacements for role names: ').
1497: '</span>'.join('; ',@fails).'.<br />';
1498: }
1499:
1500: } elsif (($item eq 'feedback') || ($item eq 'discussion') || ($item eq 'localization')) {
1501: $output .= '<span class="LC_warning">';
1502: if ($item eq 'feedback') {
1.9 raeburn 1503: if ($crstype eq 'Community') {
1504: $output .= &mt('Unable to include as a recipient of community feedback for:');
1505: } else {
1506: $output .= &mt('Unable to include as a recipient of course feedback for:');
1507: }
1.3 raeburn 1508: } elsif ($item eq 'discussion') {
1509: $output .= &mt('Unable to include in user-based access control for:');
1510: } elsif ($item eq 'localization') {
1.9 raeburn 1511: if ($crstype eq 'Community') {
1512: $output .= &mt('Unable to include in community localization:');
1513: } else {
1514: $output .= &mt('Unable to include in course localization:');
1515: }
1.3 raeburn 1516: }
1517: $output .= '</span><ul>';
1518: foreach my $key (sort(keys(%{$disallowed}))) {
1519: my $itemtext = $prefs->{$item}{'itemtext'}{$key};
1520: $output .= '<li><i>'.$itemtext.'</i> - ';
1521: if ($item eq 'localization') {
1522: $output .= &mt('reason - unsupported language: [_1]',
1523: '<b>'.$disallowed->{$key}.'</b>');
1524: } else {
1525: $output .= &mt('reason - invalid user: [_1]',
1526: '<b>'.$disallowed->{$key}.'</b>').'</li>';
1527: }
1528: }
1529: $output .= '</ul><br />';
1530: }
1531: }
1.1 raeburn 1532: }
1.3 raeburn 1533: return $output;
1.1 raeburn 1534: }
1535:
1536: sub get_course {
1537: my ($courseid) = @_;
1538: if (!defined($courseid)) {
1539: $courseid = $env{'request.course.id'};
1540: }
1541: my $cdom=$env{'course.'.$courseid.'.domain'};
1542: my $cnum=$env{'course.'.$courseid.'.num'};
1543: return ($cnum,$cdom);
1544: }
1545:
1546: sub get_jscript {
1.12 raeburn 1547: my ($cdom,$phase,$crstype) = @_;
1548: my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
1.1 raeburn 1549: my ($jscript,$categorize_js);
1550: my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();
1551: my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset');
1.3 raeburn 1552: my $cloners_js = &cloners_javascript($phase);
1.1 raeburn 1553: if ($can_categorize) {
1554: $categorize_js = <<ENDSCRIPT;
1555: function catsbrowser() {
1556: var catswin = null;
1557: var url = '/adm/courseprefs?phase=categorizecourse';
1558: if (!catswin || catswin.closed) {
1559: catswin=window.open(url,'categorieswin','height=480,width=600,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
1560: } else {
1561: catswin.focus();
1562: }
1563: }
1564: ENDSCRIPT
1565: }
1566: $jscript = '<script type="text/javascript" language="Javascript">'."\n".
1.3 raeburn 1567: $browse_js."\n".$categorize_js."\n".$cloners_js."\n".'</script>'.
1568: "\n".$stubrowse_js."\n";
1.1 raeburn 1569: return $jscript;
1570: }
1571:
1.3 raeburn 1572: sub cloners_javascript {
1573: my ($formname) = @_;
1574: return <<"ENDSCRIPT";
1575:
1576: function update_cloners(caller,num) {
1577: var delidx = getIndexByName('cloners_delete');
1578: var actidx = getIndexByName('cloners_activate');
1579: if (caller == 'cloners_all') {
1580: var selall;
1581: for (var i=0; i<document.$formname.cloners_all.length; i++) {
1582: if (document.$formname.cloners_all[i].checked) {
1583: selall = document.$formname.cloners_all[i].value;
1584: }
1585: }
1586: if (selall == 1) {
1587: if (delidx != -1) {
1588: if (document.$formname.cloners_delete.length) {
1589: for (var j=0; j<document.$formname.cloners_delete.length; j++) {
1590: document.$formname.cloners_delete[j].checked = true;
1591: }
1592: } else {
1593: document.$formname.elements[delidx].checked = true;
1594: }
1595: }
1596: if (actidx != -1) {
1597: if (document.$formname.cloners_activate.length) {
1598: for (var i=0; i<document.$formname.cloners_activate.length; i++) {
1599: if (document.$formname.cloners_activate[i].value == '0') {
1600: document.$formname.cloners_activate[i].checked = false;
1601: }
1602: if (document.$formname.cloners_activate[i].value == '') {
1603: document.$formname.cloners_activate[i].checked = true;
1604: }
1605: }
1606: }
1607: }
1608: document.$formname.cloners_newdom.selectedIndex = 0;
1609: }
1610: }
1611: if (caller == 'cloners_activate') {
1612: if (document.$formname.cloners_activate.length) {
1613: for (var j=0; j<document.$formname.cloners_activate.length; j++) {
1614: if (document.$formname.cloners_activate[j].value == num) {
1615: if (document.$formname.cloners_activate[j].checked) {
1616: for (var i=0; i<document.$formname.cloners_all.length; i++) {
1617: if (document.$formname.cloners_all[i].value == '1') {
1618: document.$formname.cloners_all[i].checked = false;
1619: }
1620: if (document.$formname.cloners_all[i].value == '0') {
1621: document.$formname.cloners_all[i].checked = true;
1622: }
1623: }
1624: }
1625: }
1626: }
1627: } else {
1628: for (var i=0; i<document.$formname.cloners_all.length; i++) {
1629: if (document.$formname.cloners_all[i].value == '1') {
1630: document.$formname.cloners_all[i].checked = false;
1631: }
1632: if (document.$formname.cloners_all[i].value == '0') {
1633: document.$formname.cloners_all[i].checked = true;
1634: }
1635: }
1636: }
1637: }
1638: return;
1639: }
1640:
1641: function getIndexByName(item) {
1642: for (var i=0;i<document.$formname.elements.length;i++) {
1643: if (document.$formname.elements[i].name == item) {
1644: return i;
1645: }
1646: }
1647: return -1;
1648: }
1649:
1650: ENDSCRIPT
1651: }
1652:
1653:
1.1 raeburn 1654: sub print_courseinfo {
1.9 raeburn 1655: my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3 raeburn 1656: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 1657: return;
1658: }
1.25 raeburn 1659: my ($cathash,$categoriesform,$autocoowner);
1.1 raeburn 1660: my %domconf =
1.25 raeburn 1661: &Apache::lonnet::get_dom('configuration',['coursecategories','autoenroll'],$cdom);
1.1 raeburn 1662: if (ref($domconf{'coursecategories'}) eq 'HASH') {
1663: $cathash = $domconf{'coursecategories'}{'cats'};
1664: if (ref($cathash) eq 'HASH') {
1665: $categoriesform =
1666: &Apache::loncommon::assign_categories_table($cathash,
1.12 raeburn 1667: $settings->{'categories'},$crstype)."\n";
1.1 raeburn 1668: }
1669: }
1.25 raeburn 1670: if (ref($domconf{'autoenroll'}) eq 'HASH') {
1671: $autocoowner = $domconf{'autoenroll'}{'co-owners'};
1672: }
1.1 raeburn 1673: if (!defined($categoriesform)) {
1.15 raeburn 1674: $categoriesform = &mt('No categories defined in this domain.');
1.1 raeburn 1675: }
1676:
1.12 raeburn 1677: my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
1.1 raeburn 1678:
1.9 raeburn 1679: my $replace;
1680: if ($crstype eq 'Community') {
1681: $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank');
1682: } else {
1683: $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank');
1684: }
1.1 raeburn 1685: my %items = (
1.3 raeburn 1686: 'url' => {
1687: text => '<b>'.&mt($itemtext->{'url'}).'</b>'.(' 'x2).
1.1 raeburn 1688: '<a href="javascript:openbrowser'.
1689: "('display','url','sequence')\">".
1690: &mt('Select Map').'</a><br /><span class="LC_warning"> '.
1691: &mt('Modification may make assessment data inaccessible!').
1692: '</span>',
1693: input => 'textbox',
1694: size => '40',
1695: },
1696: 'description' => {
1.3 raeburn 1697: text => '<b>'.&mt($itemtext->{'description'}).'</b>',
1.1 raeburn 1698: input => 'textbox',
1699: size => '25',
1700: },
1.24 raeburn 1701: 'owner' => {
1702: text => '<b>'.&mt($itemtext->{'owner'}).'</b>',
1703: },
1.25 raeburn 1704: 'co-owners' => {
1705: text => '<b>'.&mt($itemtext->{'co-owners'}).'</b>',
1706: },
1.1 raeburn 1707: 'courseid' => {
1.3 raeburn 1708: text => '<b>'.&mt($itemtext->{'courseid'}).'</b><br />'.'('.
1709: &mt('internal, optional').')',
1.1 raeburn 1710: input => 'textbox',
1711: size => '25',
1712: },
1713: 'cloners' => {
1.3 raeburn 1714: text => '<b>'.&mt($itemtext->{'cloners'}).'</b><br />'.
1.24 raeburn 1715: &mt('Owner and Coordinators included automatically'),
1.1 raeburn 1716: input => 'textbox',
1717: size => '40',
1718: },
1719: 'rolenames' => {
1.3 raeburn 1720: text => '<b>'.&mt($itemtext->{'rolenames'}).'</b><br />'.
1.9 raeburn 1721: '('.$replace.')',
1.1 raeburn 1722: input => 'textbox',
1723: size => '20',
1724: },
1725: 'externalsyllabus' => {
1.3 raeburn 1726: text => '<b>'.&mt($itemtext->{'externalsyllabus'}).'</b><br />('.
1727: &mt('not using syllabus template)'),
1.1 raeburn 1728: input => 'textbox',
1729: size => '40',
1730: },
1731: 'hidefromcat' => {
1.3 raeburn 1732: text => '<b>'.&mt($itemtext->{'hidefromcat'}).'</b><br />'.
1.1 raeburn 1733: ' ('.&mt('included by default if assigned institutional code, or categorized').')',
1734: input => 'radio',
1735: },
1736: 'categories' => {
1.3 raeburn 1737: text => '<b>'.&mt($itemtext->{'categories'}).'</b> <a href="javascript:catsbrowser()">'.
1.1 raeburn 1738: &mt('Display Categories').'</a>',
1739: input => 'textbox',
1740: size => '25',
1741: },
1742: );
1743: my $datatable;
1744: my $count = 0;
1745: foreach my $item (@{$ordered}) {
1746: if ($item eq 'hidefromcat') {
1747: next if (!$can_toggle_cat);
1748: } elsif ($item eq 'categories') {
1749: next if (!$can_categorize);
1750: }
1751: $count ++;
1.28.2.1 raeburn 1752: $datatable .= &item_table_row_start($items{$item}{text},$count);
1.1 raeburn 1753: if ($items{$item}{input} eq 'radio') {
1754: $datatable .= &yesno_radio($item,$settings);
1755: } elsif ($item eq 'cloners') {
1756: my $includeempty = 1;
1757: my $num = 0;
1758: $datatable .= &Apache::loncommon::start_data_table().
1759: &Apache::loncommon::start_data_table_row().
1760: '<td><span class="LC_nobreak"><label>'.
1761: &mt('Any user in any domain:').
1762: ' <input type="radio" name="cloners_all" value="1" ';
1763: if ($settings->{$item} eq '*') {
1764: $datatable .= ' checked="checked" ';
1765: }
1766: $datatable .= 'onchange="javascript:update_cloners('.
1767: "'cloners_all'".');" />'.&mt('Yes').'</label>'.
1768: (' 'x2).'<input type="radio" name="cloners_all" value="0" ';
1769: if ($settings->{$item} ne '*') {
1770: $datatable .= ' checked="checked" ';
1771: }
1772: $datatable .= ' onchange="javascript:update_cloners('.
1773: "'cloners_all'".');"/>'.&mt('No').'</label></td>'.
1774: &Apache::loncommon::end_data_table_row().
1775: &Apache::loncommon::end_data_table().
1776: '<table><tr><td align="left">'.&mt('Or').
1777: '</td></tr></table>'.
1778: &Apache::loncommon::start_data_table();
1779: my @cloners;
1780: if ($settings->{$item} eq '') {
1781: $datatable .= &new_cloners_dom_row($cdom,'0');
1782: } elsif ($settings->{$item} ne '*') {
1783: my @entries = split(/,/,$settings->{$item});
1784: if (@entries > 0) {
1785: foreach my $entry (@entries) {
1786: my ($uname,$udom) = split(/:/,$entry);
1.23 raeburn 1787: if ($udom =~ /^$match_domain$/) {
1788: unless (&Apache::lonnet::domain($udom)) {
1789: next;
1790: }
1791: } else {
1792: next;
1793: }
1.1 raeburn 1794: if ($uname eq '*') {
1795: $datatable .=
1796: &Apache::loncommon::start_data_table_row().
1.3 raeburn 1797: '<td valign="top" align="left"><span class="LC_nobreak">'.
1.23 raeburn 1798: &mt('Any user in domain:').'<b> '.$udom.
1.1 raeburn 1799: '</b><input type="hidden" name="cloners_dom_'.$num.
1800: '" value="'.$udom.'" /></span><br />'.
1801: '<span class="LC_nobreak"><label><input type="checkbox" '.
1.3 raeburn 1802: 'name="cloners_delete" value="'.$num.'" onchange="javascript:update_cloners('."'cloners_delete','$num'".');" />'.
1.1 raeburn 1803: &mt('Delete').'</label></span></td>'.
1804: &Apache::loncommon::end_data_table_row();
1805: $num ++;
1.23 raeburn 1806: } elsif (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
1807: unless (grep(/^\Q$entry\E$/,@cloners)) {
1808: push(@cloners,$entry);
1809: }
1.1 raeburn 1810: }
1811: }
1812: }
1813: }
1814: my $add_domtitle = &mt('Any user in additional domain:');
1815: if ($settings->{$item} eq '*') {
1816: $add_domtitle = &mt('Any user in specific domain:');
1817: } elsif ($settings->{$item} eq '') {
1818: $add_domtitle = &mt('Any user in other domain:');
1819: }
1820: my $cloners_str = join(',',@cloners);
1821: $datatable .= &Apache::loncommon::start_data_table_row().
1822: '<td align="left"><span class="LC_nobreak">'.
1823: $add_domtitle.'</span><br />'.
1824: &Apache::loncommon::select_dom_form('','cloners_newdom',
1825: $includeempty).
1826: '<input type="hidden" name="cloners_total" value="'.$num.'" />'.
1827: '</td>'.&Apache::loncommon::end_data_table_row().
1.3 raeburn 1828: &Apache::loncommon::end_data_table().
1829: '<table><tr><td align="left">'.&mt('And').
1830: '</td></tr></table>'.
1.1 raeburn 1831: &Apache::loncommon::start_data_table().
1832: &Apache::loncommon::start_data_table_row().
1833: '<td align="left">'.
1834: &mt('Specific users').' (<tt>'.
1835: &mt('user:domain,user:domain').'</tt>)<br />'.
1836: &Apache::lonhtmlcommon::textbox($item,$cloners_str,
1837: $items{$item}{'size'}).
1838: '</td>'.&Apache::loncommon::end_data_table_row().
1839: &Apache::loncommon::end_data_table();
1840: } elsif ($item eq 'rolenames') {
1841: $datatable .= &Apache::loncommon::start_data_table();
1.9 raeburn 1842: my @roles;
1843: if ($crstype eq 'Community') {
1844: @roles = ('co');
1845: } else {
1846: @roles = ('cc');
1847: }
1848: push (@roles,('in','ta','ep','ad','st'));
1849: foreach my $role (@roles) {
1.1 raeburn 1850: $datatable .= &Apache::loncommon::start_data_table_row().
1851: '<td align="left"><span class="LC_nobreak">'.
1852: &Apache::lonnet::plaintext($role,$crstype,undef,1).
1853: '</span></td><td align="left">'.
1854: &Apache::lonhtmlcommon::textbox('rolenames_'.$role,
1855: $settings->{$role.'.plaintext'},
1856: $items{$item}{size}).'</td>'.
1857: &Apache::loncommon::end_data_table_row();
1858: }
1859: $datatable .= &Apache::loncommon::end_data_table().'</td>';
1860: } elsif ($item eq 'categories') {
1.3 raeburn 1861: my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";';
1862: $datatable .= '<input type="hidden" name="categories" value="'.$settings->{$item}.'" />'.
1863: &Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item},
1864: $items{$item}{size},$launcher);
1.24 raeburn 1865: } elsif ($item eq 'owner') {
1866: my $owner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'};
1867: if ($owner =~ /:/) {
1868: my ($ownername,$ownerdom) = split(':',$owner);
1869: $owner = &Apache::loncommon::plainname($ownername,$ownerdom);
1870: } elsif ($owner ne '') {
1871: $owner = &Apache::loncommon::plainname($owner,$cdom);
1872: } else {
1873: $owner = &mt('None specified');
1874: }
1875: my $domdesc = &Apache::lonnet::domain($cdom,'description');
1876: $datatable .= $owner;
1.25 raeburn 1877: } elsif ($item eq 'co-owners') {
1878: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1879: my $coowners = $env{'course.'.$env{'request.course.id'}.'.internal.co-owners'};
1880: my @currcoown;
1881: if ($coowners) {
1882: @currcoown = split(',',$coowners);
1883: }
1884: if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
1885: if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
1886: $datatable .= &show_autocoowners(@currcoown);
1887: } else {
1888: $datatable .= &coowner_invitations($cnum,$cdom,@currcoown);
1889: }
1890: } else {
1891: if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
1892: $datatable .= &show_autocoowners(@currcoown);
1893: } else {
1894: $datatable .= &manage_coownership($cnum,$cdom,@currcoown);
1895: }
1896: }
1.1 raeburn 1897: } else {
1898: $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size});
1899: }
1900: $datatable .= &item_table_row_end();
1901: }
1902: $$rowtotal += scalar(@{$ordered});
1903: return $datatable;
1904: }
1905:
1906: sub new_cloners_dom_row {
1907: my ($newdom,$num) = @_;
1908: my $output;
1909: if ($newdom ne '') {
1910: $output .= &Apache::loncommon::start_data_table_row().
1911: '<td valign="top"><span class="LC_nobreak">'.
1912: &mt('Any user in domain:').' <b>'.$newdom.'</b>'.
1913: (' 'x2).'<label><input type="radio" '.
1914: 'name="cloners_activate" value="'.$num.'" '.
1.3 raeburn 1915: 'onchange="javascript:update_cloners('.
1.1 raeburn 1916: "'cloners_activate','$num'".');" />'.
1917: &mt('Yes').'</label>'.(' 'x2).
1918: '<label><input type="radio" '.
1919: 'name="cloners_activate" value="" checked="checked" '.
1.3 raeburn 1920: 'onchange="javascript:update_cloners('.
1.1 raeburn 1921: "'cloners_activate','$num'".');" />'.
1.3 raeburn 1922: &mt('No').'</label><input type="hidden" name="cloners_dom_'.
1923: $num.'" value="'.$newdom.'" /></span></td>'.
1.1 raeburn 1924: &Apache::loncommon::end_data_table_row();
1925: }
1926: return $output;
1927: }
1928:
1929: sub can_modify_catsettings {
1.12 raeburn 1930: my ($dom,$crstype) = @_;
1.1 raeburn 1931: my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom);
1932: my ($can_toggle_cat,$can_categorize);
1933: if (ref($domconf{'coursecategories'}) eq 'HASH') {
1.12 raeburn 1934: if ($crstype eq 'Community') {
1935: if ($domconf{'coursecategories'}{'togglecatscomm'} eq 'comm') {
1936: $can_toggle_cat = 1;
1937: }
1938: if ($domconf{'coursecategories'}{'categorizecomm'} eq 'comm') {
1939: $can_categorize = 1;
1940: }
1941: } else {
1942: if ($domconf{'coursecategories'}{'togglecats'} eq 'crs') {
1943: $can_toggle_cat = 1;
1944: }
1945: if ($domconf{'coursecategories'}{'categorize'} eq 'crs') {
1946: $can_categorize = 1;
1947: }
1.1 raeburn 1948: }
1949: }
1950: return ($can_toggle_cat,$can_categorize);
1951: }
1952:
1953: sub assign_course_categories {
1.9 raeburn 1954: my ($r,$crstype) = @_;
1.1 raeburn 1955: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1956: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1957: my $hascats = 0;
1958: my $cathash;
1959: my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom);
1960: if (ref($domconf{'coursecategories'}) eq 'HASH') {
1961: $cathash = $domconf{'coursecategories'}{'cats'};
1962: if (ref($cathash) eq 'HASH') {
1.12 raeburn 1963: foreach my $cat (keys(%{$cathash})) {
1964: next if ($cat eq 'instcode::0');
1965: unless ($crstype eq 'Community') {
1966: next if ($cat eq 'communities::0');
1967: }
1968: $hascats ++;
1969: }
1.1 raeburn 1970: }
1971: }
1972: my $catwin_js;
1973: if ($hascats) {
1.9 raeburn 1974: my $alert;
1975: if ($crstype eq 'Community') {
1976: $alert = &mt("Use 'Save' in the main window to save community categories");
1977: } else {
1978: $alert = &mt("Use 'Save' in the main window to save course categories");
1979: }
1.1 raeburn 1980: $catwin_js = <<ENDSCRIPT;
1981: <script type="text/javascript">
1982:
1983: function updateCategories() {
1984: var newcategories = '';
1985: var unescapedcats = '';
1986: if (document.chgcats.usecategory.length) {
1987: for (var i=0; i<document.chgcats.usecategory.length; i++) {
1988: if (document.chgcats.usecategory[i].checked == true) {
1989: newcategories = newcategories + document.chgcats.usecategory[i].value + '&';
1990: unescapedcats = unescapedcats + document.chgcats.catname[i].value + ' & ';
1991: }
1992: }
1993: if (newcategories.length > 0) {
1994: newcategories = newcategories.slice(0,-1);
1995: }
1996: if (unescapedcats.length > 0) {
1997: unescapedcats = unescapedcats.slice(0,-3);
1998: }
1999: } else {
2000: if (document.chgcats.usecategory.checked == true) {
2001: newcategories = document.chgcats.usecategory.value;
2002: unescapedcats = document.chgcats.catname.value;
2003: }
2004: }
2005: opener.document.display.categories.value = newcategories;
2006: opener.document.display.categories_display.value = unescapedcats;
2007: alert("$alert");
2008: self.close();
2009: return;
2010: }
2011:
2012: </script>
2013: ENDSCRIPT
2014: } else {
2015: my $onload;
2016: }
1.9 raeburn 2017: my ($crscat,$catcrs,$assign);
2018: if ($crstype eq 'Community') {
2019: $crscat = 'Community Categories';
2020: $catcrs = &mt('Categorize Community');
2021: $assign = &mt('Assign one or more categories to this community.')
2022: } else {
2023: $crscat = 'Course Categories';
2024: $catcrs = &mt('Categorize Course');
2025: $assign = &mt('Assign one or more categories to this course.')
2026: }
1.1 raeburn 2027: my $start_page =
1.9 raeburn 2028: &Apache::loncommon::start_page($crscat,$catwin_js,
1.1 raeburn 2029: {'only_body' => 1,});
2030: my $end_page = &Apache::loncommon::end_page();
1.9 raeburn 2031: my $categoriesform = '<h3>'.$catcrs.'</h3>';
1.1 raeburn 2032: if ($hascats) {
2033: my %currsettings =
2034: &Apache::lonnet::get('environment',['hidefromcat','categories'],$cdom,$cnum);
1.12 raeburn 2035: my $cattable = &Apache::loncommon::assign_categories_table($cathash,
2036: $currsettings{'categories'},$crstype);
2037: if ($cattable eq '') {
2038: $categoriesform .= &mt('No suitable categories defined for this course type in this domain.');
2039: } else {
2040: $categoriesform .= $assign.'<br /><br />'.
2041: '<form name="chgcats" action="/adm/courseprefs" method="post">'."\n".
2042: $cattable."\n".
2043: '<br /><input type="button" name="changes" value="'.
2044: &mt('Copy to main window').'" '.
2045: 'onclick="javascript:updateCategories()" /></form><br />';
2046: }
1.1 raeburn 2047: } else {
1.12 raeburn 2048: $categoriesform .= &mt('No categories defined in this domain.');
1.1 raeburn 2049: }
2050: $r->print($start_page.$categoriesform.$end_page);
2051: return;
2052: }
2053:
1.25 raeburn 2054: sub show_autocoowners {
2055: my (@currcoown) = @_;
2056: my $output = '<i>'.&mt('Co-ownership is set automatically when a Course Coordinator role is assigned to official course personnel (from institutional data).').'</i>';
2057: if (@currcoown > 0) {
2058: $output .= '<br />'.&mt('Current co-owners are:').' '.
2059: join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));
2060: } else {
2061: $output .= '<br />'.&mt('Currently no co-owners.');
2062: }
2063: return $output;
2064: }
2065:
2066: sub coowner_invitations {
2067: my ($cnum,$cdom,@currcoown) = @_;
2068: my ($output,@pendingcoown,@othercoords);
2069: my $pendingcoowners =
2070: $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
2071: if ($pendingcoowners) {
2072: @pendingcoown = split(',',$pendingcoowners);
2073: }
2074: my $ccrole = 'cc';
2075: my %ccroles = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,undef,[$ccrole]);
2076: foreach my $key (sort(keys(%ccroles))) {
2077: my ($ccname,$ccdom,$role) = split(':',$key);
2078: next if ($key eq $env{'user.name'}.':'.$env{'user.domain'}.':'.$ccrole);
2079: unless (grep(/^\Q$ccname\E:\Q$ccdom\E$/,@currcoown,@pendingcoown)) {
2080: push(@othercoords,$ccname.':'.$ccdom);
2081: }
2082: }
2083: my $coowner_rows = @currcoown + @pendingcoown + @othercoords;
2084: if ($coowner_rows) {
2085: $output .= &Apache::loncommon::start_data_table();
2086: if (@currcoown) {
2087: $output .= &Apache::loncommon::start_data_table_row().
2088: '<td><i>'.&mt('Current co-owners').'</i></td><td>';
2089: foreach my $person (@currcoown) {
2090: my ($co_uname,$co_dom) = split(':',$person);
2091: $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="coowners" checked="checked" value="'.$person.'" />'.&Apache::loncommon::plainname($co_uname,$co_dom).'</label></span>'.(' 'x2).' ';
2092: }
2093: $output .= '</td>'.
2094: &Apache::loncommon::end_data_table_row();
2095: }
2096: if ($pendingcoowners) {
2097: $output .= &Apache::loncommon::start_data_table_row().
2098: '<td><i>'.&mt('Invited as co-owners [_1](agreement pending)','<br />').'</i></td><td>';
2099: foreach my $person (@pendingcoown) {
2100: my ($co_uname,$co_dom) = split(':',$person);
2101: $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="pendingcoowners" checked="checked" value="'.$person.'" />'.&Apache::loncommon::plainname($co_uname,$co_dom).'</label></span>'.(' 'x2).' ';
2102: }
2103: $output .= '</td>'.
2104: &Apache::loncommon::end_data_table_row();
2105: }
2106: if (@othercoords) {
2107: $output .= &Apache::loncommon::start_data_table_row().
2108: '<td><i>'.&mt('Invite other Coordinators [_1]to become co-owners','<br />').'</i></td><td>';
2109: foreach my $person (@othercoords) {
2110: my ($co_uname,$co_dom) = split(':',$person);
2111: $output .= '<span class="LC_nobreak"><label><input type="checkbox" name="invitecoowners" value="'.$person.'" />'.&Apache::loncommon::plainname($co_uname,$co_dom).'</label></span>'.(' 'x2).' ';
2112: }
2113: $output .= '</td>'.
2114: &Apache::loncommon::end_data_table_row();
2115: }
2116: $output .= &Apache::loncommon::end_data_table();
2117: } else {
2118: $output = &mt('There are no coordinators to select as co-owners');
2119: }
2120: return $output;
2121: }
2122:
2123: sub manage_coownership {
2124: my ($cnum,$cdom,@currcoown) = @_;
2125: my (@pendingcoown);
2126: my $pendingcoowners =
2127: $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
2128: if ($pendingcoowners) {
2129: @pendingcoown = split(',',$pendingcoowners);
2130: }
2131: my ($is_coowner,$is_pending,$output);
2132: my $uname = $env{'user.name'};
2133: my $udom = $env{'user.domain'};
2134: if (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {
2135: $is_coowner = 1;
2136: }
2137: if (grep(/^\Q$uname\E:\Q$udom\E$/,@pendingcoown)) {
2138: $is_pending = 1;
2139: }
2140: if (@currcoown && ($is_coowner || $is_pending)) {
2141: $output = &Apache::loncommon::start_data_table();
2142: }
2143: if (@currcoown) {
2144: if ($is_coowner || $is_pending) {
2145: $output .= &Apache::loncommon::start_data_table().
2146: &Apache::loncommon::start_data_table_row().'<td>';
2147: }
2148: $output .= &mt('Current co-owners are:').' '.
2149: join(', ', map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));
2150: if ($is_coowner || $is_pending) {
2151: $output .= '</td>'.&Apache::loncommon::end_data_table_row();
2152: }
2153: }
2154: if ($is_coowner || $is_pending) {
2155: if (@currcoown) {
2156: $output .= &Apache::loncommon::start_data_table_row().'<td>';
2157: }
2158: $output .= '<span class="LC_nobreak">';
2159: if ($is_coowner) {
2160: $output .= &mt('You are currently a co-owner:').' <label><input type="checkbox" name="remove_coowoner" value="'.$uname.':'.$udom.'" />'.&mt('Discontinue?').'</label>';
2161: } else {
2162: $output .= &mt('The course owner has invited you to become a co-owner:').' <label><input type="radio" name="pending_coowoner" value="accept" />'.&mt('Accept?').'</label>'.(' 'x2).
2163: '<label><input type="radio" name=pending_coowoner" value="decline" />'.&mt('Decline?').'</label>';
2164: }
2165: $output .= '</span>';
2166: if (@currcoown) {
2167: $output .= '</td>'.&Apache::loncommon::end_data_table_row();
2168: }
2169: }
2170: if (@currcoown && ($is_coowner || $is_pending)) {
2171: $output .= &Apache::loncommon::end_data_table();
2172: }
2173: return $output;
2174: }
2175:
1.1 raeburn 2176: sub print_localization {
1.3 raeburn 2177: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
2178: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2179: return;
2180: }
2181: my %items = (
2182: languages => {
1.17 faziophi 2183: text => '<b>'.&mt($itemtext->{'languages'}).'</b><br />'.
2184: &mt("(overrides individual user preference)"),
1.1 raeburn 2185: input => 'selectbox',
2186: },
2187: timezone => {
1.17 faziophi 2188: text => '<b>'.&mt($itemtext->{'timezone'}).'</b>',
1.1 raeburn 2189: input => 'selectbox',
2190: },
2191: datelocale => {
1.17 faziophi 2192: text => '<b>'.&mt($itemtext->{'datelocale'}).'</b>',
1.1 raeburn 2193: input => 'selectbox',
2194: },
2195: );
2196: my $datatable;
2197: my $count = 0;
2198: foreach my $item (@{$ordered}) {
2199: $count ++;
2200: $datatable .= &item_table_row_start($items{$item}{text},$count);
2201: if ($item eq 'timezone') {
2202: my $includeempty = 1;
2203: my $timezone = &Apache::lonlocal::gettimezone();
2204: $datatable .=
2205: &Apache::loncommon::select_timezone($item,$timezone,undef,
2206: $includeempty);
2207: } elsif ($item eq 'datelocale') {
2208: my $includeempty = 1;
2209: my $locale_obj = &Apache::lonlocal::getdatelocale();
2210: my $currdatelocale;
2211: if (ref($locale_obj)) {
2212: $currdatelocale = $locale_obj->id();
2213: }
2214: $datatable .=
2215: &Apache::loncommon::select_datelocale($item,$currdatelocale,
2216: undef,$includeempty);
2217: } else {
2218: if ($settings->{$item} eq '') {
2219: $datatable .=
1.3 raeburn 2220: &Apache::loncommon::select_language('languages_0','',1);
1.1 raeburn 2221: } else {
2222: my $num = 0;
1.3 raeburn 2223: my @languages = split(/\s*[,;:]\s*/,$settings->{$item});
1.1 raeburn 2224: $datatable .= &Apache::loncommon::start_data_table();
2225: if (@languages > 0) {
1.3 raeburn 2226: my %langchoices = &get_lang_choices();
1.1 raeburn 2227: foreach my $lang (@languages) {
2228: my $showlang = $lang;
1.3 raeburn 2229: if (exists($langchoices{$lang})) {
2230: $showlang = $langchoices{$lang};
1.1 raeburn 2231: }
2232: $datatable .=
2233: &Apache::loncommon::start_data_table_row().
1.3 raeburn 2234: '<td align="left"><span class="LC_nobreak">'.
1.1 raeburn 2235: &mt('Language:').'<b> '.$showlang.
2236: '</b><input type="hidden" name="languages_'.$num.
2237: '" value="'.$lang.'" /></span><br />'.
2238: '<span class="LC_nobreak"><label><input type="checkbox" '.
2239: 'name="languages_delete" value="'.$num.'" />'.
2240: &mt('Delete').'</label></span></td>'.
1.3 raeburn 2241: &Apache::loncommon::end_data_table_row();
1.1 raeburn 2242: $num ++;
2243: }
2244: }
2245: $datatable .= &Apache::loncommon::start_data_table_row().
1.3 raeburn 2246: '<td align="left"><span class="LC_nobreak">'.
2247: &mt('Additional language:'). '</span><br />'.
2248: &Apache::loncommon::select_language('languages_'.$num,'',1).
1.1 raeburn 2249: '<input type="hidden" name="languages_total" value="'.$num.'" />'.
2250: '</td>'.&Apache::loncommon::end_data_table_row().
2251: &Apache::loncommon::end_data_table();
2252: }
2253: }
2254: $datatable .= &item_table_row_end();
2255: }
2256: $$rowtotal += scalar(@{$ordered});
2257: return $datatable;
2258: }
2259:
1.3 raeburn 2260: sub get_lang_choices {
2261: my %langchoices;
2262: foreach my $id (&Apache::loncommon::languageids()) {
2263: my $code = &Apache::loncommon::supportedlanguagecode($id);
2264: if ($code) {
2265: $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id);
2266: }
2267: }
2268: return %langchoices;
2269: }
2270:
1.1 raeburn 2271: sub print_feedback {
1.3 raeburn 2272: my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
2273: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2274: return;
2275: }
2276: my %items = (
1.3 raeburn 2277: 'question.email' => {
2278: text => '<b>'.&mt($itemtext->{'question.email'}).'</b>',
1.1 raeburn 2279: input => 'textbox',
2280: size => '50',
2281: },
2282:
1.3 raeburn 2283: 'comment.email' => {
2284: text => '<b>'.&mt($itemtext->{'comment.email'}).'</b>',
1.1 raeburn 2285: input => 'textbox',
2286: size => '50',
2287: },
2288:
1.3 raeburn 2289: 'policy.email' => {
2290: text => '<b>'.&mt($itemtext->{'policy.email'}).'</b>',
1.1 raeburn 2291: input => 'textbox',
2292: size => '50',
2293: },
2294: );
2295: my $datatable;
2296: my $count = 0;
2297: my ($cnum) = &get_course();
2298: my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
2299: my @sections = sort( { $a <=> $b } keys(%sections));
2300: my %lt = &Apache::lonlocal::texthash (
1.21 raeburn 2301: currone => 'Current recipient:',
2302: currmult => 'Current recipients:',
2303: add => 'Additional recipient:',
2304: del => 'Delete?',
2305: sec => 'Sections:',
1.1 raeburn 2306: );
2307:
2308: foreach my $item (@{$ordered}) {
2309: $count ++;
1.28.2.1 raeburn 2310: $datatable .= &item_table_row_start($items{$item}{text},$count);
1.1 raeburn 2311: if ($position eq 'top') {
2312: my $includeempty = 0;
2313: $datatable .= &user_table($cdom,$item,\@sections,
1.3 raeburn 2314: $settings->{$item},\%lt);
1.1 raeburn 2315: } else {
1.3 raeburn 2316: $datatable .= &Apache::lonhtmlcommon::textbox($item.'.text',
1.28.2.1 raeburn 2317: $settings->{$item.'.text'},$items{$item}{size});
1.1 raeburn 2318: }
2319: $datatable .= &item_table_row_end();
2320: }
2321: $$rowtotal += scalar(@{$ordered});
2322: return $datatable;
2323: }
2324:
2325: sub user_table {
2326: my ($cdom,$item,$sections,$currvalue,$lt) = @_;
2327: my $output;
2328: if ($currvalue eq '') {
2329: $output .= &select_recipient($item,'0',$cdom,$sections);
2330: } else {
2331: my $num = 0;
2332: my @curr = split(/,/,$currvalue);
1.10 raeburn 2333: $output .= '<table class="LC_nested_outer">';
1.1 raeburn 2334: my ($currusers);
2335: foreach my $val (@curr) {
2336: next if ($val eq '');
2337: my ($uname,$udom,$seclist) = ($val =~ /^($match_username):($match_domain)(\(?[^\)]*\)?)$/);
2338: my @selsec;
2339: if ($seclist) {
2340: $seclist =~ s/(^\(|\)$)//g;
2341: @selsec = split(/\s*;\s*/,$seclist);
2342: }
2343: $currusers .= '<tr>'.
2344: '<td valign="top"><span class="LC_nobreak">'.
2345: '<label><input type="checkbox" '.
2346: 'name="'.$item.'_delete" value="'.$num.'" />'.
2347: $lt->{'del'}.'</label>'.
2348: '<input type="hidden" name="'.$item.'_user_'.
1.3 raeburn 2349: $num.'" value="'.$uname.':'.$udom.'" />'.(' 'x2).
1.1 raeburn 2350: &Apache::loncommon::aboutmewrapper(
2351: &Apache::loncommon::plainname($uname,$udom,'firstname'),
2352: $uname,$udom,'aboutuser');
2353: if (ref($sections) eq 'ARRAY') {
2354: if (@{$sections}) {
2355: $currusers.= (' 'x3).$lt->{'sec'}.' '.
2356: &select_sections($item,$num,$sections,
2357: \@selsec);
2358: }
2359: }
2360: $currusers .= '</span></td></tr>';
2361: $num ++;
2362: }
2363: if ($num) {
1.10 raeburn 2364: $output .= '<tr>'.
1.1 raeburn 2365: '<td align="left"><i>';
1.20 faziophi 2366: if ($num == 1) {
1.1 raeburn 2367: $output .= $lt->{'currone'};
2368: } else {
1.21 raeburn 2369: $output .= $lt->{'currmult'};
1.1 raeburn 2370: }
2371: $output .= '</i><br />'.
2372: '<table>'.$currusers.'</table></td>'.
1.10 raeburn 2373: '</tr>';
1.1 raeburn 2374: }
1.10 raeburn 2375: $output .= '<tr>'.
1.1 raeburn 2376: '<td align="left"><span class="LC_nobreak"><i>'.
2377: $lt->{'add'}.'</i></span><br />'.
2378: &select_recipient($item,$num,$cdom,$sections).
2379: '<input type="hidden" name="'.$item.'_total" value="'.$num.'" />'.
1.10 raeburn 2380: '</td></tr></table>';
1.1 raeburn 2381: }
2382: return $output;
2383: }
2384:
2385: sub select_recipient {
2386: my ($item,$num,$cdom,$sections,$selected,$includeempty) = @_;
2387: my $domform = &Apache::loncommon::select_dom_form($cdom,$item.'_udom_'.$num,$includeempty);
2388: my $selectlink =
2389: &Apache::loncommon::selectstudent_link('display',$item.'_uname_'.$num,
2390: $item.'_udom_'.$num,1);
2391: my $output =
1.10 raeburn 2392: '<table><tr><td align="center">'.&mt('Username').'<br />'.
1.1 raeburn 2393: '<input type="text" name="'.$item.'_uname_'.$num.'" value="" /></td>'.
2394: '<td align="center">'.&mt('Domain').'<br />'.$domform.'</td>';
2395: if (ref($sections) eq 'ARRAY') {
2396: if (@{$sections}) {
2397: $output .= '<td align="center">'.&mt('Sections').'<br />'.
2398: &select_sections($item,$num,$sections,$selected).'</td>';
2399: }
2400: }
2401: $output .= '<td valign="top">'.
2402: $selectlink.'</td></tr></table>';
2403: return $output;
2404: }
2405:
2406: sub select_sections {
2407: my ($item,$num,$sections,$selected) = @_;
2408: my ($output,@currsecs,$allsec);
2409: if (ref($selected) eq 'ARRAY') {
2410: @currsecs = @{$selected};
2411: }
2412: if (!@currsecs) {
2413: $allsec = ' selected="selected"';
2414: }
2415: if (ref($sections) eq 'ARRAY') {
2416: if (@{$sections}) {
2417: my $mult;
2418: if (@{$sections} > 1) {
2419: $mult = ' multiple="multiple"';
2420: if (@{$sections} > 3) {
2421: $mult .= ' size="4"';
2422: }
2423: }
2424: $output = '<select name="'.$item.'_sections_'.$num.'"'.$mult.'>'.
2425: ' <option value=""'.$allsec.'>'.&mt('All').'</option>';
2426: foreach my $sec (@{$sections}) {
2427: my $is_sel;
2428: if ((@currsecs) && (grep(/^\Q$sec\E$/,@currsecs))) {
2429: $is_sel = 'selected="selected"';
2430: }
2431: $output .= '<option value="'.$sec.'"'.$is_sel.'>'.$sec.'</option>';
2432: }
2433: $output .= '</select>';
2434: }
2435: }
2436: return $output;
2437: }
2438:
2439: sub print_discussion {
1.3 raeburn 2440: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
2441: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2442: return;
2443: }
2444: my %items = (
2445: 'plc.roles.denied' => {
1.10 raeburn 2446: text => '<span class="LC_nobreak"><b>'.&mt($itemtext->{'plc.roles.denied'}).'</b>'.
2447: &Apache::loncommon::help_open_topic("Course_Disable_Discussion").'</span><br />'.
1.5 raeburn 2448: &mt('(role-based)'),
1.1 raeburn 2449: input => 'checkbox',
2450: },
2451:
2452: 'plc.users.denied' => {
1.3 raeburn 2453: text => '<b>'.&mt($itemtext->{'plc.users.denied'}).'</b><br />'.
2454: &mt('(specific user(s))'),
1.1 raeburn 2455: input => 'checkbox',
2456: },
2457:
2458: 'pch.roles.denied' => {
1.10 raeburn 2459: text => '<span class="LC_nobreak"><b>'.&mt($itemtext->{'pch.roles.denied'}).'</b>'.
2460: &Apache::loncommon::help_open_topic("Course_Disable_Discussion").'</span><br />'.
1.3 raeburn 2461: &mt('(role-based)'),
1.1 raeburn 2462: input => 'checkbox',
2463: },
2464:
2465: 'pch.users.denied' => {
1.3 raeburn 2466: text => '<b>'.&mt($itemtext->{'pch.users.denied'}).'</b><br />'.
2467: &mt('(specific user(s))'),
1.1 raeburn 2468: input => 'checkbox',
2469: },
2470: 'allow_limited_html_in_feedback' => {
1.3 raeburn 2471: text => '<b>'.&mt($itemtext->{'allow_limited_html_in_feedback'}).'</b>',
1.1 raeburn 2472: input => 'radio',
2473: },
2474:
2475: 'allow_discussion_post_editing' => {
1.3 raeburn 2476: text => '<b>'.&mt($itemtext->{'allow_discussion_post_editing'}).'</b>',
1.1 raeburn 2477: input => 'checkbox',
2478: },
2479: );
2480: my $datatable;
2481: my $count;
2482: my ($cnum) = &get_course();
2483: my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
2484: my @sections = sort( { $a <=> $b } keys(%sections));
2485: my %lt = &Apache::lonlocal::texthash (
1.21 raeburn 2486: currone => 'Disallowed:',
2487: currmult => 'Disallowed:',
2488: add => 'Disallow more:',
2489: del => 'Delete?',
2490: sec => 'Sections:',
1.1 raeburn 2491: );
2492:
2493: foreach my $item (@{$ordered}) {
2494: $count ++;
2495: $datatable .= &item_table_row_start($items{$item}{text},$count);
2496: if ($item eq 'plc.roles.denied') {
2497: $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
2498: '</table>';
2499: } elsif ($item eq 'plc.users.denied') {
2500: $datatable .= &user_table($cdom,$item,undef,
2501: $settings->{$item},\%lt);
2502: } elsif ($item eq 'pch.roles.denied') {
2503: $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
2504: '</table>';
2505: } elsif ($item eq 'pch.users.denied') {
2506: $datatable .= &user_table($cdom,$item,undef,
2507: $settings->{$item},\%lt);
2508: } elsif ($item eq 'allow_limited_html_in_feedback') {
2509: $datatable .= &yesno_radio($item,$settings);
2510: } elsif ($item eq 'allow_discussion_post_editing') {
2511: $datatable .= &Apache::loncommon::start_data_table().
2512: &Apache::loncommon::start_data_table_row().
2513: '<th align="left">'.&mt('Role').'</th><th>'.
2514: &mt('Sections').'</th>'.
2515: &Apache::loncommon::end_data_table_row().
2516: &role_checkboxes($cdom,$cnum,$item,$settings,1).
2517: &Apache::loncommon::end_data_table();
2518: }
2519: $datatable .= &item_table_row_end();
2520: }
2521: $$rowtotal += scalar(@{$ordered});
2522: return $datatable;
2523: }
2524:
2525: sub role_checkboxes {
1.9 raeburn 2526: my ($cdom,$cnum,$item,$settings,$showsections,$crstype) = @_;
2527: my @roles = ('st','ad','ta','ep','in');
2528: if ($crstype eq 'Community') {
2529: push(@roles,'co');
2530: } else {
2531: push(@roles,'cc');
2532: }
1.1 raeburn 2533: my $output;
2534: my (@current,@curr_roles,%currsec,@sections);
2535: if ($showsections) {
2536: my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
2537: @sections = sort( { $a <=> $b } keys(%sections));
2538: }
2539: if (ref($settings) eq 'HASH') {
2540: if ($settings->{$item}) {
2541: @current = split(',',$settings->{$item});
2542: if ($showsections) {
2543: foreach my $role (@current) {
2544: if ($role =~ /:/) {
2545: my ($trole,$sec) = split(':',$role);
2546: push(@curr_roles,$trole);
2547: if (ref($currsec{$trole}) eq 'ARRAY') {
2548: if (!grep(/^\Q$sec\E/,@{$currsec{$trole}})) {
2549: push(@{$currsec{$trole}},$sec);
2550: }
1.3 raeburn 2551: } else {
2552: $currsec{$trole} = [$sec];
1.1 raeburn 2553: }
2554: } else {
2555: push(@curr_roles,$role);
2556: }
2557: }
2558: @current = @curr_roles;
2559: }
2560: }
2561: }
2562: my $numinrow = 3;
2563: my $count = 0;
2564: foreach my $role (@roles) {
2565: my $checked = '';
2566: if (grep(/^\Q$role\E$/,@current)) {
2567: $checked = ' checked="checked" ';
2568: }
1.9 raeburn 2569: my $plrole=&Apache::lonnet::plaintext($role,$crstype);
1.1 raeburn 2570: if ($showsections) {
2571: $output .= &Apache::loncommon::start_data_table_row();
2572: } else {
2573: my $rem = $count%($numinrow);
2574: if ($rem == 0) {
2575: if ($count > 0) {
2576: $output .= '</tr>';
2577: }
2578: $output .= '<tr>';
2579: }
2580: }
1.28.2.2 raeburn 2581: $output .= '<td align="left"><span class="LC_nobreak"><label><input type="checkbox" name="'.
1.1 raeburn 2582: $item.'" value="'.$role.'"'.$checked.'/> '.
2583: $plrole.'</label></span></td>';
2584: if ($showsections) {
2585: $output .= '<td align="left">'.
2586: &select_sections($item,$role,\@sections,$currsec{$role}).
2587: '</td></tr>';
2588: }
2589: $count ++;
2590: }
2591: my %adv_roles =
2592: &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
2593: my $total = @roles;
2594: foreach my $role (sort(keys(%adv_roles))) {
2595: if ($role =~ m{^cr/($match_domain)/($match_name)/\w$}) {
2596: my $rolename = $3;
2597: my $value = 'cr_'.$1.'_'.$2.'_'.$rolename;
2598: my $checked = '';
2599: if (grep(/^\Q$value\E$/,@current)) {
2600: $checked = ' checked="checked" ';
2601: }
2602: if ($showsections) {
2603: $output .= &Apache::loncommon::start_data_table_row();
2604: } else {
2605: my $rem = $count%($numinrow);
2606: if ($rem == 0) {
2607: if ($count > 0) {
2608: $output .= '</tr>';
2609: }
2610: $output .= '<tr>';
2611: }
2612: }
1.28.2.2 raeburn 2613: $output .= '<td><span class="LC_nobreak"><label><input type="checkbox" name="'.
1.1 raeburn 2614: $item.'" value="'.$value.'"'.$checked.' /> '.$rolename.
2615: '</label></span></td>';
2616: if ($showsections) {
2617: $output .= '<td>'.
2618: &select_sections($item,$role,\@sections,$currsec{$role}).
2619: '</td>'.&Apache::loncommon::end_data_table_row();
2620: }
2621: $total ++;
2622: $count ++;
2623: }
2624: }
2625: if (!$showsections) {
2626: my $rem = $total%($numinrow);
2627: my $colsleft = $numinrow - $rem;
2628: if ($colsleft > 1 ) {
2629: $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
2630: ' </td>';
2631: } elsif ($colsleft == 1) {
2632: $output .= '<td class="LC_left_item"> </td>';
2633: }
2634: $output .= '</tr>';
2635: }
2636: return $output;
2637: }
2638:
2639: sub print_classlists {
1.9 raeburn 2640: my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype) = @_;
1.1 raeburn 2641: my @ordered;
2642: if ($position eq 'top') {
2643: @ordered = ('default_enrollment_start_date',
2644: 'default_enrollment_end_date');
2645: } elsif ($position eq 'middle') {
2646: @ordered = ('nothideprivileged');
2647: } else {
2648: @ordered = ('student_classlist_view',
1.26 raeburn 2649: 'student_classlist_opt_in',
2650: 'student_classlist_portfiles');
1.1 raeburn 2651: }
1.9 raeburn 2652: my %lt;
2653:
2654: if ($crstype eq 'Community') {
2655: %lt = &Apache::lonlocal::texthash (
2656: disabled => 'No viewable membership list',
2657: section => "Membership of viewer's section",
2658: all => 'List of all members',
2659: );
2660: } else {
2661: %lt = &Apache::lonlocal::texthash (
2662: disabled => 'No viewable classlist',
2663: section => "Classlist of viewer's section",
2664: all => 'Classlist of all students',
2665: );
2666: }
2667:
1.1 raeburn 2668: my %items = (
2669: 'default_enrollment_start_date' => {
1.3 raeburn 2670: text => '<b>'.&mt($itemtext->{'default_enrollment_start_date'}).'</b>',
1.1 raeburn 2671: input => 'dates',
2672: },
2673: 'default_enrollment_end_date' => {
1.3 raeburn 2674: text => '<b>'.&mt($itemtext->{'default_enrollment_end_date'}).'</b>',
1.1 raeburn 2675: input => 'dates',
2676: },
2677:
2678: 'nothideprivileged' => {
1.3 raeburn 2679: text => '<b>'.&mt($itemtext->{'nothideprivileged'}).'</b>',
1.1 raeburn 2680: input => 'checkbox',
2681: },
2682:
2683: 'student_classlist_view' => {
1.3 raeburn 2684: text => '<b>'.&mt($itemtext->{'student_classlist_view'}).'</b>',
1.1 raeburn 2685: input => 'selectbox',
1.9 raeburn 2686: options => \%lt,
1.1 raeburn 2687: order => ['disabled','all','section'],
2688: },
1.26 raeburn 2689: 'student_classlist_opt_in' => {
2690: text => '<b>'.&mt($itemtext->{'student_classlist_opt_in'}).'</b>',
1.1 raeburn 2691: input => 'radio',
2692: },
2693:
2694: 'student_classlist_portfiles' => {
1.3 raeburn 2695: text => '<b>'.&mt($itemtext->{'student_classlist_portfiles'}).'</b>',
1.1 raeburn 2696: input => 'radio',
2697: },
2698: );
2699: unless (($settings->{'student_classlist_view'} eq 'all') ||
2700: ($settings->{'student_classlist_view'} eq 'section')) {
2701: $settings->{'student_classlist_view'} = 'disabled';
2702: }
1.9 raeburn 2703: return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype);
1.1 raeburn 2704: }
2705:
2706: sub print_appearance {
1.9 raeburn 2707: my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3 raeburn 2708: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2709: return;
2710: }
1.9 raeburn 2711: my $mathdef;
2712: if ($crstype eq 'Community') {
2713: $mathdef = &mt("None specified - use member's choice");
2714: } else {
2715: $mathdef = &mt("None specified - use student's choice");
2716: }
1.1 raeburn 2717: my %items = (
2718: 'default_xml_style' => {
1.3 raeburn 2719: text => '<b>'.&mt($itemtext->{'default_xml_style'}).'</b> '.
1.1 raeburn 2720: '<a href="javascript:openbrowser'.
2721: "('display','default_xml_style'".
2722: ",'sty')".'">'.&mt('Select Style File').'</a>',
2723: input => 'textbox',
2724: size => 35,
2725: },
2726:
2727: 'pageseparators' => {
1.3 raeburn 2728: text => '<b>'.&mt($itemtext->{'pageseparators'}).'</b>',
1.1 raeburn 2729: input => 'radio',
2730: },
2731: 'disable_receipt_display' => {
1.3 raeburn 2732: text => '<b>'.&mt($itemtext->{'disable_receipt_display'}).'</b>',
1.1 raeburn 2733: input => 'radio',
2734: },
2735: 'texengine' => {
1.3 raeburn 2736: text => '<b>'.&mt($itemtext->{'texengine'}).'</b>',
1.1 raeburn 2737: input => 'selectbox',
2738: options => {
2739: jsMath => 'jsMath',
2740: mimetex => &mt('Convert to Images'),
2741: tth => &mt('TeX to HTML'),
2742: },
2743: order => ['jsMath','mimetex','tth'],
1.9 raeburn 2744: nullval => $mathdef,
1.1 raeburn 2745: },
2746: 'tthoptions' => {
1.3 raeburn 2747: text => '<b>'.&mt($itemtext->{'tthoptions'}).'</b>',
1.1 raeburn 2748: input => 'textbox',
2749: size => 40,
2750: },
2751: );
1.9 raeburn 2752: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1 raeburn 2753: }
2754:
2755: sub print_grading {
1.9 raeburn 2756: my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3 raeburn 2757: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2758: return;
2759: }
2760: my %items = (
2761: 'grading' => {
1.3 raeburn 2762: text => '<b>'.&mt($itemtext->{'grading'}).'</b>'.
1.1 raeburn 2763: &Apache::loncommon::help_open_topic('GradingOptions'),
2764: input => 'selectbox',
2765: options => {
2766: standard => &mt('Standard: shows points'),
1.11 www 2767: external => &mt('External: shows number of completed parts and totals'),
2768: externalnototals => &mt('External: shows only number of completed parts'),
1.1 raeburn 2769: spreadsheet => &mt('Spreadsheet: (with link to detailed scores)'),
2770: },
1.11 www 2771: order => ['standard','external','externalnototals','spreadsheet'],
1.1 raeburn 2772: },
2773: 'rndseed' => {
1.3 raeburn 2774: text => '<b>'.&mt($itemtext->{'rndseed'}).'</b>'.
1.17 faziophi 2775: '<span class="LC_warning">'.'<br />'.
1.1 raeburn 2776: &mt('Modifying this will make problems have different numbers and answers!').
2777: '</span>',
2778: input => 'selectbox',
2779: options => {
2780: '32bit' => '32bit',
2781: '64bit' => '64bit',
2782: '64bit2' => '64bit2',
2783: '64bit3' => '64bit3',
2784: '64bit4' => '64bit4',
2785: '64bit5' => '64bit5',
2786: },
2787: order => ['32bit','64bit','64bit2','64bit3','64bit4','64bit5'],
2788: },
2789: 'receiptalg' => {
1.3 raeburn 2790: text => '<b>'.&mt($itemtext->{'receiptalg'}).'</b><br />'.
1.5 raeburn 2791: &mt('This controls how receipt numbers are generated'),
1.1 raeburn 2792: input => 'selectbox',
2793: options => {
2794: receipt => 'receipt',
2795: receipt2 => 'receipt2',
2796: receipt3 => 'receipt3',
2797: },
2798: order => ['receipt','receipt2','receipt3'],
2799: },
2800: 'disablesigfigs' => {
1.3 raeburn 2801: text => '<b>'.&mt($itemtext->{'disablesigfigs'}).'</b>',
1.1 raeburn 2802: input => 'radio',
2803: },
2804: );
1.9 raeburn 2805: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1 raeburn 2806: }
2807:
2808: sub print_printouts {
1.9 raeburn 2809: my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3 raeburn 2810: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2811: return;
2812: }
2813: my %items = (
2814: problem_stream_switch => {
1.3 raeburn 2815: text => '<b>'.&mt($itemtext->{'problem_stream_switch'}).'</b>',
1.1 raeburn 2816: input => 'radio',
2817: },
2818: suppress_tries => {
1.3 raeburn 2819: text => '<b>'.&mt($itemtext->{'suppress_tries'}).'</b>',
1.1 raeburn 2820: input => 'radio',
2821: },
2822: default_paper_size => {
1.3 raeburn 2823: text => '<b>'.&mt($itemtext->{'default_paper_size'}).'</b>',
1.1 raeburn 2824: input => 'selectbox',
2825: options => {
2826: Letter => &mt('Letter').' [8 1/2x11 in]',
2827: Legal => &mt('Legal').' [8 1/2x14 in]',
2828: Tabloid => &mt('Tabloid').' [11x17 in]',
2829: Executive => &mt('Executive').' [7 1/2x10 in]',
2830: A2 => &mt('A2').' [420x594 mm]',
2831: A3 => &mt('A3').' [297x420 mm]',
2832: A4 => &mt('A4').' [210x297 mm]',
2833: A5 => &mt('A5').' [148x210 mm]',
2834: A6 => &mt('A6').' [105x148 mm]',
2835: },
2836: order => ['Letter','Legal','Tabloid','Executive','A2','A3','A4','A5','A6'],
2837: nullval => 'None specified',
2838: },
2839: print_header_format => {
1.3 raeburn 2840: text => '<b>'.&mt($itemtext->{'print_header_format'}).'</b>',
1.1 raeburn 2841: input => 'checkbox',
2842: },
2843: disableexampointprint => {
1.3 raeburn 2844: text => '<b>'.&mt($itemtext->{'disableexampointprint'}).'</b>',
1.1 raeburn 2845: input => 'radio',
2846: },
1.14 raeburn 2847: canuse_pdfforms => {
2848: text => '<b>'.&mt($itemtext->{'canuse_pdfforms'}).'</b>',
2849: input => 'selectbox',
2850: options => {
2851: 1 => &mt('Yes'),
2852: 0 => &mt('No'),
2853: },
2854: order => ['1','0'],
2855: nullval => 'None specified - use domain default',
2856: }
1.1 raeburn 2857: );
1.9 raeburn 2858: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1 raeburn 2859: }
2860:
2861: sub print_spreadsheet {
1.9 raeburn 2862: my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3 raeburn 2863: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2864: return;
2865: }
2866: my $SelectSpreadsheetFile=&mt('Select Spreadsheet File');
2867: my %items = (
2868: spreadsheet_default_classcalc => {
1.3 raeburn 2869: text => '<b>'.&mt($itemtext->{'spreadsheet_default_classcalc'}).'</b> '.
1.1 raeburn 2870: '<span class="LC_nobreak"><a href="javascript:openbrowser'.
2871: "('display','spreadsheet_default_classcalc'".
2872: ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
2873: input => 'textbox',
2874: },
2875: spreadsheet_default_studentcalc => {
1.3 raeburn 2876: text => '<b>'.&mt($itemtext->{'spreadsheet_default_studentcalc'}).'</b> '.
1.1 raeburn 2877: '<span class="LC_nobreak"><a href="javascript:openbrowser'.
2878: "('display','spreadsheet_default_calc'".
2879: ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
2880: input => 'textbox',
2881: },
2882: spreadsheet_default_assesscalc => {
1.3 raeburn 2883: text => '<b>'.&mt($itemtext->{'spreadsheet_default_assesscalc'}).'</b> '.
1.1 raeburn 2884: '<span class="LC_nobreak"><a href="javascript:openbrowser'.
2885: "('display','spreadsheet_default_assesscalc'".
2886: ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
2887: input => 'textbox',
2888: },
2889: hideemptyrows => {
1.3 raeburn 2890: text => '<b>'.&mt($itemtext->{'hideemptyrows'}).'</b>',
1.1 raeburn 2891: input => 'radio',
2892: },
2893: );
1.9 raeburn 2894: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
2895: }
1.1 raeburn 2896:
2897: sub print_bridgetasks {
1.9 raeburn 2898: my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype) = @_;
1.3 raeburn 2899: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2900: return;
2901: }
1.9 raeburn 2902: my ($stumsg,$msgnote);
2903: if ($crstype eq 'Community') {
2904: $stumsg = &mt('Send message to member');
2905: $msgnote = &mt('Message to member and add to user notes');
2906: } else {
2907: $stumsg = &mt('Send message to student');
2908: $msgnote = &mt('Message to student and add to user notes');
2909: }
1.1 raeburn 2910: my %items = (
2911: task_messages => {
1.3 raeburn 2912: text => '<b>'.&mt($itemtext->{'task_messages'}).'</b>',
1.1 raeburn 2913: input => 'selectbox',
2914: options => {
1.9 raeburn 2915: only_student => $stumsg,
2916: student_and_user_notes_screen => $msgnote,
1.1 raeburn 2917: },
2918: order => ['only_student','student_and_user_notes_screen'],
2919: nullval => &mt('No message or record in user notes'),
2920: },
2921: task_grading => {
1.3 raeburn 2922: text => '<b>'.&mt($itemtext->{'task_grading'}).'</b>',
1.1 raeburn 2923: input => 'selectbox',
2924: options => {
2925: any => &mt('Grade BTs in any section'),
2926: section => &mt('Grade BTs only in own section')
2927: },
2928: order => ['any','section'],
2929: },
2930: suppress_embed_prompt => {
1.3 raeburn 2931: text => '<b>'.&mt($itemtext->{'suppress_embed_prompt'}).'</b><span class="LC_nobreak">'.
2932: ' '.&mt('(applies when current role is student)').'</span>',
1.1 raeburn 2933: input => 'radio',
2934: },
2935: );
1.9 raeburn 2936: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype);
1.1 raeburn 2937: }
2938:
2939: sub print_other {
1.9 raeburn 2940: my ($cdom,$settings,$allitems,$rowtotal,$crstype) = @_;
1.1 raeburn 2941: unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
2942: return;
2943: }
1.3 raeburn 2944: my @ordered = &get_other_items($cdom,$settings,$allitems);
2945: my %items;
2946: foreach my $parameter (@ordered) {
2947: $items{$parameter} = {
2948: text => '<b>'.$parameter.'</b>',
2949: input => 'textbox',
2950: size => '15',
2951: },
2952: }
2953: push (@ordered,'newp_value');
2954: $items{'newp_value'} = {
2955: text => '<b>'.&mt('Create New Environment Variable').'</b><br />'.
2956: '<input type="textbox" name="newp_name"'.
2957: ' value="" size="30" />',
2958: input => 'textbox',
2959: size => '30',
2960: };
1.9 raeburn 2961: my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype);
1.3 raeburn 2962: }
2963:
2964: sub get_other_items {
2965: my ($cdom,$settings,$allitems) = @_;
2966: unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
2967: return;
2968: }
1.1 raeburn 2969: my @ordered;
2970: if (ref($settings) eq 'HASH') {
2971: foreach my $parameter (sort(keys(%{$settings}))) {
2972: next if (grep/^\Q$parameter\E$/,@{$allitems});
1.3 raeburn 2973: next if (($parameter eq 'course.helper.not.run') &&
2974: (!exists($env{'user.role.dc./'.$env{'request.role.domain'}.'/'})));
1.1 raeburn 2975: unless (($parameter =~ m/^internal\./)||($parameter =~ m/^metadata\./) ||
2976: ($parameter =~ m/^selfenroll_/) || ($parameter =~ /_selfenroll$/)
2977: || ($parameter eq 'type') ||
1.9 raeburn 2978: ($parameter =~ m/^(cc|co|in|ta|ep|ad|st)\.plaintext$/)) {
1.1 raeburn 2979: push(@ordered,$parameter);
2980: }
2981: }
2982: }
1.3 raeburn 2983: return @ordered;
1.1 raeburn 2984: }
2985:
2986: sub item_table_row_start {
1.19 faziophi 2987: my ($text,$count,$add_class) = @_;
1.1 raeburn 2988: my $output;
1.19 faziophi 2989: my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
2990: $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
2991: $output .= '<tr class="'.$css_class.'">'."\n";;
1.1 raeburn 2992: $output .= '<td class="LC_left_item">'.$text.
1.19 faziophi 2993: '</td><td class="LC_right_item">';
1.1 raeburn 2994: return $output;
2995: }
2996:
2997: sub item_table_row_end {
2998: return '</td></tr>';
2999: }
3000:
3001: sub yesno_radio {
3002: my ($item,$settings) = @_;
3003: my $itemon = ' ';
3004: my $itemoff = ' checked="checked" ';
3005: if (ref($settings) eq 'HASH') {
3006: if ($settings->{$item} eq 'yes') {
3007: $itemon = $itemoff;
3008: $itemoff = ' ';
3009: }
3010: }
3011: return '<span class="LC_nobreak"><label>'.
3012: '<input type="radio" name="'.$item.'"'.
3013: $itemon.' value="yes" />'.&mt('Yes').'</label> '.
3014: '<label><input type="radio" name="'.$item.'"'.
3015: $itemoff.' value="" />'.&mt('No').'</label></span>';
3016: }
3017:
3018: sub select_from_options {
3019: my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange) = @_;
3020: my $output;
3021: if ((ref($order) eq 'ARRAY') && (ref($options) eq 'HASH')) {
3022: $output='<select name="'.$item.'" '.$onchange;
3023: if ($multiple) {
3024: $output .= ' multiple="multiple"';
3025: my $num = @{$order};
3026: $num ++ if ($nullval ne '');
3027: if (($maxsize) && ($maxsize < $num)) {
3028: $output .= ' size="'.$maxsize.'"';
3029: }
3030: }
3031: $output .= '>'."\n";
3032: if ($nullval ne '') {
3033: $output .= '<option value=""';
3034: if (ref($curr) eq 'ARRAY') {
3035: if ((@{$curr} == 0) || (grep(/^$/,@{$curr}))) {
3036: $output .= ' selected="selected" ';
3037: }
3038: } else {
3039: if ($curr eq '') {
3040: $output .= ' selected="selected" ';
3041: }
3042: }
3043: $output .= '>'.$nullval.'</option>';
3044: }
3045: foreach my $option (@{$order}) {
3046: $output.= '<option value="'.$option.'"';
3047: if (ref($curr) eq 'ARRAY') {
3048: if (grep(/^\Q$option\E$/,@{$curr})) {
3049: $output .= ' selected="selected" ';
3050: }
3051: } else {
3052: if ($option eq $curr) {
3053: $output.=' selected="selected"';
3054: }
3055: }
3056: $output.=">$options->{$option}</option>\n";
3057: }
3058: $output.="</select>";
3059: }
3060: return $output;
3061: }
3062:
3063: sub make_item_rows {
1.9 raeburn 3064: my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype) = @_;
1.1 raeburn 3065: my $datatable;
3066: if ((ref($items) eq 'HASH') && (ref($ordered) eq 'ARRAY')) {
3067: my $count = 0;
3068: foreach my $item (@{$ordered}) {
3069: $count ++;
3070: $datatable .= &item_table_row_start($items->{$item}{text},$count);
3071: if ($item eq 'nothideprivileged') {
1.9 raeburn 3072: $datatable .= ¬hidepriv_row($cdom,$item,$settings,$crstype);
1.1 raeburn 3073: } elsif ($item eq 'print_header_format') {
3074: $datatable .= &print_hdrfmt_row($item,$settings);
3075: } elsif ($items->{$item}{input} eq 'dates') {
3076: $datatable .=
3077: &Apache::lonhtmlcommon::date_setter('display',$item,
3078: $settings->{$item});
3079: } elsif ($items->{$item}{input} eq 'radio') {
3080: $datatable .= &yesno_radio($item,$settings);
3081: } elsif ($items->{$item}{input} eq 'selectbox') {
3082: my $curr = $settings->{$item};
3083: $datatable .=
3084: &select_from_options($item,$items->{$item}{'order'},
3085: $items->{$item}{'options'},$curr,
3086: $items->{$item}{'nullval'});
3087: } elsif ($items->{$item}{input} eq 'textbox') {
3088: $datatable .=
3089: &Apache::lonhtmlcommon::textbox($item,$settings->{$item},
3090: $items->{$item}{size});
3091: }
3092: $datatable .= &item_table_row_end();
3093: }
3094: if (ref($rowtotal)) {
3095: $$rowtotal += scalar(@{$ordered});
3096: }
3097: }
3098: return $datatable;
3099: }
3100:
3101: sub nothidepriv_row {
1.9 raeburn 3102: my ($cdom,$item,$settings,$crstype) = @_;
1.1 raeburn 3103: my ($cnum) = &get_course();
3104: my %nothide;
3105: my $datatable;
3106: if (ref($settings) eq 'HASH') {
3107: if ($settings->{$item} ne '') {
3108: foreach my $user (split(/\s*\,\s*/,$settings->{$item})) {
3109: if ($user !~ /:/) {
3110: $nothide{join(':',split(/[\@]/,$user))}=1;
3111: } else {
3112: $nothide{$user} = 1;
3113: }
3114: }
3115: }
3116: }
3117: my %coursepersonnel = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
3118: my $now = time;
3119: my @privusers;
1.3 raeburn 3120: my %privileged;
1.1 raeburn 3121: foreach my $person (keys(%coursepersonnel)) {
3122: my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/);
3123: $user =~ s/:$//;
3124: my ($end,$start) = split(/:/,$coursepersonnel{$person});
3125: if ($end == -1 || $start == -1) {
3126: next;
3127: }
3128: my ($uname,$udom) = split(':',$user);
1.3 raeburn 3129: unless (ref($privileged{$udom}) eq 'HASH') {
3130: my %dompersonnel = &Apache::lonnet::get_domain_roles($udom,['dc'],undef,$now);
3131: $privileged{$udom} = {};
3132: if (keys(%dompersonnel)) {
3133: foreach my $server (keys(%dompersonnel)) {
3134: foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
3135: my ($trole,$uname,$udom) = split(/:/,$user);
3136: $privileged{$udom}{$uname} = $trole;
3137: }
3138: }
3139: }
3140: }
3141: if (exists($privileged{$udom}{$uname})) {
1.7 raeburn 3142: unless (grep(/^\Q$user\E$/,@privusers)) {
3143: push(@privusers,$user);
3144: }
1.1 raeburn 3145: }
3146: }
3147: if (@privusers) {
3148: $datatable .= '<table align="right">';
3149: foreach my $user (sort(@privusers)) {
3150: my $hideon = ' checked="checked" ';
3151: my $hideoff = '';
3152: if ($nothide{$user}) {
3153: $hideoff = $hideon;
3154: $hideon = '';
3155: }
3156: my ($uname,$udom) = split(':',$user);
3157: $datatable .= '<tr><td align="left">'.
3158: &Apache::loncommon::aboutmewrapper(
3159: &Apache::loncommon::plainname($uname,$udom,'firstname'),
3160: $uname,$udom,'aboutuser').
3161: '</td><td align="left">'.
3162: '<span class="LC_nobreak"><label>'.
3163: '<input type="radio" name="'.$item.'_'.$user.'"'.
1.7 raeburn 3164: $hideon.' value="" />'.&mt('Hidden').'</label> '.
3165: '<label><input type="radio" name="'.$item.'_'.$user.'"'. $hideoff.' value="yes" />'.&mt('Shown').'</label></span></td>'.
1.1 raeburn 3166: '</tr>';
3167: }
3168: $datatable .= '</table>';
3169: } else {
1.9 raeburn 3170: if ($crstype eq 'Community') {
3171: $datatable .= &mt('No Domain Coordinators have community roles');
3172: } else {
3173: $datatable .= &mt('No Domain Coordinators have course roles');
3174: }
1.1 raeburn 3175: }
3176: return $datatable;
3177: }
3178:
3179: sub print_hdrfmt_row {
3180: my ($item,$settings) = @_;
3181: my @curr;
3182: my $currnum = 0;
3183: my $maxnum = 2;
3184: my $currstr;
3185: if ($settings->{$item} ne '') {
3186: $currstr .= '<b>'.&mt('Current print header:').' <span class="LC_warning"><tt>'.
3187: $settings->{$item}.'</tt></span></b><br />';
3188: my @current = split(/(%\d*[nca])/,$settings->{$item});
1.23 raeburn 3189: foreach my $val (@current) {
3190: unless ($val eq '') {
3191: push(@curr,$val);
1.1 raeburn 3192: }
3193: }
3194: $currnum = @curr;
3195: $maxnum += $currnum;
3196: }
3197:
3198: my $output = <<ENDJS;
3199:
3200: <script type="text/javascript" language="Javascript">
3201:
3202: function reOrder(chgnum) {
3203: var maxnum = $maxnum;
3204: var oldidx = 'printfmthdr_oldpos_'+chgnum;
3205: var newidx = 'printfmthdr_pos_'+chgnum;
3206: oldidx = getIndexByName(oldidx);
3207: newidx = getIndexByName(newidx);
3208: var oldpos = document.display.elements[oldidx].value;
3209: var newpos = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
3210: document.display.elements[oldidx].value = newpos;
3211: var chgtype = 'up';
3212: if (newpos < oldpos) {
3213: chgtype = 'down';
3214: }
3215: for (var j=0; j<maxnum; j++) {
3216: if (j != chgnum) {
3217: oldidx = 'printfmthdr_oldpos_'+j;
3218: newidx = 'printfmthdr_pos_'+j;
3219: oldidx = getIndexByName(oldidx);
3220: newidx = getIndexByName(newidx);
3221: var currpos = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
3222: var currsel = document.display.elements[newidx].selectedIndex;
3223: if (chgtype == 'up') {
3224: if ((currpos > oldpos) && (currpos <= newpos)) {
3225: document.display.elements[newidx].selectedIndex = currsel-1;
3226: document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
3227: }
3228: } else {
3229: if ((currpos >= newpos) && (currpos < oldpos)) {
3230: document.display.elements[newidx].selectedIndex = currsel+1;
3231: document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
3232: }
3233: }
3234: }
3235: }
3236: return;
3237: }
3238:
3239: function getIndexByName(item) {
3240: for (var i=0;i<document.display.elements.length;i++) {
3241: if (document.display.elements[i].name == item) {
3242: return i;
3243: }
3244: }
3245: return -1;
3246: }
3247:
3248: </script>
3249:
3250: ENDJS
1.10 raeburn 3251: $output .= $currstr.'<table class="LC_nested_outer">';
1.1 raeburn 3252: if (@curr > 0) {
3253: for (my $i=0; $i<@curr; $i++) {
3254: my $pos = $i+1;
1.10 raeburn 3255: $output .= '<tr>'.
1.1 raeburn 3256: '<td align="left"><span class="LC_nobreak">'.
3257: &position_selector($pos,$i,$maxnum).&mt('Delete:').
3258: '<input type="checkbox" name="printfmthdr_del_'.$i.
3259: '" /></span></td>';
3260: if ($curr[$i] =~ /^%\d*[nca]$/) {
3261: my ($limit,$subst) = ($curr[$i] =~ /^%(\d*)([nca])$/);
3262: $output .= '<td align="left">'.
3263: &substitution_selector($i,$subst,$limit).'</td>';
3264: } else {
3265: $output .= '<td colspan="2" align="left">'.&mt('Text').'<br />'.
3266: '<input type="textbox" name="printfmthdr_text_'.$i.'"'.
3267: ' value="'.$curr[$i].'" size="25" /></td>';
3268: }
1.10 raeburn 3269: $output .= '</tr>';
1.1 raeburn 3270: }
3271: }
3272: my $pos = $currnum+1;
1.10 raeburn 3273: $output .= '<tr>'.
1.1 raeburn 3274: '<td align="left"><span class="LC_nobreak">'.
3275: &position_selector($pos,$currnum,$maxnum).
3276: '<b>'.&mt('New').'</b></span></td><td align="left">'.
3277: &substitution_selector($currnum).'</td>'.
1.10 raeburn 3278: '</tr>';
1.1 raeburn 3279: $pos ++;
3280: $currnum ++;
1.10 raeburn 3281: $output .= '<tr>'.
1.1 raeburn 3282: '<td align="left"><span class="LC_nobreak">'.
3283: &position_selector($pos,$currnum,$maxnum).
3284: '<b>'.&mt('New').'</b></span></td>'.
3285: '<td colspan="2" align="left">'.&mt('Text').'<br />'.
3286: '<input type="textbox" name="printfmthdr_text_'.$currnum.
1.3 raeburn 3287: '" value="" size ="25" />'.
3288: '<input type="hidden" name="printfmthdr_maxnum" value="'.
3289: $maxnum.'" /></td>'.
1.10 raeburn 3290: '</tr>'.
3291: '</table>';
1.1 raeburn 3292: return $output;
3293: }
3294:
3295: sub position_selector {
3296: my ($pos,$num,$maxnum) = @_;
3297: my $output = '<select name="printfmthdr_pos_'.$num.'" onchange="reOrder('."'$num'".');">';
3298: for (my $j=1; $j<=$maxnum; $j++) {
3299: my $sel = '';
3300: if ($pos == $j) {
3301: $sel = ' selected="selected"';
3302: }
3303: $output .= '<option value="'.$j.'"'.$sel.'">'.$j.'</option>';
3304: }
3305: $output .= '</select><input type="hidden" name="printfmthdr_oldpos_'.$num.
3306: '" value="'.$pos.'" />';
3307: return $output;
3308: }
3309:
3310: sub substitution_selector {
1.9 raeburn 3311: my ($num,$subst,$limit,$crstype) = @_;
3312: my ($stunametxt,$crsidtxt);
3313: if ($crstype eq 'Community') {
3314: $stunametxt = 'member name';
3315: $crsidtxt = 'community ID',
3316: } else {
3317: $stunametxt = 'student name';
3318: $crsidtxt = 'course ID',
3319: }
1.1 raeburn 3320: my %lt = &Apache::lonlocal::texthash(
1.9 raeburn 3321: n => $stunametxt,
3322: c => $crsidtxt,
1.1 raeburn 3323: a => 'assignment note',
3324: );
3325: my $output .= &mt('Substitution').'<br />'.
1.28.2.2 raeburn 3326: '<select name="printfmthdr_sub_'.$num.'">';
1.1 raeburn 3327: if ($subst eq '') {
3328: $output .= '<option value="" selected="selected"> </option>';
3329: }
3330: foreach my $field ('n','c','a') {
3331: my $sel ='';
3332: if ($subst eq $field) {
3333: $sel = ' selected="selected"';
3334: }
3335: $output .= '<option value="'.$field.'"'.$sel.'>'.
3336: $lt{$field}.'</option>';
3337: }
3338: $output .= '</select></td><td align="left">'.&mt('Size limit').'<br />'.
3339: '<input type="textbox" name="printfmthdr_limit_'.$num.
3340: '" value="'.$limit.'" size="5" /></span>';
3341: return $output;
3342: }
3343:
1.23 raeburn 3344: sub change_clone {
3345: my ($cdom,$cnum,$clonelist,$oldcloner) = @_;
3346: my $clone_crs = $cnum.':'.$cdom;
3347: if ($cnum && $cdom) {
3348: my $clone_crs = $cnum.':'.$cdom;
3349: my @allowclone;
3350: if ($clonelist =~ /,/) {
3351: @allowclone = split(',',$clonelist);
3352: } else {
3353: $allowclone[0] = $clonelist;
3354: }
3355: foreach my $currclone (@allowclone) {
3356: if (!grep(/^$currclone$/,@$oldcloner)) {
3357: if ($currclone ne '*') {
3358: my ($uname,$udom) = split(/:/,$currclone);
3359: if ($uname && $udom && $uname ne '*') {
3360: if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
3361: my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable');
3362: if ($currclonecrs{'cloneable'} !~ /\Q$clone_crs\E/) {
3363: if ($currclonecrs{'cloneable'} eq '') {
3364: $currclonecrs{'cloneable'} = $clone_crs;
3365: } else {
3366: $currclonecrs{'cloneable'} .= ','.$clone_crs;
3367: }
3368: &Apache::lonnet::put('environment',\%currclonecrs,$udom,$uname);
3369: }
3370: }
3371: }
3372: }
3373: }
3374: }
3375: foreach my $oldclone (@$oldcloner) {
3376: if (!grep(/^\Q$oldclone\E$/,@allowclone)) {
3377: if ($oldclone ne '*') {
3378: my ($uname,$udom) = split(/:/,$oldclone);
3379: if ($uname && $udom && $uname ne '*' ) {
3380: if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
3381: my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable');
3382: my %newclonecrs = ();
3383: if ($currclonecrs{'cloneable'} =~ /\Q$clone_crs\E/) {
3384: if ($currclonecrs{'cloneable'} =~ /,/) {
3385: my @currclonecrs = split/,/,$currclonecrs{'cloneable'};
3386: foreach my $crs (@currclonecrs) {
3387: if ($crs ne $clone_crs) {
3388: $newclonecrs{'cloneable'} .= $crs.',';
3389: }
3390: }
3391: $newclonecrs{'cloneable'} =~ s/,$//;
3392: } else {
3393: $newclonecrs{'cloneable'} = '';
3394: }
3395: &Apache::lonnet::put('environment',\%newclonecrs,$udom,$uname);
3396: }
3397: }
3398: }
3399: }
3400: }
3401: }
3402: }
3403: return;
3404: }
3405:
1.1 raeburn 3406: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>