{'categories'})."\n";
+ $settings->{'categories'},$crstype,$disabled)."\n";
+ }
+ }
+ if (ref($domconf{'autoenroll'}) eq 'HASH') {
+ $autocoowner = $domconf{'autoenroll'}{'co-owners'};
+ }
+ my ($currcanclone,@code_order,$cloner_instcode);
+ my %codedefaults;
+ &Apache::lonnet::auto_instcode_defaults($cdom,\%codedefaults,
+ \@code_order);
+ if ($settings->{'cloners'}) {
+ unless ($settings->{'cloners'} eq '*') {
+ my @currclone = split(/,/,$settings->{'cloners'});
+ foreach my $item (@currclone) {
+ unless ($item eq '*') {
+ if (($item !~ /\:/) && ($item =~ /=/)) {
+ $cloner_instcode = 1;
+ }
+ }
+ }
+ }
+ }
+ if (ref($domconf{'coursedefaults'}) eq 'HASH') {
+ my $canclone = $domconf{'coursedefaults'}{'canclone'};
+ if (ref($canclone) eq 'HASH') {
+ if (ref($canclone->{'instcode'}) eq 'ARRAY') {
+ if ($settings->{'internal.coursecode'}) {
+ my @posscodes;
+ if (@code_order > 0) {
+ $currcanclone = 'instcode';
+ foreach my $item (@{$canclone->{'instcode'}}) {
+ if (grep(/^\Q$item\E$/,@code_order)) {
+ push(@posscodes,$item);
+ }
+ }
+ my $codestr = join(' + ',@posscodes);
+ $clonedefaults = &mt('Default for official courses is to also allow cloning if [_1] match in cloner and cloned.',
+ '"'.$codestr.' "').' ';
+ }
+ }
+ }
+ } elsif ($canclone eq 'domain') {
+ $clonedefaults = &mt('Default is for any course requester in [_1] domain to be able to clone.',
+ ''.$cdom.' ').' ';
+ $currcanclone = 'domain';
+ }
+ if ($clonedefaults) {
+ if ($settings->{'cloners'} ne '') {
+ $clonedefaults .= ' '.&mt('Default does [_1]not[_2] currently apply because values have been set in the course.','',' ');
+ } else {
+ $clonedefaults .= &mt('Default is disregarded if [_1]any[_2] values are set here in the course.','',' ');
+ }
+ $clonedefaults = ' '.$clonedefaults;
}
}
if (!defined($categoriesform)) {
- $categoriesform = &mt('No categories defined for this domain');
+ $categoriesform = &mt('No categories defined in this domain.');
}
+ my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom,$crstype);
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
- my ($can_toggle_cat,$can_categorize) = &can_modify_catsettings($cdom);
-
+ my $replace;
+ if ($crstype eq 'Community') {
+ $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank');
+ } else {
+ $replace = &mt('To replace the standard title for a course role, enter a title, otherwise leave blank');
+ }
+ my ($editmap,$editsyllabus);
+ unless ($noedit) {
+ $editmap = (' 'x2).
+ '".
+ &mt('Select Map').' '.
+ &mt('Modification may make assessment data inaccessible!').
+ ' ';
+ $editsyllabus = &mt('[_1]Edit[_2]','',
+ ' ');
+ }
my %items = (
'url' => {
- text => ''.&mt($itemtext->{'url'}).' '.(' 'x2).
- '".
- &mt('Select Map').' '.
- &mt('Modification may make assessment data inaccessible!').
- ' ',
+ text => ''.&mt($itemtext->{'url'}).' '.$editmap,
input => 'textbox',
- size => '40',
+ size => '55',
+ advanced => 1
},
'description' => {
text => ''.&mt($itemtext->{'description'}).' ',
input => 'textbox',
- size => '25',
+ size => '55',
+ },
+ 'owner' => {
+ text => ''.&mt($itemtext->{'owner'}).' ',
+ },
+ 'co-owners' => {
+ text => ''.&mt($itemtext->{'co-owners'}).' ',
+ },
+ 'clonedfrom' => {
+ text => ''.&mt($itemtext->{'clonedfrom'}).' ',
},
'courseid' => {
text => ''.&mt($itemtext->{'courseid'}).' '.'('.
@@ -1225,23 +3979,27 @@ sub print_courseinfo {
input => 'textbox',
size => '25',
},
+ 'uniquecode' => {
+ text => ''.&mt($itemtext->{'uniquecode'}).' ',
+ },
'cloners' => {
text => ''.&mt($itemtext->{'cloners'}).' '.
- &mt('Course Coordinators included automatically'),
+ &mt('Owner and Coordinators included automatically').
+ $clonedefaults,
input => 'textbox',
- size => '40',
+ size => '40'
},
'rolenames' => {
text => ''.&mt($itemtext->{'rolenames'}).' '.
- '('.&mt('To replace the standard title for a course role, enter a title, otherwise leave blank').')',
+ '('.$replace.')',
input => 'textbox',
size => '20',
+ advanced => 1
},
- 'externalsyllabus' => {
- text => ''.&mt($itemtext->{'externalsyllabus'}).' ('.
- &mt('not using syllabus template)'),
- input => 'textbox',
- size => '40',
+ 'syllabus' => {
+ text => ''.&mt($itemtext->{'syllabus'}).' '.
+ &mt('(Syllabus type in use)').(' ' x2).
+ $editsyllabus,
},
'hidefromcat' => {
text => ''.&mt($itemtext->{'hidefromcat'}).' '.
@@ -1254,23 +4012,40 @@ sub print_courseinfo {
input => 'textbox',
size => '25',
},
+ 'loncaparev' => {
+ text => ''.&mt($itemtext->{'loncaparev'}).' ',
+ },
+ 'defaultcredits' => {
+ text => ''.&mt($itemtext->{'defaultcredits'}).' ',
+ },
);
my $datatable;
my $count = 0;
foreach my $item (@{$ordered}) {
+ my $colspan;
if ($item eq 'hidefromcat') {
next if (!$can_toggle_cat);
} elsif ($item eq 'categories') {
next if (!$can_categorize);
+ } elsif ($item eq 'uniquecode') {
+ next if (!$env{'course.'.$env{'request.course.id'}.'.internal.uniquecode'});
+ }
+ unless (($item eq 'cloners') || ($item eq 'rolenames')) {
+ $colspan = 2;
}
$count ++;
- $datatable .= &item_table_row_start($items{$item}{text},$count);
+ if (exists $items{$item}{advanced} && $items{$item}{advanced} == 1) {
+ $datatable .= &item_table_row_start($items{$item}{text},$count,"advanced",$colspan);
+ } else {
+ $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan);
+ }
if ($items{$item}{input} eq 'radio') {
- $datatable .= &yesno_radio($item,$settings);
+ $datatable .= &yesno_radio($item,$settings,undef,undef,undef,$noedit);
} elsif ($item eq 'cloners') {
my $includeempty = 1;
my $num = 0;
- $datatable .= &Apache::loncommon::start_data_table().
+ $datatable .= ''.
+ &Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_row().
' '.
&mt('Any user in any domain:').
@@ -1279,40 +4054,56 @@ sub print_courseinfo {
$datatable .= ' checked="checked" ';
}
$datatable .= 'onchange="javascript:update_cloners('.
- "'cloners_all'".');" />'.&mt('Yes').' '.
- (' 'x2).' '.&mt('Yes').''.
+ (' 'x2).''.
+ ' {$item} ne '*') {
$datatable .= ' checked="checked" ';
}
$datatable .= ' onchange="javascript:update_cloners('.
- "'cloners_all'".');"/>'.&mt('No').' '.
+ "'cloners_all'".');"'.$disabled.' />'.&mt('No').''.
&Apache::loncommon::end_data_table_row().
&Apache::loncommon::end_data_table().
- ''.
+ ''.
&Apache::loncommon::start_data_table();
my @cloners;
if ($settings->{$item} eq '') {
- $datatable .= &new_cloners_dom_row($cdom,'0');
+ unless ($noedit) {
+ my $default;
+ if ($currcanclone eq 'domain') {
+ $default = '0';
+ }
+ $datatable .= &new_cloners_dom_row($cdom,'0',$default);
+ }
} elsif ($settings->{$item} ne '*') {
my @entries = split(/,/,$settings->{$item});
if (@entries > 0) {
foreach my $entry (@entries) {
my ($uname,$udom) = split(/:/,$entry);
+ if ($udom =~ /^$match_domain$/) {
+ unless (&Apache::lonnet::domain($udom)) {
+ next;
+ }
+ } else {
+ next;
+ }
if ($uname eq '*') {
$datatable .=
&Apache::loncommon::start_data_table_row().
''.
- &mt('Domain:').' '.$udom.
+ &mt('Any user in domain:').' '.$udom.
' '.
' '.
+ 'name="cloners_delete" value="'.$num.'" onchange="javascript:update_cloners('."'cloners_delete','$num'".');"'.$disabled.' />'.
&mt('Delete').' '.
&Apache::loncommon::end_data_table_row();
$num ++;
- } else {
- push(@cloners,$entry);
+ } elsif (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
+ unless (grep(/^\Q$entry\E$/,@cloners)) {
+ push(@cloners,$entry);
+ }
}
}
}
@@ -1328,41 +4119,171 @@ sub print_courseinfo {
''.
$add_domtitle.' '.
&Apache::loncommon::select_dom_form('','cloners_newdom',
- $includeempty).
+ $includeempty,undef,undef,
+ undef,undef,$noedit).
' '.
' '.&Apache::loncommon::end_data_table_row().
&Apache::loncommon::end_data_table().
- ''.
+ ''.
&Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_row().
''.
&mt('Specific users').' ('.
&mt('user:domain,user:domain').' ) '.
&Apache::lonhtmlcommon::textbox($item,$cloners_str,
- $items{$item}{'size'}).
+ $items{$item}{'size'},$disabled).
' '.&Apache::loncommon::end_data_table_row().
&Apache::loncommon::end_data_table();
+ if (@code_order > 0) {
+ my (%cat_items,@codetitles,%cat_titles,%cat_order);
+ my ($jscript,$totcodes,$numtitles,$lasttitle) =
+ &Apache::courseclassifier::instcode_selectors_data($cdom,'display',
+ \%cat_items,\@codetitles,
+ \%cat_titles,\%cat_order);
+ my $showncodes = 'off';
+ my $checkedoff = ' checked="checked"';
+ my $checkedon = '';
+ if ($cloner_instcode) {
+ $checkedon = $checkedoff;
+ $checkedoff = '';
+ $showncodes = 'on';
+ }
+ $datatable .= ''.
+ &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_row().
+ ''.
+ &mt('Cloning by official course(s) based on course category').(' 'x2).
+ ''.
+ ' '.&mt('Yes').' '.
+ (' ').
+ ''.
+ ' '.&mt('No').' '.
+ &Apache::courseclassifier::build_instcode_selectors($numtitles,
+ $lasttitle,\%cat_items,\@codetitles,\%cat_titles,\%cat_order,
+ $showncodes,'LC_cloners_instcodes','LC_cloners_instcode',$noedit).
+ ' '.&Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::end_data_table();
+ }
} elsif ($item eq 'rolenames') {
- $datatable .= &Apache::loncommon::start_data_table();
- foreach my $role ('cc','in','ta','ep','ad','st') {
+ $datatable .= ''.
+ &Apache::loncommon::start_data_table();
+ my @roles;
+ if ($crstype eq 'Community') {
+ @roles = ('co');
+ } else {
+ @roles = ('cc');
+ }
+ push (@roles,('in','ta','ep','ad','st'));
+ foreach my $role (@roles) {
$datatable .= &Apache::loncommon::start_data_table_row().
' '.
&Apache::lonnet::plaintext($role,$crstype,undef,1).
' '.
&Apache::lonhtmlcommon::textbox('rolenames_'.$role,
$settings->{$role.'.plaintext'},
- $items{$item}{size}).' '.
+ $items{$item}{size},$disabled).''.
&Apache::loncommon::end_data_table_row();
}
$datatable .= &Apache::loncommon::end_data_table().'';
} elsif ($item eq 'categories') {
- my $launcher = 'onFocus="this.blur();javascript:catsbrowser();";';
+ my $launcher;
+ if ($noedit) {
+ $launcher = $disabled;
+ } else {
+ $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');
+ }
+ $datatable .= $owner;
+ } elsif ($item eq 'clonedfrom') {
+ my $clonesrc = $env{'course.'.$env{'request.course.id'}.'.clonedfrom'};
+ my $clonedfrom = &mt('None');
+ if ($clonesrc =~ m{/$match_domain/$match_courseid}) {
+ my %clonesrcinfo = &Apache::lonnet::coursedescription($clonesrc);
+ if ($clonesrcinfo{'description'}) {
+ $clonedfrom = $clonesrcinfo{'description'}.' '.($clonesrc);
+ }
+ }
+ $datatable .= $clonedfrom;
+ } elsif ($item eq 'uniquecode') {
+ my $code = $env{'course.'.$env{'request.course.id'}.'.internal.uniquecode'};
+ if ($code) {
+ $datatable .= $code;
+ }
+ } elsif ($item eq 'co-owners') {
+ 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,$noedit);
+ }
+ } 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,$noedit);
+ }
+ }
+ } elsif ($item eq 'syllabus') {
+ my $external = $env{'course.'.$env{'request.course.id'}.'.externalsyllabus'};
+ my $uploaded = $env{'course.'.$env{'request.course.id'}.'.uploadedsyllabus'};
+ my $minimal = $env{'course.'.$env{'request.course.id'}.'.minimalsyllabus'};
+ if (($minimal =~/\w/) || ($uploaded =~/\w/)) {
+ if ($minimal =~/\w/) {
+ if ($external =~ m{\Q$minimal\E$}) {
+ undef($external);
+ }
+ } elsif ($uploaded =~/\w/) {
+ if ($external =~ m{\Q$uploaded\E$}) {
+ undef($external);
+ }
+ }
+ } elsif ($external!~/\w/) {
+ undef($external);
+ }
+ if ($external) {
+ $datatable .= &mt('External URL');
+ } elsif ($minimal) {
+ $datatable .= &mt('Minimal template');
+ } elsif ($uploaded) {
+ $datatable .= &mt('Uploaded file');
+ } else {
+ $datatable .= &mt('Standard template');
+ }
+ $datatable .= (' ' x 2).
+ &mt('[_1]View[_2]',
+ '',
+ ' ');
+ } elsif ($item eq 'loncaparev') {
+ my $loncaparev = $env{'course.'.$env{'request.course.id'}.'.internal.releaserequired'};
+ my $showreqd;
+ if ($loncaparev) {
+ $showreqd = &mt('[_1] or newer',$loncaparev).' '.
+ &mt('Details').' ';
+ } else {
+ $showreqd = &mt('No specific version required');
+ }
+ $datatable .= $showreqd;
} else {
- $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size});
+ $datatable .= &Apache::lonhtmlcommon::textbox($item,$settings->{$item},$items{$item}{size},$disabled);
}
$datatable .= &item_table_row_end();
}
@@ -1371,19 +4292,24 @@ sub print_courseinfo {
}
sub new_cloners_dom_row {
- my ($newdom,$num) = @_;
- my $output;
+ my ($newdom,$num,$default) = @_;
+ my ($output,$checkedon,$checkedoff);
if ($newdom ne '') {
+ if ($num eq $default) {
+ $checkedon = 'checked="checked" ';
+ } else {
+ $checkedoff = 'checked="checked" ';
+ }
$output .= &Apache::loncommon::start_data_table_row().
''.
&mt('Any user in domain:').' '.$newdom.' '.
(' 'x2).' '.
&mt('Yes').' '.(' 'x2).
' '.
&mt('No').'
@@ -1461,59 +4408,824 @@ 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('Course Categories',$catwin_js,
+ &Apache::loncommon::start_page($crscat,$catwin_js,
{'only_body' => 1,});
my $end_page = &Apache::loncommon::end_page();
- my $categoriesform = ''.&mt('Categorize Course').' ';
+ my $categoriesform = ''.$catcrs.' ';
if ($hascats) {
my %currsettings =
&Apache::lonnet::get('environment',['hidefromcat','categories'],$cdom,$cnum);
- $categoriesform .= &mt('Assign one or more categories to this course.').' '.
+ 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 for this domain');
+ $categoriesform .= &mt('No categories defined in this domain.');
}
$r->print($start_page.$categoriesform.$end_page);
return;
}
+sub display_loncaparev_constraints {
+ my ($r,$navmap,$loncaparev,$crstype) = @_;
+ my ($reqdmajor,$reqdminor);
+ my $cid = $env{'request.course.id'};
+ my $cdom = $env{'course.'.$cid.'.domain'};
+ my $cnum = $env{'course.'.$cid.'.num'};
+ my $output;
+ my %lt = &Apache::lonlocal::texthash (
+ 'all' => 'all',
+ 'section/group' => 'section/group',
+ 'user' => 'user',
+ );
+ &Apache::lonrelrequtils::init_global_hashes();
+ if (defined($Apache::lonrelrequtils::checkcrstypes{$crstype})) {
+ ($reqdmajor,$reqdminor) = split(/\./,$Apache::lonrelrequtils::checkcrstypes{$crstype});
+ $output .= ''.&mt('Course type: [_1] requires [_2] or newer',$crstype,
+ $Apache::lonrelrequtils::checkcrstypes{$crstype}).' ';
+ }
+ my (%fromparam,%rowspan,%bymap,%byresource,@scopeorder,%toshow,%allmaps,
+ %byresponsetype,%bysubmission,%fromblocks);
+ @scopeorder = ('all','section/group','user');
+ my $now = time;
+ my $resourcedata = &Apache::lonparmset::readdata($cnum,$cdom);
+ if (ref($resourcedata) eq 'HASH') {
+ foreach my $key (keys(%{$resourcedata})) {
+ foreach my $item (keys(%Apache::lonrelrequtils::checkparms)) {
+ if ($key =~ /(\Q$item\E)$/) {
+ if (ref($Apache::lonrelrequtils::checkparms{$item}) eq 'ARRAY') {
+ my $value = $resourcedata->{$key};
+ if ($item eq 'examcode') {
+ if (&Apache::lonnet::validCODE($value)) {
+ $value = 'valid';
+ } else {
+ $value = '';
+ }
+ } elsif ($item eq 'printstartdate') {
+ if ($value =~ /^\d+$/) {
+ if ($value > $now) {
+ $value = 'future';
+ }
+ }
+ } elsif ($item eq 'printenddate') {
+ if ($value =~ /^\d+$/) {
+ if ($value < $now) {
+ $value = 'past';
+ }
+ }
+
+ }
+ my ($middle,$scope,$which,$level,$map,$resource);
+ if (grep(/^\Q$value\E$/,@{$Apache::lonrelrequtils::checkparms{$item}})) {
+ my $stdtype = &Apache::lonparmset::standard_parameter_types($item);
+ my $stdname = &Apache::lonparmset::standard_parameter_names($item);
+ my $valname = &get_param_description($stdtype,$value);
+ my $rev = $Apache::lonnet::needsrelease{'parameter:'.$item.':'.$value};
+ my $start = $cid.'.';
+ if ($key =~ /^\Q$start\E(\[useropt\:($match_username\:$match_domain)\]\.)/) {
+ $middle = $1;
+ $which = $2;
+ $scope = 'user';
+ } elsif ($key =~ /^\Q$start\E(\[(\w+)\]\.)/) {
+ $middle = $1;
+ $which = $2;
+ $scope = 'section/group';
+ } else {
+ $scope = 'all';
+ }
+ my $what="$stdname=$valname";
+ if ($key =~ /^\Q$start$middle\E\w+\.\Q$item\E$/) {
+ $level = 'general';
+ if ($scope eq 'all') {
+ if (ref($fromparam{$rev}{$scope}) eq 'ARRAY') {
+ unless(grep(/^\Q$what\E$/,@{$fromparam{$rev}{$scope}})) {
+ push(@{$fromparam{$rev}{$scope}},$what);
+ }
+ } else {
+ push(@{$fromparam{$rev}{$scope}},$what);
+ }
+ } else {
+ if (ref($fromparam{$rev}{$scope}{$which}) eq 'ARRAY') {
+ unless (grep(/^\Q$what\E$/,@{$fromparam{$rev}{$scope}{$which}})) {
+ push(@{$fromparam{$rev}{$scope}{$which}},$what);
+ }
+ } else {
+ push(@{$fromparam{$rev}{$scope}{$which}},$what);
+ }
+ }
+ $rowspan{$rev} ++;
+ } elsif ($key =~ /^\Q$start$middle\E(.+)___\(all\).\w+\.\Q$item\E$/) {
+ $level = 'folder';
+ $map = $1;
+ if ($scope eq 'all') {
+ if (ref($bymap{$map}{$rev}{$scope}) eq 'ARRAY') {
+ unless(grep(/^\Q$what\E$/,@{$bymap{$map}{$rev}{$scope}})) {
+ push(@{$bymap{$map}{$rev}{$scope}},$what);
+ }
+ } else {
+ push(@{$bymap{$map}{$rev}{$scope}},$what);
+ }
+ } else {
+ if (ref($bymap{$map}{$rev}{$scope}{$which}) eq 'ARRAY') {
+ unless(grep(/^\Q$what\E$/,@{$bymap{$map}{$rev}{$scope}{$which}})) {
+ push(@{$bymap{$map}{$rev}{$scope}{$which}},$what);
+ }
+ } else {
+ push(@{$bymap{$map}{$rev}{$scope}{$which}},$what);
+ }
+ }
+ } elsif ($key =~ /^\Q$start$middle\E(.+)\.\w+\.\Q$item\E$/) {
+ $level = 'resource';
+ $resource = $1;
+ if ($scope eq 'all') {
+ if (ref($byresource{$resource}{$rev}{$scope}) eq 'ARRAY') {
+ unless(grep(/^\Q$what\E$/,@{$byresource{$resource}{$rev}{$scope}})) {
+ push(@{$byresource{$resource}{$rev}{$scope}},$what);
+ }
+ } else {
+ push(@{$byresource{$resource}{$rev}{$scope}},$what);
+ }
+ } else {
+ if (ref($byresource{$resource}{$rev}{$scope}{$which}) eq 'ARRAY') {
+ unless (grep(/^\Q$what\E$/,@{$byresource{$resource}{$rev}{$scope}{$which}})) {
+ push(@{$byresource{$resource}{$rev}{$scope}{$which}},$what);
+ }
+ } else {
+ push(@{$byresource{$resource}{$rev}{$scope}{$which}},$what);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (keys(%fromparam)) {
+ $output .= ''.&mt('Requirements from general settings').' '.
+ &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ' '.&mt('Release').' '.&mt('Scope').' '.
+ ''.&mt('Extent').' '.&mt('Setting').' '.
+ &Apache::loncommon::end_data_table_header_row();
+ foreach my $rev (keys(%fromparam)) {
+ my ($major,$minor) = split(/\./,$rev);
+ ($reqdmajor,$reqdminor) =
+ &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
+ $output .= &Apache::loncommon::start_data_table_row().
+ ''.$rev.' ';
+ my $newrow;
+ foreach my $scope (@scopeorder) {
+ if (ref($fromparam{$rev}{$scope}) eq 'HASH') {
+ if ($newrow) {
+ $output .= &Apache::loncommon::continue_data_table_row();
+ }
+ $output .= ''.$lt{$scope}.' ';
+ foreach my $which (sort(keys(%{$fromparam{$rev}{$scope}}))) {
+ $output .= ''.$which.' '.
+ join(' ',@{$fromparam{$rev}{$scope}{$which}}).' ';
+ }
+ $output .= &Apache::loncommon::end_data_table_row();
+ $newrow = 1;
+ } elsif (ref($fromparam{$rev}{$scope}) eq 'ARRAY') {
+ if ($newrow) {
+ $output .= &Apache::loncommon::continue_data_table_row();
+ }
+ $output .= ''.$lt{$scope}.' '.
+ join(' ',@{$fromparam{$rev}{$scope}}).' '.
+ &Apache::loncommon::end_data_table_row();
+ $newrow = 1;
+ }
+ }
+ }
+ $output .= &Apache::loncommon::end_data_table().' ';
+ }
+ }
+
+ my %comm_blocks = &Apache::lonnet::dump('comm_block',$cdom,$cnum);
+ my $now = time;
+ if (keys(%comm_blocks) > 0) {
+ foreach my $block (keys(%comm_blocks)) {
+ if ($block =~ /^firstaccess____(.+)$/) {
+ my $rev = $Apache::lonnet::needsrelease{'course:commblock:timer'};
+ if (ref($comm_blocks{$block}) eq 'HASH') {
+ push(@{$fromblocks{'timer'}{$rev}},&unescape($comm_blocks{$block}{'event'}).
+ ' '.&mt('set by [_1]',
+ &Apache::loncommon::plainname(split(/:/,$comm_blocks{$block}{'setter'}))));
+ }
+ next;
+ } elsif ($block =~ /^(\d+)____(\d+)$/) {
+ my ($start,$end) = ($1,$2);
+ next if ($end < $now);
+ }
+ if (ref($comm_blocks{$block}) eq 'HASH') {
+ if (ref($comm_blocks{$block}{'blocks'}) eq 'HASH') {
+ if (ref($comm_blocks{$block}{'blocks'}{'docs'}) eq 'HASH') {
+ if (keys(%{$comm_blocks{$block}{'blocks'}{'docs'}}) > 0) {
+ my $rev = $Apache::lonnet::needsrelease{'course:commblock:docs'};
+ push(@{$fromblocks{'docs'}{$rev}},&unescape($comm_blocks{$block}{'event'}).
+ ' '.
+ &mt('set by [_1]',
+ &Apache::loncommon::plainname(split(/:/,$comm_blocks{$block}{'setter'}))));
+ }
+ } elsif ($comm_blocks{$block}{'blocks'}{'printout'} eq 'on') {
+ my $rev = $Apache::lonnet::needsrelease{'course:commblock:printout'};
+ push(@{$fromblocks{'printout'}{$rev}},&unescape($comm_blocks{$block}{'event'}).
+ ' '.
+ &mt('set by [_1]',
+ &Apache::loncommon::plainname(split(/:/,$comm_blocks{$block}{'setter'}))));
+
+ }
+ }
+ }
+ }
+ if (keys(%fromblocks)) {
+ my %lt = (
+ docs => 'Content blocking',
+ printout => 'Printout generation',
+ timer => 'Timed quiz trigger',
+ );
+ $output .= ''.&mt('Requirements from exam blocking').' '.
+ &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ''.&mt('Release').' '.&mt('Setting').' '.
+ ''.&mt('Event(s)').' '.
+ &Apache::loncommon::end_data_table_header_row();
+ foreach my $type ('docs','printout','timer') {
+ if (ref($fromblocks{$type}) eq 'HASH') {
+ foreach my $rev (keys(%{$fromblocks{$type}})) {
+ my ($major,$minor) = split(/\./,$rev);
+ ($reqdmajor,$reqdminor) =
+ &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor,$reqdmajor,$reqdminor);
+ $output .= &Apache::loncommon::start_data_table_row().
+ ''.$rev.' '.$lt{$type}.' ';
+ foreach my $event (sort(@{$fromblocks{$type}{$rev}})) {
+ $output .= $event.' ';
+ }
+ $output =~ s{\Q \E$}{};
+ $output .= ' '.&Apache::loncommon::end_data_table_row();
+ }
+ }
+ }
+ $output .= &Apache::loncommon::end_data_table().' ';
+ }
+ }
+
+ if (defined($navmap)) {
+ my %anonsubms=&Apache::lonnet::dump('nohist_anonsurveys',$cdom,$cnum);
+ my $rev_anonsurv=$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'};
+ my %randtrysubms=&Apache::lonnet::dump('nohist_randomizetry',$cdom,$cnum);
+ my $rev_randtry=$Apache::lonnet::needsrelease{'parameter:type:randomizetry'};
+ my $stdtype=&Apache::lonparmset::standard_parameter_types('type');
+ my $stdname=&Apache::lonparmset::standard_parameter_names('type');
+ my $valanon=&get_param_description($stdtype,'anonsurvey');
+ my $valrandtry=&get_param_description($stdtype,'randomizetry');
+ my %checkedrev;
+ foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_problem() },1,0)) {
+ my @parts = @{$res->parts()};
+ my $symb = $res->symb();
+ my $enclosing_map = &Apache::lonnet::declutter($res->enclosing_map_src());
+ foreach my $part (@parts) {
+ if (exists($anonsubms{$symb."\0".$part})) {
+ my $rev = $rev_anonsurv;
+ my $what="$stdname=$valanon";
+ if (ref($bysubmission{$symb}{$rev}) eq 'ARRAY') {
+ unless (grep(/^\Q$what\E/,@{$bysubmission{$symb}{$rev}})) {
+ push(@{$bysubmission{$symb}{$rev}},$what);
+ }
+ } else {
+ push(@{$bysubmission{$symb}{$rev}},$what);
+ }
+ $allmaps{$enclosing_map} = 1;
+ unless ($checkedrev{'anonsurvey'}) {
+ my ($major,$minor) = split(/\./,$rev);
+ ($reqdmajor,$reqdminor) =
+ &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor,
+ $reqdmajor,$reqdminor);
+ $checkedrev{'anonsurvey'} = 1;
+ }
+ }
+ if (exists($randtrysubms{$symb."\0".$part})) {
+ my $rev = $rev_randtry;
+ my $what="$stdname=$valrandtry";
+ if (ref($bysubmission{$symb}{$rev}) eq 'ARRAY') {
+ unless (grep(/^\Q$what\E/,@{$bysubmission{$symb}{$rev}})) {
+ push(@{$bysubmission{$symb}{$rev}},$what);
+ }
+ } else {
+ push(@{$bysubmission{$symb}{$rev}},$what);
+ }
+ $allmaps{$enclosing_map} = 1;
+ unless ($checkedrev{'randomizetry'}) {
+ my ($major,$minor) = split(/\./,$rev);
+ ($reqdmajor,$reqdminor) =
+ &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor,
+ $reqdmajor,$reqdminor);
+ $checkedrev{'randomizetry'} = 1;
+ }
+ }
+ }
+ my %responses = $res->responseTypes();
+ foreach my $key (keys(%responses)) {
+ if (exists($Apache::lonrelrequtils::checkresponsetypes{$key})) {
+ my $rev = $Apache::lonrelrequtils::checkresponsetypes{$key};
+ unless ($checkedrev{$key}) {
+ my ($major,$minor) = split(/\./,$rev);
+ ($reqdmajor,$reqdminor) =
+ &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor,
+ $reqdmajor,$reqdminor);
+ $checkedrev{$key} = 1;
+ }
+ push(@{$byresponsetype{$symb}{$rev}},$key);
+ $allmaps{$enclosing_map} = 1;
+ }
+ }
+ }
+ if (keys(%byresource) > 0) {
+ foreach my $symb (keys(%byresource)) {
+ my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb);
+ $allmaps{$map} = 1;
+ }
+ }
+ if (keys(%bymap) > 0) {
+ foreach my $map (keys(%bymap)) {
+ $allmaps{$map} = 1;
+ }
+ }
+ foreach my $map (keys(%allmaps)) {
+ my $mapres = $navmap->getResourceByUrl($map);
+ if (ref($mapres)) {
+ my $mapsymb = $mapres->symb();
+ $toshow{$mapsymb} = 1;
+ my $pcslist = $mapres->map_hierarchy();
+ if ($pcslist ne '') {
+ foreach my $pc (split(/,/,$pcslist)) {
+ my $res = $navmap->getByMapPc($pc);
+ if (ref($res)) {
+ my $symb = $res->symb();
+ unless ($symb eq '______') {
+ $toshow{$symb} = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ my $mapres_header = ''.
+ &mt('Requirements for specific folders or resources').
+ ' ';
+ if ((keys(%toshow) > 0) || (keys(%byresource) > 0) ||
+ (keys(%bysubmission) > 0) || (keys(%byresponsetype))) {
+ $output .= $mapres_header;
+ }
+ my $top_header = ''.&mt('LON-CAPA version dependencies').' ';
+ my $title = 'Version Constraints';
+ my $start_page =
+ &Apache::loncommon::start_page($title,undef,{'only_body' => 1,});
+ $r->print($start_page.$top_header);
+ if ($output) {
+ $r->print($output);
+ if (defined($navmap)) {
+ &show_contents_view($r,$navmap,$cid,\%toshow,\%bymap,\%byresource,\%bysubmission,
+ \%byresponsetype,\@scopeorder,\%lt);
+ }
+ $r->print(' ');
+ } else {
+ $r->print(''.
+ &mt('No version requirements from resource content or settings.').
+ '
');
+ }
+ $r->print(&Apache::loncommon::end_page());
+ my ($currmajor,$currminor) = split(/\./,$loncaparev);
+ if (($currmajor != $reqdmajor) || ($currminor != $reqdminor)) {
+ return 1;
+ }
+ return;
+}
+
+sub show_contents_view {
+ my ($r,$navmap,$cid,$toshow,$bymap,$byresource,$bysubmission,$byresponsetype,
+ $scopeorder,$lt) = @_;
+ if ((keys(%{$toshow}) > 0) || (keys(%{$byresource}) > 0) ||
+ (keys(%{$bysubmission}) > 0) || (keys(%{$byresponsetype}) > 0)) {
+ my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons");
+ my $whitespace = ' ';
+ my $icon = ' ';
+ my $topmap = $env{'course.'.$cid.'.url'};
+ $r->print(&Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ''.&mt('Location').' '.&mt('Release').' '.
+ ''.&mt('Attribute/Setting').' '.
+ &Apache::loncommon::end_data_table_header_row().
+ &Apache::loncommon::start_data_table_row().
+ ' '.$icon.' '.&mt('Main Content').' ');
+ &releases_by_map($r,$bymap,$topmap,$scopeorder,$lt);
+ $r->print(&Apache::loncommon::end_data_table_row());
+ my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
+ my $curRes;
+ my $depth = 0;
+ my %parent = ();
+ my $startcount = 5;
+ my $lastcontainer = $startcount;
+ while ($curRes = $it->next()) {
+ if ($curRes == $it->BEGIN_MAP()) {
+ $depth++;
+ $parent{$depth}= $lastcontainer;
+ }
+ if ($curRes == $it->END_MAP()) {
+ $depth--;
+ $lastcontainer = $parent{$depth};
+ }
+ my $indent;
+ for (my $i=0; $i<$depth; $i++) {
+ $indent.= $whitespace;
+ }
+ if (ref($curRes)) {
+ my $symb = $curRes->symb();
+ my $ressymb = $symb;
+ my $srcf = $curRes->src();
+ my $title = &Apache::lonnet::gettitle($srcf);
+ if (($curRes->is_sequence()) || ($curRes->is_page())) {
+ next unless($toshow->{$symb});
+ my ($parent,$ind,$url) = &Apache::lonnet::decode_symb($symb);
+ $icon = ' ';
+ if ($curRes->is_page()) {
+ $icon = ' ';
+ }
+ my $rowspan = 1;
+ if (ref($bymap->{$url}) eq 'HASH') {
+ $rowspan = scalar(keys(%{$bymap->{$url}}));
+ }
+ $r->print(&Apache::loncommon::start_data_table_row().
+ ''.$indent.$icon.' '.$title.' ');
+ &releases_by_map($r,$bymap,$url,$scopeorder,$lt);
+ $r->print(&Apache::loncommon::end_data_table_row());
+ } else {
+ my $rowspan;
+ if (ref($byresource->{$symb}) eq 'HASH') {
+ $rowspan += scalar(keys(%{$byresource->{$symb}}));
+ }
+ if (ref($bysubmission->{$symb}) eq 'HASH') {
+ $rowspan += scalar(keys(%{$bysubmission->{$symb}}));
+ }
+ if (ref($byresponsetype->{$symb}) eq 'HASH') {
+ $rowspan += scalar(keys(%{$byresponsetype->{$symb}}));
+ }
+ next if (!$rowspan);
+ $icon = ' ';
+ $r->print(&Apache::loncommon::start_data_table_row().
+ ''.$indent.$icon.' '.$title.' ');
+ my $newrow;
+ if (ref($byresource->{$symb}) eq 'HASH') {
+ foreach my $rev (sort(keys(%{$byresource->{$symb}}))) {
+ if ($newrow) {
+ $r->print(&Apache::loncommon::continue_data_table_row());
+ }
+ $r->print(''.$rev.' ');
+ if (ref($byresource->{$symb}{$rev}) eq 'HASH') {
+ $r->print('');
+ foreach my $scope (@{$scopeorder}) {
+ if (ref($byresource->{$symb}{$rev}{$scope}) eq 'HASH') {
+ $r->print(''.&mt('Setting - scope: [_1]',$lt->{$scope}).' ');
+ foreach my $which (sort(keys(%{$byresource->{$symb}{$rev}{$scope}}))) {
+ $r->print(''.$which.' '.
+ join(' ',@{$byresource->{$symb}{$rev}{$scope}{$which}}).
+ ' ');
+ }
+ $r->print(' ');
+ } elsif (ref($byresource->{$symb}{$rev}{$scope}) eq 'ARRAY') {
+ $r->print(''.&mt('Setting - scope: [_1]',$lt->{$scope}).' '.
+ ' '.
+ join(' ',@{$byresource->{$symb}{$rev}{$scope}}).' ');
+ }
+ }
+ $r->print('
');
+ }
+ $r->print(' ');
+ $r->print(&Apache::loncommon::end_data_table_row());
+ $newrow = 1;
+ }
+ }
+ if (ref($bysubmission->{$symb}) eq 'HASH') {
+ foreach my $rev (sort(keys(%{$bysubmission->{$symb}}))) {
+ if ($newrow) {
+ $r->print(&Apache::loncommon::continue_data_table_row());
+ }
+ $r->print(''.$rev.' ');
+ if (ref($bysubmission->{$symb}{$rev}) eq 'ARRAY') {
+ $r->print(&mt('Submissions to: ').' '.
+ join(', ',@{$bysubmission->{$symb}{$rev}}));
+ }
+ $r->print(' ');
+ $r->print(&Apache::loncommon::end_data_table_row());
+ $newrow = 1;
+ }
+ }
+ if (ref($byresponsetype->{$symb}) eq 'HASH') {
+ foreach my $rev (sort(keys(%{$byresponsetype->{$symb}}))) {
+ if ($newrow) {
+ $r->print(&Apache::loncommon::continue_data_table_row());
+ }
+ $r->print(''.$rev.' ');
+ if (ref($byresponsetype->{$symb}{$rev}) eq 'ARRAY') {
+ $r->print(&mt('Response Type(s): ').' '.
+ join(' ',@{$byresponsetype->{$symb}{$rev}}));
+ }
+ $r->print(' ');
+ }
+ $r->print(&Apache::loncommon::end_data_table_row());
+ }
+ }
+ }
+ }
+ $r->print(&Apache::loncommon::end_data_table());
+ }
+ return;
+}
+
+sub releases_by_map {
+ my ($r,$bymap,$url,$scopeorder,$lt) = @_;
+ return unless ((ref($bymap) eq 'HASH') && (ref($scopeorder) eq 'ARRAY'));
+ my $newrow = 0;
+ if (ref($bymap->{$url}) eq 'HASH') {
+ foreach my $rev (sort(keys(%{$bymap->{$url}}))) {
+ if ($newrow) {
+ $r->print(&Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::continue_data_table_row());
+ }
+ $r->print(''.$rev.' ');
+ if (ref($bymap->{$url}{$rev}) eq 'HASH') {
+ $r->print('');
+ foreach my $scope (@{$scopeorder}) {
+ if (ref($bymap->{$url}{$rev}{$scope}) eq 'HASH') {
+ $r->print(''.&mt('Setting - scope: [_1]',$lt->{$scope}).' ');
+ foreach my $which (sort(keys(%{$bymap->{$url}{$rev}{$scope}}))) {
+ $r->print(''.$which.' '.
+ join(' ',@{$bymap->{$url}{$rev}{$scope}{$which}}).
+ ' ');
+ }
+ $r->print(' ');
+ } elsif (ref($bymap->{$url}{$rev}{$scope}) eq 'ARRAY') {
+ $r->print(''.&mt('Setting - scope: [_1]',$lt->{$scope}).
+ ' '.
+ join(' ',@{$bymap->{$url}{$rev}{$scope}}).' ');
+ }
+ }
+ $r->print('
');
+ }
+ $r->print(' ');
+ $newrow = 1;
+ }
+ } else {
+ $r->print(' ');
+ }
+ return;
+}
+
+sub get_param_description {
+ my ($stdtype,$value) = @_;
+ my $name = $value;
+ my $paramstrings = &Apache::lonparmset::standard_string_options($stdtype);
+ unless (ref($paramstrings) eq 'ARRAY') {
+ return $name;
+ }
+ foreach my $possibilities (@{$paramstrings}) {
+ next unless (ref($possibilities) eq 'ARRAY');
+ my ($thing, $description) = @{ $possibilities };
+ if ($thing eq $value) {
+ $name = $description;
+ last;
+ }
+ }
+ return $name;
+}
+
+sub update_releasereq {
+ my $readmap = 1;
+ my $getrelreq = 1;
+ if (ref($modified_courses) eq 'ARRAY') {
+ foreach my $item (@{$modified_courses}) {
+ if (ref($item) eq 'ARRAY') {
+ my ($cdom,$cnum,$chome,$crstype) = @{$item};
+ &Apache::lonrelrequtils::modify_course_relreq(undef,undef,$cnum,$cdom,
+ $chome,$crstype,$cdom.'_'.$cnum,
+ $readmap,$getrelreq);
+ }
+ }
+ $modified_courses = [];
+ }
+ undef($registered_cleanup);
+ return;
+}
+
+sub show_autocoowners {
+ my (@currcoown) = @_;
+ my $output = ''.&mt('Co-ownership is set automatically when a Course Coordinator role[_1] 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,$currcoownref,$noedit) = @_;
+ my ($output,@pendingcoown,@othercoords,@currcoown);
+ my $pendingcoowners =
+ $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
+ if ($pendingcoowners) {
+ @pendingcoown = split(',',$pendingcoowners);
+ }
+ if (ref($currcoownref) eq 'ARRAY') {
+ @currcoown = @{$currcoownref};
+ }
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+ 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 .= ' '.&Apache::loncommon::plainname($co_uname,$co_dom).' '.(' '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 .= ' '.&Apache::loncommon::plainname($co_uname,$co_dom).' '.(' '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 .= ' '.&Apache::loncommon::plainname($co_uname,$co_dom).' '.(' '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,$currcoownref,$noedit) = @_;
+ my (@pendingcoown,@currcoown);
+ my $pendingcoowners =
+ $env{'course.'.$env{'request.course.id'}.'.internal.pendingco-owners'};
+ if ($pendingcoowners) {
+ @pendingcoown = split(',',$pendingcoowners);
+ }
+ if (ref($currcoownref) eq 'ARRAY') {
+ @currcoown = @{$currcoownref};
+ }
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+ 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().'';
+ }
+ $output .= &mt('Current co-owners are:').' '.
+ join(', ', map { &Apache::loncommon::plainname(split(':',$_)); } (@currcoown));
+ if ($is_coowner || $is_pending) {
+ $output .= ' '.&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:').' '.&mt('Discontinue?').' ';
+ } else {
+ $output .= &mt('The course owner has invited you to become a co-owner:').' '.&mt('Accept?').' '.(' 'x2).
+ ' '.&mt('Decline?').' ';
+ }
+ $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) = @_;
+ my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
my %items = (
languages => {
- text => &mt($itemtext->{'languages'}).' '.
- &mt("(will override user's preference)"),
+ text => ''.&mt($itemtext->{'languages'}).' '.
+ &mt("(overrides individual user preference)"),
input => 'selectbox',
},
timezone => {
- text => &mt($itemtext->{'timezone'}),
+ text => ''.&mt($itemtext->{'timezone'}).' ',
input => 'selectbox',
},
datelocale => {
- text => &mt($itemtext->{'datelocale'}),
+ text => ''.&mt($itemtext->{'datelocale'}).' ',
input => 'selectbox',
},
);
- my $datatable;
+ my ($datatable,$disabled);
my $count = 0;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
foreach my $item (@{$ordered}) {
$count ++;
- $datatable .= &item_table_row_start($items{$item}{text},$count);
+ my $colspan;
+ unless ($item eq 'languages') {
+ $colspan = 2;
+ }
+ $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan);
if ($item eq 'timezone') {
my $includeempty = 1;
my $timezone = &Apache::lonlocal::gettimezone();
+ my $onchange;
+ unless ($noedit) {
+ $onchange = ' onchange="javascript:toggleTimeZone();"';
+ }
+ my $id = ' id="LC_set_timezone"';
$datatable .=
- &Apache::loncommon::select_timezone($item,$timezone,undef,
- $includeempty);
+ &Apache::loncommon::select_timezone($item,$timezone,$onchange,
+ $includeempty,$id,$disabled);
+ my $tzsty = 'none';
+ if ($timezone ne '') {
+ $tzsty = 'block';
+ }
+ $datatable .= ''.
+ ''.
+ &mt('Override individual user preference?').
+ &yesno_radio('tzover',$settings,undef,1,'',$noedit).
+ '
';
} elsif ($item eq 'datelocale') {
my $includeempty = 1;
my $locale_obj = &Apache::lonlocal::getdatelocale();
@@ -1523,15 +5235,18 @@ sub print_localization {
}
$datatable .=
&Apache::loncommon::select_datelocale($item,$currdatelocale,
- undef,$includeempty);
+ undef,$includeempty,$disabled);
} else {
if ($settings->{$item} eq '') {
- $datatable .=
- &Apache::loncommon::select_language('languages_0','',1);
+ unless ($noedit) {
+ $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();
+ $datatable .= ' '.
+ &Apache::loncommon::start_data_table();
if (@languages > 0) {
my %langchoices = &get_lang_choices();
foreach my $lang (@languages) {
@@ -1546,19 +5261,22 @@ sub print_localization {
' '.
' '.
+ 'name="languages_delete" value="'.$num.'"'.$disabled.' />'.
&mt('Delete').' '.
&Apache::loncommon::end_data_table_row();
$num ++;
}
}
- $datatable .= &Apache::loncommon::start_data_table_row().
+ unless ($noedit) {
+ $datatable .=
+ &Apache::loncommon::start_data_table_row().
''.
&mt('Additional language:'). ' '.
&Apache::loncommon::select_language('languages_'.$num,'',1).
' '.
- ' '.&Apache::loncommon::end_data_table_row().
- &Apache::loncommon::end_data_table();
+ ''.&Apache::loncommon::end_data_table_row();
+ }
+ $datatable .= &Apache::loncommon::end_data_table().' ';
}
}
$datatable .= &item_table_row_end();
@@ -1579,7 +5297,7 @@ sub get_lang_choices {
}
sub print_feedback {
- my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
+ my ($position,$cdom,$settings,$ordered,$itemtext,$rowtotal,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
@@ -1608,23 +5326,31 @@ sub print_feedback {
my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
my @sections = sort( { $a <=> $b } keys(%sections));
my %lt = &Apache::lonlocal::texthash (
- currone => 'Current recipient:',
- curmult => 'Current recipients:',
- add => 'Additional recipient:',
- del => 'Delete?',
- sec => 'Sections:',
+ currone => 'Current recipient:',
+ currmult => 'Current recipients:',
+ add => 'Additional recipient:',
+ del => 'Delete?',
+ sec => 'Sections:',
);
-
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
foreach my $item (@{$ordered}) {
$count ++;
- $datatable .= &item_table_row_start($items{$item}{text},$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",2);
+ }
if ($position eq 'top') {
my $includeempty = 0;
- $datatable .= &user_table($cdom,$item,\@sections,
- $settings->{$item},\%lt);
+ $datatable .= ''.
+ &user_table($cdom,$item,\@sections,
+ $settings->{$item},\%lt,$noedit);
} else {
$datatable .= &Apache::lonhtmlcommon::textbox($item.'.text',
- $settings->{$item.'.text'},$items{$item}{size});
+ $settings->{$item.'.text'},$items{$item}{size},$disabled);
}
$datatable .= &item_table_row_end();
}
@@ -1633,15 +5359,21 @@ sub print_feedback {
}
sub user_table {
- my ($cdom,$item,$sections,$currvalue,$lt) = @_;
+ my ($cdom,$item,$sections,$currvalue,$lt,$noedit) = @_;
my $output;
if ($currvalue eq '') {
- $output .= &select_recipient($item,'0',$cdom,$sections);
+ unless ($noedit) {
+ $output .= &select_recipient($item,'0',$cdom,$sections);
+ }
} else {
my $num = 0;
my @curr = split(/,/,$currvalue);
- $output .= &Apache::loncommon::start_data_table();
+ $output .= '';
my ($currusers);
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
foreach my $val (@curr) {
next if ($val eq '');
my ($uname,$udom,$seclist) = ($val =~ /^($match_username):($match_domain)(\(?[^\)]*\)?)$/);
@@ -1653,7 +5385,7 @@ sub user_table {
$currusers .= ''.
''.
' '.
+ 'name="'.$item.'_delete" value="'.$num.'"'.$disabled.' />'.
$lt->{'del'}.' '.
' '.(' 'x2).
@@ -1664,31 +5396,34 @@ sub user_table {
if (@{$sections}) {
$currusers.= (' 'x3).$lt->{'sec'}.' '.
&select_sections($item,$num,$sections,
- \@selsec);
+ \@selsec,$noedit);
}
}
$currusers .= ' ';
$num ++;
}
if ($num) {
- $output .= &Apache::loncommon::start_data_table_row().
+ $output .= ''.
'';
- if ($num > 1) {
+ if ($num == 1) {
$output .= $lt->{'currone'};
} else {
$output .= $lt->{'currmult'};
}
$output .= ' '.
' '.
- &Apache::loncommon::end_data_table_row();
+ ' ';
}
- $output .= &Apache::loncommon::start_data_table_row().
+ unless ($noedit) {
+ $output .=
+ ''.
''.
$lt->{'add'}.' '.
&select_recipient($item,$num,$cdom,$sections).
' '.
- ' '.&Apache::loncommon::end_data_table_row().
- &Apache::loncommon::end_data_table();
+ ' ';
+ }
+ $output .= '
';
}
return $output;
}
@@ -1698,10 +5433,9 @@ sub select_recipient {
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 $css_class = ($num % 2)?'LC_even_row':'LC_odd_row';
+ $item.'_udom_'.$num,'only');
my $output =
- ''.&mt('Username').' '.
+ ''.&mt('Username').' '.
' '.
''.&mt('Domain').' '.$domform.' ';
if (ref($sections) eq 'ARRAY') {
@@ -1716,29 +5450,40 @@ sub select_recipient {
}
sub select_sections {
- my ($item,$num,$sections,$selected) = @_;
- my ($output,@currsecs,$allsec);
+ my ($item,$num,$sections,$selected,$noedit,$allval) = @_;
+ my ($output,@currsecs,$allsec,$disabled);
if (ref($selected) eq 'ARRAY') {
@currsecs = @{$selected};
}
if (!@currsecs) {
$allsec = ' selected="selected"';
}
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
if (ref($sections) eq 'ARRAY') {
if (@{$sections}) {
my $mult;
if (@{$sections} > 1) {
$mult = ' multiple="multiple"';
+ my $size;
if (@{$sections} > 3) {
- $mult .= ' size="4"';
+ $size = 4;
+ } else {
+ $size = 1 + scalar(@{$sections});
}
+ $mult .= ' size="'.$size.'"';
+ }
+ my $name = $item.'_sections';
+ unless ($item eq 'hidetotals') {
+ $name .= '_'.$num;
}
- $output = ''.
- ' '.&mt('All').' ';
+ $output = ''.
+ ' '.&mt('All').' ';
foreach my $sec (@{$sections}) {
my $is_sel;
if ((@currsecs) && (grep(/^\Q$sec\E$/,@currsecs))) {
- $is_sel = 'selected="selected"';
+ $is_sel = ' selected="selected"';
}
$output .= ''.$sec.' ';
}
@@ -1749,14 +5494,14 @@ sub select_sections {
}
sub print_discussion {
- my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
+ my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
my %items = (
'plc.roles.denied' => {
- text => ''.&mt($itemtext->{'plc.roles.denied'}).' '.
- &Apache::loncommon::help_open_topic("Course_Disable_Discussion").
+ text => ''.&mt($itemtext->{'plc.roles.denied'}).' '.
+ &Apache::loncommon::help_open_topic("Course_Disable_Discussion").' '.
&mt('(role-based)'),
input => 'checkbox',
},
@@ -1768,8 +5513,8 @@ sub print_discussion {
},
'pch.roles.denied' => {
- text => ''.&mt($itemtext->{'pch.roles.denied'}).' '.
- &Apache::loncommon::help_open_topic("Course_Disable_Discussion").' '.
+ text => ''.&mt($itemtext->{'pch.roles.denied'}).' '.
+ &Apache::loncommon::help_open_topic("Course_Disable_Discussion").' '.
&mt('(role-based)'),
input => 'checkbox',
},
@@ -1788,6 +5533,11 @@ sub print_discussion {
text => ''.&mt($itemtext->{'allow_discussion_post_editing'}).' ',
input => 'checkbox',
},
+ 'discussion_post_fonts' => {
+ text => ''.&mt($itemtext->{'discussion_post_fonts'}).' ',
+ input => 'textbox',
+ size => '20',
+ },
);
my $datatable;
my $count;
@@ -1795,38 +5545,58 @@ sub print_discussion {
my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
my @sections = sort( { $a <=> $b } keys(%sections));
my %lt = &Apache::lonlocal::texthash (
- currone => 'Disallowed:',
- curmult => 'Disallowed:',
- add => 'Disallow more:',
- del => 'Delete?',
- sec => 'Sections:',
+ currone => 'Disallowed:',
+ currmult => 'Disallowed:',
+ add => 'Disallow more:',
+ del => 'Delete?',
+ sec => 'Sections:',
);
-
foreach my $item (@{$ordered}) {
$count ++;
- $datatable .= &item_table_row_start($items{$item}{text},$count);
+ my $colspan;
+ if ($item eq 'allow_limited_html_in_feedback') {
+ $colspan = 2;
+ }
+ $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan);
if ($item eq 'plc.roles.denied') {
- $datatable .= ''.&role_checkboxes($cdom,$cnum,$item,$settings).
+ $datatable .= ''.
+ ''.&role_checkboxes($cdom,$cnum,$item,$settings,undef,undef,$noedit).
'
';
} elsif ($item eq 'plc.users.denied') {
- $datatable .= &user_table($cdom,$item,undef,
- $settings->{$item},\%lt);
+ $datatable .= ' '.
+ &user_table($cdom,$item,undef,
+ $settings->{$item},\%lt,$noedit);
} elsif ($item eq 'pch.roles.denied') {
- $datatable .= ''.&role_checkboxes($cdom,$cnum,$item,$settings).
+ $datatable .= ''.
+ ''.&role_checkboxes($cdom,$cnum,$item,$settings,undef,undef,$noedit).
'
';
} elsif ($item eq 'pch.users.denied') {
- $datatable .= &user_table($cdom,$item,undef,
- $settings->{$item},\%lt);
+ $datatable .= ' '.
+ &user_table($cdom,$item,undef,
+ $settings->{$item},\%lt,$noedit);
} elsif ($item eq 'allow_limited_html_in_feedback') {
- $datatable .= &yesno_radio($item,$settings);
+ $datatable .= &yesno_radio($item,$settings,undef,undef,undef,$noedit);
} elsif ($item eq 'allow_discussion_post_editing') {
- $datatable .= &Apache::loncommon::start_data_table().
+ $datatable .= ' '.
+ &Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_row().
''.&mt('Role').' '.
&mt('Sections').' '.
&Apache::loncommon::end_data_table_row().
- &role_checkboxes($cdom,$cnum,$item,$settings,1).
- &Apache::loncommon::end_data_table();
+ &role_checkboxes($cdom,$cnum,$item,$settings,1,undef,$noedit).
+ &Apache::loncommon::end_data_table().' ';
+ } elsif ($item eq 'discussion_post_fonts') {
+ $datatable .= ' '.
+ &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_row().
+ ''.&mt('Sum of likes/dislikes').' '.
+ ''.&mt('font-size').' '.
+ ''.&mt('font-weight').' '.
+ ''.&mt('font-style').' '.
+ ''.&mt('Other css').' '.
+ &Apache::loncommon::end_data_table_row().
+ &set_discussion_fonts($cdom,$cnum,$item,$settings,$noedit).
+ &Apache::loncommon::end_data_table().' ';
}
$datatable .= &item_table_row_end();
}
@@ -1835,8 +5605,13 @@ sub print_discussion {
}
sub role_checkboxes {
- my ($cdom,$cnum,$item,$settings,$showsections) = @_;
- my @roles = ('st','ad','ta','ep','in','cc');
+ my ($cdom,$cnum,$item,$settings,$showsections,$crstype,$noedit) = @_;
+ my @roles = ('st','ad','ta','ep','in');
+ if ($crstype eq 'Community') {
+ push(@roles,'co');
+ } else {
+ push(@roles,'cc');
+ }
my $output;
my (@current,@curr_roles,%currsec,@sections);
if ($showsections) {
@@ -1868,12 +5643,16 @@ sub role_checkboxes {
}
my $numinrow = 3;
my $count = 0;
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
foreach my $role (@roles) {
my $checked = '';
if (grep(/^\Q$role\E$/,@current)) {
$checked = ' checked="checked" ';
}
- my $plrole=&Apache::lonnet::plaintext($role);
+ my $plrole=&Apache::lonnet::plaintext($role,$crstype);
if ($showsections) {
$output .= &Apache::loncommon::start_data_table_row();
} else {
@@ -1885,12 +5664,12 @@ sub role_checkboxes {
$output .= '';
}
}
- $output .= ' '.
+ $output .= ' '.
$plrole.' ';
if ($showsections) {
$output .= ''.
- &select_sections($item,$role,\@sections,$currsec{$role}).
+ &select_sections($item,$role,\@sections,$currsec{$role},$noedit).
' ';
}
$count ++;
@@ -1917,12 +5696,12 @@ sub role_checkboxes {
$output .= '';
}
}
- $output .= ' '.$rolename.
+ $output .= ' '.$rolename.
' ';
if ($showsections) {
$output .= ''.
- &select_sections($item,$role,\@sections,$currsec{$role}).
+ &select_sections($item,$role,\@sections,$currsec{$role},$noedit).
' '.&Apache::loncommon::end_data_table_row();
}
$total ++;
@@ -1943,18 +5722,111 @@ sub role_checkboxes {
return $output;
}
+sub set_discussion_fonts {
+ my ($cdom,$cnum,$item,$settings,$noedit) = @_;
+ my ($classorder,$classtitles) = &discussion_vote_classes();
+ my ($styleorder,$styleitems) = &discussion_vote_styles();
+ my $output;
+ if (ref($classorder) eq 'ARRAY') {
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+ foreach my $cat (@{$classorder}) {
+ my %curr = ();
+ ($curr{'size'},$curr{'weight'},$curr{'style'},$curr{'other'}) =
+ split(/,/,$settings->{'discussion_post_fonts_'.$cat});
+ $output .= &Apache::loncommon::start_data_table_row().
+ ''.$classtitles->{$cat}.' ';
+ if (ref($styleorder) eq 'ARRAY') {
+ foreach my $item (@{$styleorder}) {
+ $output .= '';
+ my $selitem = $item;
+ if ($item eq 'size') {
+ my ($currsize,$currunit);
+ if ($curr{'size'} =~ /^(\d+)(px|%)$/) {
+ ($currsize,$currunit) = ($1,$2);
+ $curr{'size'} = $currunit;
+ }
+ $output .= ' '.
+ ' ';
+ $selitem = 'unit';
+ }
+ if ((ref($styleitems) eq 'HASH') && (ref($styleitems->{$item}) eq 'ARRAY')) {
+ $output .= '';
+ foreach my $val (@{$styleitems->{$item}}) {
+ my $sel;
+ if ($val eq $curr{$item}) {
+ $sel = ' selected="selected"';
+ }
+ $output .= ''.$val.' ';
+ }
+ }
+ }
+ }
+ $output .= ' ';
+ }
+ $output .= &Apache::loncommon::end_data_table_row();
+ }
+ return $output;
+}
+
+sub discussion_vote_classes {
+ my $classorder = ['twoplus','oneplus','zero','oneminus','twominus'];
+ my %classtitles = &Apache::lonlocal::texthash(
+ 'twoplus' => 'Two sigma above mean',
+ 'oneplus' => 'One sigma above mean',
+ 'zero' => 'Within one sigma of mean',
+ 'oneminus' => 'One sigma below mean',
+ 'twominus' => 'Two sigma below mean',
+ );
+ return ($classorder,\%classtitles);
+}
+
+sub discussion_vote_styles {
+ my $styleorder = ['size','weight','style'];
+ my $styleitems = {
+ size => ['','px','%','xx-small','x-small','small','medium','large',
+ 'x-large','xx-large','smaller','larger'],
+ weight => ['','normal','bold','bolder','lighter','100','200','300','400',
+ '500','600','700','800','900'],
+ style => ['','normal','italic','oblique'],
+ };
+ return ($styleorder,$styleitems);
+}
+
sub print_classlists {
- my ($position,$cdom,$settings,$itemtext,$rowtotal) = @_;
+ my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype,$noedit) = @_;
my @ordered;
if ($position eq 'top') {
@ordered = ('default_enrollment_start_date',
'default_enrollment_end_date');
+ if ($crstype eq 'Course') {
+ push(@ordered,'defaultcredits');
+ }
} elsif ($position eq 'middle') {
- @ordered = ('nothideprivileged');
+ @ordered = ('nothideprivileged','checkforpriv');
} else {
@ordered = ('student_classlist_view',
- 'student_opt_in','student_classlist_portfiles');
+ 'student_classlist_opt_in',
+ 'student_classlist_portfiles');
}
+ my %lt;
+
+ if ($crstype eq 'Community') {
+ %lt = &Apache::lonlocal::texthash (
+ disabled => 'No viewable membership list',
+ section => "Membership of viewer's section",
+ all => 'List of all members',
+ );
+ } else {
+ %lt = &Apache::lonlocal::texthash (
+ disabled => 'No viewable classlist',
+ section => "Classlist of viewer's section",
+ all => 'Classlist of all students',
+ );
+ }
+
my %items = (
'default_enrollment_start_date' => {
text => ''.&mt($itemtext->{'default_enrollment_start_date'}).' ',
@@ -1964,24 +5836,28 @@ sub print_classlists {
text => ''.&mt($itemtext->{'default_enrollment_end_date'}).' ',
input => 'dates',
},
+ 'defaultcredits' => {
+ text => ''.&mt($itemtext->{'defaultcredits'}).' ',
+ },
'nothideprivileged' => {
text => ''.&mt($itemtext->{'nothideprivileged'}).' ',
input => 'checkbox',
},
+ 'checkforpriv' => {
+ text => ''.&mt($itemtext->{'checkforpriv'}).' ',
+ input => 'selectbox',
+ },
+
'student_classlist_view' => {
text => ''.&mt($itemtext->{'student_classlist_view'}).' ',
input => 'selectbox',
- options => {
- disabled => &mt('No viewable classlist'),
- section => &mt("Classlist of viewer's section"),
- all => &mt('Classlist of all students'),
- },
+ options => \%lt,
order => ['disabled','all','section'],
},
- 'student_opt_in' => {
- text => ''.&mt($itemtext->{'student_opt_in'}).' ',
+ 'student_classlist_opt_in' => {
+ text => ''.&mt($itemtext->{'student_classlist_opt_in'}).' ',
input => 'radio',
},
@@ -1994,14 +5870,20 @@ sub print_classlists {
($settings->{'student_classlist_view'} eq 'section')) {
$settings->{'student_classlist_view'} = 'disabled';
}
- return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal);
+ return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'classlists',$noedit);
}
sub print_appearance {
- my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
+ my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
+ my $mathdef;
+ if ($crstype eq 'Community') {
+ $mathdef = &mt("None specified - use member's choice");
+ } else {
+ $mathdef = &mt("None specified - use student's choice");
+ }
my %items = (
'default_xml_style' => {
text => ''.&mt($itemtext->{'default_xml_style'}).' '.
@@ -2024,24 +5906,46 @@ sub print_appearance {
text => ''.&mt($itemtext->{'texengine'}).' ',
input => 'selectbox',
options => {
- jsMath => 'jsMath',
+ MathJax => 'MathJax',
mimetex => &mt('Convert to Images'),
tth => &mt('TeX to HTML'),
},
- order => ['jsMath','mimetex','tth'],
- nullval => &mt("None specified - use student's choice"),
+ order => ['MathJax','mimetex','tth'],
+ nullval => $mathdef,
},
'tthoptions' => {
text => ''.&mt($itemtext->{'tthoptions'}).' ',
input => 'textbox',
size => 40,
},
+ 'uselcmath' => {
+ text => ''.&mt($itemtext->{'uselcmath'}).' ',
+ input => 'radio',
+ },
+ 'usejsme' => {
+ text => ''.&mt($itemtext->{'usejsme'}).' ',
+ input => 'radio',
+ },
+ 'inline_chem' => {
+ text => ''.&mt($itemtext->{'inline_chem'}).' ',
+ input => 'radio',
+ },
+ 'extresource' => {
+ text => ''.&mt($itemtext->{'extresource'}).' ',
+ input => 'selectbox',
+ options => {
+ iframe => 'In iframe',
+ tab => 'In new tab',
+ window => 'In pop-up window',
+ },
+ order => ['iframe','tab','window'],
+ },
);
- return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
+ return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'appearance',$noedit);
}
sub print_grading {
- my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
+ my ($cdom,$cnum,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
@@ -2052,14 +5956,15 @@ sub print_grading {
input => 'selectbox',
options => {
standard => &mt('Standard: shows points'),
- external => &mt('External: shows number of completed parts'),
+ external => &mt('External: shows number of completed parts and totals'),
+ externalnototals => &mt('External: shows only number of completed parts'),
spreadsheet => &mt('Spreadsheet: (with link to detailed scores)'),
},
- order => ['standard','external','spreadsheet'],
+ order => ['standard','external','externalnototals','spreadsheet'],
},
'rndseed' => {
text => ''.&mt($itemtext->{'rndseed'}).' '.
- ''.' '.
+ ''.' '.
&mt('Modifying this will make problems have different numbers and answers!').
' ',
input => 'selectbox',
@@ -2072,6 +5977,7 @@ sub print_grading {
'64bit5' => '64bit5',
},
order => ['32bit','64bit','64bit2','64bit3','64bit4','64bit5'],
+ advanced => 1
},
'receiptalg' => {
text => ''.&mt($itemtext->{'receiptalg'}).' '.
@@ -2083,17 +5989,18 @@ sub print_grading {
receipt3 => 'receipt3',
},
order => ['receipt','receipt2','receipt3'],
+ advanced => 1
},
'disablesigfigs' => {
text => ''.&mt($itemtext->{'disablesigfigs'}).' ',
input => 'radio',
},
);
- return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
+ return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'grading',$noedit,$cnum);
}
sub print_printouts {
- my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
+ my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
@@ -2121,7 +6028,7 @@ sub print_printouts {
A6 => &mt('A6').' [105x148 mm]',
},
order => ['Letter','Legal','Tabloid','Executive','A2','A3','A4','A5','A6'],
- nullval => 'None specified',
+ nullval => &mt('None specified'),
},
print_header_format => {
text => ''.&mt($itemtext->{'print_header_format'}).' ',
@@ -2131,12 +6038,22 @@ sub print_printouts {
text => ''.&mt($itemtext->{'disableexampointprint'}).' ',
input => 'radio',
},
+ canuse_pdfforms => {
+ text => ''.&mt($itemtext->{'canuse_pdfforms'}).' ',
+ input => 'selectbox',
+ options => {
+ 1 => &mt('Yes'),
+ 0 => &mt('No'),
+ },
+ order => ['1','0'],
+ nullval => &mt('None specified - use domain default'),
+ }
);
- return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
+ return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'printouts',$noedit);
}
sub print_spreadsheet {
- my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
+ my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
@@ -2168,21 +6085,29 @@ sub print_spreadsheet {
input => 'radio',
},
);
- return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
-}
+ return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'spreadsheet',$noedit);
+}
sub print_bridgetasks {
- my ($cdom,$settings,$ordered,$itemtext,$rowtotal) = @_;
+ my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) {
return;
}
+ my ($stumsg,$msgnote);
+ if ($crstype eq 'Community') {
+ $stumsg = &mt('Send message to member');
+ $msgnote = &mt('Message to member and add to user notes');
+ } else {
+ $stumsg = &mt('Send message to student');
+ $msgnote = &mt('Message to student and add to user notes');
+ }
my %items = (
task_messages => {
text => ''.&mt($itemtext->{'task_messages'}).' ',
input => 'selectbox',
options => {
- only_student => &mt('Send message to student'),
- student_and_user_notes_screen => &mt('Message to student and add to user notes'),
+ only_student => $stumsg,
+ student_and_user_notes_screen => $msgnote,
},
order => ['only_student','student_and_user_notes_screen'],
nullval => &mt('No message or record in user notes'),
@@ -2202,11 +6127,1252 @@ sub print_bridgetasks {
input => 'radio',
},
);
- return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal);
+ return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks',$noedit);
+}
+
+sub print_ltitools {
+ my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_;
+ my ($datatable,$disabled,$css_class,$dest);
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+ my $itemcount = 1;
+ unless ($context eq 'domain') {
+ my %tooltypes = &Apache::loncommon::usable_exttools();
+ unless ($tooltypes{'crs'}) {
+ my $showtype = 'course';
+ if ($crstype eq 'Community') {
+ $showtype = lc($crstype);
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable = ''.
+ &mt("Definition of external tools is not enabled for this $showtype.").' ';
+ if ($tooltypes{'dom'}) {
+ $datatable .= &mt("Contact an administrator for the $showtype domain ([_1]) to request this feature be enabled.",
+ ''.$cdom.' ').
+ ' '.
+ &mt("Use of external tools defined at a domain level is enabled, so the $showtype editor can be used to add tool(s), if any have been defined.");
+ } else {
+ $datatable .= &mt("Use of external tools defined at a domain level is not enabled, either, for this $showtype.").
+ ' '.
+ &mt("Contact an administrator for the $showtype domain ([_1]) to request changes.",
+ ''.$cdom.' ');
+
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ return $datatable;
+ }
+ }
+ my %lt = <itools_names();
+ my $maxnum = 0;
+ my %ordered;
+ if (ref($settings) eq 'HASH') {
+ foreach my $item (keys(%{$settings})) {
+ if (ref($settings->{$item}) eq 'HASH') {
+ my $num = $settings->{$item}{'order'};
+ $ordered{$num} = $item;
+ }
+ }
+ }
+
+ if ($context eq 'domain') {
+ $dest = '/adm/domainprefs';
+ } else {
+ $dest = '/adm/courseprefs';
+ }
+ my ($switchserver,$switchmessage);
+ $switchserver = &check_switchserver($cdom,$cnum,$context,$dest);
+ if ($switchserver) {
+ if ($context eq 'domain') {
+ $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver);
+ } elsif ($crstype eq 'Community') {
+ $switchmessage = &mt("submit from community's home server: [_1].",$switchserver);
+ } else {
+ $switchmessage = &mt("submit from course's home server: [_1].",$switchserver);
+ }
+ }
+ my $maxnum = scalar(keys(%ordered));
+ my @courseroles = ('cc','in','ta','ep','st');
+ my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner);
+ my @fields = ('fullname','firstname','lastname','email','roles','user');
+ if (keys(%ordered)) {
+ my @items = sort { $a <=> $b } keys(%ordered);
+ for (my $i=0; $i<@items; $i++) {
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $item = $ordered{$items[$i]};
+ my ($title,$key,$url,$usable,$lifetime,$imgsrc,%sigsel);
+ if (ref($settings->{$item}) eq 'HASH') {
+ $title = $settings->{$item}->{'title'};
+ $url = $settings->{$item}->{'url'};
+ $key = $settings->{$item}->{'key'};
+ $usable = $settings->{$item}->{'usable'};
+ $lifetime = $settings->{$item}->{'lifetime'};
+ my $image = $settings->{$item}->{'image'};
+ if ($image ne '') {
+ $imgsrc = ' ';
+ }
+ if ($settings->{$item}->{'sigmethod'} eq 'HMAC-256') {
+ $sigsel{'HMAC-256'} = ' selected="selected"';
+ } else {
+ $sigsel{'HMAC-SHA1'} = ' selected="selected"';
+ }
+ }
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_".$item."'".');"';
+ $datatable .= ''
+ .'';
+ for (my $k=0; $k<=$maxnum; $k++) {
+ my $vpos = $k+1;
+ my $selstr;
+ if ($k == $i) {
+ $selstr = ' selected="selected" ';
+ }
+ $datatable .= ''.$vpos.' ';
+ }
+ $datatable .= ' '.(' 'x2).
+ ' '.
+ &mt('Delete?').' '.
+ ''.
+ ''.&mt('Required settings').' '.
+ ''.$lt{'title'}.': '.
+ (' 'x2).
+ ''.$lt{'version'}.':'.
+ '1.1 '.
+ (' 'x2).
+ ''.$lt{'msgtype'}.':'.
+ 'Launch '.
+ (' 'x2).
+ ''.$lt{'sigmethod'}.':'.
+ 'HMAC-SHA1 '.
+ 'HMAC-SHA256 '.
+ ' '.
+ ''.$lt{'url'}.': '.
+ (' 'x2).
+ ''.$lt{'lifetime'}.':'.
+ ' ';
+ if ($key ne '') {
+ $datatable .= ''.$lt{'key'};
+ if ($noedit) {
+ $datatable .= ': ['.&mt('not shown').']';
+ } elsif ($switchserver) {
+ $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']';
+ } else {
+ $datatable .= ': ';
+ }
+ $datatable .= ' '.(' 'x2);
+ } elsif (!$switchserver) {
+ $datatable .= ''.$lt{'key'}.':'.
+ ' '.
+ ' '.(' 'x2);
+ }
+ if ($switchserver) {
+ if ($usable ne '') {
+ $datatable .= '
'.
+ $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).' '.
+ ''.&mt('Change secret?').
+ ' '.&mt('No').' '.
+ (' 'x2).
+ ' '.&mt('Yes').' '.(' 'x2).
+ '
'.
+ ' - '.$switchmessage.' '.
+ '';
+ } elsif ($key eq '') {
+ $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.' '."\n";
+ } else {
+ $datatable .= ''.&mt('Secret required').' - '.$switchmessage.' '."\n";
+ }
+ $datatable .= ' ';
+ } else {
+ if ($usable ne '') {
+ $datatable .= '
'.
+ $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).' '.
+ ''.&mt('Change?').
+ ' '.&mt('No').' '.
+ (' 'x2).
+ ' '.&mt('Yes').
+ '
'.
+ ''.&mt('New Secret').':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
+ ' ';
+ } else {
+ $datatable .=
+ ''.$lt{'secret'}.':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
+ ' ';
+ }
+ }
+ $datatable .= ' '.
+ ''.&mt('Optional settings').' '.
+ ''.&mt('Display target:');
+ my %currdisp;
+ if (ref($settings->{$item}->{'display'}) eq 'HASH') {
+ if ($settings->{$item}->{'display'}->{'target'} eq 'window') {
+ $currdisp{'window'} = ' checked="checked"';
+ } elsif ($settings->{$item}->{'display'}->{'target'} eq 'tab') {
+ $currdisp{'tab'} = ' checked="checked"';
+ } else {
+ $currdisp{'iframe'} = ' checked="checked"';
+ }
+ if ($settings->{$item}->{'display'}->{'width'} =~ /^(\d+)$/) {
+ $currdisp{'width'} = $1;
+ }
+ if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) {
+ $currdisp{'height'} = $1;
+ }
+ $currdisp{'linktext'} = $settings->{$item}->{'display'}->{'linktext'};
+ $currdisp{'explanation'} = $settings->{$item}->{'display'}->{'explanation'};
+ } else {
+ $currdisp{'iframe'} = ' checked="checked"';
+ }
+ foreach my $disp ('iframe','tab','window') {
+ $datatable .= ' '.
+ $lt{$disp}.' '.(' 'x2);
+ }
+ $datatable .= (' 'x4);
+ foreach my $dimen ('width','height') {
+ $datatable .= ''.$lt{$dimen}.' '.
+ ' '.
+ (' 'x2);
+ }
+ $datatable .= ' '.
+ ''.$lt{'linktext'}.' '.
+ '
'.
+ ''.$lt{'explanation'}.' '.
+ '
';
+ my %units = (
+ 'passback' => 'days',
+ 'roster' => 'seconds',
+ );
+ foreach my $extra ('passback','roster') {
+ my $validsty = 'none';
+ my $currvalid;
+ my $checkedon = '';
+ my $checkedoff = ' checked="checked"';
+ if ($settings->{$item}->{$extra}) {
+ $checkedon = $checkedoff;
+ $checkedoff = '';
+ $validsty = 'inline-block';
+ if ($settings->{$item}->{$extra.'valid'} =~ /^\d+\.?\d*$/) {
+ $currvalid = $settings->{$item}->{$extra.'valid'};
+ }
+ }
+ my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','$i'".');"';
+ $datatable .= ''.$lt{$extra}.' '.
+ ' '.
+ &mt('No').' '.(' 'x2).
+ ' '.
+ &mt('Yes').'
'.
+ '
';
+ }
+ $datatable .= ''.$lt{'icon'}.': ';
+ if ($imgsrc) {
+ $datatable .= $imgsrc.
+ ' '.&mt('Delete?').' '.
+ ' '.&mt('Replace:').' ';
+ } else {
+ $datatable .= '('.&mt('if larger than 21x21 pixels, image will be scaled').') ';
+ }
+ if ($switchserver) {
+ $datatable .= &mt('Upload to library server: [_1]',$switchserver);
+ } else {
+ $datatable .= ' ';
+ }
+ $datatable .= ' ';
+ my (%checkedfields,%rolemaps,$userincdom);
+ if (ref($settings->{$item}) eq 'HASH') {
+ if (ref($settings->{$item}->{'fields'}) eq 'HASH') {
+ %checkedfields = %{$settings->{$item}->{'fields'}};
+ }
+ $userincdom = $settings->{$item}->{'incdom'};
+ if (ref($settings->{$item}->{'roles'}) eq 'HASH') {
+ %rolemaps = %{$settings->{$item}->{'roles'}};
+ $checkedfields{'roles'} = 1;
+ }
+ }
+ $datatable .= ''.&mt('User data sent on launch').' '.
+ '';
+ my $userfieldstyle = 'display:none;';
+ my $seluserdom = '';
+ my $unseluserdom = ' selected="selected"';
+ foreach my $field (@fields) {
+ my ($checked,$onclick,$id,$spacer);
+ if ($checkedfields{$field}) {
+ $checked = ' checked="checked"';
+ }
+ if ($field eq 'user') {
+ $id = ' id="ltitools_user_field_'.$i.'"';
+ $onclick = ' onclick="toggleLTITools(this.form,'."'$field','$i'".')"';
+ if ($checked) {
+ $userfieldstyle = 'display:inline-block';
+ if ($userincdom) {
+ $seluserdom = $unseluserdom;
+ $unseluserdom = '';
+ }
+ }
+ } else {
+ $spacer = (' ' x2);
+ }
+ $datatable .= ''.
+ ' '.
+ $lt{$field}.' '.$spacer;
+ }
+ $datatable .= ' ';
+ $datatable .= ''.
+ ' : '.
+ ''.
+ ''.&mt('Select').' '.
+ ''.&mt('username').' '.
+ ''.&mt('username:domain').' '.
+ '
';
+ $datatable .= ' '.
+ ''.&mt('Role mapping').' ';
+ foreach my $role (@courseroles) {
+ my ($selected,$selectnone);
+ if (!$rolemaps{$role}) {
+ $selectnone = ' selected="selected"';
+ }
+ $datatable .= ''.
+ &Apache::lonnet::plaintext($role,'Course').' '.
+ ''.
+ ''.&mt('Select').' ';
+ foreach my $ltirole (@ltiroles) {
+ unless ($selectnone) {
+ if ($rolemaps{$role} eq $ltirole) {
+ $selected = ' selected="selected"';
+ } else {
+ $selected = '';
+ }
+ }
+ $datatable .= ''.$ltirole.' ';
+ }
+ $datatable .= ' ';
+ }
+ $datatable .= '
';
+ my %courseconfig;
+ if (ref($settings->{$item}) eq 'HASH') {
+ if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') {
+ %courseconfig = %{$settings->{$item}->{'crsconf'}};
+ }
+ }
+ $datatable .= ''.&mt('Configurable in course').' ';
+ foreach my $item ('label','title','target','linktext','explanation','append') {
+ my $checked;
+ if ($courseconfig{$item}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= ''.
+ ' '.
+ $lt{'crs'.$item}.' '."\n";
+ }
+ $datatable .= ' '.
+ ''.&mt('Custom items sent on launch').' '.
+ ' '."\n";
+ $itemcount ++;
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_add_pos'".');"';
+ $datatable .= ''."\n".
+ ' '."\n".
+ '';
+ for (my $k=0; $k<$maxnum+1; $k++) {
+ my $vpos = $k+1;
+ my $selstr;
+ if ($k == $maxnum) {
+ $selstr = ' selected="selected" ';
+ }
+ $datatable .= ''.$vpos.' ';
+ }
+ $datatable .= ' '."\n".
+ ' '.&mt('Add').' '."\n".
+ ''.
+ ''.&mt('Required settings').' '.
+ ''.$lt{'title'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'version'}.':'.
+ '1.1 '."\n".
+ (' 'x2).
+ ''.$lt{'msgtype'}.':'.
+ 'Launch '.
+ ''.$lt{'sigmethod'}.':'.
+ 'HMAC-SHA1 '.
+ 'HMAC-SHA256 '.
+ ' '.
+ ''.$lt{'url'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'lifetime'}.': ';
+ if ($switchserver) {
+ $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.' '."\n";
+ } else {
+ $datatable .= ''.$lt{'key'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'secret'}.': '.
+ ' '.&mt('Visible input').' '."\n";
+ }
+ $datatable .= ' '.
+ ' '.
+ ''.&mt('Optional settings').' '.
+ ''.&mt('Display target:');
+ my %defaultdisp;
+ $defaultdisp{'iframe'} = ' checked="checked"';
+ foreach my $disp ('iframe','tab','window') {
+ $datatable .= ' '.
+ $lt{$disp}.' '.(' 'x2);
+ }
+ $datatable .= (' 'x4);
+ foreach my $dimen ('width','height') {
+ $datatable .= ''.$lt{$dimen}.' '.
+ ' '.
+ (' 'x2);
+ }
+ $datatable .= ' '.
+ ''.$lt{'linktext'}.' '.
+ '
'.
+ ''.$lt{'explanation'}.' '.
+ ''.
+ '
';
+ my %units = (
+ 'passback' => 'days',
+ 'roster' => 'seconds',
+ );
+ my %defaulttimes = (
+ 'passback' => '7',
+ 'roster' => '300',
+ );
+ foreach my $extra ('passback','roster') {
+ my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','add'".');"';
+ $datatable .= ''.$lt{$extra}.' '.
+ ' '.
+ &mt('No').' '.(' 'x2).''.
+ ' '.
+ &mt('Yes').'
'.
+ '
';
+ }
+ $datatable .= ''.$lt{'icon'}.': '.
+ '('.&mt('if larger than 21x21 pixels, image will be scaled').') ';
+ if ($switchserver) {
+ $datatable .= &mt('Upload to library server: [_1]',$switchserver);
+ } else {
+ $datatable .= ' ';
+ }
+ $datatable .= ' '.
+ ''.&mt('User data sent on launch').' '.
+ '';
+ foreach my $field (@fields) {
+ my ($id,$onclick,$spacer);
+ if ($field eq 'user') {
+ $id = ' id="ltitools_user_field_add"';
+ $onclick = ' onclick="toggleLTITools(this.form,'."'$field','add'".')"';
+ } else {
+ $spacer = (' ' x2);
+ }
+ $datatable .= ''.
+ ' '.
+ $lt{$field}.' '.$spacer;
+ }
+ $datatable .= ' '.
+ ''.
+ ' : '.
+ ''.
+ ''.&mt('Select').' '.
+ ''.&mt('username').' '.
+ ''.&mt('username:domain').' '.
+ '
';
+ $datatable .= ''.&mt('Role mapping').' ';
+ foreach my $role (@courseroles) {
+ my ($checked,$checkednone);
+ $datatable .= ''.
+ &Apache::lonnet::plaintext($role,'Course').' '.
+ ''.
+ ''.&mt('Select').' ';
+ foreach my $ltirole (@ltiroles) {
+ $datatable .= ''.$ltirole.' ';
+ }
+ $datatable .= ' ';
+ }
+ $datatable .= '
'.
+ ''.&mt('Configurable in course').' ';
+ foreach my $item ('label','title','target','linktext','explanation','append') {
+ $datatable .= ''.
+ ' '.
+ $lt{'crs'.$item}.' '.(' ' x2)."\n";
+ }
+ $datatable .= ' '.
+ ''.&mt('Custom items sent on launch').' '.
+ ' '."\n".
+ ' '."\n".
+ ' '."\n";
+ $itemcount ++;
+ return $datatable;
+}
+
+sub ltitools_names {
+ my %lt = &Apache::lonlocal::texthash(
+ 'title' => 'Title',
+ 'version' => 'Version',
+ 'msgtype' => 'Message Type',
+ 'sigmethod' => 'Signature Method',
+ 'url' => 'URL',
+ 'key' => 'Key',
+ 'lifetime' => 'Nonce lifetime (s)',
+ 'secret' => 'Secret',
+ 'icon' => 'Icon',
+ 'user' => 'User',
+ 'fullname' => 'Full Name',
+ 'firstname' => 'First Name',
+ 'lastname' => 'Last Name',
+ 'email' => 'E-mail',
+ 'roles' => 'Role',
+ 'window' => 'Window',
+ 'tab' => 'Tab',
+ 'iframe' => 'iFrame',
+ 'height' => 'Height',
+ 'width' => 'Width',
+ 'linktext' => 'Default Link Text',
+ 'explanation' => 'Default Explanation',
+ 'passback' => 'Tool can return grades:',
+ 'roster' => 'Tool can retrieve roster:',
+ 'crstarget' => 'Display target',
+ 'crslabel' => 'Course label',
+ 'crstitle' => 'Course title',
+ 'crslinktext' => 'Link Text',
+ 'crsexplanation' => 'Explanation',
+ 'crsappend' => 'Provider URL',
+ );
+ return %lt;
+}
+
+sub ltimenu_titles {
+ return &Apache::lonlocal::texthash(
+ fullname => 'Full name',
+ coursetitle => 'Course title',
+ role => 'Role',
+ logout => 'Logout',
+ grades => 'Grades',
+ );
+}
+
+sub print_menuitems {
+ my ($position,$cdom,$settings,$itemtext,$rowtotal,$crstype,$noedit) = @_;
+ unless ((ref($settings) eq 'HASH') && (ref($itemtext) eq 'HASH')) {
+ return;
+ }
+ if ($position eq 'top') {
+ my (%defaultmenu_options,@defaultmenu_order,$addcollection);
+ if ($settings->{'menucollections'} ne '') {
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ $defaultmenu_options{$num} = $num;
+ }
+ }
+ @defaultmenu_order = sort { $a <=> $b } keys(%defaultmenu_options);
+ $addcollection = $defaultmenu_order[-1] + 1;
+ } else {
+ $addcollection = 1;
+ }
+ $defaultmenu_options{$addcollection} = $addcollection;
+ my %items = (
+ 'menudefault' => {
+ text => ''.&mt($itemtext->{'menudefault'}).' '.
+ &mt("(can be overriden in deep-link context)"),
+ input => 'selectbox',
+ options => \%defaultmenu_options,
+ order => \@defaultmenu_order,
+ nullval => &mt('Standard (all menus shown)'),
+ },
+ );
+ return &make_item_rows($cdom,\%items,['menudefault'],$settings,$rowtotal,$crstype,'menuitems',$noedit);
+ } else {
+ my %menu;
+ my $count = 0;
+ my $next = 1;
+ my ($datatable,$disabled);
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+
+ my ($ordered,$cats) = &menuitems_categories();
+ my @order = @{$ordered};
+ my %categories = %{$cats};
+ my %menutitles = &menuitems_titles();
+ my %menufields = &menuitems_fields();
+
+ if ($settings->{'menucollections'} ne '') {
+ foreach my $item (split(/;/,$settings->{'menucollections'})) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $menu{$num}{$name} = $fields;
+ }
+ }
+ }
+ if (keys(%menu)) {
+ my @current = sort { $a <=> $b } keys(%menu);
+ $next += $current[-1];
+ foreach my $num (@current) {
+ my %checked;
+ my $on = ' checked="checked"';
+ foreach my $key (keys(%{$menu{$num}})) {
+ if (($key eq 'top') || ($key eq 'inline') || ($key eq 'foot') || ($key eq 'main')) {
+ if ($menu{$num}{$key} eq 'y') {
+ $checked{$key} = $on;
+ }
+ } else {
+ foreach my $field (split(/,/,$menu{$num}{$key})) {
+ if (exists($menufields{$field})) {
+ $checked{$field} = $on;
+ }
+ }
+ }
+ }
+ if (ref($menu{$num}) eq 'HASH') {
+ $datatable .= &item_table_row_start(''.$num.' ',$count,'','','','LC_left_item');
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $datatable .= ''.$menutitles{$category}.' '."\n";
+ if ($category eq 'text') {
+ $datatable .= ''.&mt('Header').' ';
+ }
+ foreach my $field (@{$categories{$category}}) {
+ if ($field eq 'disc') {
+ $datatable .= ''.&mt('Footer').' ';
+ }
+ $datatable .= ' '.
+ $menufields{$field}.' ';
+ }
+ $datatable .= ' ';
+ }
+ }
+ $datatable .= &item_table_row_end();
+ $count ++;
+ }
+ }
+ }
+ } elsif ($noedit) {
+ my $text = &mt('No menu collections defined for this course.');
+ $datatable .= &item_table_row_start($text,$count);
+ }
+ unless ($noedit) {
+ my $add = ''.&mt('Add').' ';
+ $datatable .= &item_table_row_start($add,$count,'','','','LC_left_item');
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $datatable .= '';
+ }
+ }
+ $datatable .= &item_table_row_end();
+ $count ++;
+ }
+ return $datatable;
+ }
+}
+
+sub menuitems_abbreviations {
+ my %briefcats = (
+ text => 'pt',
+ links => 'p',
+ list => 'ps',
+ inline => 's',
+ );
+ return %briefcats;
+}
+
+sub menuitems_categories {
+ my @order = ('shown','text','links','list','inline');
+ my %categories = (
+ shown => ['top','inline','foot','main'],
+ text => ['name','role','crs','disc','fdbk'],
+ links => ['pers','logo','comm','roles','help','logout'],
+ list => ['about','prefs','port','wish','anno','rss','srch','brse'],
+ inline => ['cont','grades','chat','people','groups','resv','syll','feeds'],
+ );
+ return (\@order,\%categories);
+}
+
+sub menuitems_titles {
+ return &Apache::lonlocal::texthash (
+ shown => 'Hierarchy',
+ text => 'Text',
+ links => 'Header links',
+ list => 'Drop-down list',
+ inline => 'Inline links',
+ );
+}
+
+sub menuitems_fields {
+ return &Apache::lonlocal::texthash (
+ top => 'Display header',
+ inline => 'Display inline menu',
+ foot => 'Display footer',
+ main => 'Access to main menu',
+ pers => 'Personal',
+ logo => 'LON-CAPA',
+ comm => 'Messages',
+ roles => 'Roles/Courses',
+ help => 'Help',
+ logout => 'Logout',
+ name => 'Fullname',
+ crs => 'Course Title',
+ role => 'Current Role',
+ disc => 'Discussion',
+ fdbk => 'Feedback',
+ about => 'Information',
+ prefs => 'Preferences',
+ port => 'Portfolio',
+ wish => 'Stored Links',
+ anno => 'Calendar',
+ rss => 'RSS Feeds',
+ srch => 'Search Library',
+ brse => 'Browse Library',
+ cont => 'Contents',
+ grades => 'Grades',
+ chat => 'Chat',
+ people => 'People',
+ groups => 'Groups',
+ resv => 'Reservations',
+ syll => 'Syllabus',
+ feeds => 'Feeds',
+ );
+}
+
+sub menucollections_display {
+ my ($collections) = @_;
+ my %menu;
+ my ($ordered,$cats) = &menuitems_categories();
+ my @order = @{$ordered};
+ my %categories = %{$cats};
+ my %menutitles = &menuitems_titles();
+ my %menufields = &menuitems_fields();
+ foreach my $item (split(/;/,$collections)) {
+ my ($num,$value) = split(/\%/,$item);
+ if ($num =~ /^\d+$/) {
+ my @entries = split(/\&/,$value);
+ foreach my $entry (@entries) {
+ my ($name,$fields) = split(/=/,$entry);
+ $menu{$num}{$name} = $fields;
+ }
+ }
+ }
+ my $output = '';
+ if (keys(%menu)) {
+ my @current = sort { $a <=> $b } keys(%menu);
+ foreach my $num (@current) {
+ my %checked;
+ foreach my $key (keys(%{$menu{$num}})) {
+ if (($key eq 'top') || ($key eq 'inline') || ($key eq 'foot') || ($key eq 'main')) {
+ if ($menu{$num}{$key} eq 'y') {
+ $checked{$key} = 1;
+ }
+ } else {
+ foreach my $field (split(/,/,$menu{$num}{$key})) {
+ if (exists($menufields{$field})) {
+ $checked{$field} = 1;
+ }
+ }
+ }
+ }
+ if (ref($menu{$num}) eq 'HASH') {
+ $output .= ''.&mt('Collection [_1]',$num).' ';
+ foreach my $category (@order) {
+ if ((ref($categories{$category}) eq 'ARRAY') && (@{$categories{$category}} > 0)) {
+ $output .= ''.
+ ''.$menutitles{$category}.' '."\n";
+ if ($category eq 'text') {
+ $output .= ''.&mt('Header Text').' ';
+ }
+ foreach my $field (@{$categories{$category}}) {
+ if ($field eq 'disc') {
+ $output .= ''.&mt('Footer Text').' ';
+ }
+ if ($checked{$field}) {
+ $output .= &Apache::lonhtmlcommon::confirm_success($menufields{$field});
+ } else {
+ $output .= &Apache::lonhtmlcommon::confirm_success($menufields{$field},1);
+ }
+ $output .= ' ';
+ }
+ $output .= ' ';
+ }
+ }
+ $output .= ' ';
+ }
+ }
+ }
+ return $output;
+}
+
+sub print_linkprotection {
+ my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_;
+
+ my %linkprotection;
+ my $count = 0;
+ my $next = 1;
+ my ($datatable,$disabled,$css_class,$dest);
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+ my %desc = &linkprot_names();
+ my %lt = &Apache::lonlocal::texthash (
+ 'requ' => 'Required settings',
+ 'opti' => 'Optional settings',
+ );
+ my $itemcount = 0;
+
+ my $ltiauth;
+ if ($context eq 'domain') {
+ $ltiauth = 1;
+ } else {
+ if (exists($env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'})) {
+ $ltiauth = $env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'};
+ } else {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
+ $ltiauth = $domdefs{'crsltiauth'};
+ }
+ }
+ if ($context eq 'domain') {
+ $dest = '/adm/domainprefs';
+ } else {
+ $dest = '/adm/courseprefs';
+ }
+
+ my ($switchserver,$switchmessage);
+ $switchserver = &check_switchserver($cdom,$cnum,$context,$dest);
+ if ($switchserver) {
+ if ($context eq 'domain') {
+ $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver);
+ } elsif ($crstype eq 'Community') {
+ $switchmessage = &mt("submit from community's home server: [_1].",$switchserver);
+ } else {
+ $switchmessage = &mt("submit from course's home server: [_1].",$switchserver);
+ }
+ }
+
+ if ((ref($settings) eq 'HASH') && (ref($settings->{'linkprot'}) eq 'HASH')) {
+ if (keys(%{$settings->{'linkprot'}})) {
+ my @current = sort { $a <=> $b } keys(%{$settings->{'linkprot'}});
+ $next += $current[-1];
+ for (my $i=0; $i<@current; $i++) {
+ my $num = $current[$i];
+ my %values;
+ if (ref($settings->{'linkprot'}->{$num}) eq 'HASH') {
+ %values = %{$settings->{'linkprot'}->{$num}};
+ } else {
+ next;
+ }
+ my $selected;
+ if (($values{'version'} eq 'LTI-1p0') || ($values{'version'} eq '')) {
+ $selected = ' selected="selected"';
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .=
+ ''.
+ ' '.
+ &mt('Delete?').' ';
+ my ($usersty,$onclickrequser,%checkedrequser,$onclickreturnurl,%checkedreturnurl,
+ $onclickpassback,%checkedpassback,$passbacksty,%checkedpassbackfmt);
+ $passbacksty = 'none';
+ $onclickpassback = ' onclick="toggleLinkProtExtra(this.form,'."'passback','passbackparam','1','inline-block','$i'".');"';
+ %checkedpassback = (
+ 'no' => ' checked="checked"',
+ 'yes' => '',
+ );
+ %checkedpassbackfmt = (
+ '1p1' => ' checked="checked"',
+ '1p0' => '',
+ );
+ if ($values{'passback'} ne '') {
+ $passbacksty = 'inline-block';
+ $checkedpassback{'yes'} = ' checked="checked"';
+ $checkedpassback{'no'} = '';
+ if ($values{'passbackformat'} eq '1.0') {
+ $checkedpassbackfmt{'1p0'} = ' checked="checked"';
+ $checkedpassbackfmt{'1p1'} = '';
+ }
+ }
+ if ($ltiauth) {
+ $usersty = 'display:none';
+ $onclickrequser = ' onclick="toggleLinkProtExtra(this.form,'."'requser','optional','1','block','$i'".');"';
+ %checkedrequser = (
+ no => ' checked="checked"',
+ yes => '',
+ );
+ if ($values{'requser'}) {
+ $checkedrequser{'yes'} = $checkedrequser{'no'};
+ $checkedrequser{'no'} = '';
+ }
+ $datatable .= ''.$lt{'requ'}.' ';
+ if ($values{'requser'}) {
+ $usersty = 'display:inline-block';
+ }
+ }
+ $onclickreturnurl = ' onclick="toggleLinkProtExtra(this.form,'."'returnurl','divurlparam','1','inline-block','$i'".');"';
+ %checkedreturnurl = (
+ no => ' checked="checked"',
+ yes => '',
+ );
+ if ($values{'returnurl'} ne '') {
+ $checkedreturnurl{'yes'} = $checkedreturnurl{'no'};
+ $checkedreturnurl{'no'} = '';
+ }
+ $datatable .=
+ ''.$desc{'name'}.
+ ': '.
+ (' 'x2).
+ ''.$desc{'version'}.':'.
+ '1.1 '."\n".
+ (' 'x2).
+ ''.$desc{'lifetime'}.': ';
+ if ($values{'key'} ne '') {
+ $datatable .= ''.$desc{'key'};
+ if ($noedit) {
+ $datatable .= ': ['.&mt('not shown').']';
+ } elsif ($switchserver) {
+ $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']';
+ } else {
+ $datatable .= ': ';
+ }
+ $datatable .= ' '.(' 'x2);
+ } elsif (!$switchserver) {
+ $datatable .= ''.$desc{'key'}.':'.
+ ' '.
+ ' '.(' 'x2);
+ }
+ if ($switchserver) {
+ if ($values{'usable'} ne '') {
+ $datatable .= '
'.
+ $desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).' '.
+ ''.&mt('Change secret?').
+ ' '.&mt('No').' '.
+ (' 'x2).
+ ' '.&mt('Yes').' '.(' 'x2).
+ '
'.
+ ' - '.$switchmessage.' '.
+ '';
+ } elsif ($values{'key'} eq '') {
+ $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.' '."\n";
+ } else {
+ $datatable .= ''.&mt('Secret required').' - '.$switchmessage.' '."\n";
+ }
+ $datatable .= ' ';
+ } else {
+ if ($values{'usable'} ne '') {
+ $datatable .= '
'.
+ $desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).' '.
+ ''.&mt('Change?').
+ ' '.&mt('No').' '.
+ (' 'x2).
+ ' '.&mt('Yes').
+ '
'.
+ ''.&mt('New Secret').':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
+ ' ';
+ } else {
+ $datatable .=
+ ''.$desc{'secret'}.':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
+ ' ';
+ }
+ }
+ $datatable .= ' '.
+ ''.$desc{'passback'}.'?'.
+ ' '.&mt('No').' '.
+ ' '.&mt('Yes').' '.
+ '
'.
+ ''.&mt('Grade format').
+ ' '.
+ &mt('Outcomes Service (1.1)').' '.(' 'x2).
+ ' '.
+ &mt('Outcomes Extension (1.0)').' '.
+ '
'.
+ ' '.
+ ''.$desc{'returnurl'}.'?'.
+ ' '.&mt('No').' '.
+ ' '.&mt('Yes').' '.
+ '
'.
+ ''.&mt('Parameter name').':'.
+ ' '.
+ ' ';
+ if ($ltiauth) {
+ $datatable .= (' 'x2).''.$desc{'requser'}.'?'.
+ ' '.&mt('No').' '.
+ ' '.&mt('Yes').' '.
+ ' '.
+ ''.$lt{'opti'}.' '.
+ &linkprot_options($i,$itemcount,$disabled,\%values,\%desc).
+ ' ';
+ }
+ $datatable .= ' ';
+ $itemcount ++;
+ }
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= ''."\n".
+ ' '."\n".
+ ' '.&mt('Add').' '."\n".
+ '';
+ my ($usersty,$onclickrequser,%checkedrequser,$onclickreturnurl,%checkedreturnurl,
+ $onclickpassback,%checkedpassback,%checkedpassbackfmt);
+ if ($ltiauth) {
+ $usersty = 'display:none';
+ $onclickrequser = ' onclick="toggleLinkProtExtra(this.form,'."'requser','optional','1','block','add'".');"';
+ %checkedrequser = (
+ no => ' checked="checked"',
+ yes => '',
+ );
+ $datatable .= ''.$lt{'requ'}.' ';
+ }
+ $onclickpassback = ' onclick="toggleLinkProtExtra(this.form,'."'passback','passbackparam','1','inline-block','add'".');"';
+ %checkedpassback = (
+ 'no' => ' checked="checked"',
+ 'yes' => '',
+ );
+ %checkedpassbackfmt = (
+ '1p1' => ' checked="checked"',
+ '1p0' => '',
+ );
+ $onclickreturnurl = ' onclick="toggleLinkProtExtra(this.form,'."'returnurl','divurlparam','1','inline-block','add'".');"';
+ %checkedreturnurl = (
+ no => ' checked="checked"',
+ yes => '',
+ );
+ $datatable .= ''.$desc{'name'}.
+ ': '."\n".
+ (' 'x2).
+ ''.$desc{'version'}.':'.
+ '1.1 '."\n".
+ (' 'x2).
+ ''.$desc{'lifetime'}.': '."\n".
+ ' ';
+ if ($switchserver) {
+ $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.' '."\n";
+ } else {
+ $datatable .= ''.$desc{'key'}.': '."\n".
+ (' 'x2).
+ ''.$desc{'secret'}.': '.
+ ' '.&mt('Visible input').' '."\n";
+ }
+ $datatable .= ' '.
+ ''.$desc{'passback'}.'?'.
+ ' '.&mt('No').' '.
+ ' '.&mt('Yes').' '.
+ '
'.
+ ''.&mt('Grade format').
+ ' '.
+ &mt('Outcomes Service (1.1)').' '.(' 'x2).
+ ' '.
+ &mt('Outcomes Extension (1.0)').' '.
+ '
'.
+ ' '.
+ ''.$desc{'returnurl'}.'?'.
+ ' '.&mt('No').' '.
+ ' '.&mt('Yes').' '.
+ '
'.
+ ''.&mt('Parameter name').':'.
+ ' '.
+ ' ';
+ if ($ltiauth) {
+ $datatable .= (' 'x2).''.$desc{'requser'}.'?'.
+ ' '.&mt('No').' '.
+ ' '.&mt('Yes').' '.
+ ' '.
+ ''.$lt{'opti'}.' '.
+ &linkprot_options('add',$itemcount,$disabled,{},\%desc).
+ ' ';
+ }
+ $datatable .= ' ';
+ $$rowtotal ++;
+ return $datatable;
+}
+
+sub linkprot_names {
+ return &Apache::lonlocal::texthash(
+ 'version' => 'LTI Version',
+ 'key' => 'Key',
+ 'lifetime' => 'Nonce lifetime (s)',
+ 'name' => 'Launcher Application',
+ 'secret' => 'Secret',
+ 'passback' => 'Can return grades to Launcher',
+ 'returnurl' => 'Launcher return URL',
+ 'requser' => 'Use identity',
+ 'email' => 'Email address',
+ 'sourcedid' => 'User ID',
+ 'other' => 'Other',
+ 'auth' => 'Display LON-CAPA login page',
+ 'reject' => 'Discontinue launch process',
+ );
+}
+
+sub check_switchserver {
+ my ($cdom,$cnum,$context,$dest) = @_;
+ my ($allowed,$switchserver,$home);
+ if ($context eq 'domain') {
+ $home = &Apache::lonnet::domain($cdom,'primary');
+ } else {
+ $home = &Apache::lonnet::homeserver($cnum,$cdom);
+ }
+ unless (($home eq 'no_host') || ($home eq '')) {
+ my @ids=&Apache::lonnet::current_machine_ids();
+ foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
+ if (!$allowed) {
+ $switchserver=''.&mt('Switch Server').' ';
+ }
+ }
+ return $switchserver;
+}
+
+sub linkprot_options {
+ my ($num,$itemcount,$disabled,$current,$desc) = @_;
+ my %lt;
+ if (ref($desc) eq 'HASH') {
+ %lt = %{$desc};
+ }
+ my $userfieldsty = 'none';
+ my (%checked,$userfield);
+ $checked{'sourcedid'} = ' checked="checked"';
+ $checked{'reject'} = ' checked="checked"';
+ if (ref($current) eq 'HASH') {
+ if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
+ $checked{'sourcedid'} = '';
+ if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') {
+ $checked{'email'} = ' checked="checked"';
+ } else {
+ $checked{'other'} = ' checked="checked"';
+ $userfield = $current->{'mapuser'};
+ $userfieldsty = 'inline-block';
+ }
+ }
+ if (($current->{'notstudent'} ne '') && ($current->{'notstudent'} ne 'reject')) {
+ $checked{'reject'} = '';
+ $checked{'auth'} = ' checked="checked"';
+ }
+ }
+ my $onclickuser = ' onclick="toggleLinkProtExtra(this.form,'."'mapuser','userfield','other','inline-block','$num'".');"';
+ my $output = ''.
+ &mt('Source of LON-CAPA username in LTI request').': ';
+ foreach my $option ('sourcedid','email','other') {
+ $output .= ' '.$lt{$option}.' '.
+ ($option eq 'other' ? '' : (' 'x2) );
+ }
+ $output .= '
'.
+ ''.
+ '
';
+ $output .= ' '.
+ ''.
+ &mt('Action when username is not for an enrolled student').': ';
+ foreach my $option ('reject','auth') {
+ $output .= ' '.$lt{$option}.' '.
+ ($option eq 'auth' ? '' : (' 'x2) );
+ }
+ $output .= '
';
+ return $output;
+}
+
+sub print_extresource_row {
+ my ($item,$config,$curr,$noedit) = @_;
+ my $onchange;
+ unless ($noedit) {
+ $onchange = ' onchange="javascript:toggleExtRes();"';
+ }
+ my $id = 'LC_'.$item;
+ my ($selected,$reuse,$width,$height) = split(/:/,$curr);
+ my $output = &select_from_options($item,$config->{'order'},
+ $config->{'options'},$selected,
+ $config->{'nullval'},
+ undef,undef,$onchange,$noedit,$id);
+ my ($checked,$reusesty,$sizesty);
+ if ($reuse) {
+ $checked = ' checked="checked"';
+ }
+ $reusesty = 'none';
+ $sizesty = 'none';
+ if (($selected eq 'window') || ($selected eq 'tab')) {
+ $reusesty = 'inline-block';
+ if ($selected eq 'window') {
+ $sizesty = 'inline-block';
+ }
+ }
+ $output .= ''.
+ ''.
+ ' '.
+ &mt('Re-use tab/window').' '.
+ '
'.
+ ''.
+ ''.&mt('Window size (optional)').' '.
+ ''.
+ &mt('width').': px'.
+ (' ' x 3).
+ &mt('height').': px'.
+ ' ';
+ return $output;
}
sub print_other {
- my ($cdom,$settings,$allitems,$rowtotal) = @_;
+ my ($cdom,$settings,$allitems,$rowtotal,$crstype,$noedit) = @_;
unless ((ref($settings) eq 'HASH') && (ref($allitems) eq 'ARRAY')) {
return;
}
@@ -2227,7 +7393,7 @@ sub print_other {
input => 'textbox',
size => '30',
};
- my $output = &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal);
+ return &make_item_rows($cdom,\%items,\@ordered,$settings,$rowtotal,$crstype,'other',$noedit);
}
sub get_other_items {
@@ -2244,7 +7410,10 @@ sub get_other_items {
unless (($parameter =~ m/^internal\./)||($parameter =~ m/^metadata\./) ||
($parameter =~ m/^selfenroll_/) || ($parameter =~ /_selfenroll$/)
|| ($parameter eq 'type') ||
- ($parameter =~ m/^(cc|in|ta|ep|ad|st)\.plaintext$/)) {
+ ($parameter =~ m/^(cc|co|in|ta|ep|ad|st)\.plaintext$/)
+ || ($parameter =~ m/^discussion_post_fonts/) ||
+ ($parameter =~ m{^(minimal|updated|uploaded|external)syllabus$}) ||
+ ($parameter eq 'clonedfrom')) {
push(@ordered,$parameter);
}
}
@@ -2253,15 +7422,24 @@ sub get_other_items {
}
sub item_table_row_start {
- my ($text,$count) = @_;
+ my ($text,$count,$add_class,$colspan,$leftclass,$rightclass) = @_;
my $output;
- if ($count%2) {
- $output .= '';
+ my $css_class = ($count % 2) ? 'LC_odd_row' : 'LC_even_row';
+ $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+ if ($leftclass eq '') {
+ $leftclass = 'LC_left_item';
+ }
+ if ($rightclass eq '') {
+ $rightclass = 'LC_right_item';
+ }
+ $output .= ' '."\n".
+ ''.$text.
+ ' ';
+ if ($colspan > 1) {
+ $output .= '';
} else {
- $output .= ' ';
+ $output .= '';
}
- $output .= ' '.$text.
- ' ';
return $output;
}
@@ -2270,25 +7448,53 @@ sub item_table_row_end {
}
sub yesno_radio {
- my ($item,$settings) = @_;
+ my ($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit,$onclick,$reverse) = @_;
my $itemon = ' ';
my $itemoff = ' checked="checked" ';
+ if (($valueyes eq '') && ($valueno eq '')) {
+ $valueyes = 'yes';
+ $valueno = '';
+ }
if (ref($settings) eq 'HASH') {
- if ($settings->{$item} eq 'yes') {
+ if ($settings->{$item} eq $valueyes) {
$itemon = $itemoff;
$itemoff = ' ';
}
+ unless (exists($settings->{$item})) {
+ if ($unsetdefault eq $valueyes) {
+ $itemon = $itemoff;
+ $itemoff = ' ';
+ }
+ }
+ }
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ } elsif ($onclick) {
+ $onclick = ' onclick="'.$onclick.'"';
+ }
+ if ($reverse) {
+ return ''.
+ ' '.&mt('No').' '.
+ ' '.&mt('Yes').' ';
+ } else {
+ return ''.
+ ' '.&mt('Yes').' '.
+ ' '.&mt('No').' ';
}
- return ''.
- ' '.&mt('Yes').' '.
- ' '.&mt('No').' ';
}
sub select_from_options {
- my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange) = @_;
+ my ($item,$order,$options,$curr,$nullval,$multiple,$maxsize,$onchange,$noedit,$id) = @_;
my $output;
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled=disabled"';
+ }
if ((ref($order) eq 'ARRAY') && (ref($options) eq 'HASH')) {
$output=''."\n";
if ($nullval ne '') {
$output .= '{$item}{text},$count);
- if ($item eq 'nothideprivileged') {
- $datatable .= ¬hidepriv_row($cdom,$item,$settings);
+ my $colspan;
+ if ((($caller eq 'classlists') && ($item eq 'nothideprivileged')) ||
+ (($caller eq 'printouts') && ($item ne 'print_header_format'))) {
+ $colspan = 2;
+ }
+ my $rowdesc;
+ if ($caller eq 'appearance') {
+ $rowdesc = ''.$items->{$item}{text}.' ';
+ } else {
+ $rowdesc = $items->{$item}{text};
+ }
+ if (exists $items->{$item}{advanced} && $items->{$item}{advanced} == 1) {
+ $datatable .= &item_table_row_start($rowdesc,$count,"advanced",$colspan);
+ } else {
+ $datatable .= &item_table_row_start($rowdesc,$count,undef,$colspan);
+ }
+ if ($item eq 'defaultcredits') {
+ my $defaultcredits = $env{'course.'.$env{'request.course.id'}.'.internal.defaultcredits'};
+ my $showcredits;
+ if ($defaultcredits ne '') {
+ $showcredits = &mt('Default is [quant,_1,credit]',$defaultcredits);
+ } else {
+ $showcredits = &mt('No default set');
+ }
+ $datatable .= $showcredits;
+ } elsif ($item eq 'nothideprivileged') {
+ $datatable .= ¬hidepriv_row($cdom,$item,$settings,$crstype,$noedit);
+ } elsif ($item eq 'checkforpriv') {
+ $datatable .= &checkforpriv_row($cdom,$item,$settings,$crstype,$noedit);
} elsif ($item eq 'print_header_format') {
- $datatable .= &print_hdrfmt_row($item,$settings);
+ $datatable .= &print_hdrfmt_row($item,$settings,$noedit);
+ } elsif ($item eq 'extresource') {
+ $datatable .= &print_extresource_row($item,$items->{$item},$settings->{$item},$noedit);
} elsif ($items->{$item}{input} eq 'dates') {
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
$datatable .=
&Apache::lonhtmlcommon::date_setter('display',$item,
- $settings->{$item});
+ $settings->{$item},$disabled);
} elsif ($items->{$item}{input} eq 'radio') {
- $datatable .= &yesno_radio($item,$settings);
+ my ($unsetdefault,$valueyes,$valueno);
+ if (($item eq 'usejsme') || ($item eq 'uselcmath') || ($item eq 'inline_chem')) {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
+ unless ($domdefs{$item} eq '0') {
+ $unsetdefault = 1;
+ }
+ $valueyes = "1";
+ $valueno = "0";
+ }
+ $datatable .= &yesno_radio($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit);
} elsif ($items->{$item}{input} eq 'selectbox') {
+ my ($id,$onchange);
+ if ($caller eq 'menuitems') {
+ $id = $item;
+ } elsif ($caller eq 'grading') {
+ if ($item eq 'grading') {
+ $onchange = ' onchange="javascript:toggleGrading(this.form);"';
+ $id = $item;
+ }
+ }
my $curr = $settings->{$item};
$datatable .=
&select_from_options($item,$items->{$item}{'order'},
$items->{$item}{'options'},$curr,
- $items->{$item}{'nullval'});
+ $items->{$item}{'nullval'},
+ undef,undef,$onchange,$noedit,$id);
+ if ($item eq 'grading') {
+ my ($unsetdefault,$valueyes,$valueno,$sectionbox);
+ my $gradingsty = 'none';
+ my $gradingsecsty = 'none';
+ $unsetdefault = 0;
+ my (@selsec,@sections,%current);
+ if ($curr eq 'standard') {
+ $gradingsty = 'inline-block';
+ if (ref($settings) eq 'HASH') {
+ $current{'hidetotals'} = $settings->{'hidetotals'};
+ if ($settings->{'hidetotals'} =~ /^([\w,]+)$/) {
+ my $secstr = $1;
+ unless ($secstr eq 'all') {
+ @selsec = split(/,/,$secstr);
+ }
+ $current{'hidetotals'} = 1;
+ }
+ }
+ }
+ $valueyes = "1";
+ $valueno = "0";
+ my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
+ if (keys(%sections)) {
+ @sections = sort( { $a <=> $b } keys(%sections));
+ }
+ my $onclick = 'javascript:toggleHiddenTotalsSec(this.form);';
+ my $sectionbox = '';
+ my $reverse = 1;
+ if (@sections) {
+ $sectionbox .= ' ... '.&mt('hidden in sections').': '.
+ '
'.
+ &select_sections('hidetotals','',\@sections,\@selsec,$noedit,'all').
+ '
';
+ }
+ $sectionbox .= '
';
+ $datatable .= ''.
+ ''.
+ &mt('Hide Course Points Totals').' '.
+ ''.
+ &yesno_radio('hidetotals',\%current,$unsetdefault,$valueyes,$valueno,$noedit,
+ $onclick,$reverse).'
'.
+ $sectionbox.
+ '
';
+ }
} elsif ($items->{$item}{input} eq 'textbox') {
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled=disabled"';
+ }
$datatable .=
&Apache::lonhtmlcommon::textbox($item,$settings->{$item},
- $items->{$item}{size});
+ $items->{$item}{size},
+ $disabled);
}
$datatable .= &item_table_row_end();
}
@@ -2370,10 +7679,9 @@ sub make_item_rows {
}
sub nothidepriv_row {
- my ($cdom,$item,$settings) = @_;
+ my ($cdom,$item,$settings,$crstype,$noedit) = @_;
my ($cnum) = &get_course();
- my %nothide;
- my $datatable;
+ my ($datatable,%nothide,@checkdoms);
if (ref($settings) eq 'HASH') {
if ($settings->{$item} ne '') {
foreach my $user (split(/\s*\,\s*/,$settings->{$item})) {
@@ -2384,38 +7692,34 @@ sub nothidepriv_row {
}
}
}
+ if ($settings->{'checkforpriv'}) {
+ @checkdoms = split(/,/,$settings->{'checkforpriv'});
+ }
}
- my %coursepersonnel = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
- my $now = time;
+ push(@checkdoms,$cdom);
+ my %coursepersonnel =
+ &Apache::lonnet::get_my_roles($cnum,$cdom,'',['previous','future','active']);
my @privusers;
- my %privileged;
foreach my $person (keys(%coursepersonnel)) {
- my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/);
- $user =~ s/:$//;
- my ($end,$start) = split(/:/,$coursepersonnel{$person});
+ my ($uname,$udom,$role) = split(/:/,$person);
+ my $user = $uname.':'.$udom;
+ my ($start,$end) = split(/:/,$coursepersonnel{$person});
if ($end == -1 || $start == -1) {
next;
}
- my ($uname,$udom) = split(':',$user);
- unless (ref($privileged{$udom}) eq 'HASH') {
- my %dompersonnel = &Apache::lonnet::get_domain_roles($udom,['dc'],undef,$now);
- $privileged{$udom} = {};
- if (keys(%dompersonnel)) {
- foreach my $server (keys(%dompersonnel)) {
- foreach my $user (sort(keys(%{$dompersonnel{$server}}))) {
- my ($trole,$uname,$udom) = split(/:/,$user);
- $privileged{$udom}{$uname} = $trole;
- }
+ foreach my $dom (@checkdoms) {
+ if (&Apache::lonnet::privileged($uname,$udom,\@checkdoms,['dc','su'])) {
+ unless (grep(/^\Q$user\E$/,@privusers)) {
+ push(@privusers,$user);
}
}
}
- if (exists($privileged{$udom}{$uname})) {
- unless (grep(/^\Q$user\E$/,@privusers)) {
- push(@privusers,$user);
- }
- }
}
- if (@privusers) {
+ if (@privusers > 0) {
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
$datatable .= '';
} else {
- $datatable .= &mt('No Domain Coordinators have course roles');
+ if ($crstype eq 'Community') {
+ $datatable .= &mt('No Domain Coordinators have community roles');
+ } else {
+ $datatable .= &mt('No Domain Coordinators have course roles');
+ }
+ }
+ return $datatable;
+}
+
+sub checkforpriv_row {
+ my ($cdom,$item,$settings,$crstype,$noedit) = @_;
+ my $datatable;
+ my %domains=map { $_ => 1; } &Apache::lonnet::all_domains();
+ if (keys(%domains) == 1) {
+ $datatable = ' '.
+ &mt("Course's domain is only domain");
+ return $datatable;
+ }
+ my @excdoms = ($cdom);
+ my $num = 0;
+ if ($settings->{$item} eq '') {
+ $datatable = ' '.
+ &Apache::loncommon::select_dom_form('','checkforpriv_'.$num,
+ 1,1,undef,undef,\@excdoms,
+ $noedit);
+ } else {
+ my @privdoms = split(/,/,$settings->{$item});
+ my %domains=map { $_ => 1; } &Apache::lonnet::all_domains();
+ $datatable = ' '.
+ &Apache::loncommon::start_data_table();
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
+ if (@privdoms > 0) {
+ foreach my $currdom (@privdoms) {
+ next unless ($domains{$currdom});
+ my $domdesc = &Apache::lonnet::domain($currdom,'description');
+ if ($domdesc eq '') {
+ $domdesc = $currdom;
+ }
+ $datatable .=
+ &Apache::loncommon::start_data_table_row().
+ ''.
+ &mt('Domain:').' '.$domdesc.
+ ' '.
+ ' '.
+ &mt('Delete').' '.
+ &Apache::loncommon::end_data_table_row();
+ $num ++;
+ unless (grep(/^\Q$currdom\E$/,@excdoms)) {
+ push(@excdoms,$currdom);
+ }
+ }
+ }
+ if ((scalar(keys(%domains)) - scalar(@excdoms)) > 0) {
+ $datatable .=
+ &Apache::loncommon::start_data_table_row().
+ ''.
+ &mt('Additional domain:'). ' '.
+ &Apache::loncommon::select_dom_form('','checkforpriv_'.$num,1,
+ 1,undef,undef,\@excdoms,$noedit).
+ ' '.&Apache::loncommon::end_data_table_row();
+ }
+ $datatable .= &Apache::loncommon::end_data_table().
+ ' '.
+ ' ';
}
return $datatable;
}
sub print_hdrfmt_row {
- my ($item,$settings) = @_;
+ my ($item,$settings,$noedit) = @_;
my @curr;
my $currnum = 0;
my $maxnum = 2;
@@ -2453,9 +7826,9 @@ sub print_hdrfmt_row {
$currstr .= ''.&mt('Current print header:').' '.
$settings->{$item}.' ';
my @current = split(/(%\d*[nca])/,$settings->{$item});
- foreach my $item (@current) {
- unless ($item eq '') {
- push(@curr,$item);
+ foreach my $val (@current) {
+ unless ($val eq '') {
+ push(@curr,$val);
}
}
$currnum = @curr;
@@ -2515,37 +7888,45 @@ function getIndexByName(item) {
ENDJS
- $output .= $currstr.&Apache::loncommon::start_data_table();
+ $output .= ' '.
+ $currstr.'';
+ my $disabled;
+ if ($noedit) {
+ $disabled = ' disabled="disabled"';
+ }
if (@curr > 0) {
for (my $i=0; $i<@curr; $i++) {
my $pos = $i+1;
- $output .= &Apache::loncommon::start_data_table_row().
+ $output .= ''.
''.
- &position_selector($pos,$i,$maxnum).&mt('Delete:').
+ &position_selector($pos,$i,$maxnum,$disabled).&mt('Delete:').
' ';
+ '"'.$disabled.' />';
if ($curr[$i] =~ /^%\d*[nca]$/) {
my ($limit,$subst) = ($curr[$i] =~ /^%(\d*)([nca])$/);
$output .= ''.
- &substitution_selector($i,$subst,$limit).' ';
+ &substitution_selector($i,$subst,$limit,$disabled).'';
} else {
$output .= ''.&mt('Text').' '.
' ';
+ ' value="'.$curr[$i].'" size="25"'.$disabled.' />';
}
- $output .= &Apache::loncommon::end_data_table_row();
+ $output .= ' ';
}
}
- my $pos = $currnum+1;
- $output .= &Apache::loncommon::start_data_table_row().
+ my $pos = $currnum+1;
+ unless ($noedit) {
+ $output .=
+ ''.
''.
&position_selector($pos,$currnum,$maxnum).
''.&mt('New').' '.
&substitution_selector($currnum).' '.
- &Apache::loncommon::end_data_table_row();
- $pos ++;
- $currnum ++;
- $output .= &Apache::loncommon::start_data_table_row().
+ ' ';
+ $pos ++;
+ $currnum ++;
+ $output .=
+ ''.
''.
&position_selector($pos,$currnum,$maxnum).
''.&mt('New').' '.
@@ -2554,14 +7935,15 @@ ENDJS
'" value="" size ="25" />'.
' '.
- &Apache::loncommon::end_data_table_row().
- &Apache::loncommon::end_data_table();
+ ' ';
+ }
+ $output .= '
';
return $output;
}
sub position_selector {
- my ($pos,$num,$maxnum) = @_;
- my $output = '';
+ my ($pos,$num,$maxnum,$disabled) = @_;
+ my $output = '';
for (my $j=1; $j<=$maxnum; $j++) {
my $sel = '';
if ($pos == $j) {
@@ -2575,14 +7957,22 @@ sub position_selector {
}
sub substitution_selector {
- my ($num,$subst,$limit) = @_;
+ my ($num,$subst,$limit,$crstype,$disabled) = @_;
+ my ($stunametxt,$crsidtxt);
+ if ($crstype eq 'Community') {
+ $stunametxt = 'member name';
+ $crsidtxt = 'community ID',
+ } else {
+ $stunametxt = 'student name';
+ $crsidtxt = 'course ID',
+ }
my %lt = &Apache::lonlocal::texthash(
- n => 'student name',
- c => 'course ID',
+ n => $stunametxt,
+ c => $crsidtxt,
a => 'assignment note',
);
my $output .= &mt('Substitution').' '.
- '';
+ '';
if ($subst eq '') {
$output .= ' ';
}
@@ -2596,8 +7986,98 @@ sub substitution_selector {
}
$output .= ' '.&mt('Size limit').' '.
' ';
+ '" value="'.$limit.'" size="5"'.$disabled.' />';
return $output;
}
+sub change_clone {
+ my ($cdom,$cnum,$clonelist,$oldcloner) = @_;
+ my $clone_crs = $cnum.':'.$cdom;
+ if ($cnum && $cdom) {
+ my $clone_crs = $cnum.':'.$cdom;
+ my @allowclone;
+ if ($clonelist =~ /,/) {
+ @allowclone = split(',',$clonelist);
+ } else {
+ $allowclone[0] = $clonelist;
+ }
+ foreach my $currclone (@allowclone) {
+ if (!grep(/^$currclone$/,@$oldcloner)) {
+ if ($currclone ne '*') {
+ if ($currclone =~ /:/) {
+ my ($uname,$udom) = split(/:/,$currclone);
+ if ($uname && $udom && $uname ne '*') {
+ if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
+ my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable');
+ if ($currclonecrs{'cloneable'} !~ /\Q$clone_crs\E/) {
+ if ($currclonecrs{'cloneable'} eq '') {
+ $currclonecrs{'cloneable'} = $clone_crs;
+ } else {
+ $currclonecrs{'cloneable'} .= ','.$clone_crs;
+ }
+ &Apache::lonnet::put('environment',\%currclonecrs,$udom,$uname);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach my $oldclone (@$oldcloner) {
+ if (!grep(/^\Q$oldclone\E$/,@allowclone)) {
+ if ($oldclone ne '*') {
+ if ($oldclone =~ /:/) {
+ my ($uname,$udom) = split(/:/,$oldclone);
+ if ($uname && $udom && $uname ne '*' ) {
+ if (&Apache::lonnet::homeserver($uname,$udom) ne 'no_host') {
+ my %currclonecrs = &Apache::lonnet::dump('environment',$udom,$uname,'cloneable');
+ my %newclonecrs = ();
+ if ($currclonecrs{'cloneable'} =~ /\Q$clone_crs\E/) {
+ if ($currclonecrs{'cloneable'} =~ /,/) {
+ my @currclonecrs = split/,/,$currclonecrs{'cloneable'};
+ foreach my $crs (@currclonecrs) {
+ if ($crs ne $clone_crs) {
+ $newclonecrs{'cloneable'} .= $crs.',';
+ }
+ }
+ $newclonecrs{'cloneable'} =~ s/,$//;
+ } else {
+ $newclonecrs{'cloneable'} = '';
+ }
+ &Apache::lonnet::put('environment',\%newclonecrs,$udom,$uname);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
+sub devalidate_remote_courseprefs {
+ my ($cdom,$cnum,$cachekeys) = @_;
+ return unless (ref($cachekeys) eq 'HASH');
+ my %servers = &Apache::lonnet::internet_dom_servers($cdom);
+ my %thismachine;
+ map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
+ my @posscached = ('courselti','courseltitools');
+ if (keys(%servers)) {
+ foreach my $server (keys(%servers)) {
+ next if ($thismachine{$server});
+ my @cached;
+ foreach my $name (@posscached) {
+ if ($cachekeys->{$name}) {
+ push(@cached,&escape($name).':'.&escape($cdom.'_'.$cnum));
+ }
+ }
+ if (@cached) {
+ &Apache::lonnet::remote_devalidate_cache($server,\@cached);
+ }
+ }
+ }
+ return;
+}
+
1;