# The LearningOnline Network with CAPA
# Handler to set configuration settings for a course
#
# $Id: courseprefs.pm,v 1.32 2010/11/19 12:44:40 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
#
###############################################################
##############################################################
=pod
=head1 NAME
courseprefs- Handler to set/modify course configuration
=head1 SYNOPSIS
courseprefs provides an interface for setting general course configuration
=head1 DESCRIPTION
This module is used for configuration of a course
=head1 INTERNAL SUBROUTINES
=over
=item get_allitems()
=item print_config_box()
=item process_changes()
=item get_sec_str()
=item check_clone()
=item store_changes()
=item update_env()
=item display_disallowed()
=item get_course()
=item get_jscript()
=item cloners_javascript()
=item print_courseinfo()
=item new_cloners_dom_row()
=item can_modify_catsettings()
=item assign_course_categories()
=item print_localization()
=item get_lang_choices()
=item print_feedback()
=item user_table()
=item select_recipient()
=item select_sections()
=item print_discussion()
=item role_checkboxes()
=item print_classlists()
=item print_appearance()
=item print_grading()
=item print_printouts()
=item print_spreadsheet()
=item print_bridgetasks()
=item print_other()
=item get_other_items()
=item item_table_row_start()
=item item_table_row_end()
=item yes_no_radio()
=item select_from_options()
=item make_item_rows()
Creates table used to display and set course configuration items.
Inputs: $cdom,$items,$ordered,$settings,$rowtotal,$crstype
where $cdom is course's domain, $items is HASH ref for current config
item, $ordered is ARRAY ref of items to include in row in
display order, $settings is HASH ref of current values forrow,
$rowtotal is SCALAR ref used to accumulate row count, $crstype is
course type.
Returns: $datatable
HTML mark-up of data table which accumulates individual rows.
=item nothidepriv_row()
Creates row containing form elements used to display and set
whether Domain coordinators who are currently included in
advanced course user .db file for a course are to be hidden (e.g.,
in syllabus, or from course user lists).
Inputs: $cdom,$item,$settings,$crstype
where $cdom is course domain, item is nothideprivileged, $settings is
HASH ref of the current values for nothideprivileged, $crstype is
course type (Course or Community).
Return: $datatable
HTML mark-up for Privileged users (Domain Coordinators) in staff listing.
=item print_hdrfmt_row()
Creates row containing form elements used to display and set
substitution items and text to be used in the header included
on printouts.
Inputs: $item,$settings
where $item is print_header_format, and $settings is a HASH ref
of the current values stored for print_header_format.
Returns: $output
HTML mark-up containing Javascript functions: reOrder() and getIndexByName()
used to dynamically update position selectboxes, and HTML table elements
for the "Print header format" row.
=item position_selector()
Creates a select box which can be used to reorder substitutions
and text included in a printout header.
Inputs: $pos,$num,$maxnum
where $pos is current position, $num is the unique identifier,
and $maxnum is the total number of items (both substitutions
and text in the printout header.
Returns: $output
HTML mark-up for the selectbox and a hidden form element containing
the current position.
=item substitution_selector()
Creates a combination of select box for choosing an item
(student name, course ID or assignment note) to substitute,
and a corresponding size limit in the header used for printouts.
Inputs: $num,$subst,$limit,$crstype
where $num is the unique identifier, $subst is the current
substitution (n,c or a, for name, course or note respectively,
$limit is the current size limit (integer), and $crstype is
course type - course or community.
Returns: $output
HTML mark-up for selectbox and textbox (separate table cells).
=item change_clone()
Modifies the list of courses a user can clone (stored
in the user's environment.db file), called when a
change is made to the list of users allowed to clone
a course.
Inputs: $action,$cloner
where $action is add or drop, and $cloner is identity of
user for whom cloning ability is to be changed in course.
Returns: nothing
=back
=cut
package Apache::courseprefs;
use strict;
use Apache::Constants qw(:common :http);
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon();
use Apache::lonconfigsettings;
use Apache::lonlocal;
use LONCAPA qw(:DEFAULT :match);
sub handler {
my $r=shift;
if ($r->header_only) {
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK;
}
my $context = 'course';
my $cid = $env{'request.course.id'};
my ($cnum,$cdom) = &get_course($cid);
my $crstype = &Apache::loncommon::course_type();
my $parm_permission = &Apache::lonnet::allowed('opa',$cid);
my $navmap = Apache::lonnavmaps::navmap->new();
if ($parm_permission && $navmap) {
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
} else {
if ($navmap) {
if ($crstype eq 'Community') {
$env{'user.error.msg'}=
"/adm/courseprefs:opa:0:0:Cannot modify community settings";
} else {
$env{'user.error.msg'}=
"/adm/courseprefs:opa:0:0:Cannot modify course settings";
}
} else {
if ($crstype eq 'Community') {
$env{'user.error.msg'}=
"/adm/courseprefs::0:1:Course environment gone, reinitialize the community";
} else {
$env{'user.error.msg'}=
"/adm/courseprefs::0:1:Course environment gone, reinitialize the course";
}
}
return HTTP_NOT_ACCEPTABLE;
}
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['phase','actions','origin']);
&Apache::lonhtmlcommon::clear_breadcrumbs();
if ($env{'form.origin'} eq 'params') {
&Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
text=>"Parameter Manager"});
}
my ($brtext,$brtitle,$crsinfotext,$crsinfodesc,$crscateg,$crshide);
my %lt;
if ($crstype eq 'Community') {
%lt = (
conf => 'Community Configuration',
edit => 'Edit Community Configuration',
gens => 'General community settings',
idnu => 'Community ID or number',
desc => 'Community Description',
ownr => 'Community Owner',
cown => 'Community Co-owners',
catg => 'Categorize community',
excc => 'Exclude from community catalog',
clon => 'Users allowed to clone community',
rept => 'Replacement titles for standard community roles',
time => 'Timezone where the community is located',
date => 'Locale used for community calendar',
coco => 'Community Content',
copo => 'Community Policy',
priv => 'Domain Coordinators in community',
defd => 'Default dates for member access',
stuv => 'Member-viewable membership list options',
stul => 'Member agreement needed to be listed',
clas => 'Membership and Facilitator Listing',
priv => 'Privileged users (Domain Coordinators) in facilitator listing',
defc => 'Default Community Spreadsheet',
defs => 'Default User Spreadsheet',
seme => 'Send message to member when clicking Done on Tasks'
);
} else {
%lt = (
conf => 'Course Configuration',
edit => 'Edit Course Configuration',
gens => 'General course settings',
idnu => 'Course ID or number',
desc => 'Course Description',
ownr => 'Course Owner',
cown => 'Course Co-owners',
catg => 'Categorize course',
excc => 'Exclude from course catalog',
clon => 'Users allowed to clone course',
rept => 'Replacement titles for standard course roles',
time => 'Timezone in which the course takes place',
date => 'Locale used for course calendar',
coco => 'Course Content',
copo => 'Course Policy',
priv => 'Domain Coordinators in course',
defd => 'Default dates for student access',
stuv => 'Student-viewable classlist options',
stul => 'Student agreement needed to be listed',
clas => 'Classlists and Staff Listing',
priv => 'Privileged users (Domain Coordinators) in staff listing',
defc => 'Default Course Spreadsheet',
defs => 'Default Student Spreadsheet',
seme => 'Send message to student when clicking Done on Tasks',
);
}
&Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/courseprefs',
text=>$lt{'conf'}});
my $breadcrumbs =
&Apache::lonhtmlcommon::breadcrumbs($lt{'edit'});
my $phase = 'pickactions';
if ( exists($env{'form.phase'}) ) {
$phase = $env{'form.phase'};
}
if ($phase eq 'categorizecourse') {
&assign_course_categories($r,$crstype);
return OK;
}
my %values=&Apache::lonnet::dump('environment',$cdom,$cnum);
my @prefs_order = ('courseinfo','localization','feedback','discussion',
'classlists','appearance','grading','printouts',
'spreadsheet','bridgetasks','other');
my %prefs = (
'courseinfo' =>
{ text => $lt{'gens'},
help => 'Course_Environment',
ordered => ['owner','co-owners','description','courseid',
'categories','hidefromcat','externalsyllabus',
'cloners','url','rolenames'],
itemtext => {
'owner' => $lt{'ownr'},
'co-owners' => $lt{'cown'},
'description' => $lt{'desc'},
'courseid' => $lt{'idnu'},
'categories' => $lt{'catg'},
'hidefromcat' => $lt{'excc'},
'cloners' => $lt{'clon'},
'externalsyllabus' => 'URL of Syllabus',
'url' => 'Top Level Map',
'rolenames' => $lt{'rept'},
},
},
'localization' =>
{ text => 'Language and Time Localization',
help => 'Course_Environment',
ordered => ['languages','timezone','datelocale'],
itemtext => {
languages => 'Languages used',
timezone => $lt{'time'},
datelocale => $lt{'date'},
},
},
'feedback' =>
{ text => 'Feedback messages',
help => 'Course_Environment',
header => [{col1 => 'Questions about:',
col2 => 'Recipients'}],
ordered => ['question.email','comment.email','policy.email'],
itemtext => {
'question.email' => 'Resource Content',
'comment.email' => $lt{'coco'},
'policy.email' => $lt{'copo'},
},
},
'discussion' =>
{ text => 'Discussion and Chat',
help => 'Course_Environment',
ordered => ['pch.roles.denied','pch.users.denied',
'plc.roles.denied','plc.users.denied',
'allow_limited_html_in_feedback',
'allow_discussion_post_editing'],
itemtext => {
'pch.roles.denied' => 'No Resource Discussion',
'pch.users.denied' => 'No Resource Discussion',
'plc.roles.denied' => 'No Chat room use',
'plc.users.denied' => 'No Chat room use',
allow_limited_html_in_feedback => 'Allow limited HTML in discussion',
allow_discussion_post_editing => 'Users can edit/delete own discussion posts',
},
},
'classlists' =>
{ text => $lt{'clas'},
help => 'Course_Environment',
header => [{col1 => 'Type',
col2 => $lt{'defd'}},
{col1 => 'Setting',
col2 => $lt{'priv'}},
{col1 => 'Setting',
col2 => $lt{'stuv'}}],
ordered => ['default_enrollment_start_date',
'default_enrollment_end_date',
'nothideprivileged','student_classlist_view',
'student_classlist_opt_in','student_classlist_portfiles'],
itemtext => {
default_enrollment_start_date => 'Start date',
default_enrollment_end_date => 'End date',
nothideprivileged => $lt{'priv'},
student_classlist_view => $lt{'stuv'},
student_classlist_opt_in => $lt{'stul'},
student_classlist_portfiles => 'Include link to accessible portfolio files',
},
},
'appearance' =>
{ text => 'Display of resources ',
help => 'Course_Environment',
ordered => ['default_xml_style','pageseparators',
'disable_receipt_display','texengine',
'tthoptions'],
itemtext => {
default_xml_style => 'Default XML style file',
pageseparators => 'Visibly Separate Items on Pages',
disable_receipt_display => 'Disable display of problem receipts',
texengine => 'Force use of a specific math rendering engine',
tthoptions => 'Default set of options to pass to tth/m when converting TeX',
},
},
'grading' =>
{ text => 'Grading',
help => 'Course_Environment',
ordered => ['grading','rndseed',
'receiptalg','disablesigfigs'],
itemtext => {
grading => 'Grading',
rndseed => 'Randomization algorithm used',
receiptalg => 'Receipt algorithm used',
disablesigfigs => 'Disable checking of Significant Figures',
},
},
'printouts' =>
{ text => 'Printout generation',
help => 'Course_Environment',
ordered => ['problem_stream_switch','suppress_tries',
'default_paper_size','print_header_format',
'disableexampointprint','canuse_pdfforms'],
itemtext => {
problem_stream_switch => 'Allow problems to be split over pages',
suppress_tries => 'Suppress number of tries in printing',
default_paper_size => 'Default paper type',
print_header_format => 'Print header format',
disableexampointprint => 'Disable automatically printing point values on exams',
canuse_pdfforms => 'Users can print problems as PDF forms and upload later for grading',
},
},
'spreadsheet' =>
{ text => 'Spreadsheets',
help => 'Course_Environment',
ordered => ['spreadsheet_default_classcalc',
'spreadsheet_default_studentcalc',
'spreadsheet_default_assesscalc','hideemptyrows'],
itemtext => {
spreadsheet_default_classcalc => $lt{'defc'},
spreadsheet_default_studentcalc => $lt{'defs'},
spreadsheet_default_assesscalc => 'Default Assessment Spreadsheet',
hideemptyrows => 'Hide Empty Rows in Spreadsheets',
},
},
'bridgetasks' =>
{ text => 'Bridge tasks',
help => 'Course_Environment',
ordered => ['task_messages','task_grading',
'suppress_embed_prompt'],
itemtext => {
task_messages => $lt{'seme'},
task_grading => 'Bridge Task grading by instructors and TAs in sections' ,
suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio',
},
},
'other' =>
{ text => 'Other settings',
help => 'Course_Environment',
header => [ {col1 => 'Item',
col2 => 'Value',
}],
},
);
if ($phase eq 'process') {
my @allitems = &get_allitems(%prefs);
&Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context,
\@prefs_order,\%prefs,\%values,
$cnum,undef,\@allitems);
} elsif ($phase eq 'display') {
my $jscript = &get_jscript($cdom,$phase,$crstype);
my @allitems = &get_allitems(%prefs);
&Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context,
\@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype);
} else {
&Apache::lonconfigsettings::display_choices($r,$phase,$context,
\@prefs_order,\%prefs);
}
return OK;
}
sub get_allitems {
my (%prefs) = @_;
my @allitems;
foreach my $item (keys(%prefs)) {
if (ref($prefs{$item}) eq 'HASH') {
if (ref($prefs{$item}{'ordered'}) eq 'ARRAY') {
push(@allitems,@{$prefs{$item}{'ordered'}});
if ($item eq 'feedback') {
push(@allitems,(map { $_.'.text'; } @{$prefs{$item}{'ordered'}}));
}
}
}
}
return @allitems;
}
sub print_config_box {
my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype) = @_;
my $ordered = $item->{'ordered'};
my $itemtext = $item->{'itemtext'};
my $rowtotal = 0;
my $output =
'
'.
&Apache::loncommon::end_data_table_row();
}
$datatable .= &Apache::loncommon::end_data_table().'';
} elsif ($item eq 'categories') {
my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";';
$datatable .= ''.
&Apache::lonhtmlcommon::textbox($item.'_display',$settings->{$item},
$items{$item}{size},$launcher);
} elsif ($item eq 'owner') {
my $owner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'};
if ($owner =~ /:/) {
my ($ownername,$ownerdom) = split(':',$owner);
$owner = &Apache::loncommon::plainname($ownername,$ownerdom);
} elsif ($owner ne '') {
$owner = &Apache::loncommon::plainname($owner,$cdom);
} else {
$owner = &mt('None specified');
}
my $domdesc = &Apache::lonnet::domain($cdom,'description');
$datatable .= $owner;
} elsif ($item eq 'co-owners') {
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
my $coowners = $env{'course.'.$env{'request.course.id'}.'.internal.co-owners'};
my @currcoown;
if ($coowners) {
@currcoown = split(',',$coowners);
}
if (&Apache::lonnet::is_course_owner($cdom,$cnum)) {
if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
$datatable .= &show_autocoowners(@currcoown);
} else {
$datatable .= &coowner_invitations($cnum,$cdom,@currcoown);
}
} else {
if (($crstype eq 'Course') && ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) && ($autocoowner)) {
$datatable .= &show_autocoowners(@currcoown);
} else {
$datatable .= &manage_coownership($cnum,$cdom,@currcoown);
}
}
} else {
$datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size});
}
$datatable .= &item_table_row_end();
}
$$rowtotal += scalar(@{$ordered});
return $datatable;
}
sub new_cloners_dom_row {
my ($newdom,$num) = @_;
my $output;
if ($newdom ne '') {
$output .= &Apache::loncommon::start_data_table_row().
'
'.
&mt('Any user in domain:').' '.$newdom.''.
(' 'x2).''.(' 'x2).
'
'.
&Apache::loncommon::end_data_table_row();
}
return $output;
}
sub can_modify_catsettings {
my ($dom,$crstype) = @_;
my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$dom);
my ($can_toggle_cat,$can_categorize);
if (ref($domconf{'coursecategories'}) eq 'HASH') {
if ($crstype eq 'Community') {
if ($domconf{'coursecategories'}{'togglecatscomm'} eq 'comm') {
$can_toggle_cat = 1;
}
if ($domconf{'coursecategories'}{'categorizecomm'} eq 'comm') {
$can_categorize = 1;
}
} else {
if ($domconf{'coursecategories'}{'togglecats'} eq 'crs') {
$can_toggle_cat = 1;
}
if ($domconf{'coursecategories'}{'categorize'} eq 'crs') {
$can_categorize = 1;
}
}
}
return ($can_toggle_cat,$can_categorize);
}
sub assign_course_categories {
my ($r,$crstype) = @_;
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
my $hascats = 0;
my $cathash;
my %domconf = &Apache::lonnet::get_dom('configuration',['coursecategories'],$cdom);
if (ref($domconf{'coursecategories'}) eq 'HASH') {
$cathash = $domconf{'coursecategories'}{'cats'};
if (ref($cathash) eq 'HASH') {
foreach my $cat (keys(%{$cathash})) {
next if ($cat eq 'instcode::0');
unless ($crstype eq 'Community') {
next if ($cat eq 'communities::0');
}
$hascats ++;
}
}
}
my $catwin_js;
if ($hascats) {
my $alert;
if ($crstype eq 'Community') {
$alert = &mt("Use 'Save' in the main window to save community categories");
} else {
$alert = &mt("Use 'Save' in the main window to save course categories");
}
$catwin_js = <
function updateCategories() {
var newcategories = '';
var unescapedcats = '';
if (document.chgcats.usecategory.length) {
for (var i=0; i 0) {
newcategories = newcategories.slice(0,-1);
}
if (unescapedcats.length > 0) {
unescapedcats = unescapedcats.slice(0,-3);
}
} else {
if (document.chgcats.usecategory.checked == true) {
newcategories = document.chgcats.usecategory.value;
unescapedcats = document.chgcats.catname.value;
}
}
opener.document.display.categories.value = newcategories;
opener.document.display.categories_display.value = unescapedcats;
alert("$alert");
self.close();
return;
}
ENDSCRIPT
} else {
my $onload;
}
my ($crscat,$catcrs,$assign);
if ($crstype eq 'Community') {
$crscat = 'Community Categories';
$catcrs = &mt('Categorize Community');
$assign = &mt('Assign one or more categories to this community.')
} else {
$crscat = 'Course Categories';
$catcrs = &mt('Categorize Course');
$assign = &mt('Assign one or more categories to this course.')
}
my $start_page =
&Apache::loncommon::start_page($crscat,$catwin_js,
{'only_body' => 1,});
my $end_page = &Apache::loncommon::end_page();
my $categoriesform = '
'.$catcrs.'
';
if ($hascats) {
my %currsettings =
&Apache::lonnet::get('environment',['hidefromcat','categories'],$cdom,$cnum);
my $cattable = &Apache::loncommon::assign_categories_table($cathash,
$currsettings{'categories'},$crstype);
if ($cattable eq '') {
$categoriesform .= &mt('No suitable categories defined for this course type in this domain.');
} else {
$categoriesform .= $assign.'
'.
' ';
}
} else {
$categoriesform .= &mt('No categories defined in this domain.');
}
$r->print($start_page.$categoriesform.$end_page);
return;
}
sub show_autocoowners {
my (@currcoown) = @_;
my $output = ''.&mt('Co-ownership is set automatically when a Course Coordinator role is assigned to official course personnel (from institutional data).').'';
if (@currcoown > 0) {
$output .= ' '.&mt('Current co-owners are:').' '.
join(', ',map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));
} else {
$output .= ' '.&mt('Currently no co-owners.');
}
return $output;
}
sub coowner_invitations {
my ($cnum,$cdom,@currcoown) = @_;
my ($output,@pendingcoown,@othercoords);
my $pendingcoowners =
$env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
if ($pendingcoowners) {
@pendingcoown = split(',',$pendingcoowners);
}
my $ccrole = 'cc';
my %ccroles = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,undef,[$ccrole]);
foreach my $key (sort(keys(%ccroles))) {
my ($ccname,$ccdom,$role) = split(':',$key);
next if ($key eq $env{'user.name'}.':'.$env{'user.domain'}.':'.$ccrole);
unless (grep(/^\Q$ccname\E:\Q$ccdom\E$/,@currcoown,@pendingcoown)) {
push(@othercoords,$ccname.':'.$ccdom);
}
}
my $coowner_rows = @currcoown + @pendingcoown + @othercoords;
if ($coowner_rows) {
$output .= &Apache::loncommon::start_data_table();
if (@currcoown) {
$output .= &Apache::loncommon::start_data_table_row().
'
'.&mt('Current co-owners').'
';
foreach my $person (@currcoown) {
my ($co_uname,$co_dom) = split(':',$person);
$output .= ''.(' 'x2).' ';
}
$output .= '
'.
&Apache::loncommon::end_data_table_row();
}
if ($pendingcoowners) {
$output .= &Apache::loncommon::start_data_table_row().
'
'.&mt('Invited as co-owners [_1](agreement pending)',' ').'
';
foreach my $person (@pendingcoown) {
my ($co_uname,$co_dom) = split(':',$person);
$output .= ''.(' 'x2).' ';
}
$output .= '
'.
&Apache::loncommon::end_data_table_row();
}
if (@othercoords) {
$output .= &Apache::loncommon::start_data_table_row().
'
'.&mt('Invite other Coordinators [_1]to become co-owners',' ').'
';
foreach my $person (@othercoords) {
my ($co_uname,$co_dom) = split(':',$person);
$output .= ''.(' 'x2).' ';
}
$output .= '
'.
&Apache::loncommon::end_data_table_row();
}
$output .= &Apache::loncommon::end_data_table();
} else {
$output = &mt('There are no coordinators to select as co-owners');
}
return $output;
}
sub manage_coownership {
my ($cnum,$cdom,@currcoown) = @_;
my (@pendingcoown);
my $pendingcoowners =
$env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
if ($pendingcoowners) {
@pendingcoown = split(',',$pendingcoowners);
}
my ($is_coowner,$is_pending,$output);
my $uname = $env{'user.name'};
my $udom = $env{'user.domain'};
if (grep(/^\Q$uname\E:\Q$udom\E$/,@currcoown)) {
$is_coowner = 1;
}
if (grep(/^\Q$uname\E:\Q$udom\E$/,@pendingcoown)) {
$is_pending = 1;
}
if (@currcoown && ($is_coowner || $is_pending)) {
$output = &Apache::loncommon::start_data_table();
}
if (@currcoown) {
if ($is_coowner || $is_pending) {
$output .= &Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_row().'
'.&Apache::loncommon::end_data_table_row();
}
}
if ($is_coowner || $is_pending) {
if (@currcoown) {
$output .= &Apache::loncommon::start_data_table_row().'
';
}
$output .= '';
if ($is_coowner) {
$output .= &mt('You are currently a co-owner:').' ';
} else {
$output .= &mt('The course owner has invited you to become a co-owner:').' '.(' 'x2).
'';
}
$output .= '';
if (@currcoown) {
$output .= '
'.&Apache::loncommon::end_data_table_row();
}
}
if (@currcoown && ($is_coowner || $is_pending)) {
$output .= &Apache::loncommon::end_data_table();
}
return $output;
}
sub print_localization {
my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
my %items = (
languages => {
text => ''.&mt($itemtext->{'languages'}).' '.
&mt("(overrides individual user preference)"),
input => 'selectbox',
},
timezone => {
text => ''.&mt($itemtext->{'timezone'}).'',
input => 'selectbox',
},
datelocale => {
text => ''.&mt($itemtext->{'datelocale'}).'',
input => 'selectbox',
},
);
my $datatable;
my $count = 0;
foreach my $item (@{$ordered}) {
$count ++;
$datatable .= &item_table_row_start($items{$item}{text},$count);
if ($item eq 'timezone') {
my $includeempty = 1;
my $timezone = &Apache::lonlocal::gettimezone();
$datatable .=
&Apache::loncommon::select_timezone($item,$timezone,undef,
$includeempty);
} elsif ($item eq 'datelocale') {
my $includeempty = 1;
my $locale_obj = &Apache::lonlocal::getdatelocale();
my $currdatelocale;
if (ref($locale_obj)) {
$currdatelocale = $locale_obj->id();
}
$datatable .=
&Apache::loncommon::select_datelocale($item,$currdatelocale,
undef,$includeempty);
} else {
if ($settings->{$item} eq '') {
$datatable .=
&Apache::loncommon::select_language('languages_0','',1);
} else {
my $num = 0;
my @languages = split(/\s*[,;:]\s*/,$settings->{$item});
$datatable .= &Apache::loncommon::start_data_table();
if (@languages > 0) {
my %langchoices = &get_lang_choices();
foreach my $lang (@languages) {
my $showlang = $lang;
if (exists($langchoices{$lang})) {
$showlang = $langchoices{$lang};
}
$datatable .=
&Apache::loncommon::start_data_table_row().
'
'.&Apache::loncommon::end_data_table_row().
&Apache::loncommon::end_data_table();
}
}
$datatable .= &item_table_row_end();
}
$$rowtotal += scalar(@{$ordered});
return $datatable;
}
sub get_lang_choices {
my %langchoices;
foreach my $id (&Apache::loncommon::languageids()) {
my $code = &Apache::loncommon::supportedlanguagecode($id);
if ($code) {
$langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id);
}
}
return %langchoices;
}
sub print_feedback {
my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
my %items = (
'question.email' => {
text => ''.&mt($itemtext->{'question.email'}).'',
input => 'textbox',
size => '50',
},
'comment.email' => {
text => ''.&mt($itemtext->{'comment.email'}).'',
input => 'textbox',
size => '50',
},
'policy.email' => {
text => ''.&mt($itemtext->{'policy.email'}).'',
input => 'textbox',
size => '50',
},
);
my $datatable;
my $count = 0;
my ($cnum) = &get_course();
my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
my @sections = sort( { $a <=> $b } keys(%sections));
my %lt = &Apache::lonlocal::texthash (
currone => 'Current recipient:',
currmult => 'Current recipients:',
add => 'Additional recipient:',
del => 'Delete?',
sec => 'Sections:',
);
foreach my $item (@{$ordered}) {
$count ++;
if ($position eq 'top') {
$datatable .= &item_table_row_start($items{$item}{text},$count);
} else {
$datatable .= &item_table_row_start($items{$item}{text}." (Custom text)",$count, "advanced");
}
if ($position eq 'top') {
my $includeempty = 0;
$datatable .= &user_table($cdom,$item,\@sections,
$settings->{$item},\%lt);
} else {
$datatable .= &Apache::lonhtmlcommon::textbox($item.'.text',
$settings->{$item.'.text'},$items{$item}{size});
}
$datatable .= &item_table_row_end();
}
$$rowtotal += scalar(@{$ordered});
return $datatable;
}
sub user_table {
my ($cdom,$item,$sections,$currvalue,$lt) = @_;
my $output;
if ($currvalue eq '') {
$output .= &select_recipient($item,'0',$cdom,$sections);
} else {
my $num = 0;
my @curr = split(/,/,$currvalue);
$output .= '
';
my ($currusers);
foreach my $val (@curr) {
next if ($val eq '');
my ($uname,$udom,$seclist) = ($val =~ /^($match_username):($match_domain)(\(?[^\)]*\)?)$/);
my @selsec;
if ($seclist) {
$seclist =~ s/(^\(|\)$)//g;
@selsec = split(/\s*;\s*/,$seclist);
}
$currusers .= '
';
}
return $output;
}
sub select_recipient {
my ($item,$num,$cdom,$sections,$selected,$includeempty) = @_;
my $domform = &Apache::loncommon::select_dom_form($cdom,$item.'_udom_'.$num,$includeempty);
my $selectlink =
&Apache::loncommon::selectstudent_link('display',$item.'_uname_'.$num,
$item.'_udom_'.$num,1);
my $output =
'
'.&mt('Username').' '.
'
'.
'
'.&mt('Domain').' '.$domform.'
';
if (ref($sections) eq 'ARRAY') {
if (@{$sections}) {
$output .= '