\n";
my $seconddefault = $hashref->{$firstdefault}->{'default'};
- foreach my $value (sort(keys(%select2))) {
+
+ my @secondorder = sort(keys(%select2));
+ if (ref($hashref->{$firstdefault}->{'order'}) eq 'ARRAY') {
+ @secondorder = @{$hashref->{$firstdefault}->{'order'}};
+ }
+ foreach my $value (@secondorder) {
$result.=" ".&mt($select2{$value})." \n";
@@ -685,7 +917,7 @@ END
=pod
-=item * help_open_topic($topic, $text, $stayOnPage, $width, $height)
+=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height)
Returns a string corresponding to an HTML link to the given help
$topic, where $topic corresponds to the name of a .tex file in
@@ -711,9 +943,6 @@ sub help_open_topic {
my ($topic, $text, $stayOnPage, $width, $height) = @_;
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
- if ($env{'browser.interface'} eq 'textual') {
- $stayOnPage=1;
- }
$width = 350 if (not defined $width);
$height = 400 if (not defined $height);
my $filename = $topic;
@@ -721,33 +950,33 @@ sub help_open_topic {
my $template = "";
my $link;
-
+
$topic=~s/\W/\_/g;
- if (!$stayOnPage)
- {
+ if (!$stayOnPage) {
$link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
- }
- else
- {
+ } else {
$link = "/adm/help/${filename}.hlp";
}
# Add the text
- if ($text ne "")
- {
- $template .=
- "".
- "$text ";
+ if ($text ne "") {
+ $template.=''
+ .''
+ .$text.' ';
}
- # Add the graphic
+ # (Always) Add the graphic
my $title = &mt('Online Help');
- my $helpicon=&lonhttpdurl("/adm/help/gif/smallHelp.gif");
- $template .= <<"ENDTEMPLATE";
-
-ENDTEMPLATE
- if ($text ne '') { $template.='
' };
+ my $helpicon=&lonhttpdurl("/adm/help/help.png");
+ $template.=' '
+ .' ';
+ if ($text ne "") {
+ $template.='';
+ }
return $template;
}
@@ -755,21 +984,31 @@ ENDTEMPLATE
# This is a quicky function for Latex cheatsheet editing, since it
# appears in at least four places
sub helpLatexCheatsheet {
- my $other = shift;
+ my ($topic,$text,$not_author) = @_;
+ my $out;
my $addOther = '';
- if ($other) {
- $addOther = Apache::loncommon::help_open_topic($other, shift,
- undef, undef, 600) .
- '';
- }
- return ''.
- $addOther .
- &Apache::loncommon::help_open_topic("Greek_Symbols",'Greek Symbols',
- undef,undef,600)
- .' '.
- &Apache::loncommon::help_open_topic("Other_Symbols",'Other Symbols',
- undef,undef,600)
- .'
';
+ if ($topic) {
+ $addOther = ''.&Apache::loncommon::help_open_topic($topic,&mt($text),
+ undef, undef, 600).
+ ' ';
+ }
+ $out = '' # Start cheatsheet
+ .$addOther
+ .''
+ .&Apache::loncommon::help_open_topic('Greek_Symbols',&mt('Greek Symbols'),
+ undef,undef,600)
+ .' '
+ .&Apache::loncommon::help_open_topic('Other_Symbols',&mt('Other Symbols'),
+ undef,undef,600)
+ .' ';
+ unless ($not_author) {
+ $out .= ' '
+ .&Apache::loncommon::help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),
+ undef,undef,600)
+ .' ';
+ }
+ $out .= ' '; # End cheatsheet
+ return $out;
}
sub general_help {
@@ -778,6 +1017,8 @@ sub general_help {
$helptopic='Authoring_Intro';
} elsif ($env{'request.role'}=~/^cc/) {
$helptopic='Course_Coordination_Intro';
+ } elsif ($env{'request.role'}=~/^dc/) {
+ $helptopic='Domain_Coordination_Intro';
}
return $helptopic;
}
@@ -794,7 +1035,9 @@ sub update_help_link {
my $banner_link = "/adm/helpmenu?page=banner&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage";
my $output .= <<"ENDOUTPUT";
ENDOUTPUT
return $output;
@@ -805,14 +1048,9 @@ sub help_open_menu {
my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text)
= @_;
$stayOnPage = 0 if (not defined $stayOnPage);
- # formerly only used pop-up help (stayOnPage = 0)
+ # only use pop-up help (stayOnPage == 0)
# if environment.remote is on (using remote control UI)
- # if ($env{'browser.interface'} eq 'textual' ||
- # $env{'environment.remote'} eq 'off' ) {
- # $stayOnPage=1;
- #}
- # Now making pop-up help the default even with remote control
- if ($env{'browser.interface'} eq 'textual') {
+ if ($env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
}
my $output;
@@ -834,15 +1072,12 @@ sub help_open_menu {
sub top_nav_help {
my ($text) = @_;
-
$text = &mt($text);
-
- my $stayOnPage =
- ($env{'browser.interface'} eq 'textual' ||
- $env{'environment.remote'} eq 'off' );
- my $link= ($stayOnPage) ? "javascript:helpMenu('display')"
+ my $stay_on_page =
+ ($env{'environment.remote'} eq 'off' );
+ my $link = ($stay_on_page) ? "javascript:helpMenu('display')"
: "javascript:helpMenu('open')";
- my $banner_link = &update_help_link(undef,undef,undef,undef,$stayOnPage);
+ my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
my $title = &mt('Get help');
@@ -856,8 +1091,7 @@ sub help_menu_js {
my ($text) = @_;
my $stayOnPage =
- ($env{'browser.interface'} eq 'textual' ||
- $env{'environment.remote'} eq 'off' );
+ ($env{'environment.remote'} eq 'off' );
my $width = 620;
my $height = 600;
@@ -916,8 +1150,7 @@ sub help_open_bug {
unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
- if ($env{'browser.interface'} eq 'textual' ||
- $env{'environment.remote'} eq 'off' ) {
+ if ($env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
}
$width = 600 if (not defined $width);
@@ -941,7 +1174,7 @@ sub help_open_bug {
{
$template .=
"".
- "$text ";
+ "$text ";
}
# Add the graphic
@@ -961,8 +1194,7 @@ sub help_open_faq {
unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
- if ($env{'browser.interface'} eq 'textual' ||
- $env{'environment.remote'} eq 'off' ) {
+ if ($env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
}
$width = 350 if (not defined $width);
@@ -986,7 +1218,7 @@ sub help_open_faq {
{
$template .=
"".
- "$text ";
+ "$text ";
}
# Add the graphic
@@ -1005,7 +1237,7 @@ ENDTEMPLATE
=pod
-=item * change_content_javascript():
+=item * &change_content_javascript():
This and the next function allow you to create small sections of an
otherwise static HTML page that you can update on the fly with
@@ -1060,7 +1292,7 @@ DOMBASED
=pod
-=item * changable_area($name, $origContent):
+=item * &changable_area($name,$origContent):
This provides a "changable area" that can be modified on the fly via
the Javascript code provided in C. $name is
@@ -1084,8 +1316,141 @@ sub changable_area {
=pod
+=item * &viewport_geometry_js
+
+Provides javascript object (Geometry) which can provide information about the viewport geometry for the client browser.
+
+=cut
+
+
+sub viewport_geometry_js {
+ return <<"GEOMETRY";
+var Geometry = {};
+function init_geometry() {
+ if (Geometry.init) { return };
+ Geometry.init=1;
+ if (window.innerHeight) {
+ Geometry.getViewportHeight = function() { return window.innerHeight; };
+ Geometry.getViewportWidth = function() { return window.innerWidth; };
+ Geometry.getHorizontalScroll = function() { return window.pageXOffset; };
+ Geometry.getVerticalScroll = function() { return window.pageYOffset; };
+ }
+ else if (document.documentElement && document.documentElement.clientHeight) {
+ Geometry.getViewportHeight =
+ function() { return document.documentElement.clientHeight; };
+ Geometry.getViewportWidth =
+ function() { return document.documentElement.clientWidth; };
+
+ Geometry.getHorizontalScroll =
+ function() { return document.documentElement.scrollLeft; };
+ Geometry.getVerticalScroll =
+ function() { return document.documentElement.scrollTop; };
+ }
+ else if (document.body.clientHeight) {
+ Geometry.getViewportHeight =
+ function() { return document.body.clientHeight; };
+ Geometry.getViewportWidth =
+ function() { return document.body.clientWidth; };
+ Geometry.getHorizontalScroll =
+ function() { return document.body.scrollLeft; };
+ Geometry.getVerticalScroll =
+ function() { return document.body.scrollTop; };
+ }
+}
+
+GEOMETRY
+}
+
+=pod
+
+=item * &viewport_size_js()
+
+Provides a javascript function to set values of two form elements - width and height (elements are passed in as arguments to the javascript function) to the dimensions of the user's browser window.
+
+=cut
+
+sub viewport_size_js {
+ my $geometry = &viewport_geometry_js();
+ return <<"DIMS";
+
+$geometry
+
+function getViewportDims(width,height) {
+ init_geometry();
+ width.value = Geometry.getViewportWidth();
+ height.value = Geometry.getViewportHeight();
+ return;
+}
+
+DIMS
+}
+
+=pod
+
+=item * &resize_textarea_js()
+
+emits the needed javascript to resize a textarea to be as big as possible
+
+creates a function resize_textrea that takes two IDs first should be
+the id of the element to resize, second should be the id of a div that
+surrounds everything that comes after the textarea, this routine needs
+to be attached to the for the onload and onresize events.
+
=back
-
+
+=cut
+
+sub resize_textarea_js {
+ my $geometry = &viewport_geometry_js();
+ return <<"RESIZE";
+
+RESIZE
+
+}
+
+=pod
+
=head1 Excel and CSV file utility routines
=over 4
@@ -1097,7 +1462,7 @@ sub changable_area {
=pod
-=item * csv_translate($text)
+=item * &csv_translate($text)
Translate $text to allow it to be output as a 'comma separated values'
format.
@@ -1118,7 +1483,7 @@ sub csv_translate {
=pod
-=item * define_excel_formats
+=item * &define_excel_formats()
Define some commonly used Excel cell formats.
@@ -1174,7 +1539,7 @@ sub define_excel_formats {
=pod
-=item * create_workbook
+=item * &create_workbook()
Create an Excel worksheet. If it fails, output message on the
request object and return undefs.
@@ -1217,7 +1582,7 @@ sub create_workbook {
=pod
-=item * create_text_file
+=item * &create_text_file()
Create a file to write to and eventually make available to the user.
If file creation fails, outputs an error message on the request object and
@@ -1242,9 +1607,9 @@ sub create_text_file {
$fh = Apache::File->new('>/home/httpd'.$filename);
if (! defined($fh)) {
$r->log_error("Couldn't open $filename for output $!");
- $r->print("Problems occured in creating the output file. ".
- "This error has been logged. ".
- "Please alert your LON-CAPA administrator.");
+ $r->print(&mt('Problems occurred in creating the output file. '
+ .'This error has been logged. '
+ .'Please alert your LON-CAPA administrator.'));
}
return ($fh,$filename)
}
@@ -1285,9 +1650,7 @@ sub domain_select {
=over 4
-=cut
-
-=item * multiple_select_form($name,$value,$size,$hash,$order)
+=item * &multiple_select_form($name,$value,$size,$hash,$order)
Returns a string containing a element int multiple mode
@@ -1313,7 +1676,7 @@ sub multiple_select_form {
$size = scalar(keys(%$hash));
}
}
- $output.="\n";
+ $output.="\n".'';
my @order;
if (ref($order) eq 'ARRAY') {
@order = @{$order};
@@ -1337,7 +1700,7 @@ sub multiple_select_form {
=pod
-=item * select_form($defdom,$name,%hash)
+=item * &select_form($defdom,$name,%hash)
Returns a string containing a form to
allow a user to select options from a hash option_name => displayed text.
@@ -1370,17 +1733,17 @@ sub select_form {
sub display_filter {
if (!$env{'form.show'}) { $env{'form.show'}=10; }
if (!$env{'form.displayfilter'}) { $env{'form.displayfilter'}='currentfolder'; }
- return ''.&mt('Records [_1]',
+ return ''.&mt('Records [_1]',
&Apache::lonmeta::selectbox('show',$env{'form.show'},undef,
(&mt('all'),10,20,50,100,1000,10000))).
- ' '.
+ ' '.
&mt('Filter [_1]',
&select_form($env{'form.displayfilter'},
'displayfilter',
('currentfolder' => 'Current folder/page',
'containing' => 'Containing phrase',
'none' => 'None'))).
- ' ';
+ ' ';
}
sub gradeleveldescription {
@@ -1424,7 +1787,7 @@ sub select_level_form {
=pod
-=item * select_dom_form($defdom,$name,$includeempty,$showdomdesc)
+=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$autosubmit)
Returns a string containing a form to
allow a user to select the domain to preform an operation in.
@@ -1433,16 +1796,22 @@ See loncreateuser.pm for an example invo
If the $includeempty flag is set, it also includes an empty choice ("no domain
selected");
-If the $showdomdesc flag is set, the domain name is followed by the domain description.
+If the $showdomdesc flag is set, the domain name is followed by the domain description.
+
+If the $autosubmit flag is set, the form containing the domain selector will be auto-submitted by an onchange action.
=cut
#-------------------------------------------
sub select_dom_form {
- my ($defdom,$name,$includeempty,$showdomdesc) = @_;
+ my ($defdom,$name,$includeempty,$showdomdesc,$autosubmit) = @_;
+ my $onchange;
+ if ($autosubmit) {
+ $onchange = ' onchange="this.form.submit()"';
+ }
my @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
if ($includeempty) { @domains=('',@domains); }
- my $selectdomain = "\n";
+ my $selectdomain = "\n";
foreach my $dom (@domains) {
$selectdomain.="'.$dom;
@@ -1464,24 +1833,68 @@ sub select_dom_form {
=pod
-=item * home_server_option_list($domain)
+=item * &home_server_form_item($domain,$name,$defaultflag)
+
+input: 4 arguments (two required, two optional) -
+ $domain - domain of new user
+ $name - name of form element
+ $default - Value of 'default' causes a default item to be first
+ option, and selected by default.
+ $hide - Value of 'hide' causes hiding of the name of the server,
+ if 1 server found, or default, if 0 found.
+output: returns 2 items:
+(a) form element which contains either:
+ (i)
+ $hostid $servers{$hostid}
+ $hostid $servers{$hostid}
+
+ form item if there are multiple library servers in $domain, or
+ (ii) an form item
+ if there is only one library server in $domain.
-returns a string which contains an list to be used in a
- form input. See loncreateuser.pm for an example.
+(b) number of library servers found.
+
+See loncreateuser.pm for example of use.
=cut
#-------------------------------------------
-sub home_server_option_list {
- my $domain = shift;
+sub home_server_form_item {
+ my ($domain,$name,$default,$hide) = @_;
my %servers = &Apache::lonnet::get_servers($domain,'library');
- my $result = '';
- foreach my $hostid (sort(keys(%servers))) {
- $result.=
- ''.
- $hostid.' '.$servers{$hostid}." \n";
+ my $result;
+ my $numlib = keys(%servers);
+ if ($numlib > 1) {
+ $result .= ' '."\n";
+ if ($default) {
+ $result .= ''.&mt('default').
+ ' '."\n";
+ }
+ foreach my $hostid (sort(keys(%servers))) {
+ $result.= ''.
+ $hostid.' '.$servers{$hostid}." \n";
+ }
+ $result .= ' '."\n";
+ } elsif ($numlib == 1) {
+ my $hostid;
+ foreach my $item (keys(%servers)) {
+ $hostid = $item;
+ }
+ $result .= ' ';
+ if (!$hide) {
+ $result .= $hostid.' '.$servers{$hostid};
+ }
+ $result .= "\n";
+ } elsif ($default) {
+ $result .= ' ';
+ if (!$hide) {
+ $result .= &mt('default');
+ }
+ $result .= "\n";
}
- return $result;
+ return ($result,$numlib);
}
=pod
@@ -1580,14 +1993,12 @@ sub decode_user_agent {
=over 4
-=item * authform_xxxxxx
+=item * &authform_xxxxxx()
The authform_xxxxxx subroutines provide javascript and html forms which
handle some of the conveniences required for authentication forms.
This is not an optimal method, but it works.
-See loncreateuser.pm for invocation and use examples.
-
=over 4
=item * authform_header
@@ -1604,7 +2015,7 @@ See loncreateuser.pm for invocation and
=back
-=back
+See loncreateuser.pm for invocation and use examples.
=cut
@@ -1634,19 +2045,16 @@ END
}
my $radioval = "'nochange'";
- if (exists($in{'curr_authtype'}) &&
- defined($in{'curr_authtype'}) &&
- $in{'curr_authtype'} ne '') {
- $radioval = "'$in{'curr_authtype'}arg'";
+ if (defined($in{'curr_authtype'})) {
+ if ($in{'curr_authtype'} ne '') {
+ $radioval = "'".$in{'curr_authtype'}."arg'";
+ }
}
my $argfield = 'null';
- if ( grep/^mode$/,(keys %in) ) {
+ if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
- if ( grep/^curr_authtype$/,(keys %in) ) {
- $radioval = "'$in{'curr_authtype'}'";
- }
- if ( grep/^curr_autharg$/,(keys %in) ) {
- unless ($in{'curr_autharg'} eq '') {
+ if (defined($in{'curr_autharg'})) {
+ if ($in{'curr_autharg'} ne '') {
$argfield = "'$in{'curr_autharg'}'";
}
}
@@ -1729,79 +2137,181 @@ sub authform_nochange{
kerb_def_dom => 'MSU.EDU',
@_,
);
- my $result = ''.&mt('[_1] Do not change login data',
- ' ').
' ';
+ }
return $result;
}
-sub authform_kerberos{
+sub authform_kerberos {
my %in = (
formname => 'document.cu',
kerb_def_dom => 'MSU.EDU',
kerb_def_auth => 'krb4',
@_,
);
- my ($check4,$check5,$krbarg);
+ my ($check4,$check5,$krbcheck,$krbarg,$krbver,$result,$authtype,
+ $autharg,$jscall);
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
if ($in{'kerb_def_auth'} eq 'krb5') {
- $check5 = " checked=\"on\"";
+ $check5 = ' checked="checked"';
} else {
- $check4 = " checked=\"on\"";
+ $check4 = ' checked="checked"';
}
$krbarg = $in{'kerb_def_dom'};
-
- my $krbcheck = "";
- if ( grep/^curr_authtype$/,(keys %in) ) {
- if ($in{'curr_authtype'} =~ m/^krb/) {
- $krbcheck = " checked=\"on\"";
- if ( grep/^curr_autharg$/,(keys %in) ) {
+ if (defined($in{'curr_authtype'})) {
+ if ($in{'curr_authtype'} eq 'krb') {
+ $krbcheck = ' checked="checked"';
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifyuser') {
+ $krbcheck = '';
+ }
+ }
+ if (defined($in{'curr_kerb_ver'})) {
+ if ($in{'curr_krb_ver'} eq '5') {
+ $check5 = ' checked="checked"';
+ $check4 = '';
+ } else {
+ $check4 = ' checked="checked"';
+ $check5 = '';
+ }
+ }
+ if (defined($in{'curr_autharg'})) {
$krbarg = $in{'curr_autharg'};
}
+ if (!$can_assign{'krb4'} && !$can_assign{'krb5'}) {
+ if (defined($in{'curr_autharg'})) {
+ $result =
+ &mt('Currently Kerberos authenticated with domain [_1] Version [_2].',
+ $in{'curr_autharg'},$krbver);
+ } else {
+ $result =
+ &mt('Currently Kerberos authenticated, Version [_1].',$krbver);
+ }
+ return $result;
+ }
+ }
+ } else {
+ if ($authnum == 1) {
+ $authtype = ' ';
}
}
-
- my $jscall = "javascript:changed_radio('krb',$in{'formname'});";
- my $result .= &mt
+ if (!$can_assign{'krb4'} && !$can_assign{'krb5'}) {
+ return;
+ } elsif ($authtype eq '') {
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifycourse') {
+ if ($authnum == 1) {
+ $authtype = ' ';
+ }
+ }
+ }
+ }
+ $jscall = "javascript:changed_radio('krb',$in{'formname'});";
+ if ($authtype eq '') {
+ $authtype = ' ';
+ }
+ if (($can_assign{'krb4'} && $can_assign{'krb5'}) ||
+ ($can_assign{'krb4'} && !$can_assign{'krb5'} &&
+ $in{'curr_authtype'} eq 'krb5') ||
+ (!$can_assign{'krb4'} && $can_assign{'krb5'} &&
+ $in{'curr_authtype'} eq 'krb4')) {
+ $result .= &mt
('[_1] Kerberos authenticated with domain [_2] '.
'[_3] Version 4 [_4] Version 5 [_5]',
- ' ',
+ ''.$authtype,
' ',
' ',
' ',
' ');
+ } elsif ($can_assign{'krb4'}) {
+ $result .= &mt
+ ('[_1] Kerberos authenticated with domain [_2] '.
+ '[_3] Version 4 [_4]',
+ ''.$authtype,
+ ' ',
+ ' ',
+ ' ');
+ } elsif ($can_assign{'krb5'}) {
+ $result .= &mt
+ ('[_1] Kerberos authenticated with domain [_2] '.
+ '[_3] Version 5 [_4]',
+ ''.$authtype,
+ ' ',
+ ' ',
+ ' ');
+ }
return $result;
}
sub authform_internal{
- my %args = (
+ my %in = (
formname => 'document.cu',
kerb_def_dom => 'MSU.EDU',
@_,
);
-
- my $intcheck = "";
- my $intarg = 'value=""';
- if ( grep/^curr_authtype$/,(keys %args) ) {
- if ($args{'curr_authtype'} eq 'int') {
- $intcheck = " checked=\"on\"";
- if ( grep/^curr_autharg$/,(keys %args) ) {
- $intarg = "value=\"$args{'curr_autharg'}\"";
+ my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall);
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ if (defined($in{'curr_authtype'})) {
+ if ($in{'curr_authtype'} eq 'int') {
+ if ($can_assign{'int'}) {
+ $intcheck = 'checked="checked" ';
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifyuser') {
+ $intcheck = '';
+ }
+ }
+ if (defined($in{'curr_autharg'})) {
+ $intarg = $in{'curr_autharg'};
+ }
+ } else {
+ $result = &mt('Currently internally authenticated.');
+ return $result;
}
}
+ } else {
+ if ($authnum == 1) {
+ $authtype = ' ';
+ }
}
-
- my $jscall = "javascript:changed_radio('int',$args{'formname'});";
- my $result.=&mt
+ if (!$can_assign{'int'}) {
+ return;
+ } elsif ($authtype eq '') {
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifycourse') {
+ if ($authnum == 1) {
+ $authtype = ' ';
+ }
+ }
+ }
+ }
+ $jscall = "javascript:changed_radio('int',$in{'formname'});";
+ if ($authtype eq '') {
+ $authtype = ' ';
+ }
+ $autharg = ' ';
+ $result = &mt
('[_1] Internally authenticated (with initial password [_2])',
- ' ',
- ' ');
+ ''.$authtype,' '.$autharg);
+ $result.=" ".&mt('Visible input').' ';
return $result;
}
@@ -1811,24 +2321,51 @@ sub authform_local{
kerb_def_dom => 'MSU.EDU',
@_,
);
-
- my $loccheck = "";
- my $locarg = 'value=""';
- if ( grep/^curr_authtype$/,(keys %in) ) {
+ my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall);
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'loc') {
- $loccheck = " checked=\"on\"";
- if ( grep/^curr_autharg$/,(keys %in) ) {
- $locarg = "value=\"$in{'curr_autharg'}\"";
+ if ($can_assign{'loc'}) {
+ $loccheck = 'checked="checked" ';
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifyuser') {
+ $loccheck = '';
+ }
+ }
+ if (defined($in{'curr_autharg'})) {
+ $locarg = $in{'curr_autharg'};
+ }
+ } else {
+ $result = &mt('Currently using local (institutional) authentication.');
+ return $result;
}
}
+ } else {
+ if ($authnum == 1) {
+ $authtype = ' ';
+ }
}
-
- my $jscall = "javascript:changed_radio('loc',$in{'formname'});";
- my $result.=&mt('[_1] Local Authentication with argument [_2]',
- ' ',
- ' ');
+ if (!$can_assign{'loc'}) {
+ return;
+ } elsif ($authtype eq '') {
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifycourse') {
+ if ($authnum == 1) {
+ $authtype = ' ';
+ }
+ }
+ }
+ }
+ $jscall = "javascript:changed_radio('loc',$in{'formname'});";
+ if ($authtype eq '') {
+ $authtype = ' ';
+ }
+ $autharg = ' ';
+ $result = &mt('[_1] Local Authentication with argument [_2]',
+ ''.$authtype,' '.$autharg);
return $result;
}
@@ -1838,51 +2375,96 @@ sub authform_filesystem{
kerb_def_dom => 'MSU.EDU',
@_,
);
- my $jscall = "javascript:changed_radio('fsys',$in{'formname'});";
- my $result.= &mt
+ my ($fsyscheck,$result,$authtype,$autharg,$jscall);
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ if (defined($in{'curr_authtype'})) {
+ if ($in{'curr_authtype'} eq 'fsys') {
+ if ($can_assign{'fsys'}) {
+ $fsyscheck = 'checked="checked" ';
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifyuser') {
+ $fsyscheck = '';
+ }
+ }
+ } else {
+ $result = &mt('Currently Filesystem Authenticated.');
+ return $result;
+ }
+ }
+ } else {
+ if ($authnum == 1) {
+ $authtype = ' ';
+ }
+ }
+ if (!$can_assign{'fsys'}) {
+ return;
+ } elsif ($authtype eq '') {
+ if (defined($in{'mode'})) {
+ if ($in{'mode'} eq 'modifycourse') {
+ if ($authnum == 1) {
+ $authtype = ' ';
+ }
+ }
+ }
+ }
+ $jscall = "javascript:changed_radio('fsys',$in{'formname'});";
+ if ($authtype eq '') {
+ $authtype = ' ';
+ }
+ $autharg = ' ';
+ $result = &mt
('[_1] Filesystem Authenticated (with initial password [_2])',
' ',
- ' ',
+ ' ');
return $result;
}
-###############################################################
-## Get Authentication Defaults for Domain ##
-###############################################################
-
-=pod
-
-=head1 Domains and Authentication
-
-Returns default authentication type and an associated argument as
-listed in file 'domain.tab'.
-
-=over 4
-
-=item * get_auth_defaults
-
-get_auth_defaults($target_domain) returns the default authentication
-type and an associated argument (initial password or a kerberos domain).
-These values are stored in lonTabs/domain.tab
-
-($def_auth, $def_arg) = &get_auth_defaults($target_domain);
-
-If target_domain is not found in domain.tab, returns nothing ('').
-
-=cut
-
-#-------------------------------------------
-sub get_auth_defaults {
- my $domain=shift;
- return (&Apache::lonnet::domain($domain,'auth_def'),
- &Apache::lonnet::domain($domain,'auth_arg_def'));
-
+sub get_assignable_auth {
+ my ($dom) = @_;
+ if ($dom eq '') {
+ $dom = $env{'request.role.domain'};
+ }
+ my %can_assign = (
+ krb4 => 1,
+ krb5 => 1,
+ int => 1,
+ loc => 1,
+ );
+ my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
+ if (ref($domconfig{'usercreation'}) eq 'HASH') {
+ if (ref($domconfig{'usercreation'}{'authtypes'}) eq 'HASH') {
+ my $authhash = $domconfig{'usercreation'}{'authtypes'};
+ my $context;
+ if ($env{'request.role'} =~ /^au/) {
+ $context = 'author';
+ } elsif ($env{'request.role'} =~ /^dc/) {
+ $context = 'domain';
+ } elsif ($env{'request.course.id'}) {
+ $context = 'course';
+ }
+ if ($context) {
+ if (ref($authhash->{$context}) eq 'HASH') {
+ %can_assign = %{$authhash->{$context}};
+ }
+ }
+ }
+ }
+ my $authnum = 0;
+ foreach my $key (keys(%can_assign)) {
+ if ($can_assign{$key}) {
+ $authnum ++;
+ }
+ }
+ if ($can_assign{'krb4'} && $can_assign{'krb5'}) {
+ $authnum --;
+ }
+ return ($authnum,%can_assign);
}
-###############################################################
-## End Get Authentication Defaults for Domain ##
-###############################################################
###############################################################
## Get Kerberos Defaults for Domain ##
@@ -1896,22 +2478,31 @@ sub get_auth_defaults {
=pod
-=item * get_kerberos_defaults
+=item * &get_kerberos_defaults()
get_kerberos_defaults($target_domain) returns the default kerberos
-version and domain. If not found in domain.tabs, it defaults to
-version 4 and the domain of the server.
+version and domain. If not found, it defaults to version 4 and the
+domain of the server.
+
+=over 4
($def_version, $def_krb_domain) = &get_kerberos_defaults($target_domain);
+=back
+
+=back
+
=cut
#-------------------------------------------
sub get_kerberos_defaults {
my $domain=shift;
- my ($krbdef,$krbdefdom) =
- &Apache::loncommon::get_auth_defaults($domain);
- unless ($krbdef =~/^krb/ && $krbdefdom) {
+ my ($krbdef,$krbdefdom);
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
+ if (($domdefaults{'auth_def'} =~/^krb(4|5)$/) && ($domdefaults{'auth_arg_def'} ne '')) {
+ $krbdef = $domdefaults{'auth_def'};
+ $krbdefdom = $domdefaults{'auth_arg_def'};
+ } else {
$ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/;
my $krbdefdom=$1;
$krbdefdom=~tr/a-z/A-Z/;
@@ -1920,11 +2511,6 @@ sub get_kerberos_defaults {
return ($krbdef,$krbdefdom);
}
-=pod
-
-=back
-
-=cut
###############################################################
## Thesaurus Functions ##
@@ -1936,7 +2522,7 @@ sub get_kerberos_defaults {
=over 4
-=item * initialize_keywords
+=item * &initialize_keywords()
Initializes the package variable %Keywords if it is empty. Uses the
package variable $thesaurus_db_file.
@@ -1973,7 +2559,7 @@ sub initialize_keywords {
# Remove special values from %Keywords.
foreach my $value ('total.count','average.count') {
delete($Keywords{$value}) if (exists($Keywords{$value}));
- }
+ }
return 1;
}
@@ -1981,7 +2567,7 @@ sub initialize_keywords {
=pod
-=item * keyword($word)
+=item * &keyword($word)
Returns true if $word is a keyword. A keyword is a word that appears more
than the average number of times in the thesaurus database. Calls
@@ -2002,7 +2588,7 @@ sub keyword {
=pod
-=item * get_related_words
+=item * &get_related_words()
Look up a word in the thesaurus. Takes a scalar argument and returns
an array of words. If the keyword is not in the thesaurus, an empty array
@@ -2060,7 +2646,7 @@ sub get_related_words {
=over 4
-=item * plainname($uname,$udom,$first)
+=item * &plainname($uname,$udom,$first)
Takes a users logon name and returns it as a string in
"first middle last generation" form
@@ -2089,7 +2675,7 @@ sub plainname {
# -------------------------------------------------------------------- Nickname
=pod
-=item * nickname($uname,$udom)
+=item * &nickname($uname,$udom)
Gets a users name and returns it as a string as
@@ -2139,18 +2725,21 @@ sub getnames {
}
# -------------------------------------------------------------------- getemails
+
=pod
-=item * getemails($uname,$udom)
+=item * &getemails($uname,$udom)
Gets a user's email information and returns it as a hash with keys:
notification, critnotification, permanentemail
For notification and critnotification, values are comma-separated lists
-of e-mail address(es); for permanentemail, value is a single e-mail address.
+of e-mail addresses; for permanentemail, value is a single e-mail address.
+
=cut
+
sub getemails {
my ($uname,$udom)=@_;
if ($udom eq 'public' && $uname eq 'public') {
@@ -2181,11 +2770,48 @@ sub flush_email_cache {
&Apache::lonnet::devalidate_cache_new('emailscache',$id);
}
+# -------------------------------------------------------------------- getlangs
+
+=pod
+
+=item * &getlangs($uname,$udom)
+
+Gets a user's language preference and returns it as a hash with key:
+language.
+
+=cut
+
+
+sub getlangs {
+ my ($uname,$udom) = @_;
+ if (!$udom) { $udom =$env{'user.domain'}; }
+ if (!$uname) { $uname=$env{'user.name'}; }
+ my $id=$uname.':'.$udom;
+ my ($langs,$cached)=&Apache::lonnet::is_cached_new('userlangs',$id);
+ if ($cached) {
+ return %{$langs};
+ } else {
+ my %loadlangs=&Apache::lonnet::get('environment',['languages'],
+ $udom,$uname);
+ &Apache::lonnet::do_cache_new('userlangs',$id,\%loadlangs);
+ return %loadlangs;
+ }
+}
+
+sub flush_langs_cache {
+ my ($uname,$udom)=@_;
+ if (!$udom) { $udom =$env{'user.domain'}; }
+ if (!$uname) { $uname=$env{'user.name'}; }
+ return if ($udom eq 'public' && $uname eq 'public');
+ my $id=$uname.':'.$udom;
+ &Apache::lonnet::devalidate_cache_new('userlangs',$id);
+}
+
# ------------------------------------------------------------------ Screenname
=pod
-=item * screenname($uname,$udom)
+=item * &screenname($uname,$udom)
Gets a users screenname and returns it as a string
@@ -2200,6 +2826,26 @@ sub screenname {
}
+# ------------------------------------------------------------- Confirm Wrapper
+=pod
+
+=item confirmwrapper
+
+Wrap messages about completion of operation in box
+
+=cut
+
+sub confirmwrapper {
+ my ($message)=@_;
+ if ($message) {
+ return "\n".''."\n"
+ .$message."\n"
+ .'
'."\n";
+ } else {
+ return $message;
+ }
+}
+
# ------------------------------------------------------------- Message Wrapper
sub messagewrapper {
@@ -2210,6 +2856,7 @@ sub messagewrapper {
'&subject='.&escape($subject).'&text='.&escape($text).'" '.
'title="'.&mt('Send message').'">'.$link.'';
}
+
# --------------------------------------------------------------- Notes Wrapper
sub noteswrapper {
@@ -2217,6 +2864,7 @@ sub noteswrapper {
return
"$link ";
}
+
# ------------------------------------------------------------- Aboutme Wrapper
sub aboutmewrapper {
@@ -2225,20 +2873,18 @@ sub aboutmewrapper {
return;
}
return ''.$link.' ';
+ ($target?' target="$target"':'').' title="'.&mt("View this user's personal information page").'">'.$link.'';
}
# ------------------------------------------------------------ Syllabus Wrapper
-
sub syllabuswrapper {
- my ($linktext,$coursedir,$domain,$fontcolor)=@_;
- if ($fontcolor) {
- $linktext=''.$linktext.' ';
- }
+ my ($linktext,$coursedir,$domain)=@_;
return qq{$linktext };
}
+# -----------------------------------------------------------------------------
+
sub track_student_link {
my ($linktext,$sname,$sdom,$target,$start) = @_;
my $link ="/adm/trackstudent?";
@@ -2260,6 +2906,27 @@ sub track_student_link {
&help_open_topic('View_recent_activity');
}
+sub slot_reservations_link {
+ my ($linktext,$sname,$sdom,$target) = @_;
+ my $link ="/adm/slotrequest?command=showresv&origin=aboutme";
+ my $title = 'View slot reservation history';
+ if (defined($sname) && $sname !~ /^\s*$/ &&
+ defined($sdom) && $sdom !~ /^\s*$/) {
+ $link .= "&uname=$sname&udom=$sdom";
+ $title .= ' of this student';
+ }
+ if (defined($target) && $target !~ /^\s*$/) {
+ $target = qq{target="$target"};
+ } else {
+ $target = '';
+ }
+ $title = &mt($title);
+ $linktext = &mt($linktext);
+ return qq{$linktext };
+# FIXME uncomment when help item created: &help_open_topic('Slot_Reservation_History');
+
+}
+
# ===================================================== Display a student photo
@@ -2281,7 +2948,7 @@ sub student_image_tag {
=over 4
-=item * languageids()
+=item * &languageids()
returns list of all language ids
@@ -2293,7 +2960,7 @@ sub languageids {
=pod
-=item * languagedescription()
+=item * &languagedescription()
returns description of a specified language id
@@ -2318,7 +2985,7 @@ sub supportedlanguagecode {
=pod
-=item * copyrightids()
+=item * ©rightids()
returns list of all copyrights
@@ -2330,7 +2997,7 @@ sub copyrightids {
=pod
-=item * copyrightdescription()
+=item * ©rightdescription()
returns description of a specified copyright id
@@ -2342,7 +3009,7 @@ sub copyrightdescription {
=pod
-=item * source_copyrightids()
+=item * &source_copyrightids()
returns list of all source copyrights
@@ -2354,7 +3021,7 @@ sub source_copyrightids {
=pod
-=item * source_copyrightdescription()
+=item * &source_copyrightdescription()
returns description of a specified source copyright id
@@ -2366,7 +3033,7 @@ sub source_copyrightdescription {
=pod
-=item * filecategories()
+=item * &filecategories()
returns list of all file categories
@@ -2378,7 +3045,7 @@ sub filecategories {
=pod
-=item * filecategorytypes()
+=item * &filecategorytypes()
returns list of file types belonging to a given file
category
@@ -2392,7 +3059,7 @@ sub filecategorytypes {
=pod
-=item * fileembstyle()
+=item * &fileembstyle()
returns embedding style for a specified file type
@@ -2416,7 +3083,7 @@ sub filecategoryselect {
=pod
-=item * filedescription()
+=item * &filedescription()
returns description for a specified file type
@@ -2430,7 +3097,7 @@ sub filedescription {
=pod
-=item * filedescriptionex()
+=item * &filedescriptionex()
returns description for a specified file type with
extra formatting
@@ -2462,7 +3129,7 @@ sub fileextensions {
sub display_languages {
my %languages=();
- foreach my $lang (&preferred_languages()) {
+ foreach my $lang (&Apache::lonlocal::preferred_languages()) {
$languages{$lang}=1;
}
&get_unprocessed_cgi($ENV{'QUERY_STRING'},['displaylanguage']);
@@ -2474,48 +3141,52 @@ sub display_languages {
return %languages;
}
-sub preferred_languages {
- my @languages=();
- if ($env{'course.'.$env{'request.course.id'}.'.languages'}) {
- @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,
- $env{'course.'.$env{'request.course.id'}.'.languages'}));
- }
- if ($env{'environment.languages'}) {
- @languages=(@languages,
- split(/\s*(\,|\;|\:)\s*/,$env{'environment.languages'}));
- }
- my $browser=(split(/\;/,$ENV{'HTTP_ACCEPT_LANGUAGE'}))[0];
- if ($browser) {
- @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$browser));
- }
- if (&Apache::lonnet::domain($env{'user.domain'},'lang_def')) {
- @languages=(@languages,
- &Apache::lonnet::domain($env{'user.domain'},
- 'lang_def'));
- }
- if (&Apache::lonnet::domain($env{'request.role.domain'},'lang_def')) {
- @languages=(@languages,
- &Apache::lonnet::domain($env{'request.role.domain'},
- 'lang_def'));
- }
- if (&Apache::lonnet::domain($Apache::lonnet::perlvar{'lonDefDomain'},
- 'lang_def')) {
- @languages=(@languages,
- &Apache::lonnet::domain($Apache::lonnet::perlvar{'lonDefDomain'},
- 'lang_def'));
- }
-# turn "en-ca" into "en-ca,en"
- my @genlanguages;
- foreach my $lang (@languages) {
- unless ($lang=~/\w/) { next; }
- push (@genlanguages,$lang);
- if ($lang=~/(\-|\_)/) {
- push(@genlanguages,(split(/(\-|\_)/,$lang))[0]);
+sub languages {
+ my ($possible_langs) = @_;
+ my @preferred_langs = &Apache::lonlocal::preferred_languages();
+ if (!ref($possible_langs)) {
+ if( wantarray ) {
+ return @preferred_langs;
+ } else {
+ return $preferred_langs[0];
}
}
- return @genlanguages;
+ my %possibilities = map { $_ => 1 } (@$possible_langs);
+ my @preferred_possibilities;
+ foreach my $preferred_lang (@preferred_langs) {
+ if (exists($possibilities{$preferred_lang})) {
+ push(@preferred_possibilities, $preferred_lang);
+ }
+ }
+ if( wantarray ) {
+ return @preferred_possibilities;
+ }
+ return $preferred_possibilities[0];
+}
+
+sub user_lang {
+ my ($touname,$toudom,$fromcid) = @_;
+ my @userlangs;
+ if (($fromcid ne '') && ($env{'course.'.$fromcid.'.languages'} ne '')) {
+ @userlangs=(@userlangs,split(/\s*(\,|\;|\:)\s*/,
+ $env{'course.'.$fromcid.'.languages'}));
+ } else {
+ my %langhash = &getlangs($touname,$toudom);
+ if ($langhash{'languages'} ne '') {
+ @userlangs = split(/\s*(\,|\;|\:)\s*/,$langhash{'languages'});
+ } else {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($toudom);
+ if ($domdefs{'lang_def'} ne '') {
+ @userlangs = ($domdefs{'lang_def'});
+ }
+ }
+ }
+ my @languages=&Apache::lonlocal::get_genlanguages(@userlangs);
+ my $user_lh = Apache::localize->get_handle(@languages);
+ return $user_lh;
}
+
###############################################################
## Student Answer Attempts ##
###############################################################
@@ -2526,7 +3197,7 @@ sub preferred_languages {
=over 4
-=item * get_previous_attempt($symb, $username, $domain, $course,
+=item * &get_previous_attempt($symb, $username, $domain, $course,
$getattempt, $regexp, $gradesub)
Return string with previous attempt on problem. Arguments:
@@ -2570,14 +3241,14 @@ sub get_previous_attempt {
$lasthash{$key}=$returnhash{$version.':'.$key};
}
}
- $prevattempts='';
- $prevattempts.='History ';
+ $prevattempts=&start_data_table().&start_data_table_header_row();
+ $prevattempts.=''.&mt('History').' ';
foreach my $key (sort(keys(%lasthash))) {
my ($ign,@parts) = split(/\./,$key);
if ($#parts > 0) {
my $data=$parts[-1];
pop(@parts);
- $prevattempts.='Part '.join('.',@parts).' '.$data.' ';
+ $prevattempts.=''.&mt('Part ').join('.',@parts).' '.$data.' ';
} else {
if ($#parts == 0) {
$prevattempts.=''.$parts[0].' ';
@@ -2586,41 +3257,53 @@ sub get_previous_attempt {
}
}
}
+ $prevattempts.=&end_data_table_header_row();
if ($getattempt eq '') {
for ($version=1;$version<=$returnhash{'version'};$version++) {
- $prevattempts.='Transaction '.$version.' ';
+ $prevattempts.=&start_data_table_row().
+ ''.&mt('Transaction [_1]',$version).' ';
foreach my $key (sort(keys(%lasthash))) {
- my $value;
- if ($key =~ /timestamp/) {
- $value=scalar(localtime($returnhash{$version.':'.$key}));
- } else {
- $value=$returnhash{$version.':'.$key};
- }
- $prevattempts.=''.&unescape($value).' ';
+ my $value = &format_previous_attempt_value($key,
+ $returnhash{$version.':'.$key});
+ $prevattempts.=''.$value.' ';
}
+ $prevattempts.=&end_data_table_row();
}
}
- $prevattempts.='Current ';
+ $prevattempts.=&start_data_table_row().''.&mt('Current').' ';
foreach my $key (sort(keys(%lasthash))) {
- my $value;
- if ($key =~ /timestamp/) {
- $value=scalar(localtime($lasthash{$key}));
- } else {
- $value=$lasthash{$key};
- }
- $value=&unescape($value);
+ my $value = &format_previous_attempt_value($key,$lasthash{$key});
if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
$prevattempts.=''.$value.' ';
}
- $prevattempts.='
';
+ $prevattempts.= &end_data_table_row().&end_data_table();
} else {
- $prevattempts='Nothing submitted - no attempts.';
+ $prevattempts=
+ &start_data_table().&start_data_table_row().
+ ''.&mt('Nothing submitted - no attempts.').' '.
+ &end_data_table_row().&end_data_table();
}
} else {
- $prevattempts='No data.';
+ $prevattempts=
+ &start_data_table().&start_data_table_row().
+ ''.&mt('No data.').' '.
+ &end_data_table_row().&end_data_table();
}
}
+sub format_previous_attempt_value {
+ my ($key,$value) = @_;
+ if ($key =~ /timestamp/) {
+ $value = &Apache::lonlocal::locallocaltime($value);
+ } elsif (ref($value) eq 'ARRAY') {
+ $value = '('.join(', ', @{ $value }).')';
+ } else {
+ $value = &unescape($value);
+ }
+ return $value;
+}
+
+
sub relative_to_absolute {
my ($url,$output)=@_;
my $parser=HTML::TokeParser->new(\$output);
@@ -2642,7 +3325,7 @@ sub relative_to_absolute {
}
$thisdir=~s-/[^/]*$--;
foreach my $link (@rlinks) {
- unless (($link=~/^http:\/\//i) ||
+ unless (($link=~/^https?\:\/\//i) ||
($link=~/^\//) ||
($link=~/^javascript:/i) ||
($link=~/^mailto:/i) ||
@@ -2658,7 +3341,7 @@ sub relative_to_absolute {
=pod
-=item * get_student_view
+=item * &get_student_view()
show a snapshot of what student was looking at
@@ -2677,7 +3360,7 @@ sub get_student_view {
}
if (defined($target)) { $form{'grade_target'} = $target; }
$feedurl=&Apache::lonnet::clutter($feedurl);
- my $userview=&Apache::lonnet::ssi_body($feedurl,%form);
+ my ($userview,$response)=&Apache::lonnet::ssi_body($feedurl,%form);
$userview=~s/\]*\>//gi;
$userview=~s/\<\/body\>//gi;
$userview=~s/\//gi;
@@ -2686,12 +3369,44 @@ sub get_student_view {
$userview=~s/\<\/head\>//gi;
$userview=~s/action\s*\=/would_be_action\=/gi;
$userview=&relative_to_absolute($feedurl,$userview);
- return $userview;
+ if (wantarray) {
+ return ($userview,$response);
+ } else {
+ return $userview;
+ }
+}
+
+sub get_student_view_with_retries {
+ my ($symb,$retries,$username,$domain,$courseid,$target,$moreenv) = @_;
+
+ my $ok = 0; # True if we got a good response.
+ my $content;
+ my $response;
+
+ # Try to get the student_view done. within the retries count:
+
+ do {
+ ($content, $response) = &get_student_view($symb,$username,$domain,$courseid,$target,$moreenv);
+ $ok = $response->is_success;
+ if (!$ok) {
+ &Apache::lonnet::logthis("Failed get_student_view_with_retries on $symb: ".$response->is_success.', '.$response->code.', '.$response->message);
+ }
+ $retries--;
+ } while (!$ok && ($retries > 0));
+
+ if (!$ok) {
+ $content = ''; # On error return an empty content.
+ }
+ if (wantarray) {
+ return ($content, $response);
+ } else {
+ return $content;
+ }
}
=pod
-=item * get_student_answers()
+=item * &get_student_answers()
show a snapshot of how student was answering problem
@@ -2779,9 +3494,9 @@ sub pprmlink {
if (!$symb) { $symb=&Apache::lonnet::symbread(); }
$symb=&escape($symb);
if ($target) { $target="target=\"$target\""; }
- return ''.$text.' ';
+ return ''.$text.' ';
}
##############################################
@@ -2795,16 +3510,21 @@ sub pprmlink {
sub timehash {
- my @ltime=localtime(shift);
- return ( 'seconds' => $ltime[0],
- 'minutes' => $ltime[1],
- 'hours' => $ltime[2],
- 'day' => $ltime[3],
- 'month' => $ltime[4]+1,
- 'year' => $ltime[5]+1900,
- 'weekday' => $ltime[6],
- 'dayyear' => $ltime[7]+1,
- 'dlsav' => $ltime[8] );
+ my ($thistime) = @_;
+ my $timezone = &Apache::lonlocal::gettimezone();
+ my $dt = DateTime->from_epoch(epoch => $thistime)
+ ->set_time_zone($timezone);
+ my $wday = $dt->day_of_week();
+ if ($wday == 7) { $wday = 0; }
+ return ( 'second' => $dt->second(),
+ 'minute' => $dt->minute(),
+ 'hour' => $dt->hour(),
+ 'day' => $dt->day_of_month(),
+ 'month' => $dt->month(),
+ 'year' => $dt->year(),
+ 'weekday' => $wday,
+ 'dayyear' => $dt->day_of_year(),
+ 'dlsav' => $dt->is_dst() );
}
sub utc_string {
@@ -2814,6 +3534,24 @@ sub utc_string {
sub maketime {
my %th=@_;
+ my ($epoch_time,$timezone,$dt);
+ $timezone = &Apache::lonlocal::gettimezone();
+ eval {
+ $dt = DateTime->new( year => $th{'year'},
+ month => $th{'month'},
+ day => $th{'day'},
+ hour => $th{'hour'},
+ minute => $th{'minute'},
+ second => $th{'second'},
+ time_zone => $timezone,
+ );
+ };
+ if (!$@) {
+ $epoch_time = $dt->epoch;
+ if ($epoch_time) {
+ return $epoch_time;
+ }
+ }
return POSIX::mktime(
($th{'seconds'},$th{'minutes'},$th{'hours'},
$th{'day'},$th{'month'}-1,$th{'year'}-1900,0,0,-1));
@@ -3133,8 +3871,41 @@ sub build_block_table {
}
$output .= &end_data_table();
}
-
sub blocking_status {
+ my $blocked = blocking_status_print(@_);
+ my ($activity,$uname,$udom) = @_;
+ if(!wantarray) {
+ return $blocked;
+ }
+ my $output;
+ my $querystring;
+ $querystring = "?activity=$activity";
+ if(defined($uname)) {
+ $querystring .= "&uname=$uname";
+ }if(defined($udom)) {
+ $querystring .= "&udom=$udom";
+ }
+
+ $output .= <<"END_MYBLOCK";
+
+END_MYBLOCK
+ my $popupUrl = "/adm/blockingstatus/$querystring";
+ $output.="\nBlocking Table ";
+
+ return ($blocked, $output);
+}
+sub blocking_status_print {
my ($activity,$uname,$udom) = @_;
my %setters;
my ($blocked,$output,$ownitem,$is_course);
@@ -3164,7 +3935,7 @@ sub blocking_status {
&Apache::lonnet::coursedescription($course);
$coursedesc = $courseinfo{'description'};
}
- $category = "Group files in the course '$coursedesc'";
+ $category = "Group portfolio in the course '$coursedesc'";
} else {
$category = 'Portfolio files belonging to ';
if ($env{'user.name'} eq 'public' &&
@@ -3194,6 +3965,60 @@ sub blocking_status {
###############################################
+sub check_ip_acc {
+ my ($acc)=@_;
+ &Apache::lonxml::debug("acc is $acc");
+ if (!defined($acc) || $acc =~ /^\s*$/ || $acc =~/^\s*no\s*$/i) {
+ return 1;
+ }
+ my $allowed=0;
+ my $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'};
+
+ my $name;
+ foreach my $pattern (split(',',$acc)) {
+ $pattern =~ s/^\s*//;
+ $pattern =~ s/\s*$//;
+ if ($pattern =~ /\*$/) {
+ #35.8.*
+ $pattern=~s/\*//;
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
+ } elsif ($pattern =~ /(\d+\.\d+\.\d+)\.\[(\d+)-(\d+)\]$/) {
+ #35.8.3.[34-56]
+ my $low=$2;
+ my $high=$3;
+ $pattern=$1;
+ if ($ip =~ /^\Q$pattern\E/) {
+ my $last=(split(/\./,$ip))[3];
+ if ($last <=$high && $last >=$low) { $allowed=1; }
+ }
+ } elsif ($pattern =~ /^\*/) {
+ #*.msu.edu
+ $pattern=~s/\*//;
+ if (!defined($name)) {
+ use Socket;
+ my $netaddr=inet_aton($ip);
+ ($name)=gethostbyaddr($netaddr,AF_INET);
+ }
+ if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
+ } elsif ($pattern =~ /\d+\.\d+\.\d+\.\d+/) {
+ #127.0.0.1
+ if ($ip =~ /^\Q$pattern\E/) { $allowed=1; }
+ } else {
+ #some.name.com
+ if (!defined($name)) {
+ use Socket;
+ my $netaddr=inet_aton($ip);
+ ($name)=gethostbyaddr($netaddr,AF_INET);
+ }
+ if ($name =~ /\Q$pattern\E$/i) { $allowed=1; }
+ }
+ if ($allowed) { last; }
+ }
+ return $allowed;
+}
+
+###############################################
+
=pod
=head1 Domain Template Functions
@@ -3237,45 +4062,85 @@ sub get_domainconf {
my %domconfig = &Apache::lonnet::get_dom('configuration',
['login','rolecolors'],$udom);
- my %designhash;
+ my (%designhash,%legacy);
if (keys(%domconfig) > 0) {
if (ref($domconfig{'login'}) eq 'HASH') {
- foreach my $key (keys(%{$domconfig{'login'}})) {
- $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
+ if (keys(%{$domconfig{'login'}})) {
+ foreach my $key (keys(%{$domconfig{'login'}})) {
+ if (ref($domconfig{'login'}{$key}) eq 'HASH') {
+ foreach my $img (keys(%{$domconfig{'login'}{$key}})) {
+ $designhash{$udom.'.login.'.$key.'_'.$img} =
+ $domconfig{'login'}{$key}{$img};
+ }
+ } else {
+ $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
+ }
+ }
+ } else {
+ $legacy{'login'} = 1;
}
+ } else {
+ $legacy{'login'} = 1;
}
if (ref($domconfig{'rolecolors'}) eq 'HASH') {
- foreach my $role (keys(%{$domconfig{'rolecolors'}})) {
- if (ref($domconfig{'rolecolors'}{$role}) eq 'HASH') {
- foreach my $item (keys(%{$domconfig{'rolecolors'}{$role}})) {
- $designhash{$udom.'.'.$role.'.'.$item}=$domconfig{'rolecolors'}{$role}{$item};
+ if (keys(%{$domconfig{'rolecolors'}})) {
+ foreach my $role (keys(%{$domconfig{'rolecolors'}})) {
+ if (ref($domconfig{'rolecolors'}{$role}) eq 'HASH') {
+ foreach my $item (keys(%{$domconfig{'rolecolors'}{$role}})) {
+ $designhash{$udom.'.'.$role.'.'.$item}=$domconfig{'rolecolors'}{$role}{$item};
+ }
}
}
+ } else {
+ $legacy{'rolecolors'} = 1;
}
+ } else {
+ $legacy{'rolecolors'} = 1;
}
- } else {
- my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
- my $designfile = $designdir.'/'.$udom.'.tab';
- if (-e $designfile) {
- if ( open (my $fh,"<$designfile") ) {
- while (my $line = <$fh>) {
- next if ($line =~ /^\#/);
- chomp($line);
- my ($key,$val)=(split(/\=/,$line));
- if ($val) { $designhash{$udom.'.'.$key}=$val; }
+ if (keys(%legacy) > 0) {
+ my %legacyhash = &get_legacy_domconf($udom);
+ foreach my $item (keys(%legacyhash)) {
+ if ($item =~ /^\Q$udom\E\.login/) {
+ if ($legacy{'login'}) {
+ $designhash{$item} = $legacyhash{$item};
+ }
+ } else {
+ if ($legacy{'rolecolors'}) {
+ $designhash{$item} = $legacyhash{$item};
+ }
}
- close($fh);
}
}
- if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') {
- $designhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif";
- }
+ } else {
+ %designhash = &get_legacy_domconf($udom);
}
&Apache::lonnet::do_cache_new('domainconfig',$udom,\%designhash,
$cachetime);
return %designhash;
}
+sub get_legacy_domconf {
+ my ($udom) = @_;
+ my %legacyhash;
+ my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
+ my $designfile = $designdir.'/'.$udom.'.tab';
+ if (-e $designfile) {
+ if ( open (my $fh,"<$designfile") ) {
+ while (my $line = <$fh>) {
+ next if ($line =~ /^\#/);
+ chomp($line);
+ my ($key,$val)=(split(/\=/,$line));
+ if ($val) { $legacyhash{$udom.'.'.$key}=$val; }
+ }
+ close($fh);
+ }
+ }
+ if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') {
+ $legacyhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif";
+ }
+ return %legacyhash;
+}
+
=pod
=item * &domainlogo()
@@ -3324,41 +4189,120 @@ Returns: value of designparamter $which
##############################################
sub designparm {
my ($which,$domain)=@_;
- if ($env{'browser.blackwhite'} eq 'on') {
- if ($which=~/\.(font|alink|vlink|link)$/) {
- return '#000000';
- }
- if ($which=~/\.(pgbg|sidebg)$/) {
- return '#FFFFFF';
- }
- if ($which=~/\.tabbg$/) {
- return '#CCCCCC';
- }
- }
if (exists($env{'environment.color.'.$which})) {
- return $env{'environment.color.'.$which};
+ return $env{'environment.color.'.$which};
}
$domain=&determinedomain($domain);
my %domdesign = &get_domainconf($domain);
my $output;
if ($domdesign{$domain.'.'.$which} ne '') {
- $output = $domdesign{$domain.'.'.$which};
+ $output = $domdesign{$domain.'.'.$which};
} else {
$output = $defaultdesign{$which};
}
if (($which =~ /^(student|coordinator|author|admin)\.img$/) ||
- ($which =~ /login\.(img|logo|domlogo)/)) {
+ ($which =~ /login\.(img|logo|domlogo|login)/)) {
if ($output =~ m{^/(adm|res)/}) {
- if ($output =~ m{^/res/}) {
- my $local_name = &Apache::lonnet::filelocation('',$output);
- &Apache::lonnet::repcopy($local_name);
- }
+ if ($output =~ m{^/res/}) {
+ my $local_name = &Apache::lonnet::filelocation('',$output);
+ &Apache::lonnet::repcopy($local_name);
+ }
$output = &lonhttpdurl($output);
}
}
return $output;
}
+##############################################
+=pod
+
+=item * &authorspace()
+
+Inputs: ./.
+
+Returns: Path to the Construction Space of the current user's
+ accessed author space
+ The author space will be that of the current user
+ when accessing the own author space
+ and that of the co-author/assistent co-author
+ when accessing the co-author's/assistent co-author's
+ space
+
+=cut
+
+sub authorspace {
+ my $caname = '';
+ if ($env{'request.role'} =~ /^ca|^aa/) {
+ (undef,$caname) =
+ ($env{'request.role'}=~/($match_domain)\/($match_username)$/);
+ } else {
+ $caname = $env{'user.name'};
+ }
+ return '/priv/'.$caname.'/';
+}
+
+##############################################
+=pod
+
+=item * &head_subbox()
+
+Inputs: $content (contains HTML code with page functions, etc.)
+
+Returns: HTML div with $content
+ To be included in page header
+
+=cut
+
+sub head_subbox {
+ my ($content)=@_;
+ my $output =
+ ''
+ .$content
+ .'
'
+}
+
+##############################################
+=pod
+
+=item * &CSTR_pageheader()
+
+Inputs: ./.
+
+Returns: HTML div with CSTR path and recent box
+ To be included on Construction Space pages
+
+=cut
+
+sub CSTR_pageheader {
+ # this is for resources; directories have customtitle, and crumbs
+ # and select recent are created in lonpubdir.pm
+ my ($uname,$thisdisfn)=
+ ($env{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);
+ my $formaction='/priv/'.$uname.'/'.$thisdisfn;
+ $formaction=~s/\/+/\//g;
+
+ my $parentpath = '';
+ my $lastitem = '';
+ if ($thisdisfn =~ m-(.+/)([^/]*)$-) {
+ $parentpath = $1;
+ $lastitem = $2;
+ } else {
+ $lastitem = $thisdisfn;
+ }
+ return
+ ''
+ .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
+ .''.&mt('Construction Space:').' '
+ .''
+ .&Apache::lonmenu::constspaceform()
+ .'
';
+}
+
###############################################
###############################################
@@ -3391,17 +4335,11 @@ Inputs:
=item * $forcereg, if page should register as content page (relevant for
text interface only)
-=item * $customtitle, alternate text to use instead of $title
- in the title box that appears, this text
- is not auto translated like the $title is
-
-=item * $notopbar, if true, keep the 'what is this' info but remove the
- navigational links
+=item * $no_nav_bar, if true, keep the 'what is this' info but remove the
+ navigational links
=item * $bgcolor, used to override the bgcolor on a webpage to a specific value
-=item * $notitle, if true keep the nav controls, but remove the title bar
-
=item * $no_inline_link, if true and in remote mode, don't show the
'Switch To Inline Menu' link
@@ -3421,8 +4359,8 @@ other decorations will be returned.
=cut
sub bodytag {
- my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,$customtitle,
- $notopbar,$bgcolor,$notitle,$no_inline_link,$args)=@_;
+ my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
+ $no_nav_bar,$bgcolor,$no_inline_link,$args)=@_;
if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
@@ -3431,7 +4369,7 @@ sub bodytag {
my $font = &designparm($function.'.font',$domain);
my $pgbg = $bgcolor || &designparm($function.'.pgbg',$domain);
- my %design = ( 'style' => 'margin-top: 0px',
+ my %design = ( 'style' => 'margin-top: 0',
'bgcolor' => $pgbg,
'text' => $font,
'alink' => &designparm($function.'.alink',$domain),
@@ -3467,15 +4405,7 @@ sub bodytag {
if ($bodyonly) {
return $bodytag;
- } elsif ($env{'browser.interface'} eq 'textual') {
-# Accessibility
-
- $bodytag.=&Apache::lonmenu::menubuttons($forcereg,$forcereg);
- if (!$notitle) {
- $bodytag.='LON-CAPA: '.$title.' ';
- }
- return $bodytag;
- }
+ }
my $name = &plainname($env{'user.name'},$env{'user.domain'});
if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
@@ -3484,25 +4414,7 @@ sub bodytag {
$name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});
}
- my $roleinfo=(<
-
- $name
-
-
-
-$role
-
-
-$realm
-
-
-ENDROLE
-
- my $titleinfo = ''.$title.' ';
- if ($customtitle) {
- $titleinfo = $customtitle;
- }
+ my $titleinfo = ''.$title.' ';
#
# Extra info if you are the DC
my $dc_info = '';
@@ -3515,49 +4427,29 @@ ENDROLE
$dc_info = '('.$dc_info.')';
}
+ $role = "($role)" if $role;
+ &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
+
if ($env{'environment.remote'} eq 'off') {
# No Remote
if ($env{'request.state'} eq 'construct') {
$forcereg=1;
}
- if (!$customtitle && $env{'request.state'} eq 'construct') {
- # this is for resources; directories have customtitle, and crumbs
- # and select recent are created in lonpubdir.pm
- my ($uname,$thisdisfn)=
- ($env{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);
- my $formaction='/priv/'.$uname.'/'.$thisdisfn;
- $formaction=~s/\/+/\//g;
-
- my $parentpath = '';
- my $lastitem = '';
- if ($thisdisfn =~ m-(.+/)([^/]*)$-) {
- $parentpath = $1;
- $lastitem = $2;
- } else {
- $lastitem = $thisdisfn;
- }
- $titleinfo =
- &Apache::loncommon::help_open_menu('','',3,'Authoring').
- 'Construction Space : '.
- ''
- .&Apache::lonmenu::constspaceform();
- }
-
- my $titletable;
- if (!$notitle) {
- $titletable =
- ''.
- " $titleinfo $dc_info ".$roleinfo.
- '
';
- }
- if ($notopbar) {
+# if ($env{'request.state'} eq 'construct') {
+# $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
+# }
+
+ my $titletable = ''
+ ." $titleinfo $dc_info "
+ .'
';
+
+ if ($no_nav_bar) {
$bodytag .= $titletable;
} else {
+ $bodytag .= qq|$name $role
+ $realm $dc_info
| unless $env{'form.inhibitmenu'};
+
if ($env{'request.state'} eq 'construct') {
$bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg,
$titletable);
@@ -3581,19 +4473,20 @@ ENDROLE
# Explicit link to get inline menu
my $menu= ($no_inline_link?''
- :''.&mt('Switch to Inline Menu Mode').' ');
+ :''.&mt('Switch to Inline Menu Mode').' ');
+ $bodytag .= qq|$name $role
+ $realm $dc_info
+ | unless $env{'form.inhibitmenu'};
#
- if ($notitle) {
- return $bodytag;
- }
return(<
-$upperleft
- $messages
+$upperleft
+ $messages
$titleinfo $dc_info $menu
-$roleinfo
ENDBODY
@@ -3638,15 +4531,6 @@ sub make_attr_string {
$attr_ref->{'style'}=$style.'; font-size: x-large;';
}
- if ($env{'browser.blackwhite'} eq 'on') {
- delete($attr_ref->{'font'});
- delete($attr_ref->{'link'});
- delete($attr_ref->{'alink'});
- delete($attr_ref->{'vlink'});
- delete($attr_ref->{'bgcolor'});
- delete($attr_ref->{'background'});
- }
-
my $attr_string;
foreach my $attr (keys(%$attr_ref)) {
$attr_string .= " $attr=\"".$attr_ref->{$attr}.'" ';
@@ -3664,18 +4548,25 @@ sub make_attr_string {
Returns a uniform footer for LON-CAPA web pages.
-Inputs: none
+Inputs: 1 - optional reference to an args hash
+If in the hash, key for noredirectlink has a value which evaluates to true,
+a 'Continue' link is not displayed if the page contains an
+internal redirect in the section,
+i.e., $env{'internal.head.redirect'} exists
=cut
sub endbodytag {
+ my ($args) = @_;
my $endbodytag='';
$endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;
if ( exists( $env{'internal.head.redirect'} ) ) {
- $endbodytag=
- "".
- &mt('Continue').' '.
- $endbodytag;
+ if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {
+ $endbodytag=
+ "".
+ &mt('Continue').' '.
+ $endbodytag;
+ }
}
return $endbodytag;
}
@@ -3700,6 +4591,8 @@ sub standard_css {
my $img = &designparm($function.'.img', $domain);
my $tabbg = &designparm($function.'.tabbg', $domain);
my $font = &designparm($function.'.font', $domain);
+ my $fontmenu = &designparm($function.'.fontmenu', $domain);
+#second colour for later usage
my $sidebg = &designparm($function.'.sidebg',$domain);
my $pgbg_or_bgcolor =
$bgcolor ||
@@ -3709,11 +4602,15 @@ sub standard_css {
my $vlink = &designparm($function.'.vlink', $domain);
my $link = &designparm($function.'.link', $domain);
- my $sans = 'Arial,Helvetica,sans-serif';
+ my $loginbg = &designparm('login.sidebg',$domain);
+ my $bgcol = &designparm('login.bgcol',$domain);
+ my $textcol = &designparm('login.textcol',$domain);
+
+ my $sans = 'Verdana,Arial,Helvetica,sans-serif';
my $mono = 'monospace';
- my $data_table_head = $tabbg;
- my $data_table_light = '#EEEEEE';
- my $data_table_dark = '#DDDDDD';
+ my $data_table_head = $sidebg;
+ my $data_table_light = '#FAFAFA';
+ my $data_table_dark = '#F0F0F0';
my $data_table_darker = '#CCCCCC';
my $data_table_highlight = '#FFFF00';
my $mail_new = '#FFBB77';
@@ -3726,33 +4623,72 @@ sub standard_css {
my $mail_other_hover = '#669999';
my $table_header = '#DDDDDD';
my $feedback_link_bg = '#BBBBBB';
+ my $lg_border_color = '#C8C8C8';
- my $border = ($env{'browser.type'} eq 'explorer') ? '0px 2px 0px 2px'
- : '0px 3px 0px 4px';
+ my $border = ($env{'browser.type'} eq 'explorer' ||
+ $env{'browser.type'} eq 'safari' ) ? '0 2px 0 2px'
+ : '0 3px 0 4px';
return < td {
+ background-color: #CCCCCC;
+ font-weight: bold;
+ text-align: left;
+}
+
+table.LC_data_table tr.LC_odd_row > td,
+table.LC_pick_box tr > td.LC_odd_row {
background-color: $data_table_light;
padding: 2px;
}
-table.LC_data_table tr.LC_even_row td,
-table.LC_aboutme_port tr.LC_even_row td {
+
+table.LC_data_table tr.LC_even_row > td,
+table.LC_pick_box tr > td.LC_even_row {
background-color: $data_table_dark;
+ padding: 2px;
}
+
table.LC_data_table tr.LC_data_table_highlight td {
background-color: $data_table_darker;
}
+
+table.LC_data_table tr td.LC_leftcol_header {
+ background-color: $data_table_head;
+ font-weight: bold;
+}
+
table.LC_data_table tr.LC_empty_row td,
table.LC_nested tr.LC_empty_row td {
background-color: #FFFFFF;
@@ -4030,15 +4994,19 @@ table.LC_nested tr.LC_empty_row td {
text-align: center;
padding: 8px;
}
+
table.LC_nested tr.LC_empty_row td {
padding: 4ex
}
+
table.LC_nested_outer tr th {
font-weight: bold;
+ color:$fontmenu;
background-color: $data_table_head;
- font-size: smaller;
+ font-size: small;
border-bottom: 1px solid #000000;
}
+
table.LC_nested_outer tr td.LC_subheader {
background-color: $data_table_head;
font-weight: bold;
@@ -4046,19 +5014,24 @@ table.LC_nested_outer tr td.LC_subheader
border-bottom: 1px solid #000000;
text-align: right;
}
+
table.LC_nested tr.LC_info_row td {
- background-color: #CCC;
+ background-color: #CCCCCC;
font-weight: bold;
font-size: small;
text-align: center;
}
-table.LC_nested tr.LC_info_row td.LC_left_item {
+
+table.LC_nested tr.LC_info_row td.LC_left_item,
+table.LC_nested_outer tr th.LC_left_item {
text-align: left;
}
+
table.LC_nested td {
- background-color: #FFF;
+ background-color: #FFFFFF;
font-size: small;
}
+
table.LC_nested_outer tr th.LC_right_item,
table.LC_nested tr.LC_info_row td.LC_right_item,
table.LC_nested tr.LC_odd_row td.LC_right_item,
@@ -4067,18 +5040,18 @@ table.LC_nested tr td.LC_right_item {
}
table.LC_nested tr.LC_odd_row td {
- background-color: #EEE;
+ background-color: #EEEEEE;
}
table.LC_createuser {
}
table.LC_createuser tr.LC_section_row td {
- font-size: smaller;
+ font-size: small;
}
table.LC_createuser tr.LC_info_row td {
- background-color: #CCC;
+ background-color: #CCCCCC;
font-weight: bold;
text-align: center;
}
@@ -4087,16 +5060,20 @@ table.LC_calendar {
border: 1px solid #000000;
border-collapse: collapse;
}
+
table.LC_calendar_pickdate {
font-size: xx-small;
}
+
table.LC_calendar tr td {
border: 1px solid #000000;
vertical-align: top;
}
+
table.LC_calendar tr td.LC_calendar_day_empty {
background-color: $data_table_dark;
}
+
table.LC_calendar tr td.LC_calendar_day_current {
background-color: $data_table_highlight;
}
@@ -4104,156 +5081,159 @@ table.LC_calendar tr td.LC_calendar_day_
table.LC_mail_list tr.LC_mail_new {
background-color: $mail_new;
}
+
table.LC_mail_list tr.LC_mail_new:hover {
background-color: $mail_new_hover;
}
+
+table.LC_mail_list tr.LC_mail_even {
+}
+
+table.LC_mail_list tr.LC_mail_odd {
+}
+
table.LC_mail_list tr.LC_mail_read {
background-color: $mail_read;
}
+
table.LC_mail_list tr.LC_mail_read:hover {
background-color: $mail_read_hover;
}
+
table.LC_mail_list tr.LC_mail_replied {
background-color: $mail_replied;
}
+
table.LC_mail_list tr.LC_mail_replied:hover {
background-color: $mail_replied_hover;
}
+
table.LC_mail_list tr.LC_mail_other {
background-color: $mail_other;
}
+
table.LC_mail_list tr.LC_mail_other:hover {
background-color: $mail_other_hover;
}
-table.LC_mail_list tr.LC_mail_even {
-}
-table.LC_mail_list tr.LC_mail_odd {
-}
-
-table#LC_portfolio_actions {
- width: auto;
- background: $pgbg;
- border: 0px;
- border-spacing: 2px 2px;
- padding: 0px;
- margin: 0px;
- border-collapse: separate;
-}
-table#LC_portfolio_actions td.LC_label {
- background: $tabbg;
- text-align: right;
-}
-table#LC_portfolio_actions td.LC_value {
- background: $tabbg;
+table.LC_data_table tr > td.LC_browser_file,
+table.LC_data_table tr > td.LC_browser_file_published {
+ background: #CCFF88;
}
-table#LC_cstr_controls {
- width: 100%;
- border-collapse: collapse;
-}
-table#LC_cstr_controls tr td {
- border: 4px solid $pgbg;
- padding: 4px;
- text-align: center;
- background: $tabbg;
+table.LC_data_table tr > td.LC_browser_file_locked,
+table.LC_data_table tr > td.LC_browser_file_unpublished {
+ background: #FFAA99;
}
-table#LC_cstr_controls tr th {
- border: 4px solid $pgbg;
- background: $table_header;
- text-align: center;
- font-family: $sans;
- font-size: smaller;
+
+table.LC_data_table tr > td.LC_browser_file_obsolete {
+ background: #AAAAAA;
}
-table#LC_browser {
-
+table.LC_data_table tr > td.LC_browser_file_modified,
+table.LC_data_table tr > td.LC_browser_file_metamodified {
+ background: #FFFF77;
}
-table#LC_browser tr th {
- background: $table_header;
+
+table.LC_data_table tr.LC_browser_folder > td {
+ background: #CCCCFF;
}
-table#LC_browser tr td {
- padding: 2px;
+
+table.LC_data_table tr > td.LC_roles_is {
+/* background: #77FF77; */
}
-table#LC_browser tr.LC_browser_file,
-table#LC_browser tr.LC_browser_file_published {
- background: #CCFF88;
+
+table.LC_data_table tr > td.LC_roles_future {
+ background: #FFFF77;
}
-table#LC_browser tr.LC_browser_file_locked,
-table#LC_browser tr.LC_browser_file_unpublished {
- background: #FFAA99;
+
+table.LC_data_table tr > td.LC_roles_will {
+ background: #FFAA77;
}
-table#LC_browser tr.LC_browser_file_obsolete {
- background: #AAAAAA;
+
+table.LC_data_table tr > td.LC_roles_expired {
+ background: #FF7777;
}
-table#LC_browser tr.LC_browser_file_modified,
-table#LC_browser tr.LC_browser_file_metamodified {
- background: #FFFF77;
+
+table.LC_data_table tr > td.LC_roles_will_not {
+ background: #AAFF77;
}
-table#LC_browser tr.LC_browser_folder {
- background: #CCCCFF;
+
+table.LC_data_table tr > td.LC_roles_selected {
+ background: #11CC55;
}
+
span.LC_current_location {
- font-size: x-large;
+ font-size:larger;
background: $pgbg;
}
span.LC_parm_menu_item {
font-size: larger;
- font-family: $sans;
}
+
span.LC_parm_scope_all {
color: red;
}
+
span.LC_parm_scope_folder {
color: green;
}
+
span.LC_parm_scope_resource {
color: orange;
}
+
span.LC_parm_part {
color: blue;
}
+
span.LC_parm_folder, span.LC_parm_symb {
font-size: x-small;
font-family: $mono;
color: #AAAAAA;
}
-td.LC_parm_overview_level_menu, td.LC_parm_overview_map_menu,
-td.LC_parm_overview_parm_selectors, td.LC_parm_overview_parm_restrictions {
+td.LC_parm_overview_level_menu,
+td.LC_parm_overview_map_menu,
+td.LC_parm_overview_parm_selectors,
+td.LC_parm_overview_restrictions {
border: 1px solid black;
border-collapse: collapse;
}
+
table.LC_parm_overview_restrictions td {
border-width: 1px 4px 1px 4px;
border-style: solid;
border-color: $pgbg;
text-align: center;
}
+
table.LC_parm_overview_restrictions th {
background: $tabbg;
border-width: 1px 4px 1px 4px;
border-style: solid;
border-color: $pgbg;
}
+
table#LC_helpmenu {
- border: 0px;
+ border: none;
height: 55px;
- border-spacing: 0px;
+ border-spacing: 0;
}
table#LC_helpmenu fieldset legend {
font-size: larger;
- font-weight: bold;
}
+
table#LC_helpmenu_links {
width: 100%;
border: 1px solid black;
background: $pgbg;
- padding: 0px;
+ padding: 0;
border-spacing: 1px;
}
+
table#LC_helpmenu_links tr td {
padding: 1px;
background: $tabbg;
@@ -4261,11 +5241,13 @@ table#LC_helpmenu_links tr td {
font-weight: bold;
}
-table#LC_helpmenu_links a:link, table#LC_helpmenu_links a:visited,
+table#LC_helpmenu_links a:link,
+table#LC_helpmenu_links a:visited,
table#LC_helpmenu_links a:active {
text-decoration: none;
color: $font;
}
+
table#LC_helpmenu_links a:hover {
text-decoration: underline;
color: $vlink;
@@ -4275,53 +5257,65 @@ table#LC_helpmenu_links a:hover {
border: 1px solid #339933;
margin: -1px;
}
+
.LC_chrt_popup_up {
border: 1px solid yellow;
margin: -1px;
}
+
.LC_chrt_popup {
border: 1px solid #8888FF;
background: #CCCCFF;
}
+
table.LC_pick_box {
border-collapse: separate;
background: white;
border: 1px solid black;
border-spacing: 1px;
}
+
table.LC_pick_box td.LC_pick_box_title {
- background: $tabbg;
+ background: $sidebg;
font-weight: bold;
text-align: right;
+ vertical-align: top;
width: 184px;
padding: 8px;
}
+
table.LC_pick_box td.LC_pick_box_value {
text-align: left;
padding: 8px;
}
+
table.LC_pick_box td.LC_pick_box_select {
text-align: left;
padding: 8px;
}
+
table.LC_pick_box td.LC_pick_box_separator {
- padding: 0px;
+ padding: 0;
height: 1px;
background: black;
}
+
table.LC_pick_box td.LC_pick_box_submit {
text-align: right;
}
+
table.LC_pick_box td.LC_evenrow_value {
text-align: left;
padding: 8px;
background-color: $data_table_light;
}
+
table.LC_pick_box td.LC_oddrow_value {
text-align: left;
padding: 8px;
background-color: $data_table_light;
}
+
table.LC_helpform_receipt {
width: 620px;
border-collapse: separate;
@@ -4329,6 +5323,7 @@ table.LC_helpform_receipt {
border: 1px solid black;
border-spacing: 1px;
}
+
table.LC_helpform_receipt td.LC_pick_box_title {
background: $tabbg;
font-weight: bold;
@@ -4336,51 +5331,61 @@ table.LC_helpform_receipt td.LC_pick_box
width: 184px;
padding: 8px;
}
+
table.LC_helpform_receipt td.LC_evenrow_value {
text-align: left;
padding: 8px;
background-color: $data_table_light;
}
+
table.LC_helpform_receipt td.LC_oddrow_value {
text-align: left;
padding: 8px;
background-color: $data_table_light;
}
+
table.LC_helpform_receipt td.LC_pick_box_separator {
- padding: 0px;
+ padding: 0;
height: 1px;
background: black;
}
+
span.LC_helpform_receipt_cat {
font-weight: bold;
}
+
table.LC_group_priv_box {
background: white;
border: 1px solid black;
border-spacing: 1px;
}
+
table.LC_group_priv_box td.LC_pick_box_title {
background: $tabbg;
font-weight: bold;
text-align: right;
width: 184px;
}
+
table.LC_group_priv_box td.LC_groups_fixed {
background: $data_table_light;
text-align: center;
}
+
table.LC_group_priv_box td.LC_groups_optional {
background: $data_table_dark;
text-align: center;
}
+
table.LC_group_priv_box td.LC_groups_functionality {
background: $data_table_darker;
text-align: center;
font-weight: bold;
}
+
table.LC_group_priv td {
text-align: left;
- padding: 0px;
+ padding: 0;
}
table.LC_notify_front_page {
@@ -4388,45 +5393,71 @@ table.LC_notify_front_page {
border: 1px solid black;
padding: 8px;
}
+
table.LC_notify_front_page td {
padding: 8px;
}
+
.LC_navbuttons {
margin: 2ex 0ex 2ex 0ex;
}
+
.LC_topic_bar {
- font-family: $sans;
font-weight: bold;
width: 100%;
background: $tabbg;
vertical-align: middle;
margin: 2ex 0ex 2ex 0ex;
+ padding: 3px;
}
+
.LC_topic_bar span {
vertical-align: middle;
}
+
.LC_topic_bar img {
vertical-align: bottom;
}
+
table.LC_course_group_status {
margin: 20px;
}
+
table.LC_status_selector td {
vertical-align: top;
text-align: center;
padding: 4px;
}
-table.LC_descriptive_input td.LC_description {
- vertical-align: top;
- text-align: right;
- font-weight: bold;
+
+div.LC_feedback_link {
+ clear: both;
+ background: $sidebg;
+ width: 100%;
+ padding-bottom: 10px;
+ border: 1px $tabbg solid;
+ height: 22px;
+ line-height: 22px;
+ padding-top: 5px;
}
-table.LC_feedback_link {
- background: $feedback_link_bg;
+
+div.LC_feedback_link img {
+ height: 22px;
+}
+
+div.LC_feedback_link a{
+ text-decoration: none;
}
+
span.LC_feedback_link {
- background: $feedback_link_bg;
- font-size: larger;
+ /* background: $feedback_link_bg; */
+ font-size: larger;
+}
+
+span.LC_message_link {
+ /* background: $feedback_link_bg; */
+ font-size: larger;
+ position: absolute;
+ right: 1em;
}
table.LC_prior_tries {
@@ -4440,33 +5471,43 @@ table.LC_prior_tries td {
}
.LC_answer_correct {
- background: #AAFFAA;
- color: black;
+ background: lightgreen;
+ color: darkgreen;
+ padding: 6px;
}
+
.LC_answer_charged_try {
- background: #FFAAAA ! important;
- color: black;
+ background: #FFAAAA;
+ color: darkred;
+ padding: 6px;
}
-.LC_answer_not_charged_try,
+
+.LC_answer_not_charged_try,
.LC_answer_no_grade,
.LC_answer_late {
- background: #FFFFAA;
+ background: lightyellow;
color: black;
+ padding: 6px;
}
+
.LC_answer_previous {
- background: #AAAAFF;
- color: black;
+ background: lightblue;
+ color: darkblue;
+ padding: 6px;
}
+
.LC_answer_no_message {
background: #FFFFFF;
color: black;
+ padding: 6px;
}
+
.LC_answer_unknown {
background: orange;
color: black;
+ padding: 6px;
}
-
span.LC_prior_numerical,
span.LC_prior_string,
span.LC_prior_custom,
@@ -4485,16 +5526,19 @@ table.LC_prior_option {
width: 100%;
border-collapse: collapse;
}
-table.LC_prior_rank, table.LC_prior_match {
+
+table.LC_prior_rank,
+table.LC_prior_match {
border-collapse: collapse;
}
+
table.LC_prior_option tr td,
table.LC_prior_rank tr td,
table.LC_prior_match tr td {
border: 1px solid #000000;
}
-span.LC_nobreak {
+.LC_nobreak {
white-space: nowrap;
}
@@ -4502,9 +5546,14 @@ span.LC_cusr_emph {
font-style: italic;
}
+span.LC_cusr_subheading {
+ font-weight: normal;
+ font-size: 85%;
+}
+
table.LC_docs_documents {
background: #BBBBBB;
- border-width: 0px;
+ border-width: 0;
border-collapse: collapse;
}
@@ -4513,36 +5562,30 @@ table.LC_docs_documents td.LC_docs_docum
padding: 4px;
}
-.LC_docs_course_commands div {
- float: left;
- border: 4px solid #AAAAAA;
- padding: 4px;
- background: #DDDDCC;
-}
-
.LC_docs_entry_move {
- border: 0px;
- border-collapse: collapse;
-}
-
-.LC_docs_entry_move td {
- border: 2px solid #BBBBBB;
+ border: 1px solid #BBBBBB;
background: #DDDDDD;
+ padding: 1px;
+ margin: 0;
}
-.LC_docs_editor td.LC_docs_entry_commands {
+table.LC_data_table tr > td.LC_docs_entry_commands {
background: #DDDDDD;
font-size: x-small;
}
+
.LC_docs_copy {
color: #000099;
}
+
.LC_docs_cut {
color: #550044;
}
+
.LC_docs_rename {
color: #009900;
}
+
.LC_docs_remove {
color: #990000;
}
@@ -4552,11 +5595,7 @@ table.LC_docs_documents td.LC_docs_docum
font-size: x-small;
}
-.LC_docs_editor td.LC_docs_entry_title,
-.LC_docs_editor td.LC_docs_entry_icon {
- background: #FFFFBB;
-}
-.LC_docs_editor td.LC_docs_entry_parameter {
+table.LC_data_table tr > td.LC_docs_entry_parameter {
background: #BBBBFF;
font-size: x-small;
white-space: nowrap;
@@ -4569,6 +5608,676 @@ table.LC_docs_adddocs th {
background: #DDDDDD;
}
+table.LC_sty_begin {
+ background: #BBFFBB;
+}
+
+table.LC_sty_end {
+ background: #FFBBBB;
+}
+
+table.LC_double_column {
+ border-width: 0;
+ border-collapse: collapse;
+ width: 100%;
+ padding: 2px;
+}
+
+table.LC_double_column tr td.LC_left_col {
+ top: 2px;
+ left: 2px;
+ width: 47%;
+ vertical-align: top;
+}
+
+table.LC_double_column tr td.LC_right_col {
+ top: 2px;
+ right: 2px;
+ width: 47%;
+ vertical-align: top;
+}
+
+span.LC_role_level {
+ font-weight: bold;
+}
+
+div.LC_left_float {
+ float: left;
+ padding-right: 5%;
+ padding-bottom: 4px;
+}
+
+div.LC_clear_float_header {
+ padding-bottom: 2px;
+}
+
+div.LC_clear_float_footer {
+ padding-top: 10px;
+ clear: both;
+}
+
+div.LC_grade_show_user {
+ margin-top: 20px;
+ border: 1px solid black;
+}
+
+div.LC_grade_user_name {
+ background: #DDDDEE;
+ border-bottom: 1px solid black;
+ font-weight: bold;
+ font-size: large;
+}
+
+div.LC_grade_show_user_odd_row div.LC_grade_user_name {
+ background: #DDEEDD;
+}
+
+div.LC_grade_show_problem,
+div.LC_grade_submissions,
+div.LC_grade_message_center,
+div.LC_grade_info_links,
+div.LC_grade_assign {
+ margin: 5px;
+ width: 99%;
+ background: #FFFFFF;
+}
+
+div.LC_grade_show_problem_header,
+div.LC_grade_submissions_header,
+div.LC_grade_message_center_header,
+div.LC_grade_assign_header {
+ font-weight: bold;
+ font-size: large;
+}
+
+div.LC_grade_show_problem_problem,
+div.LC_grade_submissions_body,
+div.LC_grade_message_center_body,
+div.LC_grade_assign_body {
+ border: 1px solid black;
+ width: 99%;
+ background: #FFFFFF;
+}
+
+span.LC_grade_check_note {
+ font-weight: normal;
+ font-size: medium;
+ display: inline;
+ position: absolute;
+ right: 1em;
+}
+
+table.LC_scantron_action {
+ width: 100%;
+}
+
+table.LC_scantron_action tr th {
+ font-weight:bold;
+ font-style:normal;
+}
+
+.LC_edit_problem_header,
+div.LC_edit_problem_footer {
+ font-weight: normal;
+ font-size: medium;
+ margin: 2px;
+}
+
+div.LC_edit_problem_header,
+div.LC_edit_problem_header div,
+div.LC_edit_problem_footer,
+div.LC_edit_problem_footer div,
+div.LC_edit_problem_editxml_header,
+div.LC_edit_problem_editxml_header div {
+ margin-top: 5px;
+}
+
+div.LC_edit_problem_header_title {
+ font-weight: bold;
+ font-size: larger;
+ background: $tabbg;
+ padding: 3px;
+}
+
+table.LC_edit_problem_header_title {
+ font-size: larger;
+ font-weight: bold;
+ width: 100%;
+ border-color: $pgbg;
+ border-style: solid;
+ border-width: $border;
+ background: $tabbg;
+ border-collapse: collapse;
+ padding: 0;
+}
+
+div.LC_edit_problem_discards {
+ float: left;
+ padding-bottom: 5px;
+}
+
+div.LC_edit_problem_saves {
+ float: right;
+ padding-bottom: 5px;
+}
+
+img.stift{
+ border-width: 0;
+ vertical-align: middle;
+}
+
+table#LC_mainmenu{
+ margin-top:10px;
+ width:80%;
+}
+
+table#LC_mainmenu td.LC_mainmenu_col_fieldset{
+ vertical-align: top;
+ width: 45%;
+}
+
+.LC_mainmenu_fieldset_category {
+ color: $font;
+ background: $pgbg;
+ font-size: small;
+ font-weight: bold;
+}
+
+div.LC_createcourse {
+ margin: 10px 10px 10px 10px;
+}
+
+/* ---- Remove when done ----
+# The following styles is part of the redesign of LON-CAPA and are
+# subject to change during this project.
+# Don't rely on their current functionality as they might be
+# changed or removed.
+# --------------------------*/
+
+a:hover,
+ol.LC_smallMenu a:hover,
+ol#LC_MenuBreadcrumbs a:hover,
+ol#LC_PathBreadcrumbs a:hover,
+ul#LC_TabMainMenuContent a:hover,
+.LC_FormSectionClearButton input:hover
+ul.LC_TabContent li:hover a {
+ color:#BF2317;
+ text-decoration:none;
+}
+
+h1 {
+ padding: 0;
+ line-height:130%;
+}
+
+h2,h3,h4,h5,h6 {
+ margin: 5px 0 5px 0;
+ padding: 0;
+ line-height:130%;
+}
+
+.LC_hcell {
+ padding:3px 15px 3px 15px;
+ margin: 0;
+ background-color:$tabbg;
+ color:$fontmenu;
+ border-bottom:solid 1px $lg_border_color;
+}
+
+.LC_Box > .LC_hcell {
+ margin: 0 -10px 10px -10px;
+}
+
+.LC_noBorder {
+ border: 0;
+}
+
+.LC_Right {
+ float: right;
+ margin: 0;
+ padding: 0;
+}
+
+.LC_FormSectionClearButton input {
+ background-color:transparent;
+ border: none;
+ cursor:pointer;
+ text-decoration:underline;
+}
+
+.LC_help_open_topic {
+ color: #FFFFFF;
+ background-color: #EEEEFF;
+ margin: 1px;
+ padding: 4px;
+ border: 1px solid #000033;
+ white-space: nowrap;
+/* vertical-align: middle; */
+}
+
+dl,ul,div,fieldset {
+ margin: 10px 10px 10px 0;
+/* overflow: hidden; */
+}
+
+fieldset > legend {
+ font-weight: bold;
+ padding: 0 5px 0 5px;
+}
+
+#LC_nav_bar {
+ float: left;
+ margin: 0.2em 0 0 0;
+}
+
+#LC_nav_bar em{
+ font-weight: bold;
+ font-style: normal;
+}
+
+ol.LC_smallMenu {
+ float: right;
+ margin: 0.2em 0 0 0;
+}
+
+ol#LC_PathBreadcrumbs {
+ margin: 0;
+}
+
+ol.LC_smallMenu li {
+ display: inline;
+ padding: 5px 5px 0 10px;
+ vertical-align: top;
+}
+
+ol.LC_smallMenu li img {
+ vertical-align: bottom;
+}
+
+ol.LC_smallMenu a {
+ font-size: 90%;
+ color: RGB(80, 80, 80);
+ text-decoration: none;
+}
+
+ul#LC_TabMainMenuContent {
+ clear: both;
+ color: $fontmenu;
+ background: $tabbg;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ width: 100%;
+}
+
+ul#LC_TabMainMenuContent li {
+ font-weight: bold;
+ line-height: 1.8em;
+ padding: 0 0.8em;
+ border-right: 1px solid black;
+ display: inline;
+ vertical-align: middle;
+}
+
+ul.LC_TabContent {
+ display:block;
+ background: $sidebg;
+ border-bottom: solid 1px $lg_border_color;
+ list-style:none;
+ margin: -10px -10px 0 -10px;
+ padding: 0;
+}
+
+ul.LC_TabContentBigger {
+ display:block;
+ list-style:none;
+ padding: 0;
+}
+
+
+ul.LC_TabContent li,
+ul.LC_TabContentBigger li {
+ display: inline;
+ border-right: solid 1px $lg_border_color;
+ float:left;
+ line-height:140%;
+ white-space:nowrap;
+}
+
+ul#LC_TabMainMenuContent li a {
+ color: $fontmenu;
+ text-decoration: none;
+}
+
+ul.LC_TabContent {
+ min-height:1.5em;
+}
+
+ul.LC_TabContent li {
+ vertical-align:middle;
+ padding: 0 10px 0 10px;
+ background-color:$tabbg;
+ border-bottom:solid 1px $lg_border_color;
+}
+
+ul.LC_TabContent .right {
+ float:right;
+}
+
+ul.LC_TabContent li a, ul.LC_TabContent li {
+ color:rgb(47,47,47);
+ text-decoration:none;
+ font-size:95%;
+ font-weight:bold;
+ padding-right: 16px;
+}
+
+ul.LC_TabContent li:hover, ul.LC_TabContent li.active {
+ background:#FFFFFF url(/adm/lonIcons/open.gif) no-repeat scroll right center;
+ border-bottom:solid 2px #FFFFFF;
+ padding-right: 16px;
+}
+
+ul.LC_TabContentBigger li {
+ vertical-align:bottom;
+ border-top:solid 1px $lg_border_color;
+ border-left:solid 1px $lg_border_color;
+ padding:5px 10px 5px 10px;
+ margin-left:2px;
+ background: #d9d9d9;
+}
+
+#maincoursedoc {
+ clear:both;
+}
+
+ul.LC_TabContentBigger li:hover,
+ul.LC_TabContentBigger li.active {
+ background: #ffffff;
+ color:$font;
+}
+
+ul.LC_TabContentBigger li,
+ul.LC_TabContentBigger li a {
+ font-size:110%;
+ font-weight:bold;
+ color: #737373;
+}
+
+ol#LC_MenuBreadcrumbs,
+ol#LC_PathBreadcrumbs,
+ul#LC_CourseBreadcrumbs {
+ padding-left: 10px;
+ margin: 0;
+ list-style-position: inside;
+}
+
+ol#LC_MenuBreadcrumbs li,
+ol#LC_PathBreadcrumbs li,
+ul#LC_CourseBreadcrumbs li {
+ display: inline;
+ white-space: nowrap;
+}
+
+ol#LC_MenuBreadcrumbs li a,
+ul#LC_CourseBreadcrumbs li a {
+ text-decoration: none;
+ font-size:90%;
+}
+
+ol#LC_PathBreadcrumbs li a {
+ text-decoration:none;
+ font-size:100%;
+ font-weight:bold;
+}
+
+.LC_Box {
+ border: solid 1px $lg_border_color;
+ padding: 0 10px 10px 10px;
+}
+
+.LC_AboutMe_Image {
+ float:left;
+ margin-right:10px;
+}
+
+.LC_Clear_AboutMe_Image {
+ clear:left;
+}
+
+dl.LC_ListStyleClean dt {
+ padding-right: 5px;
+ display: table-header-group;
+}
+
+dl.LC_ListStyleClean dd {
+ display: table-row;
+}
+
+.LC_ListStyleClean,
+.LC_ListStyleSimple,
+.LC_ListStyleNormal,
+.LC_ListStyle_Border,
+.LC_ListStyleSpecial {
+ /*display:block; */
+ list-style-position: inside;
+ list-style-type: none;
+ overflow: hidden;
+ padding: 0;
+}
+
+.LC_ListStyleSimple li,
+.LC_ListStyleSimple dd,
+.LC_ListStyleNormal li,
+.LC_ListStyleNormal dd,
+.LC_ListStyleSpecial li,
+.LC_ListStyleSpecial dd {
+ margin: 0;
+ padding: 5px 5px 5px 10px;
+ clear: both;
+}
+
+.LC_ListStyleClean li,
+.LC_ListStyleClean dd {
+ padding-top: 0;
+ padding-bottom: 0;
+}
+
+.LC_ListStyleSimple dd,
+.LC_ListStyleSimple li {
+ border-bottom: solid 1px $lg_border_color;
+}
+
+.LC_ListStyleSpecial li,
+.LC_ListStyleSpecial dd {
+ list-style-type: none;
+ background-color: RGB(220, 220, 220);
+ margin-bottom: 4px;
+}
+
+table.LC_SimpleTable {
+ margin:5px;
+ border:solid 1px $lg_border_color;
+}
+
+table.LC_SimpleTable tr {
+ padding: 0;
+ border:solid 1px $lg_border_color;
+}
+
+table.LC_SimpleTable thead {
+ background:rgb(220,220,220);
+}
+
+div.LC_columnSection {
+ display: block;
+ clear: both;
+ overflow: hidden;
+ margin: 0;
+}
+
+div.LC_columnSection>* {
+ float: left;
+ margin: 10px 20px 10px 0;
+ overflow:hidden;
+}
+
+.LC_loginpage_container {
+ text-align:left;
+ margin : 0 auto;
+ width:90%;
+ padding: 10px;
+ height: auto;
+ background-color:#FFFFFF;
+ border:1px solid #CCCCCC;
+}
+
+
+.LC_loginpage_loginContainer {
+ float:left;
+ width: 182px;
+ padding: 2px;
+ border:1px solid #CCCCCC;
+ background-color:$loginbg;
+}
+
+.LC_loginpage_loginContainer h2 {
+ margin-top: 0;
+ display:block;
+ background:$bgcol;
+ color:$textcol;
+ padding-left:5px;
+}
+
+.LC_loginpage_loginInfo {
+ float:left;
+ width:182px;
+ border:1px solid #CCCCCC;
+ padding:2px;
+}
+
+.LC_loginpage_space {
+ clear: both;
+ margin-bottom: 20px;
+ border-bottom: 1px solid #CCCCCC;
+}
+
+.LC_loginpage_floatLeft {
+ float: left;
+ width: 200px;
+ margin: 0;
+}
+
+table em {
+ font-weight: bold;
+ font-style: normal;
+}
+
+table.LC_tableBrowseRes,
+table.LC_tableOfContent {
+ border:none;
+ border-spacing: 1px;
+ padding: 3px;
+ background-color: #FFFFFF;
+ font-size: 90%;
+}
+
+table.LC_tableOfContent{
+ border-collapse: collapse;
+}
+
+table.LC_tableBrowseRes a,
+table.LC_tableOfContent a {
+ background-color: transparent;
+ text-decoration: none;
+}
+
+table.LC_tableBrowseRes tr.LC_trOdd,
+table.LC_tableOfContent tr.LC_trOdd{
+ background-color: #EEEEEE;
+}
+
+table.LC_tableOfContent img {
+ border: none;
+ height: 1.3em;
+ vertical-align: text-bottom;
+ margin-right: 0.3em;
+}
+
+a#LC_content_toolbar_firsthomework {
+ background-image:url(/res/adm/pages/open-first-problem.gif);
+}
+
+a#LC_content_toolbar_launchnav {
+ background-image:url(/res/adm/pages/start-navigation.gif);
+}
+
+a#LC_content_toolbar_closenav {
+ background-image:url(/res/adm/pages/close-navigation.gif);
+}
+
+a#LC_content_toolbar_everything {
+ background-image:url(/res/adm/pages/show-all.gif);
+}
+
+a#LC_content_toolbar_uncompleted {
+ background-image:url(/res/adm/pages/show-incomplete-problems.gif);
+}
+
+#LC_content_toolbar_clearbubbles {
+ background-image:url(/res/adm/pages/mark-discussionentries-read.gif);
+}
+
+a#LC_content_toolbar_changefolder {
+ background : url(/res/adm/pages/close-all-folders.gif) top center ;
+}
+
+a#LC_content_toolbar_changefolder_toggled {
+ background-image:url(/res/adm/pages/open-all-folders.gif);
+}
+
+ul#LC_toolbar li a:hover {
+ background-position: bottom center;
+}
+
+ul#LC_toolbar {
+ padding: 0;
+ margin: 2px;
+ list-style:none;
+ position:relative;
+ background-color:white;
+}
+
+ul#LC_toolbar li {
+ border:1px solid white;
+ padding: 0;
+ margin: 0;
+ float: left;
+ display:inline;
+ vertical-align:middle;
+}
+
+
+a.LC_toolbarItem {
+ display:block;
+ padding: 0;
+ margin: 0;
+ height: 32px;
+ width: 32px;
+ color:white;
+ border: none;
+ background-repeat:no-repeat;
+ background-color:transparent;
+}
+
+ul.LC_funclist li {
+ float: left;
+ white-space: nowrap;
+ height: 35px; /* at least as high as heighest list item */
+ margin: 0 15px 15px 10px;
+}
+
+
END
}
@@ -4662,10 +6371,7 @@ Inputs: none
sub font_settings {
my $headerstring='';
- if (($env{'browser.os'} eq 'mac') && (!$env{'browser.mathml'})) {
- $headerstring.=
- ' ';
- } elsif (!$env{'browser.mathml'} && $env{'browser.unicode'}) {
+ if (!$env{'browser.mathml'} && $env{'browser.unicode'}) {
$headerstring.=
' ';
}
@@ -4685,7 +6391,9 @@ Inputs: none
sub xml_begin {
my $output='';
- &Apache::lonhtmlcommon::init_htmlareafields();
+ if ($env{'internal.start_page'}==1) {
+ &Apache::lonhtmlcommon::init_htmlareafields();
+ }
if ($env{'browser.mathml'}) {
$output=''
@@ -4697,7 +6405,8 @@ sub xml_begin {
.'';
} else {
- $output='';
+ $output=''
+ .'';
}
return $output;
}
@@ -4722,8 +6431,15 @@ sub endheadtag {
Returns a uniform complete .. section for LON-CAPA web pages.
-Inputs: $title - optional title for the page
- $head_extra - optional extra HTML to put inside the
+Inputs:
+
+=over 4
+
+$title - optional title for the page
+
+$head_extra - optional extra HTML to put inside the
+
+=back
=cut
@@ -4738,44 +6454,50 @@ sub head {
Returns a complete .. section for LON-CAPA web pages.
-Inputs: $title - optional title for the page
- $head_extra - optional extra HTML to incude inside the
- $args - additional optional args supported are:
- only_body -> is true will set &bodytag() onlybodytag
+Inputs:
+
+=over 4
+
+$title - optional title for the page
+
+$head_extra - optional extra HTML to incude inside the
+
+$args - additional optional args supported are:
+
+=over 8
+
+ only_body -> is true will set &bodytag() onlybodytag
arg on
- no_nav_bar -> is true will set &bodytag() notopbar arg on
- add_entries -> additional attributes to add to the
- domain -> force to color decorate a page for a
+ no_nav_bar -> is true will set &bodytag() no_nav_bar arg on
+ add_entries -> additional attributes to add to the
+ domain -> force to color decorate a page for a
specific domain
- function -> force usage of a specific rolish color
+ function -> force usage of a specific rolish color
scheme
- redirect -> see &headtag()
- bgcolor -> override the default page bg color
- js_ready -> return a string ready for being used in
+ redirect -> see &headtag()
+ bgcolor -> override the default page bg color
+ js_ready -> return a string ready for being used in
a javascript writeln
- html_encode -> return a string ready for being used in
+ html_encode -> return a string ready for being used in
a html attribute
- force_register -> if is true will turn on the &bodytag()
+ force_register -> if is true will turn on the &bodytag()
$forcereg arg
- body_title -> alternate text to use instead of $title
- in the title box that appears, this text
- is not auto translated like the $title is
- frameset -> if true will start with a
+ frameset -> if true will start with a
rather than
- no_title -> if true the title bar won't be shown
- skip_phases -> hash ref of
+ skip_phases -> hash ref of
head -> skip the generation
body -> skip all generation
-
- no_inline_link -> if true and in remote mode, don't show the
+ no_inline_link -> if true and in remote mode, don't show the
'Switch To Inline Menu' link
-
- no_auto_mt_title -> prevent &mt()ing the title arg
-
- inherit_jsmath -> when creating popup window in a page,
+ no_auto_mt_title -> prevent &mt()ing the title arg
+ inherit_jsmath -> when creating popup window in a page,
should it have jsmath forced on by the
current page
+=back
+
+=back
+
=cut
sub start_page {
@@ -4803,23 +6525,48 @@ sub start_page {
my $attr_string = &make_attr_string($args->{'force_register'},
$args->{'add_entries'});
$result .= "\n\n";
- } else {
- $result .=
- &bodytag($title,
- $args->{'function'}, $args->{'add_entries'},
- $args->{'only_body'}, $args->{'domain'},
- $args->{'force_register'}, $args->{'body_title'},
- $args->{'no_nav_bar'}, $args->{'bgcolor'},
- $args->{'no_title'}, $args->{'no_inline_link'},
- $args);
- }
+ } else {
+ $result .=
+ &bodytag($title,
+ $args->{'function'}, $args->{'add_entries'},
+ $args->{'only_body'}, $args->{'domain'},
+ $args->{'force_register'}, $args->{'no_nav_bar'},
+ $args->{'bgcolor'}, $args->{'no_inline_link'},
+ $args);
+ }
}
if ($args->{'js_ready'}) {
- $result = &js_ready($result);
+ $result = &js_ready($result);
}
if ($args->{'html_encode'}) {
- $result = &html_encode($result);
+ $result = &html_encode($result);
+ }
+
+ # Preparation for new and consistent functionlist at top of screen
+ # if ($args->{'functionlist'}) {
+ # $result .= &build_functionlist();
+ #}
+
+ # Don't add anything more if only_body wanted
+ return $result if $args->{'only_body'};
+
+ #Breadcrumbs
+ if (exists($args->{'bread_crumbs'}) or exists($args->{'bread_crumbs_component'})) {
+ &Apache::lonhtmlcommon::clear_breadcrumbs();
+ #if any br links exists, add them to the breadcrumbs
+ if (exists($args->{'bread_crumbs'}) and ref($args->{'bread_crumbs'}) eq 'ARRAY') {
+ foreach my $crumb (@{$args->{'bread_crumbs'}}){
+ &Apache::lonhtmlcommon::add_breadcrumb($crumb);
+ }
+ }
+
+ #if bread_crumbs_component exists show it as headline else show only the breadcrumbs
+ if(exists($args->{'bread_crumbs_component'})){
+ $result .= &Apache::lonhtmlcommon::breadcrumbs($args->{'bread_crumbs_component'});
+ }else{
+ $result .= &Apache::lonhtmlcommon::breadcrumbs();
+ }
}
return $result;
}
@@ -4862,7 +6609,7 @@ sub end_page {
if ($args->{'frameset'}) {
$result .= ' ';
} else {
- $result .= &endbodytag();
+ $result .= &endbodytag($args);
}
$result .= "\n";
@@ -4934,30 +6681,30 @@ sub simple_error_page {
}
{
- my $row_count;
+ my @row_count;
sub start_data_table {
my ($add_class) = @_;
my $css_class = (join(' ','LC_data_table',$add_class));
- undef($row_count);
+ unshift(@row_count,0);
return ''."\n";
}
sub end_data_table {
- undef($row_count);
+ shift(@row_count);
return '
'."\n";;
}
sub start_data_table_row {
my ($add_class) = @_;
- $row_count++;
- my $css_class = ($row_count % 2)?'':'LC_even_row';
+ $row_count[0]++;
+ my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
$css_class = (join(' ',$css_class,$add_class));
return ''."\n";;
}
sub continue_data_table_row {
my ($add_class) = @_;
- my $css_class = ($row_count % 2)?'':'LC_even_row';
+ my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
$css_class = (join(' ',$css_class,$add_class));
return ' '."\n";;
}
@@ -4967,7 +6714,7 @@ sub simple_error_page {
}
sub start_data_table_empty_row {
- $row_count++;
+# $row_count[0]++;
return ' '."\n";;
}
@@ -5048,14 +6795,17 @@ Returns either 'student','coordinator','
###############################################
sub get_users_function {
- my $function = 'student';
+ my $function = 'norole';
+ if ($env{'request.role'}=~/^(st)/) {
+ $function='student';
+ }
if ($env{'request.role'}=~/^(cc|in|ta|ep)/) {
$function='coordinator';
}
if ($env{'request.role'}=~/^(su|dc|ad|li)/) {
$function='admin';
}
- if (($env{'request.role'}=~/^(au|ca)/) ||
+ if (($env{'request.role'}=~/^(au|ca|aa)/) ||
($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
$function='author';
}
@@ -5066,6 +6816,38 @@ sub get_users_function {
=pod
+=item * &show_course()
+
+Used by lonmenu.pm and lonroles.pm to determine whether to use the word
+'Courses' or 'Roles' in inline navigation and on screen displaying user's roles.
+
+Inputs:
+None
+
+Outputs:
+Scalar: 1 if 'Course' to be used, 0 otherwise.
+
+=cut
+
+###############################################
+sub show_course {
+ my $course = !$env{'user.adv'};
+ if (!$env{'user.adv'}) {
+ foreach my $env (keys(%env)) {
+ next if ($env !~ m/^user\.priv\./);
+ if ($env !~ m/^user\.priv\.(?:st|cm)/) {
+ $course = 0;
+ last;
+ }
+ }
+ }
+ return $course;
+}
+
+###############################################
+
+=pod
+
=item * &check_user_status()
Determines current status of supplied role for a
@@ -5239,12 +7021,17 @@ previous, future, or all.
5. reference to array of section restrictions (optional)
6. reference to results object (hash of hashes).
7. reference to optional userdata hash
-Keys of top level hash are roles.
+8. reference to optional statushash
+9. flag if privileged users (except those set to unhide in
+ course settings) should be excluded
+Keys of top level results hash are roles.
Keys of inner hashes are username:domain, with
values set to access type.
Optional userdata hash returns an array with arguments in the
same order as loncoursedata::get_classlist() for student data.
+Optional statushash returns
+
Entries for end, start, section and status are blank because
of the possibility of multiple values for non-student roles.
@@ -5253,7 +7040,7 @@ of the possibility of multiple values fo
###############################################
sub get_course_users {
- my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata) = @_;
+ my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata,$statushash,$hidepriv) = @_;
my %idx = ();
my %seclists;
@@ -5273,6 +7060,7 @@ sub get_course_users {
my $match = 0;
my $secmatch = 0;
my $section = $$classlist{$student}[$idx{section}];
+ my $status = $$classlist{$student}[$idx{status}];
if ($section eq '') {
$section = 'none';
}
@@ -5292,7 +7080,6 @@ sub get_course_users {
next;
}
}
- push(@{$seclists{$student}},$section);
if (defined($$types{'active'})) {
if ($$classlist{$student}[$idx{status}] eq 'Active') {
push(@{$$users{st}{$student}},'active');
@@ -5300,25 +7087,46 @@ sub get_course_users {
}
}
if (defined($$types{'previous'})) {
- if ($$classlist{$student}[$idx{end}] <= $now) {
+ if ($$classlist{$student}[$idx{status}] eq 'Expired') {
push(@{$$users{st}{$student}},'previous');
$match = 1;
}
}
if (defined($$types{'future'})) {
- if (($$classlist{$student}[$idx{start}] > $now) && ($$classlist{$student}[$idx{end}] > $now) || ($$classlist{$student}[$idx{end}] == 0) || ($$classlist{$student}[$idx{end}] eq '')) {
+ if ($$classlist{$student}[$idx{status}] eq 'Future') {
push(@{$$users{st}{$student}},'future');
$match = 1;
}
}
- if ($match && ref($userdata) eq 'HASH') {
- $$userdata{$student} = $$classlist{$student};
+ if ($match) {
+ push(@{$seclists{$student}},$section);
+ if (ref($userdata) eq 'HASH') {
+ $$userdata{$student} = $$classlist{$student};
+ }
+ if (ref($statushash) eq 'HASH') {
+ $statushash->{$student}{'st'}{$section} = $status;
+ }
}
}
}
if ((@{$roles} > 1) || ((@{$roles} == 1) && ($$roles[0] ne "st"))) {
my %coursepersonnel = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
my $now = time;
+ my %displaystatus = ( previous => 'Expired',
+ active => 'Active',
+ future => 'Future',
+ );
+ my %nothide;
+ if ($hidepriv) {
+ my %coursehash=&Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+ foreach my $user (split(/\s*\,\s*/,$coursehash{'nothideprivileged'})) {
+ if ($user !~ /:/) {
+ $nothide{join(':',split(/[\@]/,$user))}=1;
+ } else {
+ $nothide{$user} = 1;
+ }
+ }
+ }
foreach my $person (sort(keys(%coursepersonnel))) {
my $match = 0;
my $secmatch = 0;
@@ -5352,6 +7160,12 @@ sub get_course_users {
$usec = 'none';
}
if ($uname ne '' && $udom ne '') {
+ if ($hidepriv) {
+ if ((&Apache::lonnet::privileged($uname,$udom)) &&
+ (!$nothide{$uname.':'.$udom})) {
+ next;
+ }
+ }
if ($end > 0 && $end < $now) {
$status = 'previous';
} elsif ($start > $now) {
@@ -5374,6 +7188,9 @@ sub get_course_users {
if (!grep(/^\Q$usec\E$/,@{$seclists{$uname.':'.$udom}})) {
push(@{$seclists{$uname.':'.$udom}},$usec);
}
+ if (ref($statushash) eq 'HASH') {
+ $statushash->{$uname.':'.$udom}{$role}{$usec} = $displaystatus{$status};
+ }
}
}
}
@@ -5383,15 +7200,25 @@ sub get_course_users {
my %csettings = &Apache::lonnet::get('environment',['internal.courseowner'],$cdom,$cnum);
if ( defined($csettings{'internal.courseowner'}) ) {
my $owner = $csettings{'internal.courseowner'};
- if ($owner !~ /^[^:]+:[^:]+$/) {
- $owner = $owner.':'.$cdom;
+ next if ($owner eq '');
+ my ($ownername,$ownerdom);
+ if ($owner =~ /^([^:]+):([^:]+)$/) {
+ $ownername = $1;
+ $ownerdom = $2;
+ } else {
+ $ownername = $owner;
+ $ownerdom = $cdom;
+ $owner = $ownername.':'.$ownerdom;
}
@{$$users{'ow'}{$owner}} = 'any';
if (defined($userdata) &&
- !exists($$userdata{$owner.':'.$cdom})) {
- &get_user_info($cdom,$owner,\%idx,$userdata);
- if (!grep(/^none$/,@{$seclists{$owner.':'.$cdom}})) {
- push(@{$seclists{$owner.':'.$cdom}},'none');
+ !exists($$userdata{$owner})) {
+ &get_user_info($ownerdom,$ownername,\%idx,$userdata);
+ if (!grep(/^none$/,@{$seclists{$owner}})) {
+ push(@{$seclists{$owner}},'none');
+ }
+ if (ref($statushash) eq 'HASH') {
+ $statushash->{$owner}{'ow'}{'none'} = 'Any';
}
}
}
@@ -5411,6 +7238,8 @@ sub get_user_info {
&plainname($uname,$udom,'lastname');
$$userdata{$uname.':'.$udom}[$$idx{uname}] = $uname;
$$userdata{$uname.':'.$udom}[$$idx{udom}] = $udom;
+ my %idhash = &Apache::lonnet::idrget($udom,($uname));
+ $$userdata{$uname.':'.$udom}[$$idx{id}] = $idhash{$uname};
return;
}
@@ -5522,6 +7351,8 @@ If the user's status includes multiple t
the largest default quota which applies to the user determines the
default quota returned.
+=back
+
=cut
###############################################
@@ -5531,24 +7362,40 @@ sub default_quota {
my ($udom,$inststatus) = @_;
my ($defquota,$settingstatus);
my %quotahash = &Apache::lonnet::get_dom('configuration',
- ['quota'],$udom);
- if (ref($quotahash{'quota'}) eq 'HASH') {
+ ['quotas'],$udom);
+ if (ref($quotahash{'quotas'}) eq 'HASH') {
if ($inststatus ne '') {
- my @statuses = split(/:/,$inststatus);
+ my @statuses = map { &unescape($_); } split(/:/,$inststatus);
foreach my $item (@statuses) {
- if ($quotahash{'quota'}{$item} ne '') {
- if ($defquota eq '') {
- $defquota = $quotahash{'quota'}{$item};
- $settingstatus = $item;
- } elsif ($quotahash{'quota'}{$item} > $defquota) {
- $defquota = $quotahash{'quota'}{$item};
- $settingstatus = $item;
+ if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') {
+ if ($quotahash{'quotas'}{'defaultquota'}{$item} ne '') {
+ if ($defquota eq '') {
+ $defquota = $quotahash{'quotas'}{'defaultquota'}{$item};
+ $settingstatus = $item;
+ } elsif ($quotahash{'quotas'}{'defaultquota'}{$item} > $defquota) {
+ $defquota = $quotahash{'quotas'}{'defaultquota'}{$item};
+ $settingstatus = $item;
+ }
+ }
+ } else {
+ if ($quotahash{'quotas'}{$item} ne '') {
+ if ($defquota eq '') {
+ $defquota = $quotahash{'quotas'}{$item};
+ $settingstatus = $item;
+ } elsif ($quotahash{'quotas'}{$item} > $defquota) {
+ $defquota = $quotahash{'quotas'}{$item};
+ $settingstatus = $item;
+ }
}
}
}
}
if ($defquota eq '') {
- $defquota = $quotahash{'quota'}{'default'};
+ if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') {
+ $defquota = $quotahash{'quotas'}{'defaultquota'}{'default'};
+ } else {
+ $defquota = $quotahash{'quotas'}{'default'};
+ }
$settingstatus = 'default';
}
} else {
@@ -5600,14 +7447,14 @@ sub get_secgrprole_info {
}
sub user_picker {
- my ($dom,$srch,$forcenewuser,$caller) = @_;
+ my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype) = @_;
my $currdom = $dom;
my %curr_selected = (
srchin => 'dom',
srchby => 'lastname',
);
my $srchterm;
- if (ref($srch) eq 'HASH') {
+ if ((ref($srch) eq 'HASH') && ($env{'form.origform'} ne 'crtusername')) {
if ($srch->{'srchby'} ne '') {
$curr_selected{'srchby'} = $srch->{'srchby'};
}
@@ -5694,7 +7541,21 @@ sub user_picker {
if ($forcenewuser) {
if (ref($srch) eq 'HASH') {
if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $env{'request.role.domain'}) {
- $new_user_create = ' &"').'" onclick="javascript:setSearch(\'1\','.$caller.');" />
';
+ if ($cancreate) {
+ $new_user_create = ' &"').'" onclick="javascript:setSearch(\'1\','.$caller.');" />
';
+ } else {
+ my $helplink = 'javascript:helpMenu('."'display'".')';
+ my %usertypetext = (
+ official => 'institutional',
+ unofficial => 'non-institutional',
+ );
+ $new_user_create = ''
+ .&mt("You are not authorized to create new $usertypetext{$usertype} users in this domain.")
+ .' '
+ .&mt('Please contact the [_1]helpdesk[_2] for assistance.'
+ ,'',' ')
+ .'
';
+ }
}
}
@@ -5730,6 +7591,7 @@ ENDSCRIPT
my $output = <<"END_BLOCK";
$new_user_create
@@ -5823,15 +7686,284 @@ END_BLOCK
return $output;
}
+sub user_rule_check {
+ my ($usershash,$checks,$alerts,$rulematch,$inst_results,$curr_rules,$got_rules) = @_;
+ my $response;
+ if (ref($usershash) eq 'HASH') {
+ foreach my $user (keys(%{$usershash})) {
+ my ($uname,$udom) = split(/:/,$user);
+ next if ($udom eq '' || $uname eq '');
+ my ($id,$newuser);
+ if (ref($usershash->{$user}) eq 'HASH') {
+ $newuser = $usershash->{$user}->{'newuser'};
+ $id = $usershash->{$user}->{'id'};
+ }
+ my $inst_response;
+ if (ref($checks) eq 'HASH') {
+ if (defined($checks->{'username'})) {
+ ($inst_response,%{$inst_results->{$user}}) =
+ &Apache::lonnet::get_instuser($udom,$uname);
+ } elsif (defined($checks->{'id'})) {
+ ($inst_response,%{$inst_results->{$user}}) =
+ &Apache::lonnet::get_instuser($udom,undef,$id);
+ }
+ } else {
+ ($inst_response,%{$inst_results->{$user}}) =
+ &Apache::lonnet::get_instuser($udom,$uname);
+ return;
+ }
+ if (!$got_rules->{$udom}) {
+ my %domconfig = &Apache::lonnet::get_dom('configuration',
+ ['usercreation'],$udom);
+ if (ref($domconfig{'usercreation'}) eq 'HASH') {
+ foreach my $item ('username','id') {
+ if (ref($domconfig{'usercreation'}{$item.'_rule'}) eq 'ARRAY') {
+ $$curr_rules{$udom}{$item} =
+ $domconfig{'usercreation'}{$item.'_rule'};
+ }
+ }
+ }
+ $got_rules->{$udom} = 1;
+ }
+ foreach my $item (keys(%{$checks})) {
+ if (ref($$curr_rules{$udom}) eq 'HASH') {
+ if (ref($$curr_rules{$udom}{$item}) eq 'ARRAY') {
+ if (@{$$curr_rules{$udom}{$item}} > 0) {
+ my %rule_check = &Apache::lonnet::inst_rulecheck($udom,$uname,$id,$item,$$curr_rules{$udom}{$item});
+ foreach my $rule (@{$$curr_rules{$udom}{$item}}) {
+ if ($rule_check{$rule}) {
+ $$rulematch{$user}{$item} = $rule;
+ if ($inst_response eq 'ok') {
+ if (ref($inst_results) eq 'HASH') {
+ if (ref($inst_results->{$user}) eq 'HASH') {
+ if (keys(%{$inst_results->{$user}}) == 0) {
+ $$alerts{$item}{$udom}{$uname} = 1;
+ }
+ }
+ }
+ }
+ last;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
+sub user_rule_formats {
+ my ($domain,$domdesc,$curr_rules,$check) = @_;
+ my %text = (
+ 'username' => 'Usernames',
+ 'id' => 'IDs',
+ );
+ my $output;
+ my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($domain,$check);
+ if ((ref($rules) eq 'HASH') && (ref($ruleorder) eq 'ARRAY')) {
+ if (@{$ruleorder} > 0) {
+ $output = ' '.&mt("$text{$check} with the following format(s) may only be used for verified users at [_1]:",$domdesc).' ';
+ foreach my $rule (@{$ruleorder}) {
+ if (ref($curr_rules) eq 'ARRAY') {
+ if (grep(/^\Q$rule\E$/,@{$curr_rules})) {
+ if (ref($rules->{$rule}) eq 'HASH') {
+ $output .= ''.$rules->{$rule}{'name'}.': '.
+ $rules->{$rule}{'desc'}.' ';
+ }
+ }
+ }
+ }
+ $output .= ' ';
+ }
+ }
+ return $output;
+}
+
+sub instrule_disallow_msg {
+ my ($checkitem,$domdesc,$count,$mode) = @_;
+ my $response;
+ my %text = (
+ item => 'username',
+ items => 'usernames',
+ match => 'matches',
+ do => 'does',
+ action => 'a username',
+ one => 'one',
+ );
+ if ($count > 1) {
+ $text{'item'} = 'usernames';
+ $text{'match'} ='match';
+ $text{'do'} = 'do';
+ $text{'action'} = 'usernames',
+ $text{'one'} = 'ones';
+ }
+ if ($checkitem eq 'id') {
+ $text{'items'} = 'IDs';
+ $text{'item'} = 'ID';
+ $text{'action'} = 'an ID';
+ if ($count > 1) {
+ $text{'item'} = 'IDs';
+ $text{'action'} = 'IDs';
+ }
+ }
+ $response = &mt("The $text{'item'} you chose $text{'match'} the format of $text{'items'} defined for [_1], but the $text{'item'} $text{'do'} not exist in the institutional directory.",''.$domdesc.' ').' ';
+ if ($mode eq 'upload') {
+ if ($checkitem eq 'username') {
+ $response .= &mt("You will need to modify your upload file so it will include $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}.");
+ } elsif ($checkitem eq 'id') {
+ $response .= &mt("Either upload a file which includes $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}, or when associating fields with data columns, omit an association for the Student/Employee ID field.");
+ }
+ } elsif ($mode eq 'selfcreate') {
+ if ($checkitem eq 'id') {
+ $response .= &mt("You must either choose $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}, or leave the ID field blank.");
+ }
+ } else {
+ if ($checkitem eq 'username') {
+ $response .= &mt("You must choose $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}.");
+ } elsif ($checkitem eq 'id') {
+ $response .= &mt("You must either choose $text{'action'} with a different format -- $text{'one'} that will not conflict with 'official' institutional $text{'items'}, or leave the ID field blank.");
+ }
+ }
+ return $response;
+}
+
+sub personal_data_fieldtitles {
+ my %fieldtitles = &Apache::lonlocal::texthash (
+ id => 'Student/Employee ID',
+ permanentemail => 'E-mail address',
+ lastname => 'Last Name',
+ firstname => 'First Name',
+ middlename => 'Middle Name',
+ generation => 'Generation',
+ gen => 'Generation',
+ inststatus => 'Affiliation',
+ );
+ return %fieldtitles;
+}
+
+sub sorted_inst_types {
+ my ($dom) = @_;
+ my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom);
+ my $othertitle = &mt('All users');
+ if ($env{'request.course.id'}) {
+ $othertitle = &mt('Any users');
+ }
+ my @types;
+ if (ref($order) eq 'ARRAY') {
+ @types = @{$order};
+ }
+ if (@types == 0) {
+ if (ref($usertypes) eq 'HASH') {
+ @types = sort(keys(%{$usertypes}));
+ }
+ }
+ if (keys(%{$usertypes}) > 0) {
+ $othertitle = &mt('Other users');
+ }
+ return ($othertitle,$usertypes,\@types);
+}
+
+sub get_institutional_codes {
+ my ($settings,$allcourses,$LC_code) = @_;
+# Get complete list of course sections to update
+ my @currsections = ();
+ my @currxlists = ();
+ my $coursecode = $$settings{'internal.coursecode'};
+
+ if ($$settings{'internal.sectionnums'} ne '') {
+ @currsections = split(/,/,$$settings{'internal.sectionnums'});
+ }
+
+ if ($$settings{'internal.crosslistings'} ne '') {
+ @currxlists = split(/,/,$$settings{'internal.crosslistings'});
+ }
+
+ if (@currxlists > 0) {
+ foreach (@currxlists) {
+ if (m/^([^:]+):(\w*)$/) {
+ unless (grep/^$1$/,@{$allcourses}) {
+ push @{$allcourses},$1;
+ $$LC_code{$1} = $2;
+ }
+ }
+ }
+ }
+
+ if (@currsections > 0) {
+ foreach (@currsections) {
+ if (m/^(\w+):(\w*)$/) {
+ my $sec = $coursecode.$1;
+ my $lc_sec = $2;
+ unless (grep/^$sec$/,@{$allcourses}) {
+ push @{$allcourses},$sec;
+ $$LC_code{$sec} = $lc_sec;
+ }
+ }
+ }
+ }
+ return;
+}
+
=pod
+=head1 Slot Helpers
+
+=over 4
+
+=item * sorted_slots()
+
+Sorts an array of slot names in order of slot start time (earliest first).
+
+Inputs:
+
+=over 4
+
+slotsarr - Reference to array of unsorted slot names.
+
+slots - Reference to hash of hash, where outer hash keys are slot names.
+
+=back
+
+Returns:
+
+=over 4
+
+sorted - An array of slot names sorted by the start time of the slot.
+
=back
+=back
+
+=cut
+
+
+sub sorted_slots {
+ my ($slotsarr,$slots) = @_;
+ my @sorted;
+ if ((ref($slotsarr) eq 'ARRAY') && (ref($slots) eq 'HASH')) {
+ @sorted =
+ sort {
+ if (ref($slots->{$a}) && ref($slots->{$b})) {
+ return $slots->{$a}{'starttime'} <=> $slots->{$b}{'starttime'}
+ }
+ if (ref($slots->{$a})) { return -1;}
+ if (ref($slots->{$b})) { return 1;}
+ return 0;
+ } @{$slotsarr};
+ }
+ return @sorted;
+}
+
+
+=pod
+
=head1 HTTP Helpers
=over 4
-=item * get_unprocessed_cgi($query,$possible_names)
+=item * &get_unprocessed_cgi($query,$possible_names)
Modify the %env hash to contain unprocessed CGI form parameters held in
$query. The parameters listed in $possible_names (an array reference),
@@ -5860,7 +7992,7 @@ sub get_unprocessed_cgi {
=pod
-=item * cacheheader()
+=item * &cacheheader()
returns cache-controlling header code
@@ -5877,7 +8009,7 @@ sub cacheheader {
=pod
-=item * no_cache($r)
+=item * &no_cache($r)
specifies header code to not have cache
@@ -5913,7 +8045,7 @@ sub content_type {
=pod
-=item * add_to_env($name,$value)
+=item * &add_to_env($name,$value)
adds $name to the %env hash with value
$value, if $name already exists, the entry is converted to an array
@@ -5940,7 +8072,7 @@ sub add_to_env {
=pod
-=item * get_env_multiple($name)
+=item * &get_env_multiple($name)
gets $name from the %env hash, it seemlessly handles the cases where multiple
values may be defined and end up as an array ref.
@@ -5963,6 +8095,232 @@ sub get_env_multiple {
return(@values);
}
+sub ask_for_embedded_content {
+ my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
+ my $upload_output = '
+ ';
+ return $upload_output;
+}
+
+sub upload_embedded {
+ my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota,
+ $current_disk_usage) = @_;
+ my $output;
+ for (my $i=0; $i<$env{'form.number_embedded_items'}; $i++) {
+ next if (!exists($env{'form.embedded_item_'.$i.'.filename'}));
+ my $orig_uploaded_filename =
+ $env{'form.embedded_item_'.$i.'.filename'};
+
+ $env{'form.embedded_orig_'.$i} =
+ &unescape($env{'form.embedded_orig_'.$i});
+ my ($path,$fname) =
+ ($env{'form.embedded_orig_'.$i} =~ m{(.*/)([^/]*)});
+ # no path, whole string is fname
+ if (!$fname) { $fname = $env{'form.embedded_orig_'.$i} };
+
+ $path = $env{'form.currentpath'}.$path;
+ $fname = &Apache::lonnet::clean_filename($fname);
+ # See if there is anything left
+ next if ($fname eq '');
+
+ # Check if file already exists as a file or directory.
+ my ($state,$msg);
+ if ($context eq 'portfolio') {
+ my $port_path = $dirpath;
+ if ($group ne '') {
+ $port_path = "groups/$group/$port_path";
+ }
+ ($state,$msg) = &check_for_upload($path,$fname,$group,'embedded_item_'.$i,
+ $dir_root,$port_path,$disk_quota,
+ $current_disk_usage,$uname,$udom);
+ if ($state eq 'will_exceed_quota'
+ || $state eq 'file_locked'
+ || $state eq 'file_exists' ) {
+ $output .= $msg;
+ next;
+ }
+ } elsif (($context eq 'author') || ($context eq 'testbank')) {
+ ($state,$msg) = &check_for_existing($path,$fname,'embedded_item_'.$i);
+ if ($state eq 'exists') {
+ $output .= $msg;
+ next;
+ }
+ }
+ # Check if extension is valid
+ if (($fname =~ /\.(\w+)$/) &&
+ (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
+ $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1);
+ next;
+ } elsif (($fname =~ /\.(\w+)$/) &&
+ (!defined(&Apache::loncommon::fileembstyle($1)))) {
+ $output .= &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1);
+ next;
+ } elsif ($fname=~/\.(\d+)\.(\w+)$/) {
+ $output .= &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2);
+ next;
+ }
+
+ $env{'form.embedded_item_'.$i.'.filename'}=$fname;
+ if ($context eq 'portfolio') {
+ my $result=
+ &Apache::lonnet::userfileupload('embedded_item_'.$i,'',
+ $dirpath.$path);
+ if ($result !~ m|^/uploaded/|) {
+ $output .= ''
+ .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
+ ,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})
+ .' ';
+ next;
+ } else {
+ $output .= ''.&mt('Uploaded [_1]',''.
+ $path.$fname.' ').'
';
+ }
+ } else {
+# Save the file
+ my $target = $env{'form.embedded_item_'.$i};
+ my $fullpath = $dir_root.$dirpath.'/'.$path;
+ my $dest = $fullpath.$fname;
+ my $url = $url_root.$dirpath.'/'.$path.$fname;
+ my @parts=split(/\//,$fullpath);
+ my $count;
+ my $filepath = $dir_root;
+ for ($count=4;$count<=$#parts;$count++) {
+ $filepath .= "/$parts[$count]";
+ if ((-e $filepath)!=1) {
+ mkdir($filepath,0770);
+ }
+ }
+ my $fh;
+ if (!open($fh,'>'.$dest)) {
+ &Apache::lonnet::logthis('Failed to create '.$dest);
+ $output .= ''.
+ &mt('An error occurred while trying to upload [_1] for embedded element [_2].',$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
+ ' ';
+ } else {
+ if (!print $fh $env{'form.embedded_item_'.$i}) {
+ &Apache::lonnet::logthis('Failed to write to '.$dest);
+ $output .= ''.
+ &mt('An error occurred while writing the file [_1] for embedded element [_2].',$orig_uploaded_filename,$env{'form.embedded_orig_'.$i}).
+ ' ';
+ } else {
+ if ($context eq 'testbank') {
+ $output .= &mt('Embedded file uploaded successfully:').
+ ' '.
+ $orig_uploaded_filename.' ';
+ } else {
+ $output .= ''.
+ &mt('View embedded file: [_1]',''.
+ $orig_uploaded_filename.' ').' ';
+ }
+ }
+ close($fh);
+ }
+ }
+ }
+ return $output;
+}
+
+sub check_for_existing {
+ my ($path,$fname,$element) = @_;
+ my ($state,$msg);
+ if (-d $path.'/'.$fname) {
+ $state = 'exists';
+ $msg = &mt('Unable to upload [_1]. A directory by that name was found in [_2].',''.$fname.' ',$path);
+ } elsif (-e $path.'/'.$fname) {
+ $state = 'exists';
+ $msg = &mt('Unable to upload [_1]. A file by that name was found in [_2].',''.$fname.' ',$path);
+ }
+ if ($state eq 'exists') {
+ $msg = ''.$msg.' ';
+ }
+ return ($state,$msg);
+}
+
+sub check_for_upload {
+ my ($path,$fname,$group,$element,$portfolio_root,$port_path,
+ $disk_quota,$current_disk_usage,$uname,$udom) = @_;
+ my $filesize = (length($env{'form.'.$element})) / 1000; #express in k (1024?)
+ my $getpropath = 1;
+ my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$path,$udom,$uname,
+ $getpropath);
+ my $found_file = 0;
+ my $locked_file = 0;
+ foreach my $line (@dir_list) {
+ my ($file_name)=split(/\&/,$line,2);
+ if ($file_name eq $fname){
+ $file_name = $path.$file_name;
+ if ($group ne '') {
+ $file_name = $group.$file_name;
+ }
+ $found_file = 1;
+ if (&Apache::lonnet::is_locked($file_name,$udom,$uname) eq 'true') {
+ $locked_file = 1;
+ }
+ }
+ }
+ if (($current_disk_usage + $filesize) > $disk_quota){
+ my $msg = ''.
+ &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.',''.$fname.' ',$filesize).' '.
+ ' '.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',$disk_quota,$current_disk_usage);
+ return ('will_exceed_quota',$msg);
+ } elsif ($found_file) {
+ if ($locked_file) {
+ my $msg = '';
+ $msg .= &mt('Unable to upload [_1]. A locked file by that name was found in [_2].',''.$fname.' ',''.$port_path.$env{'form.currentpath'}.' ');
+ $msg .= ' ';
+ $msg .= &mt('You will be able to rename or delete existing [_1] after a grade has been assigned.',''.$fname.' ');
+ return ('file_locked',$msg);
+ } else {
+ my $msg = '';
+ $msg .= &mt('Unable to upload [_1]. A file by that name was found in [_2].',''.$fname.' ',$port_path.$env{'form.currentpath'});
+ $msg .= ' ';
+ $msg .= ' ';
+ $msg .= &mt('To upload, rename or delete existing [_1] in [_2].',''.$fname.' ', $port_path.$env{'form.currentpath'});
+ return ('file_exists',$msg);
+ }
+ }
+}
+
=pod
@@ -5972,7 +8330,7 @@ sub get_env_multiple {
=over 4
-=item * upfile_store($r)
+=item * &upfile_store($r)
Store uploaded file, $r should be the HTTP Request object,
needs $env{'form.upfile'}
@@ -6002,7 +8360,7 @@ sub upfile_store {
=pod
-=item * load_tmp_file($r)
+=item * &load_tmp_file($r)
Load uploaded file from tmp, $r should be the HTTP Request object,
needs $env{'form.datatoken'},
@@ -6026,7 +8384,7 @@ sub load_tmp_file {
=pod
-=item * upfile_record_sep()
+=item * &upfile_record_sep()
Separate uploaded file into records
returns array of records,
@@ -6048,7 +8406,7 @@ sub upfile_record_sep {
=pod
-=item * record_sep($record)
+=item * &record_sep($record)
Separate a record into fields $record should be an item from the upfile_record_sep(), needs $env{'form.upfiletype'}
@@ -6133,7 +8491,7 @@ sub record_sep {
=pod
-=item * upfile_select_html()
+=item * &upfile_select_html()
Return HTML code to select a file from the users machine and specify
the file type.
@@ -6151,7 +8509,7 @@ sub upfile_select_html {
# xml => &mt('HTML/XML'),
);
my $Str = ' '.
- ' Type: ';
+ ' '.&mt('Type').': ';
foreach my $type (sort(keys(%Types))) {
$Str .= ''.$Types{$type}." \n";
}
@@ -6180,7 +8538,7 @@ sub get_samples {
=pod
-=item * csv_print_samples($r,$records)
+=item * &csv_print_samples($r,$records)
Prints a table of sample values from each column uploaded $r is an
Apache Request ref, $records is an arrayref from
@@ -6192,22 +8550,23 @@ Apache Request ref, $records is an array
######################################################
sub csv_print_samples {
my ($r,$records) = @_;
- my $samples = &get_samples($records,3);
+ my $samples = &get_samples($records,5);
- $r->print(&mt('Samples').'');
+ $r->print(&mt('Samples').' '.&start_data_table().
+ &start_data_table_header_row());
foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
- $r->print(''.&mt('Column [_1]',($sample+1)).' '); }
- $r->print(' ');
+ $r->print(''.&mt('Column [_1]',($sample+1)).' '); }
+ $r->print(&end_data_table_header_row());
foreach my $hash (@$samples) {
- $r->print('');
+ $r->print(&start_data_table_row());
foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
$r->print('');
if (defined($$hash{$sample})) { $r->print($$hash{$sample}); }
$r->print(' ');
}
- $r->print(' ');
+ $r->print(&end_data_table_row());
}
- $r->print('
'."\n");
+ $r->print(&end_data_table().' '."\n");
}
######################################################
@@ -6215,7 +8574,7 @@ sub csv_print_samples {
=pod
-=item * csv_print_select_table($r,$records,$d)
+=item * &csv_print_select_table($r,$records,$d)
Prints a table to create associations between values and table columns.
@@ -6232,12 +8591,13 @@ sub csv_print_select_table {
my $i=0;
my $samples = &get_samples($records,1);
$r->print(&mt('Associate columns with student attributes.')."\n".
- ''.
+ &start_data_table().&start_data_table_header_row().
''.&mt('Attribute').' '.
- ''.&mt('Column').' '."\n");
+ ''.&mt('Column').' '.
+ &end_data_table_header_row()."\n");
foreach my $array_ref (@$d) {
my ($value,$display,$defaultcol)=@{ $array_ref };
- $r->print(''.$display.' ');
+ $r->print(&start_data_table_row().''.$display.' ');
$r->print('');
@@ -6245,11 +8605,12 @@ sub csv_print_select_table {
foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
$r->print('Column '.($sample+1).' ');
+ '>'.&mt('Column [_1]',($sample+1)).'');
}
- $r->print(' '."\n");
+ $r->print(''.&end_data_table_row()."\n");
$i++;
}
+ $r->print(&end_data_table());
$i--;
return $i;
}
@@ -6259,7 +8620,7 @@ sub csv_print_select_table {
=pod
-=item * csv_samples_select_table($r,$records,$d)
+=item * &csv_samples_select_table($r,$records,$d)
Prints a table of sample values from the upload and can make associate samples to internal names.
@@ -6275,12 +8636,15 @@ sub csv_samples_select_table {
my ($r,$records,$d) = @_;
my $i=0;
#
- my $samples = &get_samples($records,3);
- $r->print(''.
- &mt('Field').' '.&mt('Samples').' ');
+ my $max_samples = 5;
+ my $samples = &get_samples($records,$max_samples);
+ $r->print(&start_data_table().
+ &start_data_table_header_row().''.
+ &mt('Field').' '.&mt('Samples').' '.
+ &end_data_table_header_row());
foreach my $key (sort(keys(%{ $samples->[0] }))) {
- $r->print('print(&start_data_table_row().'');
foreach my $option (@$d) {
my ($value,$display,$defaultcol)=@{ $option };
@@ -6289,14 +8653,15 @@ sub csv_samples_select_table {
$display.'');
}
$r->print(' ');
- foreach my $line (0..2) {
+ foreach my $line (0..($max_samples-1)) {
if (defined($samples->[$line]{$key})) {
$r->print($samples->[$line]{$key}." \n");
}
}
- $r->print(' ');
+ $r->print(''.&end_data_table_row());
$i++;
}
+ $r->print(&end_data_table());
$i--;
return($i);
}
@@ -6306,7 +8671,7 @@ sub csv_samples_select_table {
=pod
-=item clean_excel_name($name)
+=item * &clean_excel_name($name)
Returns a replacement for $name which does not contain any illegal characters.
@@ -6325,7 +8690,7 @@ sub clean_excel_name {
=pod
-=item * check_if_partid_hidden($id,$symb,$udom,$uname)
+=item * &check_if_partid_hidden($id,$symb,$udom,$uname)
Returns either 1 or undef
@@ -6366,7 +8731,7 @@ sub check_if_partid_hidden {
=over 4
-=item get_cgi_id
+=item * &get_cgi_id()
Inputs: none
@@ -6390,7 +8755,7 @@ sub get_cgi_id {
=pod
-=item DrawBarGraph
+=item * &DrawBarGraph()
Facilitates the plotting of data in a (stacked) bar graph.
Puts plot definition data into the users environment in order for
@@ -6525,7 +8890,7 @@ sub DrawBarGraph {
$ValuesHash{$id.'.'.$key} = $value;
}
#
- &Apache::lonnet::appenv(%ValuesHash);
+ &Apache::lonnet::appenv(\%ValuesHash);
return ' ';
}
@@ -6534,7 +8899,7 @@ sub DrawBarGraph {
=pod
-=item DrawXYGraph
+=item * &DrawXYGraph()
Facilitates the plotting of data in an XY graph.
Puts plot definition data into the users environment in order for
@@ -6615,7 +8980,7 @@ sub DrawXYGraph {
$ValuesHash{$id.'.'.$key} = $value;
}
#
- &Apache::lonnet::appenv(%ValuesHash);
+ &Apache::lonnet::appenv(\%ValuesHash);
return ' ';
}
@@ -6624,7 +8989,7 @@ sub DrawXYGraph {
=pod
-=item DrawXYYGraph
+=item * &DrawXYYGraph()
Facilitates the plotting of data in an XY graph with two Y axes.
Puts plot definition data into the users environment in order for
@@ -6717,7 +9082,7 @@ sub DrawXYYGraph {
$ValuesHash{$id.'.'.$key} = $value;
}
#
- &Apache::lonnet::appenv(%ValuesHash);
+ &Apache::lonnet::appenv(\%ValuesHash);
return ' ';
}
@@ -6734,7 +9099,7 @@ Bad place for them but what the hell.
=over 4
-=item &chartlink
+=item * &chartlink()
Returns a link to the chart for a specific student.
@@ -6773,9 +9138,9 @@ sub chartlink {
=over 4
-=item &restore_course_settings
+=item * &restore_course_settings()
-=item &store_course_settings
+=item * &store_course_settings()
Restores/Store indicated form parameters from the course environment.
Will not overwrite existing values of the form parameters.
@@ -6795,6 +9160,8 @@ a hash ref describing the data to be sto
Returns: both routines return nothing
+=back
+
=cut
#######################################################
@@ -6847,7 +9214,7 @@ sub store_settings {
'got error:'.$put_result);
}
# Make sure these settings stick around in this session, too
- &Apache::lonnet::appenv(%AppHash);
+ &Apache::lonnet::appenv(\%AppHash);
return;
}
@@ -6875,16 +9242,429 @@ sub restore_settings {
}
}
+#######################################################
+#######################################################
+
+=pod
+
+=head1 Domain E-mail Routines
+
+=over 4
+
+=item * &build_recipient_list()
+
+Build recipient lists for four types of e-mail:
+(a) Error Reports, (b) Package Updates, (c) lonstatus warnings/errors
+(d) Help requests, generated by
+lonerrorhandler.pm, CHECKRPMS, loncron, and lonsupportreq.pm respectively.
+
+Inputs:
+defmail (scalar - email address of default recipient),
+mailing type (scalar - errormail, packagesmail, or helpdeskmail),
+defdom (domain for which to retrieve configuration settings),
+origmail (scalar - email address of recipient from loncapa.conf,
+i.e., predates configuration by DC via domainprefs.pm
+
+Returns: comma separated list of addresses to which to send e-mail.
+
+=back
+
+=cut
+
+############################################################
+############################################################
+sub build_recipient_list {
+ my ($defmail,$mailing,$defdom,$origmail) = @_;
+ my @recipients;
+ my $otheremails;
+ my %domconfig =
+ &Apache::lonnet::get_dom('configuration',['contacts'],$defdom);
+ if (ref($domconfig{'contacts'}) eq 'HASH') {
+ if (exists($domconfig{'contacts'}{$mailing})) {
+ if (ref($domconfig{'contacts'}{$mailing}) eq 'HASH') {
+ my @contacts = ('adminemail','supportemail');
+ foreach my $item (@contacts) {
+ if ($domconfig{'contacts'}{$mailing}{$item}) {
+ my $addr = $domconfig{'contacts'}{$item};
+ if (!grep(/^\Q$addr\E$/,@recipients)) {
+ push(@recipients,$addr);
+ }
+ }
+ $otheremails = $domconfig{'contacts'}{$mailing}{'others'};
+ }
+ }
+ } elsif ($origmail ne '') {
+ push(@recipients,$origmail);
+ }
+ } elsif ($origmail ne '') {
+ push(@recipients,$origmail);
+ }
+ if (defined($defmail)) {
+ if ($defmail ne '') {
+ push(@recipients,$defmail);
+ }
+ }
+ if ($otheremails) {
+ my @others;
+ if ($otheremails =~ /,/) {
+ @others = split(/,/,$otheremails);
+ } else {
+ push(@others,$otheremails);
+ }
+ foreach my $addr (@others) {
+ if (!grep(/^\Q$addr\E$/,@recipients)) {
+ push(@recipients,$addr);
+ }
+ }
+ }
+ my $recipientlist = join(',',@recipients);
+ return $recipientlist;
+}
+
############################################################
############################################################
+=pod
+
+=head1 Course Catalog Routines
+
+=over 4
+
+=item * &gather_categories()
+
+Converts category definitions - keys of categories hash stored in
+coursecategories in configuration.db on the primary library server in a
+domain - to an array. Also generates javascript and idx hash used to
+generate Domain Coordinator interface for editing Course Categories.
+
+Inputs:
+
+categories (reference to hash of category definitions).
+
+cats (reference to array of arrays/hashes which encapsulates hierarchy of
+ categories and subcategories).
+
+idx (reference to hash of counters used in Domain Coordinator interface for
+ editing Course Categories).
+
+jsarray (reference to array of categories used to create Javascript arrays for
+ Domain Coordinator interface for editing Course Categories).
+
+Returns: nothing
+
+Side effects: populates cats, idx and jsarray.
+
+=cut
+
+sub gather_categories {
+ my ($categories,$cats,$idx,$jsarray) = @_;
+ my %counters;
+ my $num = 0;
+ foreach my $item (keys(%{$categories})) {
+ my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item);
+ if ($container eq '' && $depth == 0) {
+ $cats->[$depth][$categories->{$item}] = $cat;
+ } else {
+ $cats->[$depth]{$container}[$categories->{$item}] = $cat;
+ }
+ my ($escitem,$tail) = split(/:/,$item,2);
+ if ($counters{$tail} eq '') {
+ $counters{$tail} = $num;
+ $num ++;
+ }
+ if (ref($idx) eq 'HASH') {
+ $idx->{$item} = $counters{$tail};
+ }
+ if (ref($jsarray) eq 'ARRAY') {
+ push(@{$jsarray->[$counters{$tail}]},$item);
+ }
+ }
+ return;
+}
+
+=pod
+
+=item * &extract_categories()
+
+Used to generate breadcrumb trails for course categories.
+
+Inputs:
+
+categories (reference to hash of category definitions).
+
+cats (reference to array of arrays/hashes which encapsulates hierarchy of
+ categories and subcategories).
+
+trails (reference to array of breacrumb trails for each category).
+
+allitems (reference to hash - key is category key
+ (format: escaped(name):escaped(parent category):depth in hierarchy).
+
+idx (reference to hash of counters used in Domain Coordinator interface for
+ editing Course Categories).
+
+jsarray (reference to array of categories used to create Javascript arrays for
+ Domain Coordinator interface for editing Course Categories).
+
+subcats (reference to hash of arrays containing all subcategories within each
+ category, -recursive)
+
+Returns: nothing
+
+Side effects: populates trails and allitems hash references.
+
+=cut
+
+sub extract_categories {
+ my ($categories,$cats,$trails,$allitems,$idx,$jsarray,$subcats) = @_;
+ if (ref($categories) eq 'HASH') {
+ &gather_categories($categories,$cats,$idx,$jsarray);
+ if (ref($cats->[0]) eq 'ARRAY') {
+ for (my $i=0; $i<@{$cats->[0]}; $i++) {
+ my $name = $cats->[0][$i];
+ my $item = &escape($name).'::0';
+ my $trailstr;
+ if ($name eq 'instcode') {
+ $trailstr = &mt('Official courses (with institutional codes)');
+ } else {
+ $trailstr = $name;
+ }
+ if ($allitems->{$item} eq '') {
+ push(@{$trails},$trailstr);
+ $allitems->{$item} = scalar(@{$trails})-1;
+ }
+ my @parents = ($name);
+ if (ref($cats->[1]{$name}) eq 'ARRAY') {
+ for (my $j=0; $j<@{$cats->[1]{$name}}; $j++) {
+ my $category = $cats->[1]{$name}[$j];
+ if (ref($subcats) eq 'HASH') {
+ push(@{$subcats->{$item}},&escape($category).':'.&escape($name).':1');
+ }
+ &recurse_categories($cats,2,$category,$trails,$allitems,\@parents,$subcats);
+ }
+ } else {
+ if (ref($subcats) eq 'HASH') {
+ $subcats->{$item} = [];
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
+=pod
+
+=item *&recurse_categories()
+
+Recursively used to generate breadcrumb trails for course categories.
+
+Inputs:
+
+cats (reference to array of arrays/hashes which encapsulates hierarchy of
+ categories and subcategories).
+
+depth (current depth in hierarchy of categories and sub-categories - 0 indexed).
+
+category (current course category, for which breadcrumb trail is being generated).
+
+trails (reference to array of breadcrumb trails for each category).
+
+allitems (reference to hash - key is category key
+ (format: escaped(name):escaped(parent category):depth in hierarchy).
+
+parents (array containing containers directories for current category,
+ back to top level).
+
+Returns: nothing
+
+Side effects: populates trails and allitems hash references
+
+=cut
+
+sub recurse_categories {
+ my ($cats,$depth,$category,$trails,$allitems,$parents,$subcats) = @_;
+ my $shallower = $depth - 1;
+ if (ref($cats->[$depth]{$category}) eq 'ARRAY') {
+ for (my $k=0; $k<@{$cats->[$depth]{$category}}; $k++) {
+ my $name = $cats->[$depth]{$category}[$k];
+ my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower;
+ my $trailstr = join(' -> ',(@{$parents},$category));
+ if ($allitems->{$item} eq '') {
+ push(@{$trails},$trailstr);
+ $allitems->{$item} = scalar(@{$trails})-1;
+ }
+ my $deeper = $depth+1;
+ push(@{$parents},$category);
+ if (ref($subcats) eq 'HASH') {
+ my $subcat = &escape($name).':'.$category.':'.$depth;
+ for (my $j=@{$parents}; $j>=0; $j--) {
+ my $higher;
+ if ($j > 0) {
+ $higher = &escape($parents->[$j]).':'.
+ &escape($parents->[$j-1]).':'.$j;
+ } else {
+ $higher = &escape($parents->[$j]).'::'.$j;
+ }
+ push(@{$subcats->{$higher}},$subcat);
+ }
+ }
+ &recurse_categories($cats,$deeper,$name,$trails,$allitems,$parents,
+ $subcats);
+ pop(@{$parents});
+ }
+ } else {
+ my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower;
+ my $trailstr = join(' -> ',(@{$parents},$category));
+ if ($allitems->{$item} eq '') {
+ push(@{$trails},$trailstr);
+ $allitems->{$item} = scalar(@{$trails})-1;
+ }
+ }
+ return;
+}
+
+=pod
+
+=item *&assign_categories_table()
+
+Create a datatable for display of hierarchical categories in a domain,
+with checkboxes to allow a course to be categorized.
+
+Inputs:
+
+cathash - reference to hash of categories defined for the domain (from
+ configuration.db)
+
+currcat - scalar with an & separated list of categories assigned to a course.
+
+Returns: $output (markup to be displayed)
+
+=cut
+
+sub assign_categories_table {
+ my ($cathash,$currcat) = @_;
+ my $output;
+ if (ref($cathash) eq 'HASH') {
+ my (@cats,@trails,%allitems,%idx,@jsarray,@path,$maxdepth);
+ &extract_categories($cathash,\@cats,\@trails,\%allitems,\%idx,\@jsarray);
+ $maxdepth = scalar(@cats);
+ if (@cats > 0) {
+ my $itemcount = 0;
+ if (ref($cats[0]) eq 'ARRAY') {
+ $output = &Apache::loncommon::start_data_table();
+ my @currcategories;
+ if ($currcat ne '') {
+ @currcategories = split('&',$currcat);
+ }
+ for (my $i=0; $i<@{$cats[0]}; $i++) {
+ my $parent = $cats[0][$i];
+ my $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ next if ($parent eq 'instcode');
+ my $item = &escape($parent).'::0';
+ my $checked = '';
+ if (@currcategories > 0) {
+ if (grep(/^\Q$item\E$/,@currcategories)) {
+ $checked = ' checked="checked"';
+ }
+ }
+ $output .= ''.
+ ' '.$parent.' '.
+ ' ';
+ my $depth = 1;
+ push(@path,$parent);
+ $output .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);
+ pop(@path);
+ $output .= ' ';
+ $itemcount ++;
+ }
+ $output .= &Apache::loncommon::end_data_table();
+ }
+ }
+ }
+ return $output;
+}
+
+=pod
+
+=item *&assign_category_rows()
+
+Create a datatable row for display of nested categories in a domain,
+with checkboxes to allow a course to be categorized,called recursively.
+
+Inputs:
+
+itemcount - track row number for alternating colors
+
+cats - reference to array of arrays/hashes which encapsulates hierarchy of
+ categories and subcategories.
+
+depth - current depth in hierarchy of categories and sub-categories - 0 indexed.
+
+parent - parent of current category item
+
+path - Array containing all categories back up through the hierarchy from the
+ current category to the top level.
+
+currcategories - reference to array of current categories assigned to the course
+
+Returns: $output (markup to be displayed).
+
+=cut
+
+sub assign_category_rows {
+ my ($itemcount,$cats,$depth,$parent,$path,$currcategories) = @_;
+ my ($text,$name,$item,$chgstr);
+ if (ref($cats) eq 'ARRAY') {
+ my $maxdepth = scalar(@{$cats});
+ if (ref($cats->[$depth]) eq 'HASH') {
+ if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
+ my $numchildren = @{$cats->[$depth]{$parent}};
+ my $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $text .= ' ';
+ }
+ }
+ }
+ return $text;
+}
+
+############################################################
+############################################################
+
+
sub commit_customrole {
- my ($udom,$uname,$url,$three,$four,$five,$start,$end) = @_;
- my $output = &mt('Assigning custom role').' "'.$five.'" by '.$four.'@'.$three.' in '.$url.
+ my ($udom,$uname,$url,$three,$four,$five,$start,$end,$context) = @_;
+ my $output = &mt('Assigning custom role').' "'.$five.'" by '.$four.':'.$three.' in '.$url.
($start?', '.&mt('starting').' '.localtime($start):'').
($end?', ending '.localtime($end):'').': '.
&Apache::lonnet::assigncustomrole(
- $udom,$uname,$url,$three,$four,$five,$end,$start).
+ $udom,$uname,$url,$three,$four,$five,$end,$start,undef,undef,$context).
' ';
return $output;
}
@@ -6901,8 +9681,8 @@ sub commit_standardrole {
my $result = &commit_studentrole(\$logmsg,$udom,$uname,$url,$three,$start,$end,
$one,$two,$sec,$context);
if (($result =~ /^error/) || ($result eq 'not_in_class') ||
- ($result eq 'unknown_course')) {
- $output = "Error: $result\n";
+ ($result eq 'unknown_course') || ($result eq 'refused')) {
+ $output = $logmsg.' '.&mt('Error: ').$result."\n";
} else {
$output = $logmsg.$linefeed.&mt('Assigning').' '.$three.' in '.$url.
($start?', '.&mt('starting').' '.localtime($start):'').
@@ -6919,7 +9699,7 @@ sub commit_standardrole {
$output = &mt('Assigning').' '.$three.' in '.$url.
($start?', '.&mt('starting').' '.localtime($start):'').
($end?', '.&mt('ending').' '.localtime($end):'').': ';
- my $result = &Apache::lonnet::assignrole($udom,$uname,$url,$three,$end,$start);
+ my $result = &Apache::lonnet::assignrole($udom,$uname,$url,$three,$end,$start,'','',$context);
if ($context eq 'auto') {
$output .= $result.$linefeed;
} else {
@@ -6931,7 +9711,7 @@ sub commit_standardrole {
sub commit_studentrole {
my ($logmsg,$udom,$uname,$url,$three,$start,$end,$one,$two,$sec,$context) = @_;
- my ($result,$linefeed);
+ my ($result,$linefeed,$oldsecurl,$newsecurl);
if ($context eq 'auto') {
$linefeed = "\n";
} else {
@@ -6943,37 +9723,92 @@ sub commit_studentrole {
my $secchange = 0;
my $expire_role_result;
my $modify_section_result;
- unless ($oldsec eq '-1') {
- unless ($sec eq $oldsec) {
+ if ($oldsec ne '-1') {
+ if ($oldsec ne $sec) {
$secchange = 1;
+ my $now = time;
my $uurl='/'.$cid;
$uurl=~s/\_/\//g;
if ($oldsec) {
$uurl.='/'.$oldsec;
}
- $expire_role_result = &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',time);
+ $oldsecurl = $uurl;
+ $expire_role_result =
+ &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',$now,'','',$context);
+ if ($env{'request.course.sec'} ne '') {
+ if ($expire_role_result eq 'refused') {
+ my @roles = ('st');
+ my @statuses = ('previous');
+ my @roledoms = ($one);
+ my $withsec = 1;
+ my %roleshash =
+ &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
+ \@statuses,\@roles,\@roledoms,$withsec);
+ if (defined ($roleshash{$two.':'.$one.':st:'.$oldsec})) {
+ my ($oldstart,$oldend) =
+ split(':',$roleshash{$two.':'.$one.':st:'.$oldsec});
+ if ($oldend > 0 && $oldend <= $now) {
+ $expire_role_result = 'ok';
+ }
+ }
+ }
+ }
$result = $expire_role_result;
}
}
if (($expire_role_result eq 'ok') || ($secchange == 0)) {
- $modify_section_result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,'','',$cid);
+ $modify_section_result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,'','',$cid,'',$context);
if ($modify_section_result =~ /^ok/) {
if ($secchange == 1) {
- $$logmsg .= "Section for $uname switched from old section: $oldsec to new section: $sec".$linefeed;
+ if ($sec eq '') {
+ $$logmsg .= &mt('Section for [_1] switched from (possibly expired) old section: [_2] to student role without a section.',$uname,$oldsec).$linefeed;
+ } else {
+ $$logmsg .= &mt('Section for [_1] switched from (possibly expired) old section: [_2] to new section: [_3].',$uname,$oldsec,$sec).$linefeed;
+ }
} elsif ($oldsec eq '-1') {
- $$logmsg .= "New student role for $uname in section $sec in course $cid".$linefeed;
+ if ($sec eq '') {
+ $$logmsg .= &mt('New student role without a section for [_1] in course [_2].',$uname,$cid).$linefeed;
+ } else {
+ $$logmsg .= &mt('New student role for [_1] in section [_2] in course [_3].',$uname,$sec,$cid).$linefeed;
+ }
} else {
- $$logmsg .= "Student $uname assigned to unchanged section $sec in course $cid".$linefeed;
+ if ($sec eq '') {
+ $$logmsg .= &mt('Student [_1] assigned to course [_2] without a section.',$uname,$cid).$linefeed;
+ } else {
+ $$logmsg .= &mt('Student [_1] assigned to section [_2] in course [_3].',$uname,$sec,$cid).$linefeed;
+ }
}
} else {
- $$logmsg .= "Error when attempting section change for $uname from old section $oldsec to new section: $sec in course $cid -error: $modify_section_result".$linefeed;
+ if ($secchange) {
+ $$logmsg .= &mt('Error when attempting section change for [_1] from old section "[_2]" to new section: "[_3]" in course [_4] -error:',$uname,$oldsec,$sec,$cid).' '.$modify_section_result.$linefeed;
+ } else {
+ $$logmsg .= &mt('Error when attempting to modify role for [_1] for section: "[_2]" in course [_3] -error:',$uname,$sec,$cid).' '.$modify_section_result.$linefeed;
+ }
}
$result = $modify_section_result;
} elsif ($secchange == 1) {
- $$logmsg .= "Error when attempting to expire role for $uname in old section $oldsec in course $cid -error: $expire_role_result".$linefeed;
+ if ($oldsec eq '') {
+ $$logmsg .= &mt('Error when attempting to expire existing role without a section for [_1] in course [_3] -error: ',$uname,$cid).' '.$expire_role_result.$linefeed;
+ } else {
+ $$logmsg .= &mt('Error when attempting to expire existing role for [_1] in section [_2] in course [_3] -error: ',$uname,$oldsec,$cid).' '.$expire_role_result.$linefeed;
+ }
+ if ($expire_role_result eq 'refused') {
+ my $newsecurl = '/'.$cid;
+ $newsecurl =~ s/\_/\//g;
+ if ($sec ne '') {
+ $newsecurl.='/'.$sec;
+ }
+ if (&Apache::lonnet::allowed('cst',$newsecurl) && !(&Apache::lonnet::allowed('cst',$oldsecurl))) {
+ if ($sec eq '') {
+ $$logmsg .= &mt('Although your current role has privileges to add students to section "[_1]", you do not have privileges to modify existing enrollments unaffiliated with any section.',$sec).$linefeed;
+ } else {
+ $$logmsg .= &mt('Although your current role has privileges to add students to section "[_1]", you do not have privileges to modify existing enrollments in other sections.',$sec).$linefeed;
+ }
+ }
+ }
}
} else {
- $$logmsg .= "Incomplete course id defined. Addition of user $uname from domain $udom to course $one\_$two, section $sec not completed.$linefeed";
+ $$logmsg .= &mt('Incomplete course id defined.').$linefeed.&mt('Addition of user [_1] from domain [_2] to course [_3], section [_4] not completed.',$uname,$udom,$one.'_'.$two,$sec).$linefeed;
$result = "error: incomplete course id\n";
}
return $result;
@@ -7085,19 +9920,28 @@ sub construct_course {
$outcome .= $clonemsg.$linefeed;
my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum);
# Copy all files
- &Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid);
+ &Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid,$args->{'datemode'},$args->{'dateshift'});
# Restore URL
$cenv{'url'}=$oldcenv{'url'};
# Restore title
$cenv{'description'}=$oldcenv{'description'};
-# restore grading mode
- if (defined($oldcenv{'grading'})) {
- $cenv{'grading'}=$oldcenv{'grading'};
- }
# Mark as cloned
$cenv{'clonedfrom'}=$cloneid;
- delete($cenv{'default_enrollment_start_date'});
- delete($cenv{'default_enrollment_end_date'});
+# Need to clone grading mode
+ my %newenv=&Apache::lonnet::get('environment',['grading'],$$crsudom,$$crsunum);
+ $cenv{'grading'}=$newenv{'grading'};
+# Do not clone these environment entries
+ &Apache::lonnet::del('environment',
+ ['default_enrollment_start_date',
+ 'default_enrollment_end_date',
+ 'question.email',
+ 'policy.email',
+ 'comment.email',
+ 'pch.users.denied',
+ 'plc.users.denied',
+ 'hidefromcat',
+ 'categories'],
+ $$crsudom,$$crsunum);
}
#
@@ -7125,7 +9969,6 @@ sub construct_course {
} else {
$cenv{'internal.courseowner'} = $args->{'curruser'};
}
-
my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner.
if ($args->{'crssections'}) {
$cenv{'internal.sectionnums'} = '';
@@ -7185,7 +10028,7 @@ sub construct_course {
}
if ($args->{'notify_dc'}) {
if ($uname ne '') {
- push(@notified,$uname.'@'.$udom);
+ push(@notified,$uname.':'.$udom);
}
}
if (@notified > 0) {
@@ -7325,10 +10168,10 @@ sub construct_course {
$outcome .= ($fatal?$errtext:'read ok').' - ';
my $title; my $url;
if ($args->{'firstres'} eq 'syl') {
- $title='Syllabus';
+ $title=&mt('Syllabus');
$url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';
} else {
- $title='Navigate Contents';
+ $title=&mt('Navigate Contents');
$url='/adm/navmaps';
}
@@ -7382,28 +10225,14 @@ sub icon {
return &lonhttpdurl($iconname);
}
-sub lonhttpd_port {
- my $lonhttpd_port=$Apache::lonnet::perlvar{'lonhttpdPort'};
- if (!defined($lonhttpd_port)) { $lonhttpd_port='8080'; }
- # IE doesn't like a secure page getting images from a non-secure
- # port (when logging we haven't parsed the browser type so default
- # back to secure
- if ((!exists($env{'browser.type'}) || $env{'browser.type'} eq 'explorer')
- && $ENV{'SERVER_PORT'} == 443) {
- return 443;
- }
- return $lonhttpd_port;
-
-}
-
sub lonhttpdurl {
+#
+# Had been used for "small fry" static images on separate port 8080.
+# Modify here if lightweight http functionality desired again.
+# Currently eliminated due to increasing firewall issues.
+#
my ($url)=@_;
-
- my $lonhttpd_port = &lonhttpd_port();
- if ($lonhttpd_port == 443) {
- return 'https://'.$ENV{'SERVER_NAME'}.$url;
- }
- return 'http://'.$ENV{'SERVER_NAME'}.':'.$lonhttpd_port.$url;
+ return $url;
}
sub connection_aborted {
@@ -7439,7 +10268,23 @@ sub escape_url {
return join('/',@urlslices).'/'.$lastitem;
}
-# -------------------------------------------------------- Initliaze user login
+sub compare_arrays {
+ my ($arrayref1,$arrayref2) = @_;
+ my (@difference,%count);
+ @difference = ();
+ %count = ();
+ if ((ref($arrayref1) eq 'ARRAY') && (ref($arrayref2) eq 'ARRAY')) {
+ foreach my $element (@{$arrayref1}, @{$arrayref2}) { $count{$element}++; }
+ foreach my $element (keys(%count)) {
+ if ($count{$element} == 1) {
+ push(@difference,$element);
+ }
+ }
+ }
+ return @difference;
+}
+
+# -------------------------------------------------------- Initialize user login
sub init_user_environment {
my ($r, $username, $domain, $authhost, $form, $args) = @_;
my $lonids=$Apache::lonnet::perlvar{'lonIDsDir'};
@@ -7481,7 +10326,7 @@ sub init_user_environment {
}
# Give them a new cookie
my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'}
- : $now);
+ : $now.$$.int(rand(10000)));
$cookie="$username\_$id\_$domain\_$authhost";
# Initialize roles
@@ -7493,19 +10338,6 @@ sub init_user_environment {
my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
$clientunicode,$clientos) = &decode_user_agent($r);
-# -------------------------------------- Any accessibility options to remember?
- if (($form->{'interface'}) && ($form->{'remember'} eq 'true')) {
- foreach my $option ('imagesuppress','appletsuppress',
- 'embedsuppress','fontenhance','blackwhite') {
- if ($form->{$option} eq 'true') {
- &Apache::lonnet::put('environment',{$option => 'on'},
- $domain,$username);
- } else {
- &Apache::lonnet::del('environment',[$option],
- $domain,$username);
- }
- }
- }
# ------------------------------------------------------------- Get environment
my %userenv = &Apache::lonnet::dump('environment',$domain,$username);
@@ -7523,10 +10355,8 @@ sub init_user_environment {
if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; }
# --------------- Do not trust query string to be put directly into environment
- foreach my $option ('imagesuppress','appletsuppress',
- 'embedsuppress','fontenhance','blackwhite',
- 'interface','localpath','localres') {
- $form->{$option}=~s/[\n\r\=]//gs;
+ foreach my $option ('interface','localpath','localres') {
+ $form->{$option}=~s/[\n\r\=]//gs;
}
# --------------------------------------------------------- Write first profile
@@ -7560,15 +10390,19 @@ sub init_user_environment {
$form->{'interface'}=~s/\W//gs;
$initial_env{"browser.interface"} = $form->{'interface'};
$env{'browser.interface'}=$form->{'interface'};
- foreach my $option ('imagesuppress','appletsuppress',
- 'embedsuppress','fontenhance','blackwhite') {
- if (($form->{$option} eq 'true') ||
- ($userenv{$option} eq 'on')) {
- $initial_env{"browser.$option"} = "on";
- }
- }
}
+ foreach my $tool ('aboutme','blog','portfolio') {
+ $userenv{'availabletools.'.$tool} =
+ &Apache::lonnet::usertools_access($username,$domain,$tool,'reload');
+ }
+
+ foreach my $crstype ('official','unofficial') {
+ $userenv{'canrequest.'.$crstype} =
+ &Apache::lonnet::usertools_access($username,$domain,$crstype,
+ 'reload','requestcourses');
+ }
+
$env{'user.environment'} = "$lonids/$cookie.id";
if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",
@@ -7581,8 +10415,8 @@ sub init_user_environment {
}
untie(%disk_env);
} else {
- &Apache::lonnet::logthis("WARNING: ".
- 'Could not create environment storage in lonauth: '.$!.' ');
+ &Apache::lonnet::logthis("WARNING: ".
+ 'Could not create environment storage in lonauth: '.$!.' ');
return 'error: '.$!;
}
}
@@ -7596,12 +10430,54 @@ sub init_user_environment {
sub _add_to_env {
my ($idf,$env_data,$prefix) = @_;
- while (my ($key,$value) = each(%$env_data)) {
- $idf->{$prefix.$key} = $value;
- $env{$prefix.$key} = $value;
+ if (ref($env_data) eq 'HASH') {
+ while (my ($key,$value) = each(%$env_data)) {
+ $idf->{$prefix.$key} = $value;
+ $env{$prefix.$key} = $value;
+ }
+ }
+}
+
+# --- Get the symbolic name of a problem and the url
+sub get_symb {
+ my ($request,$silent) = @_;
+ (my $url=$env{'form.url'}) =~ s-^https?\://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
+ my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url)));
+ if ($symb eq '') {
+ if (!$silent) {
+ $request->print("Unable to handle ambiguous references:$url:.");
+ return ();
+ }
}
+ &Apache::lonenc::check_decrypt(\$symb);
+ return ($symb);
}
+# --------------------------------------------------------------Get annotation
+
+sub get_annotation {
+ my ($symb,$enc) = @_;
+
+ my $key = $symb;
+ if (!$enc) {
+ $key =
+ &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]);
+ }
+ my %annotation=&Apache::lonnet::get('nohist_annotations',[$key]);
+ return $annotation{$key};
+}
+
+sub clean_symb {
+ my ($symb,$delete_enc) = @_;
+
+ &Apache::lonenc::check_decrypt(\$symb);
+ my $enc = $env{'request.enc'};
+ if ($delete_enc) {
+ delete($env{'request.enc'});
+ }
+
+ return ($symb,$enc);
+}
=pod