Annotation of loncom/interface/courseprefs.pm, revision 1.3
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.3 ! raeburn 4: # $Id: courseprefs.pm,v 1.2 2009/04/26 00:43:14 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:
31: package Apache::courseprefs;
32:
33: use strict;
34: use Apache::Constants qw(:common :http);
35: use Apache::lonnet;
36: use Apache::loncommon();
37: use Apache::lonhtmlcommon();
38: use Apache::lonconfigsettings;
39: use Apache::lonlocal;
40: use LONCAPA qw(:DEFAULT :match);
41:
42: sub handler {
43: my $r=shift;
44: if ($r->header_only) {
45: &Apache::loncommon::content_type($r,'text/html');
46: $r->send_http_header;
47: return OK;
48: }
49: my $context = 'course';
50: my $cid = $env{'request.course.id'};
51: my ($cnum,$cdom) = &get_course($cid);
52: my $crstype = &Apache::loncommon::course_type();
53: my $parm_permission = &Apache::lonnet::allowed('opa',$cid);
54: my $navmap = Apache::lonnavmaps::navmap->new();
55: if ($parm_permission && $navmap) {
56: &Apache::loncommon::content_type($r,'text/html');
57: $r->send_http_header;
58: } else {
59: if ($navmap) {
60: $env{'user.error.msg'}=
1.2 raeburn 61: "/adm/courseprefs:opa:0:0:Cannot modify course settings";
1.1 raeburn 62: } else {
63: $env{'user.error.msg'}=
64: "/adm/courseprefs::0:1:Course environment gone, reinitialize the course";
65: }
66: return HTTP_NOT_ACCEPTABLE;
67: }
68:
69: &Apache::lonhtmlcommon::clear_breadcrumbs();
70: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs',
71: text=>"Course Configuration"});
72: my $breadcrumbs =
73: &Apache::lonhtmlcommon::breadcrumbs('Edit Course Configuration');
74:
75: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
76: ['phase','actions']);
77:
78: my $phase = 'pickactions';
79: if ( exists($env{'form.phase'}) ) {
80: $phase = $env{'form.phase'};
81: }
82:
83: if ($phase eq 'categorizecourse') {
84: &assign_course_categories($r);
85: return OK;
86: }
87:
88: my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
89: my @prefs_order = ('courseinfo','localization','feedback','discussion',
90: 'classlists','appearance','grading','printouts',
91: 'spreadsheet','bridgetasks','other');
92:
93: my %prefs = (
94: 'courseinfo' =>
95: { text => 'General course settings',
96: help => 'Course_Environment',
97: header => [{col1 => 'Setting',
98: col2 => 'Value'}],
99: ordered => ['description','courseid','categories',
100: 'hidefromcat','cloners','externalsyllabus',
101: 'url','rolenames'],
1.3 ! raeburn 102: itemtext => {
! 103: description => 'Course Description',
! 104: courseid => 'Course ID or number',
! 105: categories => 'Categorize course',
! 106: hidefromcat => 'Exclude from course catalog',
! 107: cloners => 'Users allowed to clone course',
! 108: externalsyllabus => 'URL of Syllabus',
! 109: url => 'Top Level Map',
! 110: rolenames => 'Replacement titles for standard course roles',
! 111: },
1.1 raeburn 112: },
113: 'localization' =>
114: { text => 'Language/TimeZone/Locale',
115: help => 'Course_Environment',
116: header => [{col1 => 'Setting',
117: col2 => 'Value',}],
118: ordered => ['languages','timezone','datelocale'],
1.3 ! raeburn 119: itemtext => {
! 120: languages => 'Languages used',
! 121: timezone => 'Timezone in which the course takes place',
! 122: datelocale => 'Locale used for course calendar',
! 123: },
1.1 raeburn 124: },
125: 'feedback' =>
126: { text => 'Feedback messages',
127: help => 'Course_Environment',
128: header => [{col1 => 'Questions about:',
129: col2 => 'Recipients'},
130: {col1 => 'Questions about:',
131: col2 => 'Custom Text'}],
1.3 ! raeburn 132: ordered => ['question.email','comment.email','policy.email'],
! 133: itemtext => {
! 134: 'question.email' => 'Resource Content',
! 135: 'comment.email' => 'Course Content',
! 136: 'policy.email' => 'Course Policy',
! 137: },
1.1 raeburn 138: },
139: 'discussion' =>
140: { text => 'Discussion and Chat',
141: help => 'Course_Environment',
142: header => [{col1 => 'Setting',
143: col2 => 'Value',}],
144: ordered => ['plc.roles.denied','plc.users.denied',
145: 'pch.roles.denied','pch.users.denied',
146: 'allow_limited_html_in_feedback',
147: 'allow_discussion_post_editing'],
1.3 ! raeburn 148: itemtext => {
! 149: 'plc.roles.denied' => 'No Resource Discussion',
! 150: 'plc.users.denied' => 'No Resource Discussion',
! 151: 'pch.roles.denied' => 'No Chat room use',
! 152: 'pch.users.denied' => 'No Chat room use',
! 153: allow_limited_html_in_feedback => 'Allow limited HTML in discussion posts',
! 154: allow_discussion_post_editing => 'Users can edit/delete own discussion posts',
! 155: },
1.1 raeburn 156: },
157: 'classlists' =>
158: { text => 'Classlists and Staff Listing',
159: help => 'Course_Environment',
160: header => [{col1 => 'Type',
161: col2 => 'Default dates for student access'},
162: {col1 => 'Setting',
163: col2 => 'Privileged users (Domain Coordinators) in staff listing'},
164: {col1 => 'Setting',
165: col2 => 'Student-viewable classlist options'}],
166: ordered => ['default_enrollment_start_date',
167: 'default_enrollment_end_date',
168: 'nothideprivileged','student_classlist_view',
169: 'student_opt_in','student_classlist_portfiles'],
1.3 ! raeburn 170: itemtext => {
! 171: default_enrollment_start_date => 'Start date',
! 172: default_enrollment_end_date => 'End date',
! 173: nothideprivileged => 'Domain Coodinators in course',
! 174: student_classlist_view => 'Student-viewable classlist',
! 175: student_opt_in => 'Student agreement needed to be listed',
! 176: student_classlist_portfiles => 'Include link to accessible portfolio files',
! 177: },
1.1 raeburn 178: },
179: 'appearance' =>
180: { text => 'Display of resources ',
181: help => 'Course_Environment',
182: header => [{col1 => 'Setting',
183: col2 => 'Value'}],
184: ordered => ['default_xml_style','pageseparators',
185: 'disable_receipt_display','texengine',
186: 'tthoptions'],
1.3 ! raeburn 187: itemtext => {
! 188: default_xml_style => 'Default XML Style File',
! 189: pageseparators => 'Visibly Separate Items on Pages',
! 190: disable_receipt_display => 'Disable display of problem receipts',
! 191: texengine => 'Force use of a specific math rendering engine.',
! 192: tthoptions => 'Default set of options to pass to tth/m when converting TeX',
! 193: },
1.1 raeburn 194: },
195: 'grading' =>
196: { text => 'Grading',
197: help => 'Course_Environment',
198: header => [{col1 => 'Setting',
199: col2 => 'Value',}],
200: ordered => ['grading','rndseed',
201: 'receiptalg','disablesigfigs'],
1.3 ! raeburn 202: itemtext => {
! 203: grading => 'Grading',
! 204: rndseed => 'Randomization algorithm used',
! 205: receiptalg => 'Receipt algorithm used',
! 206: disablesigfigs => 'Disable checking of Significant Figures',
! 207: },
! 208:
1.1 raeburn 209: },
210: 'printouts' =>
211: { text => 'Printout generation',
212: help => 'Course_Environment',
213: header => [{col1 => 'Setting',
214: col2 => 'Value',}],
215: ordered => ['problem_stream_switch','suppress_tries',
216: 'default_paper_size','print_header_format',
217: 'disableexampointprint'],
1.3 ! raeburn 218: itemtext => {
! 219: problem_stream_switch => 'Allow problems to be split over pages',
! 220: suppress_tries => 'Suppress number of tries in printing',
! 221: default_paper_size => 'Default paper type',
! 222: print_header_format => 'Print header format',
! 223: disableexampointprint => 'Disable automatically printing point values on exams',
! 224: },
1.1 raeburn 225: },
226: 'spreadsheet' =>
227: { text => 'Spreadsheets',
228: help => 'Course_Environment',
229: header => [{col1 => 'Setting',
230: col2 => 'Value'}],
231: ordered => ['spreadsheet_default_classcalc',
232: 'spreadsheet_default_studentcalc',
233: 'spreadsheet_default_assesscalc','hideemptyrows'],
1.3 ! raeburn 234: itemtext => {
! 235: spreadsheet_default_classcalc => 'Default Course Spreadsheet',
! 236: spreadsheet_default_studentcalc => 'Default Student Spreadsheet',
! 237: spreadsheet_default_assesscalc => 'Default Assessment Spreadsheet',
! 238: hideemptyrows => 'Hide Empty Rows in Spreadsheets',
! 239: },
1.1 raeburn 240: },
241: 'bridgetasks' =>
242: { text => 'Bridge tasks',
243: help => 'Course_Environment',
244: header => [{col1 => 'Setting',
245: col2 => 'Value'}],
246: ordered => ['task_messages','task_grading',
247: 'suppress_embed_prompt'],
1.3 ! raeburn 248: itemtext => {
! 249: task_messages => 'Send message to student when clicking Done on Tasks',
! 250: task_grading => 'Bridge Task grading by instructors and TAs in sections' ,
! 251: suppress_embed_prompt => 'Hi$de upload references prompt if uploading file to portfolio',
! 252: },
1.1 raeburn 253: },
254: 'other' =>
255: { text => 'Other settings',
256: help => 'Course_Environment',
257: header => [ {col1 => 'Item',
258: col2 => 'Value',
259: }],
260: },
261: );
262: if ($phase eq 'process') {
1.3 ! raeburn 263: my @allitems = &get_allitems(%prefs);
1.1 raeburn 264: &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context,
1.3 ! raeburn 265: \@prefs_order,\%prefs,\%values,
! 266: $cnum,undef,\@allitems);
1.1 raeburn 267: } elsif ($phase eq 'display') {
1.3 ! raeburn 268: my $jscript = &get_jscript($cdom,$phase);
! 269: my @allitems = &get_allitems(%prefs);
1.1 raeburn 270: &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,
271: \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems);
272: } else {
273: &Apache::lonconfigsettings::display_choices($r,$phase,$context,
274: \@prefs_order,\%prefs);
275: }
276: return OK;
277: }
278:
1.3 ! raeburn 279: sub get_allitems {
! 280: my (%prefs) = @_;
! 281: my @allitems;
! 282: foreach my $item (keys(%prefs)) {
! 283: if (ref($prefs{$item}) eq 'HASH') {
! 284: if (ref($prefs{$item}{'ordered'}) eq 'ARRAY') {
! 285: push(@allitems,@{$prefs{$item}{'ordered'}});
! 286: if ($item eq 'feedback') {
! 287: push(@allitems,(map { $_.'.text'; } @{$prefs{$item}{'ordered'}}));
! 288: }
! 289: }
! 290: }
! 291: }
! 292: return @allitems;
! 293: }
! 294:
1.1 raeburn 295: sub print_config_box {
296: my ($r,$cdom,$phase,$action,$item,$settings,$allitems) = @_;
297: my $ordered = $item->{'ordered'};
1.3 ! raeburn 298: my $itemtext = $item->{'itemtext'};
1.1 raeburn 299: my $rowtotal = 0;
300: my $output =
301: '<table class="LC_nested_outer">
302: <tr>
303: <th align="left" valign="middle"><span class="LC_font_larger">'.
304: &mt($item->{text}).' '.
305: &Apache::loncommon::help_open_topic($item->{'help'}).'</span></th>'."\n".
306: '</tr>';
307: if (($action eq 'feedback') || ($action eq 'classlists')) {
308: $output .= '
309: <tr>
310: <td>
311: <table class="LC_nested">
312: <tr class="LC_info_row">
313: <td class="LC_left_item">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
314: <td class="LC_right_item">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
315: </tr>';
316: $rowtotal ++;
317: if ($action eq 'feedback') {
1.3 ! raeburn 318: $output .= &print_feedback('top',$cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 319: } elsif ($action eq 'classlists') {
1.3 ! raeburn 320: $output .= &print_classlists('top',$cdom,$settings,$itemtext,\$rowtotal);
1.1 raeburn 321: }
322: $output .= '
323: </table>
324: </td>
325: </tr>
326: <tr>
327: <td>
328: <table class="LC_nested">
329: <tr class="LC_info_row">
330: <td class="LC_left_item">'.&mt($item->{'header'}->[1]->{'col1'}).'</td>';
331: $output .= '
332: <td class="LC_right_item">'.&mt($item->{'header'}->[1]->{'col2'}).'</td>
333: </tr>';
334: if ($action eq 'classlists') {
1.3 ! raeburn 335: $output .= &print_classlists('middle',$cdom,$settings,$itemtext,\$rowtotal).
1.1 raeburn 336: '
337: </table>
338: </td>
339: </tr>
340: <tr>
341: <td>
342: <table class="LC_nested">
343: <tr class="LC_info_row">
344: <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[2]->{'col1'}).'</td>
345: <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[2]->{'col2'}).'</td>
346: </tr>';
347: }
348: } else {
349: $output .= '
350: <tr>
351: <td>
352: <table class="LC_nested">
353: <tr class="LC_info_row">
354: <td class="LC_left_item" valign="top">'.&mt($item->{'header'}->[0]->{'col1'}).'</td>
355: <td class="LC_right_item" valign="top">'.&mt($item->{'header'}->[0]->{'col2'}).'</td>
356: </tr>';
357: }
358: $rowtotal ++;
359: if ($action eq 'courseinfo') {
1.3 ! raeburn 360: $output .= &print_courseinfo($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 361: } elsif ($action eq 'localization') {
1.3 ! raeburn 362: $output .= &print_localization($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 363: } elsif ($action eq 'feedback') {
1.3 ! raeburn 364: $output .= &print_feedback('bottom',$cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 365: } elsif ($action eq 'discussion') {
1.3 ! raeburn 366: $output .= &print_discussion($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 367: } elsif ($action eq 'classlists') {
1.3 ! raeburn 368: $output .= &print_classlists('bottom',$cdom,$settings,$itemtext,\$rowtotal);
1.1 raeburn 369: } elsif ($action eq 'appearance') {
1.3 ! raeburn 370: $output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 371: } elsif ($action eq 'grading') {
1.3 ! raeburn 372: $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 373: } elsif ($action eq 'printouts') {
1.3 ! raeburn 374: $output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 375: } elsif ($action eq 'spreadsheet') {
1.3 ! raeburn 376: $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 377: } elsif ($action eq 'bridgetasks') {
1.3 ! raeburn 378: $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal);
1.1 raeburn 379: } elsif ($action eq 'other') {
380: $output .= &print_other($cdom,$settings,$allitems,\$rowtotal);
381: }
382: $output .= '
383: </table>
384: </td>
385: </tr>
386: </table><br />';
387: return ($output,$rowtotal);
388: }
389:
390: sub process_changes {
1.3 ! raeburn 391: my ($cdom,$action,$values,$item,$changes,$allitems,$disallowed) = @_;
! 392: my %newvalues;
! 393: if (ref($item) eq 'HASH') {
! 394: if (ref($changes) eq 'HASH') {
! 395: my @ordered;
! 396: if ($action eq 'other') {
! 397: @ordered = &get_other_items($cdom,$values,$allitems);
! 398: if ($env{'form.newp_name'} ne '') {
! 399: my $newp = $env{'form.newp_name'};
! 400: if ($env{'form.newp_value'} ne '') {
! 401: if (ref($allitems) eq 'ARRAY') {
! 402: unless ((grep(/^\Q$newp\E$/,@ordered)) ||
! 403: (grep(/^\Q$newp\E$/,@{$allitems}))) {
! 404: $changes->{$newp} = $env{'form.newp_value'};
! 405: }
! 406: }
! 407: }
! 408: }
! 409: } elsif (ref($item->{'ordered'}) eq 'ARRAY') {
! 410: @ordered = @{$item->{'ordered'}};
! 411: }
! 412: if (@ordered > 0) {
! 413: if ($action eq 'feedback') {
! 414: foreach my $entry (@ordered) {
! 415: my $userstr = '';
! 416: my $total = $env{'form.'.$entry.'_total'};
! 417: if ($total) {
! 418: my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
! 419: for (my $i=0; $i<$total; $i++) {
! 420: unless (grep(/^$i$/,@deletes)) {
! 421: $userstr .= $env{'form.'.$entry.'_user_'.$i}.
! 422: &get_sec_str($entry,$i).',';
! 423: }
! 424: }
! 425: } else {
! 426: $total = 0;
! 427: }
! 428: if ($env{'form.'.$entry.'_uname_'.$total} ne '') {
! 429: my $uname = $env{'form.'.$entry.'_uname_'.$total};
! 430: my $udom = $env{'form.'.$entry.'_udom_'.$total};
! 431: if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') {
! 432: $userstr =~ s/,$//;
! 433: $disallowed->{'feedback'}{$entry} = $uname.':'.$udom;
! 434: } else {
! 435: $userstr .= $uname.':'.$udom.&get_sec_str($entry,$total);
! 436: }
! 437: } else {
! 438: $userstr =~ s/,$//;
! 439: }
! 440: $newvalues{$entry} = $userstr;
! 441: if ($newvalues{$entry} ne $values->{$entry}) {
! 442: $changes->{$entry} = $newvalues{$entry};
! 443: }
! 444: my $ext_entry = $entry.'.text';
! 445: $newvalues{$ext_entry} = $env{'form.'.$ext_entry};
! 446: if ($newvalues{$ext_entry} ne $values->{$ext_entry}) {
! 447: $changes->{$ext_entry} = $newvalues{$ext_entry};
! 448: }
! 449: }
! 450: } else {
! 451: foreach my $entry (@ordered) {
! 452: if ($entry eq 'cloners') {
! 453: if ($env{'form.cloners_all'}) {
! 454: $newvalues{$entry} = '*';
! 455: } else {
! 456: my @clonedoms;
! 457: if (exists($env{'form.cloners_activate'})) {
! 458: my $actnum = $env{'form.cloners_activate'};
! 459: if ($actnum ne '') {
! 460: if ($env{'form.clonersdom_'.$actnum} ne '') {
! 461: my $clonedom = $env{'form.clonersdom_'.$actnum};
! 462: if (&check_clone($clonedom,$disallowed) eq 'ok') {
! 463: $newvalues{$entry} = '*:'.$clonedom;
! 464: push(@clonedoms,$newvalues{$entry});
! 465: }
! 466: }
! 467: }
! 468: } else {
! 469: my $num = $env{'form.cloners_total'};
! 470: my @deletes =
! 471: &Apache::loncommon::get_env_multiple('form.cloners_delete');
! 472: for (my $i=0; $i<$num; $i++) {
! 473: if (!grep(/^$i$/,@deletes)) {
! 474: my $clonedom = $env{'form.cloners_dom_'.$i};
! 475: if (&check_clone($clonedom,$disallowed) eq 'ok') {
! 476: if (!grep(/^\*:\Q$clonedom\E$/,@clonedoms)) {
! 477: push (@clonedoms,'*:'.$clonedom);
! 478: }
! 479: }
! 480: }
! 481: }
! 482: if (@clonedoms) {
! 483: $newvalues{$entry}=join(',',@clonedoms);
! 484: }
! 485: }
! 486: if ($env{'form.cloners_newdom'} ne '') {
! 487: my $clonedom = $env{'form.cloners_newdom'};
! 488: if (&check_clone($clonedom,$disallowed) eq 'ok') {
! 489: my $newdom = '*:'.$env{'form.cloners_newdom'};
! 490: if (@clonedoms) {
! 491: if (!grep(/^\Q$newdom\E$/,@clonedoms)) {
! 492: $newvalues{$entry} .= ','.$newdom;
! 493: }
! 494: } else {
! 495: $newvalues{$entry} = $newdom;
! 496: }
! 497: }
! 498: }
! 499: if ($env{'form.'.$entry} ne '') {
! 500: my @cloners = split(',',$env{'form.'.$entry});
! 501: my @okcloners;
! 502: foreach my $cloner (@cloners) {
! 503: my ($uname,$udom) = split(':',$cloner);
! 504: if (&check_clone($udom,$disallowed,$uname) eq 'ok') {
! 505: if (!grep(/^\Q$cloner\E$/,@okcloners)) {
! 506: push(@okcloners,$cloner);
! 507: }
! 508: }
! 509: }
! 510: if (@okcloners) {
! 511: my $okclonestr = join(',',@okcloners);
! 512: if ($newvalues{$entry} ne '') {
! 513: $newvalues{$entry} .= ','.$okclonestr;
! 514: } else {
! 515: $newvalues{$entry} = $okclonestr;
! 516: }
! 517: }
! 518: }
! 519: }
! 520: if (ref($disallowed) eq 'HASH') {
! 521: if (ref($disallowed->{'cloners'}) eq 'HASH') {
! 522: foreach my $key (keys(%{$disallowed->{'cloners'}})) {
! 523: $disallowed->{'cloners'}{$key} =~ s/,$//;
! 524: }
! 525: }
! 526: }
! 527: } elsif ($entry =~ /^default_enrollment_(start|end)_date$/) {
! 528: $newvalues{$entry}=&Apache::lonhtmlcommon::get_date_from_form($entry);
! 529: } elsif ($entry eq 'rolenames') {
! 530: my $crstype = &Apache::loncommon::course_type();
! 531: my %adv_roles =
! 532: &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
! 533: my @stds = ('cc','in','ta','ep','ad','st');
! 534: my (@replacements,@regulars);
! 535: foreach my $role (@stds) {
! 536: if ($values->{$role.'.plaintext'} ne '') {
! 537: push(@replacements,$role);
! 538: } else {
! 539: push(@regulars,$role);
! 540: }
! 541: }
! 542: foreach my $stdrole (@stds) {
! 543: my $ext_entry = $entry.'_'.$stdrole;
! 544: my $stdname = &Apache::lonnet::plaintext($stdrole,$crstype,
! 545: $env{'request.course.id'},1);
! 546: if ($env{'form.'.$ext_entry} eq $stdname) {
! 547: $newvalues{$ext_entry} = '';
! 548: } else {
! 549: $newvalues{$ext_entry} = $env{'form.'.$ext_entry};
! 550: }
! 551: if ($newvalues{$ext_entry} ne $values->{$stdrole.'.plaintext'}) {
! 552: my $dupname = 0;
! 553: if ($newvalues{$ext_entry} ne '') {
! 554: my $dupname = 0;
! 555: if (grep(/^\Q$newvalues{$ext_entry}\E$/,@replacements)) {
! 556: $dupname = 1;
! 557: push(@{$disallowed->{'rolenames'}{'replacements'}},$newvalues{$ext_entry});
! 558: }
! 559: if (!$dupname) {
! 560: if (grep(/^\Q$newvalues{$ext_entry}\E$/,@regulars)) {
! 561: $dupname = 1;
! 562: push(@{$disallowed->{rolenames}{'regulars'}},$newvalues{$ext_entry});
! 563: }
! 564: }
! 565: if (!$dupname) {
! 566: foreach my $role (keys(%adv_roles)) {
! 567: if ($role =~ m{^cr/$match_domain/$match_name/\Q$newvalues{$ext_entry}\E$}) {
! 568: $dupname = 1;
! 569: push(@{$disallowed->{rolenames}{'customrole'}},$newvalues{$ext_entry});
! 570: last;
! 571: }
! 572: }
! 573: }
! 574: }
! 575: if (!$dupname) {
! 576: $changes->{$ext_entry} = $newvalues{$ext_entry};
! 577: }
! 578: }
! 579: }
! 580: } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied')) {
! 581: my @denied = &Apache::loncommon::get_env_multiple('form.'.$entry);
! 582: @denied = sort(@denied);
! 583: my $deniedstr = '';
! 584: if (@denied > 0) {
! 585: $deniedstr = join(',',@denied);
! 586: }
! 587: $newvalues{$entry} = $deniedstr;
! 588: } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied')) {
! 589: my $total = $env{'form.'.$entry.'_total'};
! 590: my $userstr = '';
! 591: my @denied;
! 592: if ($total > 0) {
! 593: my @deletes =
! 594: &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
! 595: for (my $i=0; $i<$total; $i++) {
! 596: unless (grep(/^$i$/,@deletes)) {
! 597: $userstr .= $env{'form.'.$entry.'_user_'.$i}.',';
! 598: push(@denied,$env{'form.'.$entry.'_user_'.$i});
! 599: }
! 600: }
! 601: } else {
! 602: $total = 0;
! 603: }
! 604: if ($env{'form.'.$entry.'_uname_'.$total} ne '') {
! 605: my $uname = $env{'form.'.$entry.'_uname_'.$total};
! 606: my $udom = $env{'form.'.$entry.'_udom_'.$total};
! 607: if (&Apache::lonnet::homeserver($uname,$udom) eq 'no_host') {
! 608: $userstr =~ s/,$//;
! 609: $disallowed->{'discussion'}{$entry} = $uname.':'.$udom;
! 610: } else {
! 611: my $newuser .= $uname.':'.$udom;
! 612: if (grep(/^\Q$newuser\E$/,@denied)) {
! 613: $userstr =~ s/,$//;
! 614: } else {
! 615: $userstr .= $newuser;
! 616: }
! 617: }
! 618: } else {
! 619: $userstr =~ s/,$//;
! 620: }
! 621: $newvalues{$entry} = $userstr;
! 622: } elsif ($entry eq 'allow_discussion_post_editing') {
! 623: my @canedit = &Apache::loncommon::get_env_multiple('form.'.$entry);
! 624: @canedit = sort(@canedit);
! 625: foreach my $role (@canedit) {
! 626: my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$role);
! 627: if ((grep(/^\s*$/,@secs)) || (@secs == 0)) {
! 628: $newvalues{$entry} .= $role.',';
! 629: } else {
! 630: foreach my $sec (@secs) {
! 631: $newvalues{$entry} .= $role.':'.$sec.',';
! 632: }
! 633: }
! 634: }
! 635: $newvalues{$entry} =~ s/,$//;
! 636: } elsif ($entry eq 'nothideprivileged') {
! 637: my @curr_nothide;
! 638: my @new_nothide;
! 639: if ($values->{$entry} ne '') {
! 640: foreach my $user (split(/\s*\,\s*/,$values->{$entry})) {
! 641: my $nothide;
! 642: if ($user !~ /:/) {
! 643: $nothide = join(':',split(/[\@]/,$user));
! 644: } else {
! 645: $nothide = $user;
! 646: }
! 647: if ((defined($nothide)) &&
! 648: (!grep(/^\Q$nothide\E$/,@curr_nothide))) {
! 649: push(@curr_nothide,$nothide);
! 650: }
! 651: }
! 652: }
! 653: foreach my $key (keys(%env)) {
! 654: if ($key =~ /^form\.\Q$entry\E_($match_username:$match_domain)$/) {
! 655: if ($env{'form.'.$key}) {
! 656: my $nothide = $1;
! 657: if (!grep(/^\Q$nothide\E$/,@new_nothide)) {
! 658: push(@new_nothide,$nothide);
! 659: }
! 660: }
! 661: }
! 662: }
! 663: @new_nothide = sort(@new_nothide);
! 664: my @differences =
! 665: &Apache::loncommon::compare_arrays(\@curr_nothide,
! 666: \@new_nothide);
! 667: if (@differences > 0) {
! 668: if (@new_nothide > 0) {
! 669: $newvalues{$entry} = join(',',@new_nothide);
! 670: } else {
! 671: $newvalues{$entry} = '';
! 672: }
! 673: } else {
! 674: $newvalues{$entry} = $values->{$entry};
! 675: }
! 676: } elsif ($entry eq 'print_header_format') {
! 677: my $maxnum = $env{'form.printfmthdr_maxnum'};
! 678: my @newhdr;
! 679: if ($maxnum > 2) {
! 680: for (my $i=0; $i<$maxnum-2; $i++) {
! 681: if ($env{'form.printfmthdr_del_'.$i}) {
! 682: $newhdr[$env{'form.printfmthdr_pos_'.$i}] = '';
! 683: } else {
! 684: my $hdr;
! 685: if ($env{'form.printfmthdr_sub_'.$i} =~ /^[nca]$/) {
! 686: $hdr = '%';
! 687: if ($env{'form.printfmthdr_limit_'.$i} =~ /^\d+$/) {
! 688: $hdr .= $env{'form.printfmthdr_limit_'.$i};
! 689: }
! 690: $hdr .= $env{'form.printfmthdr_sub_'.$i};
! 691: } elsif ($env{'form.printfmthdr_sub_'.$i} ne '') {
! 692: $hdr = $env{'form.printfmthdr_sub_'.$i};
! 693: }
! 694: $newhdr[$env{'form.printfmthdr_pos_'.$i}] = $hdr;
! 695: }
! 696: }
! 697: }
! 698: my $newsub = $maxnum-2;
! 699: if ($env{'form.printfmthdr_sub_'.$newsub} =~ /^[nca]$/) {
! 700: my $hdr = '%';
! 701: if ($env{'form.printfmthdr_limit_'.$newsub} =~ /^\d+$/) {
! 702: $hdr .= $env{'form.printfmthdr_limit_'.$newsub};
! 703: }
! 704: $hdr .= $env{'form.printfmthdr_sub_'.$newsub};
! 705: $newhdr[$env{'form.printfmthdr_pos_'.$newsub}] = $hdr;
! 706: }
! 707: my $newtext = $maxnum-1;
! 708: $newhdr[$env{'form.printfmthdr_pos_'.$newtext}] = $env{'form.printfmthdr_text_'.$newtext};
! 709: $newvalues{$entry} = join('',@newhdr);
! 710: } elsif ($entry eq 'languages') {
! 711: my $langstr;
! 712: my $total = $env{'form.'.$entry.'_total'};
! 713: if ($total) {
! 714: my @deletes = &Apache::loncommon::get_env_multiple('form.'.$entry.'_delete');
! 715: for (my $i=0; $i<$total; $i++) {
! 716: unless (grep(/^$i$/,@deletes)) {
! 717: $langstr .= $env{'form.'.$entry.'_'.$i}.',';
! 718: }
! 719: }
! 720: } else {
! 721: $total = 0;
! 722: }
! 723: if ($env{'form.'.$entry.'_'.$total} ne '') {
! 724: my $newlang = $env{'form.'.$entry.'_'.$total};
! 725: my %langchoices = &get_lang_choices();
! 726: if ($langchoices{$newlang}) {
! 727: $langstr .= $newlang;
! 728: } else {
! 729: $langstr =~ s/,$//;
! 730: $disallowed->{'localization'}{$entry} = $newlang;
! 731: }
! 732: } else {
! 733: $langstr =~ s/,$//;
! 734: }
! 735: $newvalues{$entry} = $langstr;
! 736: } else {
! 737: $newvalues{$entry} = $env{'form.'.$entry};
! 738: }
! 739: if ($newvalues{$entry} ne $values->{$entry}) {
! 740: $changes->{$entry} = $newvalues{$entry};
! 741: }
! 742: }
! 743: }
! 744: }
! 745: }
! 746: }
! 747: return;
! 748: }
! 749:
! 750: sub get_sec_str {
! 751: my ($entry,$num) = @_;
! 752: my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$num);
! 753: my $secstr;
! 754: if (grep(/^\s*$/,@secs)) {
! 755: $secstr = '';
! 756: } elsif (@secs > 0) {
! 757: $secstr = join(';',@secs);
! 758: }
! 759: if ($secstr ne '') {
! 760: return '('.$secstr.')';
! 761: }
! 762: return;
! 763: }
! 764:
! 765: sub check_clone {
! 766: my ($clonedom,$disallowed,$clonename) = @_;
! 767: return if (ref($disallowed) ne 'HASH');
! 768: if ($clonedom !~ /^$match_domain$/) {
! 769: $disallowed->{'cloners'}{'format'} .= $clonedom.',';
! 770: return;
! 771: } elsif (!&Apache::lonnet::domain($clonedom)) {
! 772: $disallowed->{'cloners'}{'domain'} .= $clonedom.',';
! 773: return;
! 774: }
! 775: if ($clonename ne '') {
! 776: if ($clonename !~ /^$match_username$/) {
! 777: $disallowed->{'cloners'}{'format'} .= $clonename.':'.$clonedom.',';
! 778: return;
! 779: } else {
! 780: if (&Apache::lonnet::homeserver($clonename,$clonedom) eq 'no_host') {
! 781: $disallowed->{'cloners'}{'newuser'} .= $clonename.':'.$clonedom.',';
! 782: return;
! 783: }
! 784: }
! 785: }
! 786: return 'ok';
! 787: }
! 788:
! 789: sub store_changes {
! 790: my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes) = @_;
! 791: my ($chome,$output);
! 792: my (%storehash,@delkeys,@need_env_update);
! 793: if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) {
! 794: %storehash = %{$values};
! 795: } else {
! 796: $output = &mt('No changes made to course settings.');
! 797: return;
! 798: }
! 799: my %yesno = (
! 800: hidefromcat => '1',
! 801: problem_stream_switch => '1',
! 802: suppress_tries => '1',
! 803: disableexampointprint => '1',
! 804: hideemptyrows => '1',
! 805: suppress_embed_prompt => '1',
! 806: );
! 807: foreach my $item (@{$prefs_order}) {
! 808: if (grep(/^\Q$item\E$/,@{$actions})) {
! 809: $output .= '<h3>'.&mt($prefs->{$item}{'text'}).'</h3>';
! 810: if (ref($changes->{$item}) eq 'HASH') {
! 811: if (keys(%{$changes->{$item}}) > 0) {
! 812: $output .= &mt('Changes made:').'<ul>';
! 813: if ($item eq 'other') {
! 814: foreach my $key (sort(keys(%{$changes->{$item}}))) {
! 815: $storehash{$key} = $changes->{$item}{$key};
! 816: if ($changes->{$item}{$key} eq '') {
! 817: push(@delkeys,$key);
! 818: $output .= '<li>'.&mt('Deleted setting for [_1]','<i>'.$key.'</i>').'</li>';
! 819: } else {
! 820: $output .= '<li>'.&mt('[_1] set to [_2]','<i>'.$key.'</i>',
! 821: "'$storehash{$key}'").'</li>';
! 822: }
! 823: }
! 824: } else {
! 825: if (ref($prefs->{$item}->{'ordered'}) eq 'ARRAY') {
! 826: my @settings = @{$prefs->{$item}->{'ordered'}};
! 827: if ($item eq 'feedback') {
! 828: push(@settings,(map { $_.'.text'; } @settings));
! 829: }
! 830: foreach my $key (@settings) {
! 831: if ($key eq 'rolenames') {
! 832: my $displayname = $prefs->{$item}->{'itemtext'}{$key};
! 833: my $crstype = &Apache::loncommon::course_type();
! 834: my $msg;
! 835: foreach my $role ('cc','in','ta','ep','ad','st') {
! 836: next if (!exists($changes->{$item}{$key.'_'.$role}));
! 837: my $stdname = &Apache::lonnet::plaintext($role,$crstype,undef,1);
! 838: my $newname = $changes->{$item}{$key.'_'.$role};
! 839: $storehash{$role.'.plaintext'} = $newname;
! 840: if ($newname eq '') {
! 841: $newname = $stdname;
! 842: }
! 843: $msg .= '<li>'.&mt('[_1] set to [_2]','<i>'.$stdname.'</i>',
! 844: "'<b>".$newname."</b>'").'</li>';
! 845: }
! 846: if ($msg ne '') {
! 847: $output .= '<li>'.&mt($displayname).'<ul>'.$msg.'</ul></li>';
! 848: }
! 849: } else {
! 850: next if (!exists($changes->{$item}{$key}));
! 851: my ($displayname,$text);
! 852: $text = $prefs->{$item}->{'itemtext'}{$key};
! 853: my $displayval = $changes->{$item}{$key};
! 854: if ($item eq 'feedback') {
! 855: if ($key =~ /^(question|policy|comment)(\.email)\.text$/) {
! 856: $text = $prefs->{$item}->{'itemtext'}{$1.$2};
! 857: $displayname = &mt('Custom text for '.$text.' questions');
! 858: } else {
! 859: $displayname = &mt('Recipients of '.$text.' questions');
! 860: }
! 861: } elsif ($item eq 'discussion') {
! 862: if ($key =~ /^p(lc|ch)\.roles\.denied/) {
! 863: $displayname = &mt("$text (role-based)");
! 864: if ($displayval ne '') {
! 865: my @roles = split(',',$displayval);
! 866: @roles = map { &Apache::lonnet::plaintext($_); } @roles;
! 867: $displayval = join(', ',@roles);
! 868: }
! 869: } elsif ($key =~ /^p(lc|ch)\.users\.denied/) {
! 870: $displayname = &mt("$text (specific user(s))");
! 871: } else {
! 872: if ($key eq 'allow_discussion_post_editing') {
! 873: if ($displayval ne '') {
! 874: my @roles = split(',',$displayval);
! 875: my @longroles;
! 876: foreach my $role (@roles) {
! 877: my ($trole,$sec) = split(':',$role);
! 878: my $rolename =
! 879: &Apache::lonnet::plaintext($trole);
! 880: if ($sec ne '') {
! 881: $rolename .= ':'.$sec;
! 882: }
! 883: push(@longroles,$rolename);
! 884: }
! 885: $displayval = join(', ',@longroles);
! 886: }
! 887: }
! 888: $displayname = &mt($text);
! 889: }
! 890: } elsif ($item eq 'spreadsheet') {
! 891: if ($key =~ /^spreadsheet_default_(studentcalc|assesscalc)$/x) {
! 892: my $sheettype = $1;
! 893: if ($sheettype eq 'studentcalc') {
! 894: &Apache::lonnet::expirespread('','','studentcalc');
! 895: } else {
! 896: &Apache::lonnet::expirespread('','','assesscalc');
! 897: &Apache::lonnet::expirespread('','','studentcalc');
! 898: }
! 899: }
! 900: $displayname = &mt($text);
! 901: } else {
! 902: $displayname = &mt($text);
! 903: }
! 904: if (defined($yesno{$key})) {
! 905: $displayval = 'no';
! 906: if ($changes->{$item}{$key} eq 'yes') {
! 907: $displayval = 'yes';
! 908: }
! 909: } elsif (($key =~ /^default_enrollment_(start|end)_date$/) && ($displayval)) {
! 910: $displayval = &Apache::lonlocal::locallocaltime($displayval);
! 911: } elsif ($key eq 'categories') {
! 912: $displayval = $env{'form.categories_display'};
! 913: }
! 914: if ($changes->{$item}{$key} eq '') {
! 915: push(@delkeys,$key);
! 916: $output .= '<li>'.&mt('Deleted setting for [_1]',
! 917: '<i>'.$displayname.'</i>').'</li>';
! 918: } else {
! 919: $output .= '<li>'.&mt('[_1] set to [_2]',
! 920: '<i>'.$displayname.'</i>',
! 921: "'<b>$displayval</b>'");
! 922: if ($key eq 'url') {
! 923: my $bkuptime=time;
! 924: $output .= (' 'x2).&mt('(Previous URL backed up)').': '.
! 925: $storehash{'top level map backup '.$bkuptime} => $values->{$key};
! 926: }
! 927: $output .= '</li>';
! 928: }
! 929: $storehash{$key} = $changes->{$item}{$key};
! 930: }
! 931: if (($key eq 'description') || ($key eq 'cloners') ||
! 932: ($key eq 'hidefromcat') || ($key eq 'categories')) {
! 933: push(@need_env_update,$key);
! 934: }
! 935: }
! 936: }
! 937: }
! 938: $output .= '</ul>';
! 939: } else {
! 940: $output = &mt('No changes made to course settings.');
! 941: }
! 942: }
! 943: }
! 944: }
! 945: if (&Apache::lonnet::put('environment',\%storehash,$cdom,$cnum) eq 'ok') {
! 946: if (@delkeys) {
! 947: if (&Apache::lonnet::del('environment',\@delkeys,$cdom,$cnum) ne 'ok') {
! 948: $output .= '<br /><span class="LC_error">'.
! 949: &mt('An error occurred when removing course settings which are no longer in use.').'</span>';
! 950: }
! 951: }
! 952: if (@need_env_update) {
! 953: $chome = &Apache::lonnet::homeserver($cnum,$cdom);
! 954: &update_env($cnum,$cdom,$chome,\@need_env_update,\%storehash);
! 955: }
! 956: &Apache::lonnet::coursedescription($env{'request.course.id'},
! 957: {'freshen_cache' => 1});
! 958: } else {
! 959: $output = '<span class="LC_error">'.
! 960: &mt('An error occurred when saving changes to course settings, which remain unchanged.').'</span>';
! 961: }
! 962: return $output;
! 963: }
! 964:
! 965: sub update_env {
! 966: my ($cnum,$cdom,$chome,$need_env_update,$storehash) = @_;
! 967: my $count = 0;
! 968: if ((ref($need_env_update) eq 'ARRAY') && (ref($storehash) eq 'HASH')) {
! 969: my %crsinfo = &Apache::lonnet::courseiddump($cdom,'.',1,'.','.',$cnum,undef,undef,'.');
! 970: if (ref($crsinfo{$env{'request.course.id'}}) eq 'HASH') {
! 971: foreach my $key (@{$need_env_update}) {
! 972: if ($key eq 'description' && defined($storehash->{$key})) {
! 973: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.description' => $storehash->{$key}});
! 974: $crsinfo{$env{'request.course.id'}}{'description'} = $storehash->{$key};
! 975: $count ++;
! 976: } elsif (($key eq 'cloners') || ($key eq 'hidefromcat') || ($key eq 'categories')) {
! 977: &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash->{$key}});
! 978: $crsinfo{$env{'request.course.id'}}{$key} = $storehash->{$key};
! 979: $count ++;
! 980: }
! 981: }
! 982: if ($count) {
! 983: my $putresult = &Apache::lonnet::courseidput($cdom,\%crsinfo,$chome,'notime');
! 984: }
! 985: }
! 986: }
! 987: return;
! 988: }
! 989:
! 990: sub display_disallowed {
! 991: my ($item,$disallowed,$prefs) = @_;
! 992: my $output;
! 993: if ((ref($disallowed) eq 'HASH') && (ref($prefs) eq 'HASH')) {
! 994: if (keys(%{$disallowed})) {
! 995: if ($item eq 'cloners') {
! 996: my @fails;
! 997: my %lt = &Apache::lonlocal::texthash (
! 998: format => 'Invalid format',
! 999: domain => 'Domain does not exist',
! 1000: newuser => 'LON-CAPA user(s) do(es) not exist.',
! 1001: );
! 1002: foreach my $error ('format','domain','newuser') {
! 1003: if (defined($disallowed->{$error})) {
! 1004: my $msg = '<b>'.$disallowed->{$error}.'</b>, '.&mt('reason').' - '.
! 1005: $lt{$error};
! 1006: if ($error eq 'newuser') {
! 1007: $msg .= '<br />'.&mt('Please [_1]add the user(s)[_2] before returning to the [_3]Course Configuration[_2] to add as potential cloners.','<a href="/adm/createuser">','</a>','<a href="/adm/courseprefs">');
! 1008: }
! 1009: push(@fails,$msg);
! 1010: }
! 1011: }
! 1012: if (@fails) {
! 1013: $output .= '<span class="LC_warning">'.&mt('Unable to add to allowed cloners: ').
! 1014: '</span>'.join('; ',@fails).'.<br />';
! 1015: }
! 1016: } elsif ($item eq 'rolenames') {
! 1017: my %lt = &Apache::lonlocal::texthash (
! 1018: replacements => 'Name already used to replace a different standard role name',
! 1019: regulars => 'Name already used as a standard role name',
! 1020: customrole => 'Name already used as the name of a custom role',
! 1021: );
! 1022: my @fails;
! 1023: foreach my $error ('replacements','regulars','customrole') {
! 1024: if (ref($disallowed->{$error}) eq 'ARRAY') {
! 1025: push(@fails,'<b>'.join(', ',@{$disallowed->{$error}}).
! 1026: '</b>, '.&mt('reason').' - '.$lt{'error'});
! 1027: }
! 1028: }
! 1029: if (@fails) {
! 1030: $output .= '<span class="LC_warning">'.
! 1031: &mt('Unable to include amongst replacements for role names: ').
! 1032: '</span>'.join('; ',@fails).'.<br />';
! 1033: }
! 1034:
! 1035: } elsif (($item eq 'feedback') || ($item eq 'discussion') || ($item eq 'localization')) {
! 1036: $output .= '<span class="LC_warning">';
! 1037: if ($item eq 'feedback') {
! 1038: $output .= &mt('Unable to include as a recipient of course feedback for:');
! 1039: } elsif ($item eq 'discussion') {
! 1040: $output .= &mt('Unable to include in user-based access control for:');
! 1041: } elsif ($item eq 'localization') {
! 1042: $output .= &mt('Unable to include in course localization:');
! 1043: }
! 1044: $output .= '</span><ul>';
! 1045: foreach my $key (sort(keys(%{$disallowed}))) {
! 1046: my $itemtext = $prefs->{$item}{'itemtext'}{$key};
! 1047: $output .= '<li><i>'.$itemtext.'</i> - ';
! 1048: if ($item eq 'localization') {
! 1049: $output .= &mt('reason - unsupported language: [_1]',
! 1050: '<b>'.$disallowed->{$key}.'</b>');
! 1051: } else {
! 1052: $output .= &mt('reason - invalid user: [_1]',
! 1053: '<b>'.$disallowed->{$key}.'</b>').'</li>';
! 1054: }
! 1055: }
! 1056: $output .= '</ul><br />';
! 1057: }
! 1058: }
1.1 raeburn 1059: }
1.3 ! raeburn 1060: return $output;
1.1 raeburn 1061: }
1062:
1063: sub get_course {
1064: my ($courseid) = @_;
1065: if (!defined($courseid)) {
1066: $courseid = $env{'request.course.id'};
1067: }
1068: my $cdom=$env{'course.'.$courseid.'.domain'};
1069: my $cnum=$env{'course.'.$courseid.'.num'};
1070: return ($cnum,$cdom);
1071: }
1072:
1073: sub get_jscript {
1.3 ! raeburn 1074: my ($cdom,$phase) = @_;
1.1 raeburn 1075: my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom);
1076: my ($jscript,$categorize_js);
1077: my $stubrowse_js = &Apache::loncommon::studentbrowser_javascript();
1078: my $browse_js = &Apache::loncommon::browser_and_searcher_javascript('parmset');
1.3 ! raeburn 1079: my $cloners_js = &cloners_javascript($phase);
1.1 raeburn 1080: if ($can_categorize) {
1081: $categorize_js = <<ENDSCRIPT;
1082: function catsbrowser() {
1083: var catswin = null;
1084: var url = '/adm/courseprefs?phase=categorizecourse';
1085: if (!catswin || catswin.closed) {
1086: catswin=window.open(url,'categorieswin','height=480,width=600,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
1087: } else {
1088: catswin.focus();
1089: }
1090: }
1091: ENDSCRIPT
1092: }
1093: $jscript = '<script type="text/javascript" language="Javascript">'."\n".
1.3 ! raeburn 1094: $browse_js."\n".$categorize_js."\n".$cloners_js."\n".'</script>'.
! 1095: "\n".$stubrowse_js."\n";
1.1 raeburn 1096: return $jscript;
1097: }
1098:
1.3 ! raeburn 1099: sub cloners_javascript {
! 1100: my ($formname) = @_;
! 1101: return <<"ENDSCRIPT";
! 1102:
! 1103: function update_cloners(caller,num) {
! 1104: var delidx = getIndexByName('cloners_delete');
! 1105: var actidx = getIndexByName('cloners_activate');
! 1106: if (caller == 'cloners_all') {
! 1107: var selall;
! 1108: for (var i=0; i<document.$formname.cloners_all.length; i++) {
! 1109: if (document.$formname.cloners_all[i].checked) {
! 1110: selall = document.$formname.cloners_all[i].value;
! 1111: }
! 1112: }
! 1113: if (selall == 1) {
! 1114: if (delidx != -1) {
! 1115: if (document.$formname.cloners_delete.length) {
! 1116: for (var j=0; j<document.$formname.cloners_delete.length; j++) {
! 1117: document.$formname.cloners_delete[j].checked = true;
! 1118: }
! 1119: } else {
! 1120: document.$formname.elements[delidx].checked = true;
! 1121: }
! 1122: }
! 1123: if (actidx != -1) {
! 1124: if (document.$formname.cloners_activate.length) {
! 1125: for (var i=0; i<document.$formname.cloners_activate.length; i++) {
! 1126: if (document.$formname.cloners_activate[i].value == '0') {
! 1127: document.$formname.cloners_activate[i].checked = false;
! 1128: }
! 1129: if (document.$formname.cloners_activate[i].value == '') {
! 1130: document.$formname.cloners_activate[i].checked = true;
! 1131: }
! 1132: }
! 1133: }
! 1134: }
! 1135: document.$formname.cloners_newdom.selectedIndex = 0;
! 1136: }
! 1137: }
! 1138: if (caller == 'cloners_activate') {
! 1139: if (document.$formname.cloners_activate.length) {
! 1140: for (var j=0; j<document.$formname.cloners_activate.length; j++) {
! 1141: if (document.$formname.cloners_activate[j].value == num) {
! 1142: if (document.$formname.cloners_activate[j].checked) {
! 1143: for (var i=0; i<document.$formname.cloners_all.length; i++) {
! 1144: if (document.$formname.cloners_all[i].value == '1') {
! 1145: document.$formname.cloners_all[i].checked = false;
! 1146: }
! 1147: if (document.$formname.cloners_all[i].value == '0') {
! 1148: document.$formname.cloners_all[i].checked = true;
! 1149: }
! 1150: }
! 1151: }
! 1152: }
! 1153: }
! 1154: } else {
! 1155: for (var i=0; i<document.$formname.cloners_all.length; i++) {
! 1156: if (document.$formname.cloners_all[i].value == '1') {
! 1157: document.$formname.cloners_all[i].checked = false;
! 1158: }
! 1159: if (document.$formname.cloners_all[i].value == '0') {
! 1160: document.$formname.cloners_all[i].checked = true;
! 1161: }
! 1162: }
! 1163: }
! 1164: }
! 1165: return;
! 1166: }
! 1167:
! 1168: function getIndexByName(item) {
! 1169: for (var i=0;i<document.$formname.elements.length;i++) {
! 1170: if (document.$formname.elements[i].name == item) {
! 1171: return i;
! 1172: }
! 1173: }
! 1174: return -1;
! 1175: }
! 1176:
! 1177: ENDSCRIPT
! 1178: }
! 1179:
! 1180:
1.1 raeburn 1181: sub print_courseinfo {
1.3 ! raeburn 1182: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 1183: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 1184: return;
1185: }
1186: my ($cathash,$categoriesform);
1187: my $crstype = &Apache::loncommon::course_type();
1188: my %domconf =
1189: &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom);
1190: if (ref($domconf{'coursecategories'}) eq 'HASH') {
1191: $cathash = $domconf{'coursecategories'}{'cats'};
1192: if (ref($cathash) eq 'HASH') {
1193: $categoriesform =
1194: &Apache::loncommon::assign_categories_table($cathash,
1195: $settings->{'categories'})."\n";
1196: }
1197: }
1198: if (!defined($categoriesform)) {
1199: $categoriesform = &mt('No categories defined for this domain');
1200: }
1201:
1202: my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom);
1203:
1204: my %items = (
1.3 ! raeburn 1205: 'url' => {
! 1206: text => '<b>'.&mt($itemtext->{'url'}).'</b>'.(' 'x2).
1.1 raeburn 1207: '<a href="javascript:openbrowser'.
1208: "('display','url','sequence')\">".
1209: &mt('Select Map').'</a><br /><span class="LC_warning"> '.
1210: &mt('Modification may make assessment data inaccessible!').
1211: '</span>',
1212: input => 'textbox',
1213: size => '40',
1214: },
1215: 'description' => {
1.3 ! raeburn 1216: text => '<b>'.&mt($itemtext->{'description'}).'</b>',
1.1 raeburn 1217: input => 'textbox',
1218: size => '25',
1219: },
1220: 'courseid' => {
1.3 ! raeburn 1221: text => '<b>'.&mt($itemtext->{'courseid'}).'</b><br />'.'('.
! 1222: &mt('internal, optional').')',
1.1 raeburn 1223: input => 'textbox',
1224: size => '25',
1225: },
1226: 'cloners' => {
1.3 ! raeburn 1227: text => '<b>'.&mt($itemtext->{'cloners'}).'</b><br />'.
1.1 raeburn 1228: &mt('Course Coordinators included automatically'),
1229: input => 'textbox',
1230: size => '40',
1231: },
1232: 'rolenames' => {
1.3 ! raeburn 1233: text => '<b>'.&mt($itemtext->{'rolenames'}).'</b><br />'.
1.1 raeburn 1234: '('.&mt('To replace the standard title for a course role, enter a title, otherwise leave blank').')',
1235: input => 'textbox',
1236: size => '20',
1237: },
1238: 'externalsyllabus' => {
1.3 ! raeburn 1239: text => '<b>'.&mt($itemtext->{'externalsyllabus'}).'</b><br />('.
! 1240: &mt('not using syllabus template)'),
1.1 raeburn 1241: input => 'textbox',
1242: size => '40',
1243: },
1244: 'hidefromcat' => {
1.3 ! raeburn 1245: text => '<b>'.&mt($itemtext->{'hidefromcat'}).'</b><br />'.
1.1 raeburn 1246: ' ('.&mt('included by default if assigned institutional code, or categorized').')',
1247: input => 'radio',
1248: },
1249: 'categories' => {
1.3 ! raeburn 1250: text => '<b>'.&mt($itemtext->{'categories'}).'</b> <a href="javascript:catsbrowser()">'.
1.1 raeburn 1251: &mt('Display Categories').'</a>',
1252: input => 'textbox',
1253: size => '25',
1254: },
1255: );
1256: my $datatable;
1257: my $count = 0;
1258: foreach my $item (@{$ordered}) {
1259: if ($item eq 'hidefromcat') {
1260: next if (!$can_toggle_cat);
1261: } elsif ($item eq 'categories') {
1262: next if (!$can_categorize);
1263: }
1264: $count ++;
1265: $datatable .= &item_table_row_start($items{$item}{text},$count);
1266: if ($items{$item}{input} eq 'radio') {
1267: $datatable .= &yesno_radio($item,$settings);
1268: } elsif ($item eq 'cloners') {
1269: my $includeempty = 1;
1270: my $num = 0;
1271: $datatable .= &Apache::loncommon::start_data_table().
1272: &Apache::loncommon::start_data_table_row().
1273: '<td><span class="LC_nobreak"><label>'.
1274: &mt('Any user in any domain:').
1275: ' <input type="radio" name="cloners_all" value="1" ';
1276: if ($settings->{$item} eq '*') {
1277: $datatable .= ' checked="checked" ';
1278: }
1279: $datatable .= 'onchange="javascript:update_cloners('.
1280: "'cloners_all'".');" />'.&mt('Yes').'</label>'.
1281: (' 'x2).'<input type="radio" name="cloners_all" value="0" ';
1282: if ($settings->{$item} ne '*') {
1283: $datatable .= ' checked="checked" ';
1284: }
1285: $datatable .= ' onchange="javascript:update_cloners('.
1286: "'cloners_all'".');"/>'.&mt('No').'</label></td>'.
1287: &Apache::loncommon::end_data_table_row().
1288: &Apache::loncommon::end_data_table().
1289: '<table><tr><td align="left">'.&mt('Or').
1290: '</td></tr></table>'.
1291: &Apache::loncommon::start_data_table();
1292: my @cloners;
1293: if ($settings->{$item} eq '') {
1294: $datatable .= &new_cloners_dom_row($cdom,'0');
1295: } elsif ($settings->{$item} ne '*') {
1296: my @entries = split(/,/,$settings->{$item});
1297: if (@entries > 0) {
1298: foreach my $entry (@entries) {
1299: my ($uname,$udom) = split(/:/,$entry);
1300: if ($uname eq '*') {
1301: $datatable .=
1302: &Apache::loncommon::start_data_table_row().
1.3 ! raeburn 1303: '<td valign="top" align="left"><span class="LC_nobreak">'.
1.1 raeburn 1304: &mt('Domain:').'<b> '.$udom.
1305: '</b><input type="hidden" name="cloners_dom_'.$num.
1306: '" value="'.$udom.'" /></span><br />'.
1307: '<span class="LC_nobreak"><label><input type="checkbox" '.
1.3 ! raeburn 1308: 'name="cloners_delete" value="'.$num.'" onchange="javascript:update_cloners('."'cloners_delete','$num'".');" />'.
1.1 raeburn 1309: &mt('Delete').'</label></span></td>'.
1310: &Apache::loncommon::end_data_table_row();
1311: $num ++;
1312: } else {
1313: push(@cloners,$entry);
1314: }
1315: }
1316: }
1317: }
1318: my $add_domtitle = &mt('Any user in additional domain:');
1319: if ($settings->{$item} eq '*') {
1320: $add_domtitle = &mt('Any user in specific domain:');
1321: } elsif ($settings->{$item} eq '') {
1322: $add_domtitle = &mt('Any user in other domain:');
1323: }
1324: my $cloners_str = join(',',@cloners);
1325: $datatable .= &Apache::loncommon::start_data_table_row().
1326: '<td align="left"><span class="LC_nobreak">'.
1327: $add_domtitle.'</span><br />'.
1328: &Apache::loncommon::select_dom_form('','cloners_newdom',
1329: $includeempty).
1330: '<input type="hidden" name="cloners_total" value="'.$num.'" />'.
1331: '</td>'.&Apache::loncommon::end_data_table_row().
1.3 ! raeburn 1332: &Apache::loncommon::end_data_table().
! 1333: '<table><tr><td align="left">'.&mt('And').
! 1334: '</td></tr></table>'.
1.1 raeburn 1335: &Apache::loncommon::start_data_table().
1336: &Apache::loncommon::start_data_table_row().
1337: '<td align="left">'.
1338: &mt('Specific users').' (<tt>'.
1339: &mt('user:domain,user:domain').'</tt>)<br />'.
1340: &Apache::lonhtmlcommon::textbox($item,$cloners_str,
1341: $items{$item}{'size'}).
1342: '</td>'.&Apache::loncommon::end_data_table_row().
1343: &Apache::loncommon::end_data_table();
1344: } elsif ($item eq 'rolenames') {
1345: $datatable .= &Apache::loncommon::start_data_table();
1346: foreach my $role ('cc','in','ta','ep','ad','st') {
1347: $datatable .= &Apache::loncommon::start_data_table_row().
1348: '<td align="left"><span class="LC_nobreak">'.
1349: &Apache::lonnet::plaintext($role,$crstype,undef,1).
1350: '</span></td><td align="left">'.
1351: &Apache::lonhtmlcommon::textbox('rolenames_'.$role,
1352: $settings->{$role.'.plaintext'},
1353: $items{$item}{size}).'</td>'.
1354: &Apache::loncommon::end_data_table_row();
1355: }
1356: $datatable .= &Apache::loncommon::end_data_table().'</td>';
1357: } elsif ($item eq 'categories') {
1.3 ! raeburn 1358: my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";';
! 1359: $datatable .= '<input type="hidden" name="categories" value="'.$settings->{$item}.'" />'.
! 1360: &Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item},
! 1361: $items{$item}{size},$launcher);
1.1 raeburn 1362: } else {
1363: $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size});
1364: }
1365: $datatable .= &item_table_row_end();
1366: }
1367: $$rowtotal += scalar(@{$ordered});
1368: return $datatable;
1369: }
1370:
1371: sub new_cloners_dom_row {
1372: my ($newdom,$num) = @_;
1373: my $output;
1374: if ($newdom ne '') {
1375: $output .= &Apache::loncommon::start_data_table_row().
1376: '<td valign="top"><span class="LC_nobreak">'.
1377: &mt('Any user in domain:').' <b>'.$newdom.'</b>'.
1378: (' 'x2).'<label><input type="radio" '.
1379: 'name="cloners_activate" value="'.$num.'" '.
1.3 ! raeburn 1380: 'onchange="javascript:update_cloners('.
1.1 raeburn 1381: "'cloners_activate','$num'".');" />'.
1382: &mt('Yes').'</label>'.(' 'x2).
1383: '<label><input type="radio" '.
1384: 'name="cloners_activate" value="" checked="checked" '.
1.3 ! raeburn 1385: 'onchange="javascript:update_cloners('.
1.1 raeburn 1386: "'cloners_activate','$num'".');" />'.
1.3 ! raeburn 1387: &mt('No').'</label><input type="hidden" name="cloners_dom_'.
! 1388: $num.'" value="'.$newdom.'" /></span></td>'.
1.1 raeburn 1389: &Apache::loncommon::end_data_table_row();
1390: }
1391: return $output;
1392: }
1393:
1394: sub can_modify_catsettings {
1395: my ($dom) = @_;
1396: my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom);
1397: my ($can_toggle_cat,$can_categorize);
1398: if (ref($domconf{'coursecategories'}) eq 'HASH') {
1399: if ($domconf{'coursecategories'}{'togglecats'} eq 'crs') {
1400: $can_toggle_cat = 1;
1401: }
1402: if ($domconf{'coursecategories'}{'categorize'} eq 'crs') {
1403: $can_categorize = 1;
1404: }
1405: }
1406: return ($can_toggle_cat,$can_categorize);
1407: }
1408:
1409: sub assign_course_categories {
1410: my ($r) = @_;
1411: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1412: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1413: my $hascats = 0;
1414: my $cathash;
1415: my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom);
1416: if (ref($domconf{'coursecategories'}) eq 'HASH') {
1417: $cathash = $domconf{'coursecategories'}{'cats'};
1418: if (ref($cathash) eq 'HASH') {
1419: $hascats = 1;
1420: }
1421: }
1422: my $catwin_js;
1423: if ($hascats) {
1424: my $alert = &mt('Use \"Save\" in the main window to save course categories');
1425: $catwin_js = <<ENDSCRIPT;
1426: <script type="text/javascript">
1427:
1428: function updateCategories() {
1429: var newcategories = '';
1430: var unescapedcats = '';
1431: if (document.chgcats.usecategory.length) {
1432: for (var i=0; i<document.chgcats.usecategory.length; i++) {
1433: if (document.chgcats.usecategory[i].checked == true) {
1434: newcategories = newcategories + document.chgcats.usecategory[i].value + '&';
1435: unescapedcats = unescapedcats + document.chgcats.catname[i].value + ' & ';
1436: }
1437: }
1438: if (newcategories.length > 0) {
1439: newcategories = newcategories.slice(0,-1);
1440: }
1441: if (unescapedcats.length > 0) {
1442: unescapedcats = unescapedcats.slice(0,-3);
1443: }
1444: } else {
1445: if (document.chgcats.usecategory.checked == true) {
1446: newcategories = document.chgcats.usecategory.value;
1447: unescapedcats = document.chgcats.catname.value;
1448: }
1449: }
1450: opener.document.display.categories.value = newcategories;
1451: opener.document.display.categories_display.value = unescapedcats;
1452: alert("$alert");
1453: self.close();
1454: return;
1455: }
1456:
1457: </script>
1458: ENDSCRIPT
1459: } else {
1460: my $onload;
1461: }
1462: my $start_page =
1463: &Apache::loncommon::start_page('Course Categories',$catwin_js,
1464: {'only_body' => 1,});
1465: my $end_page = &Apache::loncommon::end_page();
1466: my $categoriesform = '<h3>'.&mt('Categorize Course').'</h3>';
1467: if ($hascats) {
1468: my %currsettings =
1469: &Apache::lonnet::get('environment',['hidefromcat','categories'],$cdom,$cnum);
1470: $categoriesform .= &mt('Assign one or more categories to this course.').'<br /><br />'.
1471: '<form name="chgcats" action="/adm/courseprefs" method="post">'."\n".
1472: &Apache::loncommon::assign_categories_table($cathash,
1473: $currsettings{'categories'})."\n".
1474: '<br /><input type="button" name="changes" value="'.
1475: &mt('Copy to main window').'" '.
1476: 'onclick="javascript:updateCategories()" /></form><br />';
1477: } else {
1478: $categoriesform .= &mt('No categories defined for this domain');
1479: }
1480: $r->print($start_page.$categoriesform.$end_page);
1481: return;
1482: }
1483:
1484: sub print_localization {
1.3 ! raeburn 1485: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 1486: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 1487: return;
1488: }
1489: my %items = (
1490: languages => {
1.3 ! raeburn 1491: text => &mt($itemtext->{'languages'}).'<br />'.
! 1492: &mt("(will override user's preference)"),
1.1 raeburn 1493: input => 'selectbox',
1494: },
1495: timezone => {
1.3 ! raeburn 1496: text => &mt($itemtext->{'timezone'}),
1.1 raeburn 1497: input => 'selectbox',
1498: },
1499: datelocale => {
1.3 ! raeburn 1500: text => &mt($itemtext->{'datelocale'}),
1.1 raeburn 1501: input => 'selectbox',
1502: },
1503: );
1504: my $datatable;
1505: my $count = 0;
1506: foreach my $item (@{$ordered}) {
1507: $count ++;
1508: $datatable .= &item_table_row_start($items{$item}{text},$count);
1509: if ($item eq 'timezone') {
1510: my $includeempty = 1;
1511: my $timezone = &Apache::lonlocal::gettimezone();
1512: $datatable .=
1513: &Apache::loncommon::select_timezone($item,$timezone,undef,
1514: $includeempty);
1515: } elsif ($item eq 'datelocale') {
1516: my $includeempty = 1;
1517: my $locale_obj = &Apache::lonlocal::getdatelocale();
1518: my $currdatelocale;
1519: if (ref($locale_obj)) {
1520: $currdatelocale = $locale_obj->id();
1521: }
1522: $datatable .=
1523: &Apache::loncommon::select_datelocale($item,$currdatelocale,
1524: undef,$includeempty);
1525: } else {
1526: if ($settings->{$item} eq '') {
1527: $datatable .=
1.3 ! raeburn 1528: &Apache::loncommon::select_language('languages_0','',1);
1.1 raeburn 1529: } else {
1530: my $num = 0;
1.3 ! raeburn 1531: my @languages = split(/\s*[,;:]\s*/,$settings->{$item});
1.1 raeburn 1532: $datatable .= &Apache::loncommon::start_data_table();
1533: if (@languages > 0) {
1.3 ! raeburn 1534: my %langchoices = &get_lang_choices();
1.1 raeburn 1535: foreach my $lang (@languages) {
1536: my $showlang = $lang;
1.3 ! raeburn 1537: if (exists($langchoices{$lang})) {
! 1538: $showlang = $langchoices{$lang};
1.1 raeburn 1539: }
1540: $datatable .=
1541: &Apache::loncommon::start_data_table_row().
1.3 ! raeburn 1542: '<td align="left"><span class="LC_nobreak">'.
1.1 raeburn 1543: &mt('Language:').'<b> '.$showlang.
1544: '</b><input type="hidden" name="languages_'.$num.
1545: '" value="'.$lang.'" /></span><br />'.
1546: '<span class="LC_nobreak"><label><input type="checkbox" '.
1547: 'name="languages_delete" value="'.$num.'" />'.
1548: &mt('Delete').'</label></span></td>'.
1.3 ! raeburn 1549: &Apache::loncommon::end_data_table_row();
1.1 raeburn 1550: $num ++;
1551: }
1552: }
1553: $datatable .= &Apache::loncommon::start_data_table_row().
1.3 ! raeburn 1554: '<td align="left"><span class="LC_nobreak">'.
! 1555: &mt('Additional language:'). '</span><br />'.
! 1556: &Apache::loncommon::select_language('languages_'.$num,'',1).
1.1 raeburn 1557: '<input type="hidden" name="languages_total" value="'.$num.'" />'.
1558: '</td>'.&Apache::loncommon::end_data_table_row().
1559: &Apache::loncommon::end_data_table();
1560: }
1561: }
1562: $datatable .= &item_table_row_end();
1563: }
1564: $$rowtotal += scalar(@{$ordered});
1565: return $datatable;
1566: }
1567:
1.3 ! raeburn 1568: sub get_lang_choices {
! 1569: my %langchoices;
! 1570: foreach my $id (&Apache::loncommon::languageids()) {
! 1571: my $code = &Apache::loncommon::supportedlanguagecode($id);
! 1572: if ($code) {
! 1573: $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id);
! 1574: }
! 1575: }
! 1576: return %langchoices;
! 1577: }
! 1578:
1.1 raeburn 1579: sub print_feedback {
1.3 ! raeburn 1580: my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 1581: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 1582: return;
1583: }
1584: my %items = (
1.3 ! raeburn 1585: 'question.email' => {
! 1586: text => '<b>'.&mt($itemtext->{'question.email'}).'</b>',
1.1 raeburn 1587: input => 'textbox',
1588: size => '50',
1589: },
1590:
1.3 ! raeburn 1591: 'comment.email' => {
! 1592: text => '<b>'.&mt($itemtext->{'comment.email'}).'</b>',
1.1 raeburn 1593: input => 'textbox',
1594: size => '50',
1595: },
1596:
1.3 ! raeburn 1597: 'policy.email' => {
! 1598: text => '<b>'.&mt($itemtext->{'policy.email'}).'</b>',
1.1 raeburn 1599: input => 'textbox',
1600: size => '50',
1601: },
1602: );
1603: my $datatable;
1604: my $count = 0;
1605: my ($cnum) = &get_course();
1606: my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
1607: my @sections = sort( { $a <=> $b } keys(%sections));
1608: my %lt = &Apache::lonlocal::texthash (
1609: currone => 'Current recipient:',
1610: curmult => 'Current recipients:',
1611: add => 'Additional recipient:',
1612: del => 'Delete?',
1613: sec => 'Sections:',
1614: );
1615:
1616: foreach my $item (@{$ordered}) {
1617: $count ++;
1618: $datatable .= &item_table_row_start($items{$item}{text},$count);
1619: if ($position eq 'top') {
1620: my $includeempty = 0;
1621: $datatable .= &user_table($cdom,$item,\@sections,
1.3 ! raeburn 1622: $settings->{$item},\%lt);
1.1 raeburn 1623: } else {
1.3 ! raeburn 1624: $datatable .= &Apache::lonhtmlcommon::textbox($item.'.text',
! 1625: $settings->{$item.'.text'},$items{$item}{size});
1.1 raeburn 1626: }
1627: $datatable .= &item_table_row_end();
1628: }
1629: $$rowtotal += scalar(@{$ordered});
1630: return $datatable;
1631: }
1632:
1633: sub user_table {
1634: my ($cdom,$item,$sections,$currvalue,$lt) = @_;
1635: my $output;
1636: if ($currvalue eq '') {
1637: $output .= &select_recipient($item,'0',$cdom,$sections);
1638: } else {
1639: my $num = 0;
1640: my @curr = split(/,/,$currvalue);
1641: $output .= &Apache::loncommon::start_data_table();
1642: my ($currusers);
1643: foreach my $val (@curr) {
1644: next if ($val eq '');
1645: my ($uname,$udom,$seclist) = ($val =~ /^($match_username):($match_domain)(\(?[^\)]*\)?)$/);
1646: my @selsec;
1647: if ($seclist) {
1648: $seclist =~ s/(^\(|\)$)//g;
1649: @selsec = split(/\s*;\s*/,$seclist);
1650: }
1651: $currusers .= '<tr>'.
1652: '<td valign="top"><span class="LC_nobreak">'.
1653: '<label><input type="checkbox" '.
1654: 'name="'.$item.'_delete" value="'.$num.'" />'.
1655: $lt->{'del'}.'</label>'.
1656: '<input type="hidden" name="'.$item.'_user_'.
1.3 ! raeburn 1657: $num.'" value="'.$uname.':'.$udom.'" />'.(' 'x2).
1.1 raeburn 1658: &Apache::loncommon::aboutmewrapper(
1659: &Apache::loncommon::plainname($uname,$udom,'firstname'),
1660: $uname,$udom,'aboutuser');
1661: if (ref($sections) eq 'ARRAY') {
1662: if (@{$sections}) {
1663: $currusers.= (' 'x3).$lt->{'sec'}.' '.
1664: &select_sections($item,$num,$sections,
1665: \@selsec);
1666: }
1667: }
1668: $currusers .= '</span></td></tr>';
1669: $num ++;
1670: }
1671: if ($num) {
1672: $output .= &Apache::loncommon::start_data_table_row().
1673: '<td align="left"><i>';
1674: if ($num > 1) {
1675: $output .= $lt->{'currone'};
1676: } else {
1677: $output .= $lt->{'currmult'};
1678: }
1679: $output .= '</i><br />'.
1680: '<table>'.$currusers.'</table></td>'.
1681: &Apache::loncommon::end_data_table_row();
1682: }
1683: $output .= &Apache::loncommon::start_data_table_row().
1684: '<td align="left"><span class="LC_nobreak"><i>'.
1685: $lt->{'add'}.'</i></span><br />'.
1686: &select_recipient($item,$num,$cdom,$sections).
1687: '<input type="hidden" name="'.$item.'_total" value="'.$num.'" />'.
1.3 ! raeburn 1688: '</td>'.&Apache::loncommon::end_data_table_row().
! 1689: &Apache::loncommon::end_data_table();
1.1 raeburn 1690: }
1691: return $output;
1692: }
1693:
1694: sub select_recipient {
1695: my ($item,$num,$cdom,$sections,$selected,$includeempty) = @_;
1696: my $domform = &Apache::loncommon::select_dom_form($cdom,$item.'_udom_'.$num,$includeempty);
1697: my $selectlink =
1698: &Apache::loncommon::selectstudent_link('display',$item.'_uname_'.$num,
1699: $item.'_udom_'.$num,1);
1.3 ! raeburn 1700: my $css_class = ($num % 2)?'LC_even_row':'LC_odd_row';
1.1 raeburn 1701: my $output =
1.3 ! raeburn 1702: '<table><tr class="'.$css_class.'"><td align="center">'.&mt('Username').'<br />'.
1.1 raeburn 1703: '<input type="text" name="'.$item.'_uname_'.$num.'" value="" /></td>'.
1704: '<td align="center">'.&mt('Domain').'<br />'.$domform.'</td>';
1705: if (ref($sections) eq 'ARRAY') {
1706: if (@{$sections}) {
1707: $output .= '<td align="center">'.&mt('Sections').'<br />'.
1708: &select_sections($item,$num,$sections,$selected).'</td>';
1709: }
1710: }
1711: $output .= '<td valign="top">'.
1712: $selectlink.'</td></tr></table>';
1713: return $output;
1714: }
1715:
1716: sub select_sections {
1717: my ($item,$num,$sections,$selected) = @_;
1718: my ($output,@currsecs,$allsec);
1719: if (ref($selected) eq 'ARRAY') {
1720: @currsecs = @{$selected};
1721: }
1722: if (!@currsecs) {
1723: $allsec = ' selected="selected"';
1724: }
1725: if (ref($sections) eq 'ARRAY') {
1726: if (@{$sections}) {
1727: my $mult;
1728: if (@{$sections} > 1) {
1729: $mult = ' multiple="multiple"';
1730: if (@{$sections} > 3) {
1731: $mult .= ' size="4"';
1732: }
1733: }
1734: $output = '<select name="'.$item.'_sections_'.$num.'"'.$mult.'>'.
1735: ' <option value=""'.$allsec.'>'.&mt('All').'</option>';
1736: foreach my $sec (@{$sections}) {
1737: my $is_sel;
1738: if ((@currsecs) && (grep(/^\Q$sec\E$/,@currsecs))) {
1739: $is_sel = 'selected="selected"';
1740: }
1741: $output .= '<option value="'.$sec.'"'.$is_sel.'>'.$sec.'</option>';
1742: }
1743: $output .= '</select>';
1744: }
1745: }
1746: return $output;
1747: }
1748:
1749: sub print_discussion {
1.3 ! raeburn 1750: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 1751: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 1752: return;
1753: }
1754: my %items = (
1755: 'plc.roles.denied' => {
1.3 ! raeburn 1756: text => '<b>'.&mt($itemtext->{'plc.roles.denied'}).'</b>'.
! 1757: &Apache::loncommon::help_open_topic("Course_Disable_Discussion").
! 1758: &mt('(roles-based)'),
1.1 raeburn 1759: input => 'checkbox',
1760: },
1761:
1762: 'plc.users.denied' => {
1.3 ! raeburn 1763: text => '<b>'.&mt($itemtext->{'plc.users.denied'}).'</b><br />'.
! 1764: &mt('(specific user(s))'),
1.1 raeburn 1765: input => 'checkbox',
1766: },
1767:
1768: 'pch.roles.denied' => {
1.3 ! raeburn 1769: text => '<b>'.&mt($itemtext->{'pch.roles.denied'}).'</b>'.
! 1770: &Apache::loncommon::help_open_topic("Course_Disable_Discussion").'<br />'.
! 1771: &mt('(role-based)'),
1.1 raeburn 1772: input => 'checkbox',
1773: },
1774:
1775: 'pch.users.denied' => {
1.3 ! raeburn 1776: text => '<b>'.&mt($itemtext->{'pch.users.denied'}).'</b><br />'.
! 1777: &mt('(specific user(s))'),
1.1 raeburn 1778: input => 'checkbox',
1779: },
1780: 'allow_limited_html_in_feedback' => {
1.3 ! raeburn 1781: text => '<b>'.&mt($itemtext->{'allow_limited_html_in_feedback'}).'</b>',
1.1 raeburn 1782: input => 'radio',
1783: },
1784:
1785: 'allow_discussion_post_editing' => {
1.3 ! raeburn 1786: text => '<b>'.&mt($itemtext->{'allow_discussion_post_editing'}).'</b>',
1.1 raeburn 1787: input => 'checkbox',
1788: },
1789: );
1790: my $datatable;
1791: my $count;
1792: my ($cnum) = &get_course();
1793: my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
1794: my @sections = sort( { $a <=> $b } keys(%sections));
1795: my %lt = &Apache::lonlocal::texthash (
1796: currone => 'Disallowed:',
1797: curmult => 'Disallowed:',
1798: add => 'Disallow more:',
1799: del => 'Delete?',
1800: sec => 'Sections:',
1801: );
1802:
1803: foreach my $item (@{$ordered}) {
1804: $count ++;
1805: $datatable .= &item_table_row_start($items{$item}{text},$count);
1806: if ($item eq 'plc.roles.denied') {
1807: $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
1808: '</table>';
1809: } elsif ($item eq 'plc.users.denied') {
1810: $datatable .= &user_table($cdom,$item,undef,
1811: $settings->{$item},\%lt);
1812: } elsif ($item eq 'pch.roles.denied') {
1813: $datatable .= '<table>'.&role_checkboxes($cdom,$cnum,$item,$settings).
1814: '</table>';
1815: } elsif ($item eq 'pch.users.denied') {
1816: $datatable .= &user_table($cdom,$item,undef,
1817: $settings->{$item},\%lt);
1818: } elsif ($item eq 'allow_limited_html_in_feedback') {
1819: $datatable .= &yesno_radio($item,$settings);
1820: } elsif ($item eq 'allow_discussion_post_editing') {
1821: $datatable .= &Apache::loncommon::start_data_table().
1822: &Apache::loncommon::start_data_table_row().
1823: '<th align="left">'.&mt('Role').'</th><th>'.
1824: &mt('Sections').'</th>'.
1825: &Apache::loncommon::end_data_table_row().
1826: &role_checkboxes($cdom,$cnum,$item,$settings,1).
1827: &Apache::loncommon::end_data_table();
1828: }
1829: $datatable .= &item_table_row_end();
1830: }
1831: $$rowtotal += scalar(@{$ordered});
1832: return $datatable;
1833: }
1834:
1835: sub role_checkboxes {
1836: my ($cdom,$cnum,$item,$settings,$showsections) = @_;
1837: my @roles = ('st','ad','ta','ep','in','cc');
1838: my $output;
1839: my (@current,@curr_roles,%currsec,@sections);
1840: if ($showsections) {
1841: my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
1842: @sections = sort( { $a <=> $b } keys(%sections));
1843: }
1844: if (ref($settings) eq 'HASH') {
1845: if ($settings->{$item}) {
1846: @current = split(',',$settings->{$item});
1847: if ($showsections) {
1848: foreach my $role (@current) {
1849: if ($role =~ /:/) {
1850: my ($trole,$sec) = split(':',$role);
1851: push(@curr_roles,$trole);
1852: if (ref($currsec{$trole}) eq 'ARRAY') {
1853: if (!grep(/^\Q$sec\E/,@{$currsec{$trole}})) {
1854: push(@{$currsec{$trole}},$sec);
1855: }
1.3 ! raeburn 1856: } else {
! 1857: $currsec{$trole} = [$sec];
1.1 raeburn 1858: }
1859: } else {
1860: push(@curr_roles,$role);
1861: }
1862: }
1863: @current = @curr_roles;
1864: }
1865: }
1866: }
1867: my $numinrow = 3;
1868: my $count = 0;
1869: foreach my $role (@roles) {
1870: my $checked = '';
1871: if (grep(/^\Q$role\E$/,@current)) {
1872: $checked = ' checked="checked" ';
1873: }
1874: my $plrole=&Apache::lonnet::plaintext($role);
1875: if ($showsections) {
1876: $output .= &Apache::loncommon::start_data_table_row();
1877: } else {
1878: my $rem = $count%($numinrow);
1879: if ($rem == 0) {
1880: if ($count > 0) {
1881: $output .= '</tr>';
1882: }
1883: $output .= '<tr>';
1884: }
1885: }
1886: $output .= '<td align="left"><span class="LC_nobreak"><label><input type="checkbox" name='.
1887: $item.'" value="'.$role.'"'.$checked.'/> '.
1888: $plrole.'</label></span></td>';
1889: if ($showsections) {
1890: $output .= '<td align="left">'.
1891: &select_sections($item,$role,\@sections,$currsec{$role}).
1892: '</td></tr>';
1893: }
1894: $count ++;
1895: }
1896: my %adv_roles =
1897: &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
1898: my $total = @roles;
1899: foreach my $role (sort(keys(%adv_roles))) {
1900: if ($role =~ m{^cr/($match_domain)/($match_name)/\w$}) {
1901: my $rolename = $3;
1902: my $value = 'cr_'.$1.'_'.$2.'_'.$rolename;
1903: my $checked = '';
1904: if (grep(/^\Q$value\E$/,@current)) {
1905: $checked = ' checked="checked" ';
1906: }
1907: if ($showsections) {
1908: $output .= &Apache::loncommon::start_data_table_row();
1909: } else {
1910: my $rem = $count%($numinrow);
1911: if ($rem == 0) {
1912: if ($count > 0) {
1913: $output .= '</tr>';
1914: }
1915: $output .= '<tr>';
1916: }
1917: }
1918: $output .= '<td><span class="LC_nobreak"><label><input type="checkbox" name='.
1919: $item.'" value="'.$value.'"'.$checked.' /> '.$rolename.
1920: '</label></span></td>';
1921: if ($showsections) {
1922: $output .= '<td>'.
1923: &select_sections($item,$role,\@sections,$currsec{$role}).
1924: '</td>'.&Apache::loncommon::end_data_table_row();
1925: }
1926: $total ++;
1927: $count ++;
1928: }
1929: }
1930: if (!$showsections) {
1931: my $rem = $total%($numinrow);
1932: my $colsleft = $numinrow - $rem;
1933: if ($colsleft > 1 ) {
1934: $output .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
1935: ' </td>';
1936: } elsif ($colsleft == 1) {
1937: $output .= '<td class="LC_left_item"> </td>';
1938: }
1939: $output .= '</tr>';
1940: }
1941: return $output;
1942: }
1943:
1944: sub print_classlists {
1.3 ! raeburn 1945: my ($position,$cdom,$settings,$itemtext,$rowtotal) = @_;
1.1 raeburn 1946: my @ordered;
1947: if ($position eq 'top') {
1948: @ordered = ('default_enrollment_start_date',
1949: 'default_enrollment_end_date');
1950: } elsif ($position eq 'middle') {
1951: @ordered = ('nothideprivileged');
1952: } else {
1953: @ordered = ('student_classlist_view',
1954: 'student_opt_in','student_classlist_portfiles');
1955: }
1956: my %items = (
1957: 'default_enrollment_start_date' => {
1.3 ! raeburn 1958: text => '<b>'.&mt($itemtext->{'default_enrollment_start_date'}).'</b>',
1.1 raeburn 1959: input => 'dates',
1960: },
1961: 'default_enrollment_end_date' => {
1.3 ! raeburn 1962: text => '<b>'.&mt($itemtext->{'default_enrollment_end_date'}).'</b>',
1.1 raeburn 1963: input => 'dates',
1964: },
1965:
1966: 'nothideprivileged' => {
1.3 ! raeburn 1967: text => '<b>'.&mt($itemtext->{'nothideprivileged'}).'</b>',
1.1 raeburn 1968: input => 'checkbox',
1969: },
1970:
1971: 'student_classlist_view' => {
1.3 ! raeburn 1972: text => '<b>'.&mt($itemtext->{'student_classlist_view'}).'</b>',
1.1 raeburn 1973: input => 'selectbox',
1974: options => {
1975: disabled => &mt('No viewable classlist'),
1976: section => &mt("Classlist of viewer's section"),
1977: all => &mt('Classlist of all students'),
1978: },
1979: order => ['disabled','all','section'],
1980: },
1981: 'student_opt_in' => {
1.3 ! raeburn 1982: text => '<b>'.&mt($itemtext->{'student_opt_in'}).'</b>',
1.1 raeburn 1983: input => 'radio',
1984: },
1985:
1986: 'student_classlist_portfiles' => {
1.3 ! raeburn 1987: text => '<b>'.&mt($itemtext->{'student_classlist_portfiles'}).'</b>',
1.1 raeburn 1988: input => 'radio',
1989: },
1990: );
1991: unless (($settings->{'student_classlist_view'} eq 'all') ||
1992: ($settings->{'student_classlist_view'} eq 'section')) {
1993: $settings->{'student_classlist_view'} = 'disabled';
1994: }
1995: return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal);
1996: }
1997:
1998: sub print_appearance {
1.3 ! raeburn 1999: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 2000: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2001: return;
2002: }
2003: my %items = (
2004: 'default_xml_style' => {
1.3 ! raeburn 2005: text => '<b>'.&mt($itemtext->{'default_xml_style'}).'</b> '.
1.1 raeburn 2006: '<a href="javascript:openbrowser'.
2007: "('display','default_xml_style'".
2008: ",'sty')".'">'.&mt('Select Style File').'</a>',
2009: input => 'textbox',
2010: size => 35,
2011: },
2012:
2013: 'pageseparators' => {
1.3 ! raeburn 2014: text => '<b>'.&mt($itemtext->{'pageseparators'}).'</b>',
1.1 raeburn 2015: input => 'radio',
2016: },
2017: 'disable_receipt_display' => {
1.3 ! raeburn 2018: text => '<b>'.&mt($itemtext->{'disable_receipt_display'}).'</b>',
1.1 raeburn 2019: input => 'radio',
2020: },
2021: 'texengine' => {
1.3 ! raeburn 2022: text => '<b>'.&mt($itemtext->{'texengine'}).'</b>',
1.1 raeburn 2023: input => 'selectbox',
2024: options => {
2025: jsMath => 'jsMath',
2026: mimetex => &mt('Convert to Images'),
2027: tth => &mt('TeX to HTML'),
2028: },
2029: order => ['jsMath','mimetex','tth'],
2030: nullval => &mt("None specified - use student's choice"),
2031: },
2032: 'tthoptions' => {
1.3 ! raeburn 2033: text => '<b>'.&mt($itemtext->{'tthoptions'}).'</b>',
1.1 raeburn 2034: input => 'textbox',
2035: size => 40,
2036: },
2037: );
2038: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
2039: }
2040:
2041: sub print_grading {
1.3 ! raeburn 2042: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 2043: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2044: return;
2045: }
2046: my %items = (
2047: 'grading' => {
1.3 ! raeburn 2048: text => '<b>'.&mt($itemtext->{'grading'}).'</b>'.
1.1 raeburn 2049: &Apache::loncommon::help_open_topic('GradingOptions'),
2050: input => 'selectbox',
2051: options => {
2052: standard => &mt('Standard: shows points'),
2053: external => &mt('External: shows number of completed parts'),
2054: spreadsheet => &mt('Spreadsheet: (with link to detailed scores)'),
2055: },
2056: order => ['standard','external','spreadsheet'],
2057: },
2058: 'rndseed' => {
1.3 ! raeburn 2059: text => '<b>'.&mt($itemtext->{'rndseed'}).'</b>'.
1.1 raeburn 2060: '<span class="LC_error">'.'<br />'.
2061: &mt('Modifying this will make problems have different numbers and answers!').
2062: '</span>',
2063: input => 'selectbox',
2064: options => {
2065: '32bit' => '32bit',
2066: '64bit' => '64bit',
2067: '64bit2' => '64bit2',
2068: '64bit3' => '64bit3',
2069: '64bit4' => '64bit4',
2070: '64bit5' => '64bit5',
2071: },
2072: order => ['32bit','64bit','64bit2','64bit3','64bit4','64bit5'],
2073: },
2074: 'receiptalg' => {
1.3 ! raeburn 2075: text => '<b>'.&mt($itemtext->{'receiptalg'}).'</b><br />'.
1.1 raeburn 2076: &mt('This controls how receipt numbers are generated.'),
2077: input => 'selectbox',
2078: options => {
2079: receipt => 'receipt',
2080: receipt2 => 'receipt2',
2081: receipt3 => 'receipt3',
2082: },
2083: order => ['receipt','receipt2','receipt3'],
2084: },
2085: 'disablesigfigs' => {
1.3 ! raeburn 2086: text => '<b>'.&mt($itemtext->{'disablesigfigs'}).'</b>',
1.1 raeburn 2087: input => 'radio',
2088: },
2089: );
2090: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
2091: }
2092:
2093: sub print_printouts {
1.3 ! raeburn 2094: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 2095: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2096: return;
2097: }
2098: my %items = (
2099: problem_stream_switch => {
1.3 ! raeburn 2100: text => '<b>'.&mt($itemtext->{'problem_stream_switch'}).'</b>',
1.1 raeburn 2101: input => 'radio',
2102: },
2103: suppress_tries => {
1.3 ! raeburn 2104: text => '<b>'.&mt($itemtext->{'suppress_tries'}).'</b>',
1.1 raeburn 2105: input => 'radio',
2106: },
2107: default_paper_size => {
1.3 ! raeburn 2108: text => '<b>'.&mt($itemtext->{'default_paper_size'}).'</b>',
1.1 raeburn 2109: input => 'selectbox',
2110: options => {
2111: Letter => &mt('Letter').' [8 1/2x11 in]',
2112: Legal => &mt('Legal').' [8 1/2x14 in]',
2113: Tabloid => &mt('Tabloid').' [11x17 in]',
2114: Executive => &mt('Executive').' [7 1/2x10 in]',
2115: A2 => &mt('A2').' [420x594 mm]',
2116: A3 => &mt('A3').' [297x420 mm]',
2117: A4 => &mt('A4').' [210x297 mm]',
2118: A5 => &mt('A5').' [148x210 mm]',
2119: A6 => &mt('A6').' [105x148 mm]',
2120: },
2121: order => ['Letter','Legal','Tabloid','Executive','A2','A3','A4','A5','A6'],
2122: nullval => 'None specified',
2123: },
2124: print_header_format => {
1.3 ! raeburn 2125: text => '<b>'.&mt($itemtext->{'print_header_format'}).'</b>',
1.1 raeburn 2126: input => 'checkbox',
2127: },
2128: disableexampointprint => {
1.3 ! raeburn 2129: text => '<b>'.&mt($itemtext->{'disableexampointprint'}).'</b>',
1.1 raeburn 2130: input => 'radio',
2131: },
2132: );
2133: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
2134: }
2135:
2136: sub print_spreadsheet {
1.3 ! raeburn 2137: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 2138: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2139: return;
2140: }
2141: my $SelectSpreadsheetFile=&mt('Select Spreadsheet File');
2142: my %items = (
2143: spreadsheet_default_classcalc => {
1.3 ! raeburn 2144: text => '<b>'.&mt($itemtext->{'spreadsheet_default_classcalc'}).'</b> '.
1.1 raeburn 2145: '<span class="LC_nobreak"><a href="javascript:openbrowser'.
2146: "('display','spreadsheet_default_classcalc'".
2147: ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
2148: input => 'textbox',
2149: },
2150: spreadsheet_default_studentcalc => {
1.3 ! raeburn 2151: text => '<b>'.&mt($itemtext->{'spreadsheet_default_studentcalc'}).'</b> '.
1.1 raeburn 2152: '<span class="LC_nobreak"><a href="javascript:openbrowser'.
2153: "('display','spreadsheet_default_calc'".
2154: ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
2155: input => 'textbox',
2156: },
2157: spreadsheet_default_assesscalc => {
1.3 ! raeburn 2158: text => '<b>'.&mt($itemtext->{'spreadsheet_default_assesscalc'}).'</b> '.
1.1 raeburn 2159: '<span class="LC_nobreak"><a href="javascript:openbrowser'.
2160: "('display','spreadsheet_default_assesscalc'".
2161: ",'spreadsheet')".'">'.$SelectSpreadsheetFile.'</a></span>',
2162: input => 'textbox',
2163: },
2164: hideemptyrows => {
1.3 ! raeburn 2165: text => '<b>'.&mt($itemtext->{'hideemptyrows'}).'</b>',
1.1 raeburn 2166: input => 'radio',
2167: },
2168: );
2169: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
2170: }
2171:
2172: sub print_bridgetasks {
1.3 ! raeburn 2173: my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
! 2174: unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
1.1 raeburn 2175: return;
2176: }
2177: my %items = (
2178: task_messages => {
1.3 ! raeburn 2179: text => '<b>'.&mt($itemtext->{'task_messages'}).'</b>',
1.1 raeburn 2180: input => 'selectbox',
2181: options => {
2182: only_student => &mt('Send message to student'),
2183: student_and_user_notes_screen => &mt('Message to student and add to user notes'),
2184: },
2185: order => ['only_student','student_and_user_notes_screen'],
2186: nullval => &mt('No message or record in user notes'),
2187: },
2188: task_grading => {
1.3 ! raeburn 2189: text => '<b>'.&mt($itemtext->{'task_grading'}).'</b>',
1.1 raeburn 2190: input => 'selectbox',
2191: options => {
2192: any => &mt('Grade BTs in any section'),
2193: section => &mt('Grade BTs only in own section')
2194: },
2195: order => ['any','section'],
2196: },
2197: suppress_embed_prompt => {
1.3 ! raeburn 2198: text => '<b>'.&mt($itemtext->{'suppress_embed_prompt'}).'</b><span class="LC_nobreak">'.
! 2199: ' '.&mt('(applies when current role is student)').'</span>',
1.1 raeburn 2200: input => 'radio',
2201: },
2202: );
2203: return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
2204: }
2205:
2206: sub print_other {
2207: my ($cdom,$settings,$allitems,$rowtotal) = @_;
2208: unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
2209: return;
2210: }
1.3 ! raeburn 2211: my @ordered = &get_other_items($cdom,$settings,$allitems);
! 2212: my %items;
! 2213: foreach my $parameter (@ordered) {
! 2214: $items{$parameter} = {
! 2215: text => '<b>'.$parameter.'</b>',
! 2216: input => 'textbox',
! 2217: size => '15',
! 2218: },
! 2219: }
! 2220: push (@ordered,'newp_value');
! 2221: $items{'newp_value'} = {
! 2222: text => '<b>'.&mt('Create New Environment Variable').'</b><br />'.
! 2223: '<input type="textbox" name="newp_name"'.
! 2224: ' value="" size="30" />',
! 2225: input => 'textbox',
! 2226: size => '30',
! 2227: };
! 2228: my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal);
! 2229: }
! 2230:
! 2231: sub get_other_items {
! 2232: my ($cdom,$settings,$allitems) = @_;
! 2233: unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
! 2234: return;
! 2235: }
1.1 raeburn 2236: my @ordered;
2237: if (ref($settings) eq 'HASH') {
2238: foreach my $parameter (sort(keys(%{$settings}))) {
2239: next if (grep/^\Q$parameter\E$/,@{$allitems});
1.3 ! raeburn 2240: next if (($parameter eq 'course.helper.not.run') &&
! 2241: (!exists($env{'user.role.dc./'.$env{'request.role.domain'}.'/'})));
1.1 raeburn 2242: unless (($parameter =~ m/^internal\./)||($parameter =~ m/^metadata\./) ||
2243: ($parameter =~ m/^selfenroll_/) || ($parameter =~ /_selfenroll$/)
2244: || ($parameter eq 'type') ||
2245: ($parameter =~ m/^(cc|in|ta|ep|ad|st)\.plaintext$/)) {
2246: push(@ordered,$parameter);
2247: }
2248: }
2249: }
1.3 ! raeburn 2250: return @ordered;
1.1 raeburn 2251: }
2252:
2253: sub item_table_row_start {
2254: my ($text,$count) = @_;
2255: my $output;
2256: if ($count%2) {
2257: $output .= '<tr class="LC_odd_row">';
2258: } else {
2259: $output .= '<tr>';
2260: }
2261: $output .= '<td class="LC_left_item">'.$text.
1.3 ! raeburn 2262: '</td><td class="LC_right_item" align="right">';
1.1 raeburn 2263: return $output;
2264: }
2265:
2266: sub item_table_row_end {
2267: return '</td></tr>';
2268: }
2269:
2270: sub yesno_radio {
2271: my ($item,$settings) = @_;
2272: my $itemon = ' ';
2273: my $itemoff = ' checked="checked" ';
2274: if (ref($settings) eq 'HASH') {
2275: if ($settings->{$item} eq 'yes') {
2276: $itemon = $itemoff;
2277: $itemoff = ' ';
2278: }
2279: }
2280: return '<span class="LC_nobreak"><label>'.
2281: '<input type="radio" name="'.$item.'"'.
2282: $itemon.' value="yes" />'.&mt('Yes').'</label> '.
2283: '<label><input type="radio" name="'.$item.'"'.
2284: $itemoff.' value="" />'.&mt('No').'</label></span>';
2285: }
2286:
2287: sub select_from_options {
2288: my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange) = @_;
2289: my $output;
2290: if ((ref($order) eq 'ARRAY') && (ref($options) eq 'HASH')) {
2291: $output='<select name="'.$item.'" '.$onchange;
2292: if ($multiple) {
2293: $output .= ' multiple="multiple"';
2294: my $num = @{$order};
2295: $num ++ if ($nullval ne '');
2296: if (($maxsize) && ($maxsize < $num)) {
2297: $output .= ' size="'.$maxsize.'"';
2298: }
2299: }
2300: $output .= '>'."\n";
2301: if ($nullval ne '') {
2302: $output .= '<option value=""';
2303: if (ref($curr) eq 'ARRAY') {
2304: if ((@{$curr} == 0) || (grep(/^$/,@{$curr}))) {
2305: $output .= ' selected="selected" ';
2306: }
2307: } else {
2308: if ($curr eq '') {
2309: $output .= ' selected="selected" ';
2310: }
2311: }
2312: $output .= '>'.$nullval.'</option>';
2313: }
2314: foreach my $option (@{$order}) {
2315: $output.= '<option value="'.$option.'"';
2316: if (ref($curr) eq 'ARRAY') {
2317: if (grep(/^\Q$option\E$/,@{$curr})) {
2318: $output .= ' selected="selected" ';
2319: }
2320: } else {
2321: if ($option eq $curr) {
2322: $output.=' selected="selected"';
2323: }
2324: }
2325: $output.=">$options->{$option}</option>\n";
2326: }
2327: $output.="</select>";
2328: }
2329: return $output;
2330: }
2331:
2332: sub make_item_rows {
2333: my ($cdom,$items,$ordered,$settings,$rowtotal) = @_;
2334: my $datatable;
2335: if ((ref($items) eq 'HASH') && (ref($ordered) eq 'ARRAY')) {
2336: my $count = 0;
2337: foreach my $item (@{$ordered}) {
2338: $count ++;
2339: $datatable .= &item_table_row_start($items->{$item}{text},$count);
2340: if ($item eq 'nothideprivileged') {
2341: $datatable .= ¬hidepriv_row($cdom,$item,$settings);
2342: } elsif ($item eq 'print_header_format') {
2343: $datatable .= &print_hdrfmt_row($item,$settings);
2344: } elsif ($items->{$item}{input} eq 'dates') {
2345: $datatable .=
2346: &Apache::lonhtmlcommon::date_setter('display',$item,
2347: $settings->{$item});
2348: } elsif ($items->{$item}{input} eq 'radio') {
2349: $datatable .= &yesno_radio($item,$settings);
2350: } elsif ($items->{$item}{input} eq 'selectbox') {
2351: my $curr = $settings->{$item};
2352: $datatable .=
2353: &select_from_options($item,$items->{$item}{'order'},
2354: $items->{$item}{'options'},$curr,
2355: $items->{$item}{'nullval'});
2356: } elsif ($items->{$item}{input} eq 'textbox') {
2357: $datatable .=
2358: &Apache::lonhtmlcommon::textbox($item,$settings->{$item},
2359: $items->{$item}{size});
2360: }
2361: $datatable .= &item_table_row_end();
2362: }
2363: if (ref($rowtotal)) {
2364: $$rowtotal += scalar(@{$ordered});
2365: }
2366: }
2367: return $datatable;
2368: }
2369:
2370: sub nothidepriv_row {
2371: my ($cdom,$item,$settings) = @_;
2372: my ($cnum) = &get_course();
2373: my %nothide;
2374: my $datatable;
2375: if (ref($settings) eq 'HASH') {
2376: if ($settings->{$item} ne '') {
2377: foreach my $user (split(/\s*\,\s*/,$settings->{$item})) {
2378: if ($user !~ /:/) {
2379: $nothide{join(':',split(/[\@]/,$user))}=1;
2380: } else {
2381: $nothide{$user} = 1;
2382: }
2383: }
2384: }
2385: }
2386: my %coursepersonnel = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
2387: my $now = time;
2388: my @privusers;
1.3 ! raeburn 2389: my %privileged;
1.1 raeburn 2390: foreach my $person (keys(%coursepersonnel)) {
2391: my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/);
2392: $user =~ s/:$//;
2393: my ($end,$start) = split(/:/,$coursepersonnel{$person});
2394: if ($end == -1 || $start == -1) {
2395: next;
2396: }
2397: my ($uname,$udom) = split(':',$user);
1.3 ! raeburn 2398: unless (ref($privileged{$udom}) eq 'HASH') {
! 2399: my %dompersonnel = &Apache::lonnet::get_domain_roles($udom,['dc'],undef,$now);
! 2400: $privileged{$udom} = {};
! 2401: if (keys(%dompersonnel)) {
! 2402: foreach my $server (keys(%dompersonnel)) {
! 2403: foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
! 2404: my ($trole,$uname,$udom) = split(/:/,$user);
! 2405: $privileged{$udom}{$uname} = $trole;
! 2406: }
! 2407: }
! 2408: }
! 2409: }
! 2410: if (exists($privileged{$udom}{$uname})) {
1.1 raeburn 2411: push(@privusers,$user);
2412: }
2413: }
2414: if (@privusers) {
2415: $datatable .= '<table align="right">';
2416: foreach my $user (sort(@privusers)) {
2417: my $hideon = ' checked="checked" ';
2418: my $hideoff = '';
2419: if ($nothide{$user}) {
2420: $hideoff = $hideon;
2421: $hideon = '';
2422: }
2423: my ($uname,$udom) = split(':',$user);
2424: $datatable .= '<tr><td align="left">'.
2425: &Apache::loncommon::aboutmewrapper(
2426: &Apache::loncommon::plainname($uname,$udom,'firstname'),
2427: $uname,$udom,'aboutuser').
2428: '</td><td align="left">'.
2429: '<span class="LC_nobreak"><label>'.
2430: '<input type="radio" name="'.$item.'_'.$user.'"'.
2431: $hideon.' value="yes" />'.&mt('Hidden').'</label> '.
2432: '<label><input type="radio" name="'.$item.'_'.$user.'"'. $hideoff.' value="" />'.&mt('Shown').'</label></span></td>'.
2433: '</tr>';
2434: }
2435: $datatable .= '</table>';
2436: } else {
2437: $datatable .= &mt('No Domain Coordinators have course roles');
2438: }
2439: return $datatable;
2440: }
2441:
2442: sub print_hdrfmt_row {
2443: my ($item,$settings) = @_;
2444: my @curr;
2445: my $currnum = 0;
2446: my $maxnum = 2;
2447: my $currstr;
2448: if ($settings->{$item} ne '') {
2449: $currstr .= '<b>'.&mt('Current print header:').' <span class="LC_warning"><tt>'.
2450: $settings->{$item}.'</tt></span></b><br />';
2451: my @current = split(/(%\d*[nca])/,$settings->{$item});
2452: foreach my $item (@current) {
2453: unless ($item eq '') {
2454: push(@curr,$item);
2455: }
2456: }
2457: $currnum = @curr;
2458: $maxnum += $currnum;
2459: }
2460:
2461: my $output = <<ENDJS;
2462:
2463: <script type="text/javascript" language="Javascript">
2464:
2465: function reOrder(chgnum) {
2466: var maxnum = $maxnum;
2467: var oldidx = 'printfmthdr_oldpos_'+chgnum;
2468: var newidx = 'printfmthdr_pos_'+chgnum;
2469: oldidx = getIndexByName(oldidx);
2470: newidx = getIndexByName(newidx);
2471: var oldpos = document.display.elements[oldidx].value;
2472: var newpos = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
2473: document.display.elements[oldidx].value = newpos;
2474: var chgtype = 'up';
2475: if (newpos < oldpos) {
2476: chgtype = 'down';
2477: }
2478: for (var j=0; j<maxnum; j++) {
2479: if (j != chgnum) {
2480: oldidx = 'printfmthdr_oldpos_'+j;
2481: newidx = 'printfmthdr_pos_'+j;
2482: oldidx = getIndexByName(oldidx);
2483: newidx = getIndexByName(newidx);
2484: var currpos = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
2485: var currsel = document.display.elements[newidx].selectedIndex;
2486: if (chgtype == 'up') {
2487: if ((currpos > oldpos) && (currpos <= newpos)) {
2488: document.display.elements[newidx].selectedIndex = currsel-1;
2489: document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
2490: }
2491: } else {
2492: if ((currpos >= newpos) && (currpos < oldpos)) {
2493: document.display.elements[newidx].selectedIndex = currsel+1;
2494: document.display.elements[oldidx].value = document.display.elements[newidx].options[document.display.elements[newidx].selectedIndex].value;
2495: }
2496: }
2497: }
2498: }
2499: return;
2500: }
2501:
2502: function getIndexByName(item) {
2503: for (var i=0;i<document.display.elements.length;i++) {
2504: if (document.display.elements[i].name == item) {
2505: return i;
2506: }
2507: }
2508: return -1;
2509: }
2510:
2511: </script>
2512:
2513: ENDJS
2514: $output .= $currstr.&Apache::loncommon::start_data_table();
2515: if (@curr > 0) {
2516: for (my $i=0; $i<@curr; $i++) {
2517: my $pos = $i+1;
2518: $output .= &Apache::loncommon::start_data_table_row().
2519: '<td align="left"><span class="LC_nobreak">'.
2520: &position_selector($pos,$i,$maxnum).&mt('Delete:').
2521: '<input type="checkbox" name="printfmthdr_del_'.$i.
2522: '" /></span></td>';
2523: if ($curr[$i] =~ /^%\d*[nca]$/) {
2524: my ($limit,$subst) = ($curr[$i] =~ /^%(\d*)([nca])$/);
2525: $output .= '<td align="left">'.
2526: &substitution_selector($i,$subst,$limit).'</td>';
2527: } else {
2528: $output .= '<td colspan="2" align="left">'.&mt('Text').'<br />'.
2529: '<input type="textbox" name="printfmthdr_text_'.$i.'"'.
2530: ' value="'.$curr[$i].'" size="25" /></td>';
2531: }
2532: $output .= &Apache::loncommon::end_data_table_row();
2533: }
2534: }
2535: my $pos = $currnum+1;
2536: $output .= &Apache::loncommon::start_data_table_row().
2537: '<td align="left"><span class="LC_nobreak">'.
2538: &position_selector($pos,$currnum,$maxnum).
2539: '<b>'.&mt('New').'</b></span></td><td align="left">'.
2540: &substitution_selector($currnum).'</td>'.
2541: &Apache::loncommon::end_data_table_row();
2542: $pos ++;
2543: $currnum ++;
2544: $output .= &Apache::loncommon::start_data_table_row().
2545: '<td align="left"><span class="LC_nobreak">'.
2546: &position_selector($pos,$currnum,$maxnum).
2547: '<b>'.&mt('New').'</b></span></td>'.
2548: '<td colspan="2" align="left">'.&mt('Text').'<br />'.
2549: '<input type="textbox" name="printfmthdr_text_'.$currnum.
1.3 ! raeburn 2550: '" value="" size ="25" />'.
! 2551: '<input type="hidden" name="printfmthdr_maxnum" value="'.
! 2552: $maxnum.'" /></td>'.
1.1 raeburn 2553: &Apache::loncommon::end_data_table_row().
2554: &Apache::loncommon::end_data_table();
2555: return $output;
2556: }
2557:
2558: sub position_selector {
2559: my ($pos,$num,$maxnum) = @_;
2560: my $output = '<select name="printfmthdr_pos_'.$num.'" onchange="reOrder('."'$num'".');">';
2561: for (my $j=1; $j<=$maxnum; $j++) {
2562: my $sel = '';
2563: if ($pos == $j) {
2564: $sel = ' selected="selected"';
2565: }
2566: $output .= '<option value="'.$j.'"'.$sel.'">'.$j.'</option>';
2567: }
2568: $output .= '</select><input type="hidden" name="printfmthdr_oldpos_'.$num.
2569: '" value="'.$pos.'" />';
2570: return $output;
2571: }
2572:
2573: sub substitution_selector {
2574: my ($num,$subst,$limit) = @_;
2575: my %lt = &Apache::lonlocal::texthash(
2576: n => 'student name',
2577: c => 'course ID',
2578: a => 'assignment note',
2579: );
2580: my $output .= &mt('Substitution').'<br />'.
2581: '<select name=""printfmthdr_sub__'.$num.'">';
2582: if ($subst eq '') {
2583: $output .= '<option value="" selected="selected"> </option>';
2584: }
2585: foreach my $field ('n','c','a') {
2586: my $sel ='';
2587: if ($subst eq $field) {
2588: $sel = ' selected="selected"';
2589: }
2590: $output .= '<option value="'.$field.'"'.$sel.'>'.
2591: $lt{$field}.'</option>';
2592: }
2593: $output .= '</select></td><td align="left">'.&mt('Size limit').'<br />'.
2594: '<input type="textbox" name="printfmthdr_limit_'.$num.
2595: '" value="'.$limit.'" size="5" /></span>';
2596: return $output;
2597: }
2598:
2599: 1;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>