".&mt('Select Course')."";
+ my ($form,$unameele,$udomele,$desc,$extra_element,$multflag,$selecttype,
+ $typeelement) = @_;
+ my $type = $selecttype;
+ my $linktext = &mt('Select Course');
+ if ($selecttype eq 'Community') {
+ $linktext = &mt('Select Community');
+ } elsif ($selecttype eq 'Course/Community') {
+ $linktext = &mt('Select Course/Community');
+ $type = '';
+ } elsif ($selecttype eq 'Select') {
+ $linktext = &mt('Select');
+ $type = '';
+ }
+ return ''
+ ."".$linktext.' '
+ .' ';
}
sub selectauthor_link {
@@ -610,6 +866,14 @@ sub selectauthor_link {
&mt('Select Author').'';
}
+sub selectuser_link {
+ my ($form,$unameelem,$domelem,$lastelem,$firstelem,$emailelem,$hdomelem,
+ $coursedom,$linktext,$caller) = @_;
+ return ''.$linktext.' ';
+}
+
sub check_uncheck_jscript {
my $jscript = <<"ENDSCRT";
function checkAll(field) {
@@ -657,6 +921,72 @@ sub select_timezone {
return $output;
}
+sub select_datelocale {
+ my ($name,$selected,$onchange,$includeempty)=@_;
+ my $output=''."\n";
+ if ($includeempty) {
+ $output .= '{'id'};
+ if ($id ne '') {
+ my $en_terr = $locale->{'en_territory'};
+ my $native_terr = $locale->{'native_territory'};
+ my @languages = &Apache::lonlocal::preferred_languages();
+ if (grep(/^en$/,@languages) || !@languages) {
+ if ($en_terr ne '') {
+ $locale_names{$id} = '('.$en_terr.')';
+ } elsif ($native_terr ne '') {
+ $locale_names{$id} = $native_terr;
+ }
+ } else {
+ if ($native_terr ne '') {
+ $locale_names{$id} = $native_terr.' ';
+ } elsif ($en_terr ne '') {
+ $locale_names{$id} = '('.$en_terr.')';
+ }
+ }
+ push (@possibles,$id);
+ }
+ }
+ }
+ foreach my $item (sort(@possibles)) {
+ $output.= ' $item";
+ if ($locale_names{$item} ne '') {
+ $output.=" $locale_names{$item} \n";
+ }
+ $output.="\n";
+ }
+ $output.=" ";
+ return $output;
+}
+
+sub select_language {
+ my ($name,$selected,$includeempty) = @_;
+ my %langchoices;
+ if ($includeempty) {
+ %langchoices = ('' => 'No language preference');
+ }
+ foreach my $id (&languageids()) {
+ my $code = &supportedlanguagecode($id);
+ if ($code) {
+ $langchoices{$code} = &plainlanguagedescription($id);
+ }
+ }
+ return &select_form($selected,$name,\%langchoices);
+}
+
=pod
=item * &linked_select_forms(...)
@@ -743,7 +1073,8 @@ sub linked_select_forms {
my $first = "document.$formname.$firstselectname";
# output the javascript to do the changing
my $result = '';
- $result.="
END
# output the initial values for the selection lists
@@ -824,7 +1156,7 @@ END
=pod
-=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height)
+=item * &help_open_topic($topic,$text,$stayOnPage,$width,$height,$imgid)
Returns a string corresponding to an HTML link to the given help
$topic, where $topic corresponds to the name of a .tex file in
@@ -842,17 +1174,18 @@ a new window using Javascript. (Default
$width and $height are optional numerical parameters that will
override the width and height of the popped up window, which may
-be useful for certain help topics with big pictures included.
+be useful for certain help topics with big pictures included.
+
+$imgid is the id of the img tag used for the help icon. This may be
+used in a javascript call to switch the image src. See
+lonhtmlcommon::htmlareaselectactive() for an example.
=cut
sub help_open_topic {
- my ($topic, $text, $stayOnPage, $width, $height) = @_;
+ my ($topic, $text, $stayOnPage, $width, $height, $imgid) = @_;
$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;
@@ -870,19 +1203,26 @@ sub help_open_topic {
}
# 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/help.png");
- $template .= <<"ENDTEMPLATE";
-
-ENDTEMPLATE
- if ($text ne '') { $template.='
' };
+ if ($imgid ne '') {
+ $imgid = ' id="'.$imgid.'"';
+ }
+ $template.=' '
+ .' ';
+ if ($text ne "") {
+ $template.='';
+ }
return $template;
}
@@ -890,29 +1230,41 @@ 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",&mt('Greek Symbols'),
- undef,undef,600)
- .' '.
- &Apache::loncommon::help_open_topic("Other_Symbols",&mt('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 {
my $helptopic='Student_Intro';
if ($env{'request.role'}=~/^(ca|au)/) {
$helptopic='Authoring_Intro';
- } elsif ($env{'request.role'}=~/^cc/) {
+ } elsif ($env{'request.role'}=~/^(cc|co)/) {
$helptopic='Course_Coordination_Intro';
+ } elsif ($env{'request.role'}=~/^dc/) {
+ $helptopic='Domain_Coordination_Intro';
}
return $helptopic;
}
@@ -929,7 +1281,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;
@@ -939,13 +1293,7 @@ ENDOUTPUT
sub help_open_menu {
my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text)
= @_;
- $stayOnPage = 0 if (not defined $stayOnPage);
- # 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;
- }
+ $stayOnPage = 1;
my $output;
if ($component_help) {
if (!$text) {
@@ -966,9 +1314,8 @@ sub help_open_menu {
sub top_nav_help {
my ($text) = @_;
$text = &mt($text);
- my $stay_on_page =
- ($env{'browser.interface'} eq 'textual' ||
- $env{'environment.remote'} eq 'off' );
+ my $stay_on_page = 1;
+
my $link = ($stay_on_page) ? "javascript:helpMenu('display')"
: "javascript:helpMenu('open')";
my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
@@ -983,11 +1330,7 @@ END
sub help_menu_js {
my ($text) = @_;
-
- my $stayOnPage =
- ($env{'browser.interface'} eq 'textual' ||
- $env{'environment.remote'} eq 'off' );
-
+ my $stayOnPage = 1;
my $width = 620;
my $height = 600;
my $helptopic=&general_help();
@@ -1006,8 +1349,8 @@ sub help_menu_js {
my $template .= <<"ENDTEMPLATE";
ENDTEMPLATE
return $template;
@@ -1044,11 +1387,7 @@ sub help_open_bug {
unless ($env{'user.adv'}) { return ''; }
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' ) {
$stayOnPage=1;
- }
$width = 600 if (not defined $width);
$height = 600 if (not defined $height);
@@ -1070,7 +1409,7 @@ sub help_open_bug {
{
$template .=
"".
- "$text ";
+ "$text ";
}
# Add the graphic
@@ -1089,11 +1428,7 @@ sub help_open_faq {
unless ($env{'user.adv'}) { return ''; }
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' ) {
$stayOnPage=1;
- }
$width = 350 if (not defined $width);
$height = 400 if (not defined $height);
@@ -1115,7 +1450,7 @@ sub help_open_faq {
{
$template .=
"".
- "$text ";
+ "$text ";
}
# Add the graphic
@@ -1301,6 +1636,7 @@ sub resize_textarea_js {
my $geometry = &viewport_geometry_js();
return <<"RESIZE";
RESIZE
@@ -1459,14 +1796,17 @@ sub create_workbook {
my $workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
if (! defined($workbook)) {
$r->log_error("Error creating excel spreadsheet $filename: $!");
- $r->print(''.&mt("Unable to create new Excel file. ".
- "This error has been logged. ".
- "Please alert your LON-CAPA administrator").
- '
');
+ $r->print(
+ ''
+ .&mt('Problems occurred in creating the new Excel file.')
+ .' '.&mt('This error has been logged.')
+ .' '.&mt('Please alert your LON-CAPA administrator.')
+ .'
'
+ );
return (undef);
}
#
- $workbook->set_tempdir('/home/httpd/perl/tmp');
+ $workbook->set_tempdir(LONCAPA::tempdir());
#
my $format = &Apache::loncommon::define_excel_formats($workbook);
return ($workbook,$filename,$format);
@@ -1502,9 +1842,13 @@ 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.')
+ .' '.&mt('This error has been logged.')
+ .' '.&mt('Please alert your LON-CAPA administrator.')
+ .'
'
+ );
}
return ($fh,$filename)
}
@@ -1533,7 +1877,7 @@ sub domain_select {
return &multiple_select_form($name,$value,4,\%domains);
} else {
$domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))];
- return &select_form($name,$value,%domains);
+ return &select_form($name,$value,\%domains);
}
}
@@ -1571,7 +1915,7 @@ sub multiple_select_form {
$size = scalar(keys(%$hash));
}
}
- $output.="\n";
+ $output.="\n".'';
my @order;
if (ref($order) eq 'ARRAY') {
@order = @{$order};
@@ -1595,29 +1939,36 @@ sub multiple_select_form {
=pod
-=item * &select_form($defdom,$name,%hash)
+=item * &select_form($defdom,$name,$hashref,$onchange)
Returns a string containing a form to
-allow a user to select options from a hash option_name => displayed text.
+allow a user to select options from a ref to a hash containing:
+option_name => displayed text. An optional $onchange can include
+a javascript onchange item, e.g., onchange="this.form.submit();"
+
See lonrights.pm for an example invocation and use.
=cut
#-------------------------------------------
sub select_form {
- my ($def,$name,%hash) = @_;
- my $selectform = "\n";
+ my ($def,$name,$hashref,$onchange) = @_;
+ return unless (ref($hashref) eq 'HASH');
+ if ($onchange) {
+ $onchange = ' onchange="'.$onchange.'"';
+ }
+ my $selectform = "\n";
my @keys;
- if (exists($hash{'select_form_order'})) {
- @keys=@{$hash{'select_form_order'}};
+ if (exists($hashref->{'select_form_order'})) {
+ @keys=@{$hashref->{'select_form_order'}};
} else {
- @keys=sort(keys(%hash));
+ @keys=sort(keys(%{$hashref}));
}
foreach my $key (@keys) {
$selectform.=
'&').'" '.
($key eq $def ? 'selected="selected" ' : '').
- ">".&mt($hash{$key})." \n";
+ ">".$hashref->{$key}."\n";
}
$selectform.=" ";
return $selectform;
@@ -1628,17 +1979,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',
+ {'currentfolder' => 'Current folder/page',
'containing' => 'Containing phrase',
- 'none' => 'None'))).
- ' ';
+ 'none' => 'None'})).
+ ' ';
}
sub gradeleveldescription {
@@ -1682,7 +2033,7 @@ sub select_level_form {
=pod
-=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc)
+=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms)
Returns a string containing a form to
allow a user to select the domain to preform an operation in.
@@ -1691,16 +2042,28 @@ 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.
+
+The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.
+
+The optional $incdoms is a reference to an array of domains which will be the only available options.
=cut
#-------------------------------------------
sub select_dom_form {
- my ($defdom,$name,$includeempty,$showdomdesc) = @_;
- my @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
+ my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) = @_;
+ if ($onchange) {
+ $onchange = ' onchange="'.$onchange.'"';
+ }
+ my @domains;
+ if (ref($incdoms) eq 'ARRAY') {
+ @domains = sort {lc($a) cmp lc($b)} (@{$incdoms});
+ } else {
+ @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;
@@ -1756,7 +2119,7 @@ sub home_server_form_item {
if ($numlib > 1) {
$result .= ' '."\n";
if ($default) {
- $result .= ' '.&mt('default').
+ $result .= ' '.&mt('default').
' '."\n";
}
foreach my $hostid (sort(keys(%servers))) {
@@ -1995,12 +2358,16 @@ function changed_text(choice,currentform
}
function set_auth_radio_buttons(newvalue,currentform) {
+ var numauthchoices = currentform.login.length;
+ if (typeof numauthchoices == "undefined") {
+ return;
+ }
var i=0;
- while (i < currentform.login.length) {
+ while (i < numauthchoices) {
if (currentform.login[i].value == newvalue) { break; }
i++;
}
- if (i == currentform.login.length) {
+ if (i == numauthchoices) {
return;
}
current.radiovalue = newvalue;
@@ -2051,14 +2418,14 @@ sub authform_kerberos {
$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'};
if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'krb') {
- $krbcheck = ' checked="on"';
+ $krbcheck = ' checked="checked"';
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifyuser') {
$krbcheck = '';
@@ -2066,10 +2433,10 @@ sub authform_kerberos {
}
if (defined($in{'curr_kerb_ver'})) {
if ($in{'curr_krb_ver'} eq '5') {
- $check5 = ' checked="on"';
+ $check5 = ' checked="checked"';
$check4 = '';
} else {
- $check4 = ' checked="on"';
+ $check4 = ' checked="checked"';
$check5 = '';
}
}
@@ -2090,7 +2457,7 @@ sub authform_kerberos {
}
} else {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
if (!$can_assign{'krb4'} && !$can_assign{'krb5'}) {
@@ -2099,7 +2466,7 @@ sub authform_kerberos {
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2160,7 +2527,7 @@ sub authform_internal{
if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'int') {
if ($can_assign{'int'}) {
- $intcheck = 'checked="on" ';
+ $intcheck = 'checked="checked" ';
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifyuser') {
$intcheck = '';
@@ -2176,7 +2543,7 @@ sub authform_internal{
}
} else {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
if (!$can_assign{'int'}) {
@@ -2185,7 +2552,7 @@ sub authform_internal{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2200,7 +2567,7 @@ sub authform_internal{
$result = &mt
('[_1] Internally authenticated (with initial password [_2])',
''.$authtype,' '.$autharg);
- $result.=" ".&mt('Visible input').' ';
+ $result.=" ".&mt('Visible input').' ';
return $result;
}
@@ -2215,7 +2582,7 @@ sub authform_local{
if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'loc') {
if ($can_assign{'loc'}) {
- $loccheck = 'checked="on" ';
+ $loccheck = 'checked="checked" ';
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifyuser') {
$loccheck = '';
@@ -2231,7 +2598,7 @@ sub authform_local{
}
} else {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
if (!$can_assign{'loc'}) {
@@ -2240,7 +2607,7 @@ sub authform_local{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2269,7 +2636,7 @@ sub authform_filesystem{
if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'fsys') {
if ($can_assign{'fsys'}) {
- $fsyscheck = 'checked="on" ';
+ $fsyscheck = 'checked="checked" ';
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifyuser') {
$fsyscheck = '';
@@ -2282,7 +2649,7 @@ sub authform_filesystem{
}
} else {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
if (!$can_assign{'fsys'}) {
@@ -2291,7 +2658,7 @@ sub authform_filesystem{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2659,6 +3026,43 @@ 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
@@ -2678,6 +3082,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 {
@@ -2688,13 +3112,15 @@ sub messagewrapper {
'&subject='.&escape($subject).'&text='.&escape($text).'" '.
'title="'.&mt('Send message').'">'.$link.'';
}
+
# --------------------------------------------------------------- Notes Wrapper
sub noteswrapper {
my ($link,$un,$do)=@_;
return
-"$link ";
+"$link ";
}
+
# ------------------------------------------------------------- Aboutme Wrapper
sub aboutmewrapper {
@@ -2702,23 +3128,21 @@ sub aboutmewrapper {
if (!defined($username) && !defined($domain)) {
return;
}
- return ''.$link.' ';
+ return ''.$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 ($linktext,$sname,$sdom,$target,$start,$only_body) = @_;
my $link ="/adm/trackstudent?";
my $title = 'View recent activity';
if (defined($sname) && $sname !~ /^\s*$/ &&
@@ -2732,12 +3156,34 @@ sub track_student_link {
$target = '';
}
if ($start) { $link.='&start='.$start; }
+ if ($only_body) { $link .= '&only_body=1'; }
$title = &mt($title);
$linktext = &mt($linktext);
return qq{$linktext }.
&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
@@ -2888,8 +3334,7 @@ sub filemimetype {
sub filecategoryselect {
my ($name,$value)=@_;
return &select_form($value,$name,
- '' => &mt('Any category'),
- map { $_,$_ } sort(keys(%category_extensions)));
+ {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))});
}
=pod
@@ -2940,7 +3385,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']);
@@ -2952,54 +3397,9 @@ sub display_languages {
return %languages;
}
-sub preferred_languages {
- my @languages=();
- if (($env{'request.role.adv'}) && ($env{'form.languages'})) {
- @languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$env{'form.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=$ENV{'HTTP_ACCEPT_LANGUAGE'};
- if ($browser) {
- my @browser =
- map { (split(/\s*;\s*/,$_))[0] } (split(/\s*,\s*/,$browser));
- push(@languages,@browser);
- }
-
- foreach my $domtype ($env{'user.domain'},$env{'request.role.domain'},
- $Apache::lonnet::perlvar{'lonDefDomain'}) {
- if ($domtype ne '') {
- my %domdefs = &Apache::lonnet::get_domain_defaults($domtype);
- if ($domdefs{'lang_def'} ne '') {
- push(@languages,$domdefs{'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]);
- }
- }
- #uniqueify the languages list
- my %count;
- @genlanguages = map { $count{$_}++ == 0 ? $_ : () } @genlanguages;
- return @genlanguages;
-}
-
sub languages {
my ($possible_langs) = @_;
- my @preferred_langs = &preferred_languages();
+ my @preferred_langs = &Apache::lonlocal::preferred_languages();
if (!ref($possible_langs)) {
if( wantarray ) {
return @preferred_langs;
@@ -3020,6 +3420,29 @@ sub languages {
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 ##
###############################################################
@@ -3076,12 +3499,24 @@ sub get_previous_attempt {
}
$prevattempts=&start_data_table().&start_data_table_header_row();
$prevattempts.=''.&mt('History').' ';
+ my (%typeparts,%lasthidden);
+ my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'});
foreach my $key (sort(keys(%lasthash))) {
my ($ign,@parts) = split(/\./,$key);
if ($#parts > 0) {
my $data=$parts[-1];
+ next if ($data eq 'foilorder');
pop(@parts);
- $prevattempts.=''.&mt('Part ').join('.',@parts).' '.$data.' ';
+ $prevattempts.=''.&mt('Part ').join('.',@parts).' '.$data.' ';
+ if ($data eq 'type') {
+ unless ($showsurv) {
+ my $id = join(',',@parts);
+ $typeparts{$ign.'.'.$id} = $lasthash{$key};
+ if (($lasthash{$key} eq 'anonsurvey') || ($lasthash{$key} eq 'anonsurveycred')) {
+ $lasthidden{$ign.'.'.$id} = 1;
+ }
+ }
+ }
} else {
if ($#parts == 0) {
$prevattempts.=''.$parts[0].' ';
@@ -3093,21 +3528,93 @@ sub get_previous_attempt {
$prevattempts.=&end_data_table_header_row();
if ($getattempt eq '') {
for ($version=1;$version<=$returnhash{'version'};$version++) {
- $prevattempts.=&start_data_table_row().
- ''.&mt('Transaction [_1]',$version).' ';
- foreach my $key (sort(keys(%lasthash))) {
- my $value = &format_previous_attempt_value($key,
- $returnhash{$version.':'.$key});
- $prevattempts.=''.$value.' ';
- }
- $prevattempts.=&end_data_table_row();
+ my @hidden;
+ if (%typeparts) {
+ foreach my $id (keys(%typeparts)) {
+ if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {
+ push(@hidden,$id);
+ }
+ }
+ }
+ $prevattempts.=&start_data_table_row().
+ ''.&mt('Transaction [_1]',$version).' ';
+ if (@hidden) {
+ foreach my $key (sort(keys(%lasthash))) {
+ next if ($key =~ /\.foilorder$/);
+ my $hide;
+ foreach my $id (@hidden) {
+ if ($key =~ /^\Q$id\E/) {
+ $hide = 1;
+ last;
+ }
+ }
+ if ($hide) {
+ my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/);
+ if (($data eq 'award') || ($data eq 'awarddetail')) {
+ my $value = &format_previous_attempt_value($key,
+ $returnhash{$version.':'.$key});
+ $prevattempts.=''.$value.' ';
+ } else {
+ $prevattempts.=' ';
+ }
+ } else {
+ if ($key =~ /\./) {
+ my $value = &format_previous_attempt_value($key,
+ $returnhash{$version.':'.$key});
+ $prevattempts.=''.$value.' ';
+ } else {
+ $prevattempts.=' ';
+ }
+ }
+ }
+ } else {
+ foreach my $key (sort(keys(%lasthash))) {
+ next if ($key =~ /\.foilorder$/);
+ my $value = &format_previous_attempt_value($key,
+ $returnhash{$version.':'.$key});
+ $prevattempts.=''.$value.' ';
+ }
+ }
+ $prevattempts.=&end_data_table_row();
}
}
+ my @currhidden = keys(%lasthidden);
$prevattempts.=&start_data_table_row().''.&mt('Current').' ';
foreach my $key (sort(keys(%lasthash))) {
- my $value = &format_previous_attempt_value($key,$lasthash{$key});
- if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
- $prevattempts.=''.$value.' ';
+ next if ($key =~ /\.foilorder$/);
+ if (%typeparts) {
+ my $hidden;
+ foreach my $id (@currhidden) {
+ if ($key =~ /^\Q$id\E/) {
+ $hidden = 1;
+ last;
+ }
+ }
+ if ($hidden) {
+ my ($id,$data) = ($key =~ /^(.+)\.([^.]+)$/);
+ if (($data eq 'award') || ($data eq 'awarddetail')) {
+ my $value = &format_previous_attempt_value($key,$lasthash{$key});
+ if ($key =~/$regexp$/ && (defined &$gradesub)) {
+ $value = &$gradesub($value);
+ }
+ $prevattempts.=''.$value.' ';
+ } else {
+ $prevattempts.=' ';
+ }
+ } else {
+ my $value = &format_previous_attempt_value($key,$lasthash{$key});
+ if ($key =~/$regexp$/ && (defined &$gradesub)) {
+ $value = &$gradesub($value);
+ }
+ $prevattempts.=''.$value.' ';
+ }
+ } else {
+ my $value = &format_previous_attempt_value($key,$lasthash{$key});
+ if ($key =~/$regexp$/ && (defined &$gradesub)) {
+ $value = &$gradesub($value);
+ }
+ $prevattempts.=''.$value.' ';
+ }
}
$prevattempts.= &end_data_table_row().&end_data_table();
} else {
@@ -3126,10 +3633,33 @@ sub get_previous_attempt {
sub format_previous_attempt_value {
my ($key,$value) = @_;
- if ($key =~ /timestamp/) {
+ if (($key =~ /timestamp/) || ($key=~/duedate/)) {
$value = &Apache::lonlocal::locallocaltime($value);
} elsif (ref($value) eq 'ARRAY') {
$value = '('.join(', ', @{ $value }).')';
+ } elsif ($key =~ /answerstring$/) {
+ my %answers = &Apache::lonnet::str2hash($value);
+ my @anskeys = sort(keys(%answers));
+ if (@anskeys == 1) {
+ my $answer = $answers{$anskeys[0]};
+ if ($answer =~ m{\0}) {
+ $answer =~ s{\0}{,}g;
+ }
+ my $tag_internal_answer_name = 'INTERNAL';
+ if ($anskeys[0] eq $tag_internal_answer_name) {
+ $value = $answer;
+ } else {
+ $value = $anskeys[0].'='.$answer;
+ }
+ } else {
+ foreach my $ans (@anskeys) {
+ my $answer = $answers{$ans};
+ if ($answer =~ m{\0}) {
+ $answer =~ s{\0}{,}g;
+ }
+ $value .= $ans.'='.$answer.' ';;
+ }
+ }
} else {
$value = &unescape($value);
}
@@ -3158,7 +3688,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) ||
@@ -3280,10 +3810,13 @@ sub submlink {
}
if (!$symb) { $symb=&Apache::lonnet::symbread(); }
$symb=&escape($symb);
- if ($target) { $target="target=\"$target\""; }
- return ''.$text.' ';
+ if ($target) { $target=" target=\"$target\""; }
+ return
+ ''.$text.' ';
}
##############################################
@@ -3343,16 +3876,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 {
@@ -3362,6 +3900,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));
@@ -3382,10 +3938,13 @@ sub findallcourses {
$udom = $env{'user.domain'};
}
if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
- my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname);
+ my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
+ my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,
+ $extra);
if (!%roles) {
%roles = (
cc => 1,
+ co => 1,
in => 1,
ep => 1,
ta => 1,
@@ -3576,7 +4135,7 @@ sub blockcheck {
($env{'request.role'} !~ m{^st\./\Q$cdom\E/\Q$cnum\E}));
next if ($no_userblock);
- # Retrieve blocking times and identity of blocker for course
+ # Retrieve blocking times and identity of locker for course
# of specified user, unless user has 'evb' privilege.
my ($start,$end)=&get_blocks($setters,$activity,$cdom,$cnum);
@@ -3641,103 +4200,105 @@ sub parse_block_record {
return ($setuname,$setudom,$title,$blocks);
}
-sub build_block_table {
- my ($startblock,$endblock,$setters) = @_;
- my %lt = &Apache::lonlocal::texthash(
- 'cacb' => 'Currently active communication blocks',
- 'cour' => 'Course',
- 'dura' => 'Duration',
- 'blse' => 'Block set by'
- );
- my $output;
- $output = ' '.$lt{'cacb'}.': ';
- $output .= &start_data_table();
- $output .= '
-
- '.$lt{'cour'}.'
- '.$lt{'dura'}.'
- '.$lt{'blse'}.'
-
-';
- foreach my $course (keys(%{$setters})) {
- my %courseinfo=&Apache::lonnet::coursedescription($course);
- for (my $i=0; $i<@{$$setters{$course}{staff}}; $i++) {
- my ($uname,$udom) = @{$$setters{$course}{staff}[$i]};
- my $fullname = &plainname($uname,$udom);
- if (defined($env{'user.name'}) && defined($env{'user.domain'})
- && $env{'user.name'} ne 'public'
- && $env{'user.domain'} ne 'public') {
- $fullname = &aboutmewrapper($fullname,$uname,$udom);
- }
- my ($openblock,$closeblock) = @{$$setters{$course}{times}[$i]};
- $openblock = &Apache::lonlocal::locallocaltime($openblock);
- $closeblock= &Apache::lonlocal::locallocaltime($closeblock);
- $output .= &Apache::loncommon::start_data_table_row().
- ''.$courseinfo{'description'}.' '.
- ''.$openblock.' to '.$closeblock.' '.
- ''.$fullname.' '.
- &Apache::loncommon::end_data_table_row();
- }
- }
- $output .= &end_data_table();
+sub blocking_status {
+ my ($activity,$uname,$udom) = @_;
+ my %setters;
+
+ # check for active blocking
+ my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);
+
+ my $blocked = $startblock && $endblock ? 1 : 0;
+
+ # caller just wants to know whether a block is active
+ if (!wantarray) { return $blocked; }
+
+ # build a link to a popup window containing the details
+ my $querystring = "?activity=$activity";
+ # $uname and $udom decide whose portfolio the user is trying to look at
+ $querystring .= "&udom=$udom" if $udom;
+ $querystring .= "&uname=$uname" if $uname;
+
+ my $output .= <<'END_MYBLOCK';
+ function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
+ var options = "width=" + w + ",height=" + h + ",";
+ options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
+ options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
+ var newWin = window.open(url, wdwName, options);
+ newWin.focus();
+ }
+END_MYBLOCK
+
+ $output = Apache::lonhtmlcommon::scripttag($output);
+
+ my $popupUrl = "/adm/blockingstatus/$querystring";
+ my $text = mt('Communication Blocked');
+
+ $output .= <<"END_BLOCK";
+
+
+END_BLOCK
+
+ return ($blocked, $output);
}
-sub blocking_status {
- my ($activity,$uname,$udom) = @_;
- my %setters;
- my ($blocked,$output,$ownitem,$is_course);
- my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);
- if ($startblock && $endblock) {
- $blocked = 1;
- if (wantarray) {
- my $category;
- if ($activity eq 'boards') {
- $category = 'Discussion posts in this course';
- } elsif ($activity eq 'blogs') {
- $category = 'Blogs';
- } elsif ($activity eq 'port') {
- if (defined($uname) && defined($udom)) {
- if ($uname eq $env{'user.name'} &&
- $udom eq $env{'user.domain'}) {
- $ownitem = 1;
- }
- }
- $is_course = &Apache::lonnet::is_course($udom,$uname);
- if ($ownitem) {
- $category = 'Your portfolio files';
- } elsif ($is_course) {
- my $coursedesc;
- foreach my $course (keys(%setters)) {
- my %courseinfo =
- &Apache::lonnet::coursedescription($course);
- $coursedesc = $courseinfo{'description'};
- }
- $category = "Group files in the course '$coursedesc'";
- } else {
- $category = 'Portfolio files belonging to ';
- if ($env{'user.name'} eq 'public' &&
- $env{'user.domain'} eq 'public') {
- $category .= &plainname($uname,$udom);
- } else {
- $category .= &aboutmewrapper(&plainname($uname,$udom),$uname,$udom);
- }
- }
- } elsif ($activity eq 'groups') {
- $category = 'Groups in this course';
- }
- my $showstart = &Apache::lonlocal::locallocaltime($startblock);
- my $showend = &Apache::lonlocal::locallocaltime($endblock);
- $output = ' '.&mt('[_1] will be inaccessible between [_2] and [_3] because communication is being blocked.',$category,$showstart,$showend).' ';
- if (!($activity eq 'port' && !($ownitem) && !($is_course))) {
- $output .= &build_block_table($startblock,$endblock,\%setters);
+###############################################
+
+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; }
}
- if (wantarray) {
- return ($blocked,$output);
- } else {
- return $blocked;
- }
+ return $allowed;
}
###############################################
@@ -3761,7 +4322,7 @@ sub determinedomain {
my $domain=shift;
if (! $domain) {
# Determine domain if we have not been given one
- $domain = $Apache::lonnet::perlvar{'lonDefDomain'};
+ $domain = &Apache::lonnet::default_login_domain();
if ($env{'user.domain'}) { $domain=$env{'user.domain'}; }
if ($env{'request.role.domain'}) {
$domain=$env{'request.role.domain'};
@@ -3784,13 +4345,42 @@ sub get_domainconf {
if (defined($cached)) { return %{$result}; }
my %domconfig = &Apache::lonnet::get_dom('configuration',
- ['login','rolecolors'],$udom);
+ ['login','rolecolors','autoenroll'],$udom);
my (%designhash,%legacy);
if (keys(%domconfig) > 0) {
if (ref($domconfig{'login'}) eq 'HASH') {
if (keys(%{$domconfig{'login'}})) {
foreach my $key (keys(%{$domconfig{'login'}})) {
- $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
+ if (ref($domconfig{'login'}{$key}) eq 'HASH') {
+ if ($key eq 'loginvia') {
+ if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {
+ foreach my $hostname (keys(%{$domconfig{'login'}{'loginvia'}})) {
+ if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') {
+ if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {
+ my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
+ $designhash{$udom.'.login.loginvia'} = $server;
+ if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') {
+
+ $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
+ } else {
+ $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
+ }
+ if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) {
+ $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'};
+ }
+ }
+ }
+ }
+ }
+ } else {
+ 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;
@@ -3813,6 +4403,11 @@ sub get_domainconf {
} else {
$legacy{'rolecolors'} = 1;
}
+ if (ref($domconfig{'autoenroll'}) eq 'HASH') {
+ if ($domconfig{'autoenroll'}{'co-owners'}) {
+ $designhash{$udom.'.autoassign.co-owners'}=$domconfig{'autoenroll'}{'co-owners'};
+ }
+ }
if (keys(%legacy) > 0) {
my %legacyhash = &get_legacy_domconf($udom);
foreach my $item (keys(%legacyhash)) {
@@ -3905,41 +4500,135 @@ Returns: value of designparamter $which
##############################################
sub designparm {
my ($which,$domain)=@_;
- if ($env{'browser.blackwhite'} eq 'on') {
- if ($which=~/\.(font|alink|vlink|link|textcol)$/) {
- return '#000000';
- }
- if ($which=~/\.(pgbg|sidebg|bgcol)$/) {
- 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 %domdesign;
+ unless ($domain eq 'public') {
+ %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|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;
+ }
+
+ my $output =
+ ''
+ .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
+ .''.&mt('Construction Space:').' '
+ .''
+ .&Apache::lonmenu::constspaceform()
+ .'
';
+
+ return $output;
+}
+
###############################################
###############################################
@@ -3972,20 +4661,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
-
=item * $args, optional argument valid values are
no_auto_mt_title -> prevents &mt()ing the title arg
inherit_jsmath -> when creating popup window in a page,
@@ -4002,9 +4682,14 @@ 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,$args)=@_;
+ my $public;
+ if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
+ || ($env{'user.name'} eq '') && ($env{'user.domain'} eq '')) {
+ $public = 1;
+ }
if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
$function = &get_users_function() if (!$function);
@@ -4012,7 +4697,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),
@@ -4031,14 +4716,15 @@ sub bodytag {
if ($env{'request.role'} !~ /^cr/) {
$role = &Apache::lonnet::plaintext($role,&course_type());
}
+ if ($env{'request.course.sec'}) {
+ $role .= (' 'x2).'- '.&mt('section:').' '.$env{'request.course.sec'};
+ }
$realm = $env{'course.'.$env{'request.course.id'}.'.description'};
} else {
$role = &Apache::lonnet::plaintext($role);
}
if (!$realm) { $realm=' '; }
-# Set messages
- my $messages=&domainlogo($domain);
my $extra_body_attr = &make_attr_string($forcereg,\%design);
@@ -4048,42 +4734,16 @@ 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') {
+ if ($public) {
undef($role);
} else {
$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 = '';
@@ -4091,93 +4751,75 @@ ENDROLE
$env{'course.'.$env{'request.course.id'}.
'.domain'}.'/'})) {
my $cid = $env{'request.course.id'};
- $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
+ $dc_info = $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
$dc_info =~ s/\s+$//;
- $dc_info = '('.$dc_info.')';
}
- if (($env{'environment.remote'} eq 'off') || ($args->{'suppress_header_logos'})) {
- # No Remote
- if ($env{'request.state'} eq 'construct') {
- $forcereg=1;
- }
+ $role = '('.$role.') ' if $role;
+ &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
- 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')
- .''.&mt('Construction Space').' : '
- .''
- .&Apache::lonmenu::constspaceform();
- }
-
- my $titletable;
- if (!$notitle) {
- $titletable =
- ''.
- " $titleinfo $dc_info ".$roleinfo.
- '
';
- }
- if ($notopbar) {
- $bodytag .= $titletable;
- } else {
- if ($env{'request.state'} eq 'construct') {
- $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg,
- $titletable);
- } else {
- $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg).
- $titletable;
+ if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') {
+ return $bodytag;
+ }
+
+ if ($env{'request.state'} eq 'construct') { $forcereg=1; }
+
+ # if ($env{'request.state'} eq 'construct') {
+ # $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
+ # }
+
+
+
+ if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
+ if ($dc_info) {
+ $dc_info = qq|$dc_info |;
+ }
+ $bodytag .= qq|$name $role
+ $realm $dc_info
|;
+ return $bodytag;
+ }
+
+ unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
+ $bodytag .= qq|$name $role
|;
+ }
+
+ $bodytag .= Apache::lonhtmlcommon::scripttag(
+ Apache::lonmenu::utilityfunctions(), 'start');
+
+ $bodytag .= Apache::lonmenu::primary_menu();
+
+ if ($dc_info) {
+ $dc_info = &dc_courseid_toggle($dc_info);
+ }
+ $bodytag .= qq|$realm $dc_info
|;
+
+ #don't show menus for public users
+ if (!$public){
+ $bodytag .= Apache::lonmenu::secondary_menu();
+ $bodytag .= Apache::lonmenu::serverform();
+ $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+ if ($env{'request.state'} eq 'construct') {
+ $bodytag .= &Apache::lonmenu::innerregister($forcereg,
+ $args->{'bread_crumbs'});
+ } elsif ($forcereg) {
+ $bodytag .= &Apache::lonmenu::innerregister($forcereg);
}
+ }else{
+ # this is to seperate menu from content when there's no secondary
+ # menu. Especially needed for public accessible ressources.
+ $bodytag .= ' ';
+ $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
}
- return $bodytag;
- }
-#
-# Top frame rendering, Remote is up
-#
+ return $bodytag;
+}
- my $imgsrc = $img;
- if ($img =~ /^\/adm/) {
- $imgsrc = &lonhttpdurl($img);
- }
- my $upperleft=' ';
-
- # Explicit link to get inline menu
- my $menu= ($no_inline_link?''
- :''.&mt('Switch to Inline Menu Mode').' ');
- #
- if ($notitle) {
- return $bodytag;
- }
- return(<
-$upperleft
- $messages
-
-$titleinfo $dc_info $menu
-$roleinfo
-
-
-ENDBODY
+sub dc_courseid_toggle {
+ my ($dc_info) = @_;
+ return ' '.
+ ''.
+ &mt('(More ...)').' '.
+ ''.$dc_info.'
';
}
sub make_attr_string {
@@ -4201,31 +4843,8 @@ sub make_attr_string {
delete($attr_ref->{$key});
}
}
- $attr_ref->{'onload'} =
- &Apache::lonmenu::loadevents(). $on_load;
- $attr_ref->{'onunload'}=
- &Apache::lonmenu::unloadevents().$on_unload;
- }
-
-# Accessibility font enhance
- if ($env{'browser.fontenhance'} eq 'on') {
- my $style;
- foreach my $key (keys(%{$attr_ref})) {
- if (lc($key) eq 'style') {
- $style.=$attr_ref->{$key}.';';
- delete($attr_ref->{$key});
- }
- }
- $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'});
+ $attr_ref->{'onload'} = $on_load;
+ $attr_ref->{'onunload'}= $on_unload;
}
my $attr_string;
@@ -4288,6 +4907,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 ||
@@ -4299,9 +4920,9 @@ sub standard_css {
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';
@@ -4314,34 +4935,89 @@ sub standard_css {
my $mail_other_hover = '#669999';
my $table_header = '#DDDDDD';
my $feedback_link_bg = '#BBBBBB';
+ my $lg_border_color = '#C8C8C8';
+ my $button_hover = '#BF2317';
my $border = ($env{'browser.type'} eq 'explorer' ||
- $env{'browser.type'} eq 'safari' ) ? '0px 2px 0px 2px'
- : '0px 3px 0px 4px';
+ $env{'browser.type'} eq 'safari' ) ? '0 2px 0 2px'
+ : '0 3px 0 4px';
return < td,
-table.LC_aboutme_port tr td {
+
+table.LC_innerpickbox tr th,
+table.LC_innerpickbox tr td {
+ vertical-align: top;
+}
+
+table.LC_data_table tr.LC_info_row > td {
+ background-color: #CCCCCC;
+ font-weight: bold;
+ text-align: left;
+}
+
+table.LC_data_table tr.LC_odd_row > td {
+ background-color: $data_table_light;
+ padding: 2px;
+ vertical-align: top;
+}
+
+table.LC_pick_box tr > td.LC_odd_row {
background-color: $data_table_light;
+ vertical-align: top;
+}
+
+table.LC_data_table tr.LC_even_row > td {
+ background-color: $data_table_dark;
padding: 2px;
+ vertical-align: top;
}
-table.LC_data_table tr.LC_even_row > td,
-table.LC_aboutme_port tr.LC_even_row td {
+
+table.LC_pick_box tr > td.LC_even_row {
background-color: $data_table_dark;
+ vertical-align: top;
}
+
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;
font-weight: bold;
font-style: italic;
text-align: center;
padding: 8px;
}
+
+table.LC_data_table tr.LC_empty_row td {
+ background-color: $sidebg;
+}
+
+table.LC_nested tr.LC_empty_row td {
+ background-color: #FFFFFF;
+}
+
+table.LC_caption {
+}
+
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;
@@ -4645,20 +5347,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_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,
@@ -4667,18 +5373,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;
}
@@ -4686,174 +5392,192 @@ table.LC_createuser tr.LC_info_row td {
table.LC_calendar {
border: 1px solid #000000;
border-collapse: collapse;
+ width: 98%;
}
+
table.LC_calendar_pickdate {
font-size: xx-small;
}
+
table.LC_calendar tr td {
border: 1px solid #000000;
vertical-align: top;
+ width: 14%;
}
+
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;
}
-table.LC_mail_list tr.LC_mail_new {
+table.LC_data_table tr td.LC_mail_new {
background-color: $mail_new;
}
-table.LC_mail_list tr.LC_mail_new:hover {
+
+table.LC_data_table tr.LC_mail_new:hover {
background-color: $mail_new_hover;
}
-table.LC_mail_list tr.LC_mail_read {
+
+table.LC_data_table tr td.LC_mail_read {
background-color: $mail_read;
}
-table.LC_mail_list tr.LC_mail_read:hover {
+
+/*
+table.LC_data_table tr.LC_mail_read:hover {
background-color: $mail_read_hover;
}
-table.LC_mail_list tr.LC_mail_replied {
+*/
+
+table.LC_data_table tr td.LC_mail_replied {
background-color: $mail_replied;
}
-table.LC_mail_list tr.LC_mail_replied:hover {
+
+/*
+table.LC_data_table tr.LC_mail_replied:hover {
background-color: $mail_replied_hover;
}
-table.LC_mail_list tr.LC_mail_other {
+*/
+
+table.LC_data_table tr td.LC_mail_other {
background-color: $mail_other;
}
-table.LC_mail_list tr.LC_mail_other:hover {
+
+/*
+table.LC_data_table 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: #AAEE77;
}
-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: #888888;
}
-table#LC_browser {
-
+table.LC_data_table tr > td.LC_browser_file_modified,
+table.LC_data_table tr > td.LC_browser_file_metamodified {
+ background: #F8F866;
}
-table#LC_browser tr th {
- background: $table_header;
+
+table.LC_data_table tr.LC_browser_folder > td {
+ background: #E0E8FF;
}
-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 {
+ border-right: 8px solid #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 {
+ border-right: 8px solid #FFAA77;
}
-table#LC_browser tr.LC_browser_file_obsolete {
- background: #AAAAAA;
+
+table.LC_data_table tr > td.LC_roles_expired {
+ border-right: 8px solid #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 {
+ border-right: 8px solid #AAFF77;
}
-table#LC_browser tr.LC_browser_folder {
- background: #CCCCFF;
+
+table.LC_data_table tr > td.LC_roles_selected {
+ border-right: 8px solid #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 {
+
+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 {
+ul.LC_parm_parmlist li {
+ display: inline-block;
+ padding: 0.3em 0.8em;
+ vertical-align: top;
+ width: 150px;
+ border-top:1px solid $lg_border_color;
+}
+
+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;
@@ -4861,11 +5585,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;
@@ -4875,171 +5601,173 @@ 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;
+ text-align: left;
+ vertical-align: top;
width: 184px;
padding: 8px;
}
-table.LC_pick_box td.LC_selfenroll_pick_box_title {
- background: $tabbg;
- font-weight: bold;
- text-align: right;
- width: 350px;
- 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;
- background: white;
- border: 1px solid black;
- border-spacing: 1px;
-}
-table.LC_helpform_receipt td.LC_pick_box_title {
- background: $tabbg;
- font-weight: bold;
- text-align: right;
- 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;
- 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 {
- background: white;
- 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;
+ margin: 1em 0em 1em 2em;
+ padding: 3px;
+ font-size: 1.2em;
}
+
.LC_topic_bar span {
+ left: 0.5em;
+ position: absolute;
vertical-align: middle;
+ font-size: 1.2em;
}
-.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: white;
- width: 100%;
+ background: $sidebg;
+ width: 100%;
+ padding-bottom: 10px;
+ border: 1px $tabbg solid;
+ height: 22px;
+ line-height: 22px;
+ padding-top: 5px;
+}
+
+div.LC_feedback_link img {
+ height: 22px;
+ vertical-align:middle;
}
+
+div.LC_feedback_link a {
+ text-decoration: none;
+}
+
+div.LC_comblock {
+ display:inline;
+ color:$font;
+ font-size:90%;
+}
+
+div.LC_feedback_link div.LC_comblock {
+ padding-left:5px;
+}
+
+div.LC_feedback_link div.LC_comblock a {
+ color:$font;
+}
+
span.LC_feedback_link {
- background: $feedback_link_bg;
+ /* background: $feedback_link_bg; */
font-size: larger;
}
+
span.LC_message_link {
- background: $feedback_link_bg;
+ /* background: $feedback_link_bg; */
font-size: larger;
position: absolute;
right: 1em;
@@ -5056,44 +5784,54 @@ 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,
span.LC_prior_reaction,
span.LC_prior_math {
- font-family: monospace;
+ font-family: $mono;
white-space: pre;
}
span.LC_prior_string {
- font-family: monospace;
+ font-family: $mono;
white-space: pre;
}
@@ -5101,16 +5839,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;
}
@@ -5123,47 +5864,36 @@ span.LC_cusr_subheading {
font-size: 85%;
}
-table.LC_docs_documents {
- background: #BBBBBB;
- border-width: 0px;
- border-collapse: collapse;
-}
-
-table.LC_docs_documents td.LC_docs_document {
- border: 2px solid black;
- 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;
+div.LC_docs_entry_move {
+ border: 1px solid #BBBBBB;
background: #DDDDDD;
+ width: 22px;
+ padding: 1px;
+ margin: 0;
}
-.LC_docs_editor td.LC_docs_entry_commands {
+table.LC_data_table tr > td.LC_docs_entry_commands,
+table.LC_data_table tr > td.LC_docs_entry_parameter {
background: #DDDDDD;
font-size: x-small;
}
+
+.LC_docs_entry_parameter {
+ white-space: nowrap;
+}
+
.LC_docs_copy {
color: #000099;
}
+
.LC_docs_cut {
color: #550044;
}
+
.LC_docs_rename {
color: #009900;
}
+
.LC_docs_remove {
color: #990000;
}
@@ -5173,16 +5903,6 @@ 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 {
- background: #BBBBFF;
- font-size: x-small;
- white-space: nowrap;
-}
-
table.LC_docs_adddocs td,
table.LC_docs_adddocs th {
border: 1px solid #BBBBBB;
@@ -5193,12 +5913,13 @@ table.LC_docs_adddocs th {
table.LC_sty_begin {
background: #BBFFBB;
}
+
table.LC_sty_end {
background: #FFBBBB;
}
table.LC_double_column {
- border-width: 0px;
+ border-width: 0;
border-collapse: collapse;
width: 100%;
padding: 2px;
@@ -5213,15 +5934,11 @@ table.LC_double_column tr td.LC_left_col
table.LC_double_column tr td.LC_right_col {
top: 2px;
- right: 2px;
+ right: 2px;
width: 47%;
vertical-align: top;
}
-span.LC_role_level {
- font-weight: bold;
-}
-
div.LC_left_float {
float: left;
padding-right: 5%;
@@ -5237,79 +5954,58 @@ div.LC_clear_float_footer {
clear: both;
}
-
-div.LC_grade_select_mode {
- font-family: $sans;
-}
-div.LC_grade_select_mode div div {
- margin: 5px;
-}
-div.LC_grade_select_mode_selector {
- margin: 5px;
- float: left;
-}
-div.LC_grade_select_mode_selector_header {
- font: bold medium $sans;
-}
-div.LC_grade_select_mode_type {
- clear: left;
-}
-
div.LC_grade_show_user {
- margin-top: 20px;
- border: 1px solid black;
+/* border-left: 5px solid $sidebg; */
+ border-top: 5px solid #000000;
+ margin: 50px 0 0 0;
+ padding: 15px 0 5px 10px;
}
-div.LC_grade_user_name {
- background: #DDDDEE;
- border-bottom: 1px solid black;
- font: bold large $sans;
+
+div.LC_grade_show_user_odd_row {
+/* border-left: 5px solid #000000; */
}
-div.LC_grade_show_user_odd_row div.LC_grade_user_name {
- background: #DDEEDD;
+
+div.LC_grade_show_user div.LC_Box {
+ margin-right: 50px;
}
-div.LC_grade_show_problem,
div.LC_grade_submissions,
div.LC_grade_message_center,
-div.LC_grade_info_links,
-div.LC_grade_assign {
+div.LC_grade_info_links {
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: bold large $sans;
+div.LC_grade_message_center_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 {
+div.LC_grade_message_center_body {
border: 1px solid black;
width: 99%;
background: #FFFFFF;
}
-span.LC_grade_check_note {
- font: normal medium $sans;
- display: inline;
- position: absolute;
- right: 1em;
-}
table.LC_scantron_action {
width: 100%;
}
+
table.LC_scantron_action tr th {
- font: normal bold $sans;
+ font-weight:bold;
+ font-style:normal;
}
-div.LC_edit_problem_header,
+.LC_edit_problem_header,
div.LC_edit_problem_footer {
- font: normal medium $sans;
+ font-weight: normal;
+ font-size: medium;
margin: 2px;
}
+
div.LC_edit_problem_header,
div.LC_edit_problem_header div,
div.LC_edit_problem_footer,
@@ -5318,43 +6014,600 @@ div.LC_edit_problem_editxml_header,
div.LC_edit_problem_editxml_header div {
margin-top: 5px;
}
-div.LC_edit_problem_header_edit_row {
- background: $tabbg;
- padding: 3px;
- margin-bottom: 5px;
-}
+
div.LC_edit_problem_header_title {
- font: larger bold $sans;
+ font-weight: bold;
+ font-size: larger;
background: $tabbg;
padding: 3px;
}
+
table.LC_edit_problem_header_title {
- font: larger bold $sans;
width: 100%;
- border-color: $pgbg;
- border-style: solid;
- border-width: $border;
-
background: $tabbg;
- border-collapse: collapse;
- padding: 0px
}
div.LC_edit_problem_discards {
float: left;
padding-bottom: 5px;
}
+
div.LC_edit_problem_saves {
float: right;
padding-bottom: 5px;
}
-hr.LC_edit_problem_divide {
+
+img.stift {
+ border-width: 0;
+ vertical-align: middle;
+}
+
+table td.LC_mainmenu_col_fieldset {
+ vertical-align: top;
+}
+
+div.LC_createcourse {
+ margin: 10px 10px 10px 10px;
+}
+
+.LC_dccid {
+ margin: 0.2em 0 0 0;
+ padding: 0;
+ font-size: 90%;
+ display:none;
+}
+
+a:hover,
+ol.LC_primary_menu a:hover,
+ol#LC_MenuBreadcrumbs a:hover,
+ol#LC_PathBreadcrumbs a:hover,
+ul#LC_secondary_menu a:hover,
+.LC_FormSectionClearButton input:hover
+ul.LC_TabContent li:hover a {
+ color:$button_hover;
+ 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_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;
+ background-color: $pgbg_or_bgcolor;
+ margin: 0 0 2px 0;
+}
+
+#LC_realm {
+ margin: 0.2em 0 0 0;
+ padding: 0;
+ font-weight: bold;
+ text-align: center;
+ background-color: $pgbg_or_bgcolor;
+}
+
+#LC_nav_bar em {
+ font-weight: bold;
+ font-style: normal;
+}
+
+ol.LC_primary_menu {
+ float: right;
+ margin: 0;
+ background-color: $pgbg_or_bgcolor;
+}
+
+ol#LC_PathBreadcrumbs {
+ margin: 0;
+}
+
+ol.LC_primary_menu li {
+ display: inline;
+ padding: 5px 5px 0 10px;
+ vertical-align: top;
+}
+
+ol.LC_primary_menu li img {
+ vertical-align: bottom;
+ height: 1.1em;
+}
+
+ol.LC_primary_menu a {
+ color: RGB(80, 80, 80);
+ text-decoration: none;
+}
+
+ol.LC_primary_menu a.LC_new_message {
+ font-weight:bold;
+ color: darkred;
+}
+
+ol.LC_docs_parameters {
+ margin-left: 0;
+ padding: 0;
+ list-style: none;
+}
+
+ol.LC_docs_parameters li {
+ margin: 0;
+ padding-right: 20px;
+ display: inline;
+}
+
+ol.LC_docs_parameters li:before {
+ content: "\\002022 \\0020";
+}
+
+li.LC_docs_parameters_title {
+ font-weight: bold;
+}
+
+ol.LC_docs_parameters li.LC_docs_parameters_title:before {
+ content: "";
+}
+
+ul#LC_secondary_menu {
clear: both;
- color: $tabbg;
- background-color: $tabbg;
- height: 3px;
- border: 0px;
+ color: $fontmenu;
+ background: $tabbg;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ width: 100%;
+ text-align: left;
+}
+
+ul#LC_secondary_menu 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: -1px -10px 0 -10px;
+ padding: 0;
+}
+
+ul.LC_TabContent li,
+ul.LC_TabContentBigger li {
+ float:left;
+}
+
+ul#LC_secondary_menu li a {
+ color: $fontmenu;
+ text-decoration: none;
+}
+
+ul.LC_TabContent {
+ min-height:20px;
+}
+
+ul.LC_TabContent li {
+ vertical-align:middle;
+ padding: 0 16px 0 10px;
+ background-color:$tabbg;
+ border-bottom:solid 1px $lg_border_color;
+ border-left: solid 1px $font;
+}
+
+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;
+ min-height:20px;
+}
+
+ul.LC_TabContent li a:hover,
+ul.LC_TabContent li a:focus {
+ color: $button_hover;
+ background:none;
+ outline:none;
+}
+
+ul.LC_TabContent li:hover {
+ color: $button_hover;
+ cursor:pointer;
+}
+
+ul.LC_TabContent li.active {
+ color: $font;
+ background:#FFFFFF url(/adm/lonIcons/open.gif) no-repeat scroll right center;
+ border-bottom:solid 1px #FFFFFF;
+ cursor: default;
+}
+
+ul.LC_TabContent li.active a {
+ color:$font;
+ background:#FFFFFF;
+ outline: none;
+}
+#maincoursedoc {
+ clear:both;
+}
+
+ul.LC_TabContentBigger {
+ display:block;
+ list-style:none;
+ padding: 0;
+}
+
+ul.LC_TabContentBigger li {
+ vertical-align:bottom;
+ height: 30px;
+ font-size:110%;
+ font-weight:bold;
+ color: #737373;
+}
+
+ul.LC_TabContentBigger li.active {
+ position: relative;
+ top: 1px;
+}
+
+ul.LC_TabContentBigger li a {
+ background:url('/adm/lonIcons/tabbgleft.gif') left bottom no-repeat;
+ height: 30px;
+ line-height: 30px;
+ text-align: center;
+ display: block;
+ text-decoration: none;
+ outline: none;
+}
+
+ul.LC_TabContentBigger li.active a {
+ background:url('/adm/lonIcons/tabbgleft.gif') left top no-repeat;
+ color:$font;
+}
+
+ul.LC_TabContentBigger li b {
+ background: url('/adm/lonIcons/tabbgright.gif') no-repeat right bottom;
+ display: block;
+ float: left;
+ padding: 0 30px;
+ border-bottom: 1px solid $lg_border_color;
+}
+
+ul.LC_TabContentBigger li:hover b {
+ color:$button_hover;
+}
+
+ul.LC_TabContentBigger li.active b {
+ background:url('/adm/lonIcons/tabbgright.gif') right top no-repeat;
+ color:$font;
+ border: 0;
+}
+
+
+ul.LC_CourseBreadcrumbs {
+ background: $sidebg;
+ height: 2em;
+ padding-left: 10px;
+ margin: 0;
+ list-style-position: inside;
+}
+
+ol#LC_MenuBreadcrumbs,
+ol#LC_PathBreadcrumbs {
+ padding-left: 10px;
+ margin: 0;
+ height: 2.5em; /* equal to #LC_breadcrumbs line-height */
+}
+
+ol#LC_MenuBreadcrumbs li,
+ol#LC_PathBreadcrumbs li,
+ul.LC_CourseBreadcrumbs li {
+ display: inline;
+ white-space: normal;
+}
+
+ol#LC_MenuBreadcrumbs li a,
+ul.LC_CourseBreadcrumbs li a {
+ text-decoration: none;
+ font-size:90%;
+}
+
+ol#LC_MenuBreadcrumbs h1 {
+ display: inline;
+ font-size: 90%;
+ line-height: 2.5em;
+ margin: 0;
+ padding: 0;
+}
+
+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_DocsBox {
+ border: solid 1px $lg_border_color;
+ padding: 0 0 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_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;
+}
+
+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_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_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 {
+ margin: 0;
+ padding: 0.5em 1em 0.5em 0;
+}
+
+ul.LC_funclist > li:first-child {
+ font-weight:bold;
+ margin-left:0.8em;
+}
+
+ul.LC_funclist + ul.LC_funclist {
+ /*
+ left border as a seperator if we have more than
+ one list
+ */
+ border-left: 1px solid $sidebg;
+ /*
+ this hides the left border behind the border of the
+ outer box if element is wrapped to the next 'line'
+ */
+ margin-left: -1px;
+}
+
+ul.LC_funclist li {
+ display: inline;
+ white-space: nowrap;
+ margin: 0 0 0 25px;
+ line-height: 150%;
+}
+
+.LC_hidden {
+ display: none;
}
+
END
}
@@ -5406,8 +6659,8 @@ sub headtag {
if (!$args->{'frameset'}) {
$result .= &Apache::lonhtmlcommon::htmlareaheaders();
}
- if ($args->{'force_register'}) {
- $result .= &Apache::lonmenu::registerurl(1);
+ if ($args->{'force_register'} && $env{'request.noversionuri'} !~ m{^/res/adm/pages/}) {
+ $result .= Apache::lonxml::display_title();
}
if (!$args->{'no_nav_bar'}
&& !$args->{'only_body'}
@@ -5433,7 +6686,7 @@ ADDMETA
$result .= ' LON-CAPA '.$title.' '
.' '
.$head_extra;
- return $result;
+ return $result.'';
}
=pod
@@ -5468,10 +6721,6 @@ Inputs: none
sub xml_begin {
my $output='';
- if ($env{'internal.start_page'}==1) {
- &Apache::lonhtmlcommon::init_htmlareafields();
- }
-
if ($env{'browser.mathml'}) {
$output=''
#.''."\n"
@@ -5482,50 +6731,14 @@ sub xml_begin {
.'';
} else {
- $output='';
+ $output=''
+ .'';
}
return $output;
}
=pod
-=item * &endheadtag()
-
-Returns a uniform for LON-CAPA web pages.
-
-Inputs: none
-
-=cut
-
-sub endheadtag {
- return '';
-}
-
-=pod
-
-=item * &head()
-
-Returns a uniform complete .. section for LON-CAPA web pages.
-
-Inputs:
-
-=over 4
-
-$title - optional title for the page
-
-$head_extra - optional extra HTML to put inside the
-
-=back
-
-=cut
-
-sub head {
- my ($title,$head_extra,$args) = @_;
- return &headtag($title,$head_extra,$args).&endheadtag();
-}
-
-=pod
-
=item * &start_page()
Returns a complete .. section for LON-CAPA web pages.
@@ -5544,7 +6757,7 @@ $args - additional optional args support
only_body -> is true will set &bodytag() onlybodytag
arg on
- no_nav_bar -> is true will set &bodytag() notopbar arg on
+ 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
@@ -5558,21 +6771,17 @@ $args - additional optional args support
a html attribute
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
rather than
- no_title -> if true the title bar won't be shown
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
- 'Switch To Inline Menu' link
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
+ bread_crumbs -> Array containing breadcrumbs
+ bread_crumbs_component -> if exists show it as headline else show only the breadcrumbs
=back
@@ -5583,6 +6792,14 @@ $args - additional optional args support
sub start_page {
my ($title,$head_extra,$args) = @_;
#&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
+#SD
+#I don't see why we copy certain elements of %$args to %head_args
+#head args is passed to headtag() and this routine only reads those
+#keys that are needed. There doesn't happen any writes or any processing
+#of other keys.
+#proposal: just pass $args to headtag instead of \%head_args and delete
+#marked lines
+#<- MARK
my %head_args;
foreach my $arg ('redirect','force_register','domain','function',
'bgcolor','frameset','no_nav_bar','only_body',
@@ -5591,13 +6808,16 @@ sub start_page {
$head_args{$arg} = $args->{$arg};
}
}
+#MARK ->
$env{'internal.start_page'}++;
my $result;
+
if (! exists($args->{'skip_phases'}{'head'}) ) {
- $result.=
- &xml_begin().
- &headtag($title,$head_extra,\%head_args).&endheadtag();
+ $result .=
+ &xml_begin() . &headtag($title,$head_extra,\%head_args);
+#replace prev line by
+# &xml_begin() . &headtag($title, $head_extra, $args);
}
if (! exists($args->{'skip_phases'}{'body'}) ) {
@@ -5605,48 +6825,51 @@ 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);
+ }
}
if ($args->{'js_ready'}) {
- $result = &js_ready($result);
+ $result = &js_ready($result);
}
if ($args->{'html_encode'}) {
- $result = &html_encode($result);
+ $result = &html_encode($result);
}
- return $result;
-}
-
-=pod
-
-=item * &head()
-
-Returns a complete section for LON-CAPA web pages.
-
-Inputs: $args - additional optional args supported are:
- js_ready -> return a string ready for being used in
- a javascript writeln
- html_encode -> return a string ready for being used in
- a html attribute
- frameset -> if true will start with a
- rather than
- dicsussion -> if true will get discussion from
- lonxml::xmlend
- (you can pass the target and parser arguments
- through optional 'target' and 'parser' args
- to this routine)
+ # 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 or in const space
+ return $result if $args->{'only_body'}
+ || $env{'request.state'} eq 'construct';
+
+ #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);
+ }
+ }
-=cut
+ #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;
+}
sub end_page {
my ($args) = @_;
@@ -5722,6 +6945,24 @@ sub validate_page {
}
}
+
+sub start_scrollbox {
+ my ($outerwidth,$width,$height,$id)=@_;
+ unless ($outerwidth) { $outerwidth='520px'; }
+ unless ($width) { $width='500px'; }
+ unless ($height) { $height='200px'; }
+ my ($table_id,$div_id);
+ if ($id ne '') {
+ $table_id = " id='table_$id'";
+ $div_id = " id='div_$id'";
+ }
+ return "";
+}
+
+sub end_scrollbox {
+ return '
';
+}
+
sub simple_error_page {
my ($r,$title,$msg) = @_;
my $page =
@@ -5737,31 +6978,48 @@ sub simple_error_page {
{
my @row_count;
+
+ sub start_data_table_count {
+ unshift(@row_count, 0);
+ return;
+ }
+
+ sub end_data_table_count {
+ shift(@row_count);
+ return;
+ }
+
sub start_data_table {
- my ($add_class) = @_;
+ my ($add_class,$id) = @_;
my $css_class = (join(' ','LC_data_table',$add_class));
- unshift(@row_count,0);
- return ''."\n";
+ my $table_id;
+ if (defined($id)) {
+ $table_id = ' id="'.$id.'"';
+ }
+ &start_data_table_count();
+ return ''."\n";
}
sub end_data_table {
- shift(@row_count);
+ &end_data_table_count();
return '
'."\n";;
}
sub start_data_table_row {
- my ($add_class) = @_;
+ my ($add_class, $id) = @_;
$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";;
+ $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+ $id = (' id="'.$id.'"') unless ($id eq '');
+ return ' '."\n";
}
sub continue_data_table_row {
- my ($add_class) = @_;
+ my ($add_class, $id) = @_;
my $css_class = ($row_count[0] % 2)?'LC_odd_row':'LC_even_row';
- $css_class = (join(' ',$css_class,$add_class));
- return ' '."\n";;
+ $css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+ $id = (' id="'.$id.'"') unless ($id eq '');
+ return ' '."\n";
}
sub end_data_table_row {
@@ -5769,7 +7027,7 @@ sub simple_error_page {
}
sub start_data_table_empty_row {
- $row_count[0]++;
+# $row_count[0]++;
return ' '."\n";;
}
@@ -5784,6 +7042,11 @@ sub simple_error_page {
sub end_data_table_header_row {
return ' '."\n";;
}
+
+ sub data_table_caption {
+ my $caption = shift;
+ return "$caption ";
+ }
}
=pod
@@ -5850,14 +7113,17 @@ Returns either 'student','coordinator','
###############################################
sub get_users_function {
- my $function = 'student';
- if ($env{'request.role'}=~/^(cc|in|ta|ep)/) {
+ my $function = 'norole';
+ if ($env{'request.role'}=~/^(st)/) {
+ $function='student';
+ }
+ if ($env{'request.role'}=~/^(cc|co|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';
}
@@ -5868,6 +7134,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
@@ -5884,13 +7182,14 @@ role status: active, previous or future.
sub check_user_status {
my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
- my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
+ my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
+ my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,$extra);
my @uroles = keys %userinfo;
my $srchstr;
my $active_chk = 'none';
my $now = time;
if (@uroles > 0) {
- if (($role eq 'cc') || ($sec eq '') || (!defined($sec))) {
+ if (($role eq 'cc') || ($role eq 'co') || ($sec eq '') || (!defined($sec))) {
$srchstr = '/'.$cdom.'/'.$crs.'_'.$role;
} else {
$srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role;
@@ -6371,6 +7670,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
###############################################
@@ -6383,21 +7684,37 @@ sub default_quota {
['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{'quotas'}{$item} ne '') {
- if ($defquota eq '') {
- $defquota = $quotahash{'quotas'}{$item};
- $settingstatus = $item;
- } elsif ($quotahash{'quotas'}{$item} > $defquota) {
- $defquota = $quotahash{'quotas'}{$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{'quotas'}{'default'};
+ if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') {
+ $defquota = $quotahash{'quotas'}{'defaultquota'}{'default'};
+ } else {
+ $defquota = $quotahash{'quotas'}{'default'};
+ }
$settingstatus = 'default';
}
} else {
@@ -6449,7 +7766,7 @@ sub get_secgrprole_info {
}
sub user_picker {
- my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype) = @_;
+ my ($dom,$srch,$forcenewuser,$caller,$cancreate,$usertype,$context) = @_;
my $currdom = $dom;
my %curr_selected = (
srchin => 'dom',
@@ -6503,6 +7820,7 @@ sub user_picker {
# loncreateuser::print_user_query_page()
# has been completed.
next if ($option eq 'alc');
+ next if (($option eq 'crs') && ($env{'form.form'} eq 'requestcrs'));
next if ($option eq 'crs' && !$env{'request.course.id'});
if ($curr_selected{'srchin'} eq $option) {
$srchinsel .= '
@@ -6539,19 +7857,29 @@ sub user_picker {
$srchtypesel .= "\n \n";
my ($newuserscript,$new_user_create);
-
+ my $context_dom = $env{'request.role.domain'};
+ if ($context eq 'requestcrs') {
+ if ($env{'form.coursedom'} ne '') {
+ $context_dom = $env{'form.coursedom'};
+ }
+ }
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'}) {
+ if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $context_dom) {
if ($cancreate) {
$new_user_create = ' &"').'" onclick="javascript:setSearch(\'1\','.$caller.');" />
';
} else {
- my $helplink = ' href="javascript:helpMenu('."'display'".')"';
+ 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('Contact the helpdesk for assistance.',$helplink).' ';
+ $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.'
+ ,'',' ')
+ .'
';
}
}
}
@@ -6576,7 +7904,7 @@ function setSearch(createnew,callingForm
}
}
for (var i=0; i
+//
$new_user_create
-
-
END_BLOCK
+ $output .= &Apache::lonhtmlcommon::start_pick_box().
+ &Apache::lonhtmlcommon::row_title($lt{'doma'}).
+ $domform.
+ &Apache::lonhtmlcommon::row_closure().
+ &Apache::lonhtmlcommon::row_title($lt{'usr'}).
+ $srchbysel.
+ $srchtypesel.
+ ' '.
+ $srchinsel.
+ &Apache::lonhtmlcommon::row_closure(1).
+ &Apache::lonhtmlcommon::end_pick_box().
+ ' ';
return $output;
}
@@ -6803,12 +8129,12 @@ sub instrule_disallow_msg {
$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).' ';
+ $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 ID/Student Number field.");
+ $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') {
@@ -6833,6 +8159,7 @@ sub personal_data_fieldtitles {
middlename => 'Middle Name',
generation => 'Generation',
gen => 'Generation',
+ inststatus => 'Affiliation',
);
return %fieldtitles;
}
@@ -6900,10 +8227,63 @@ sub get_institutional_codes {
return;
}
+sub get_standard_codeitems {
+ return ('Year','Semester','Department','Number','Section');
+}
+
=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
@@ -7042,68 +8422,307 @@ sub get_env_multiple {
sub ask_for_embedded_content {
my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
- my $upload_output = '
- ';
- return $upload_output;
+ $upload_output .= &embedded_file_element('upload_embedded',$num,
+ $embed_file,\%mapping,
+ $allfiles,$codebase);
+ $num++;
+ }
+ $upload_output .= ''.&Apache::loncommon::end_data_table_row()."\n";
+ }
+ foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%existing)) {
+ $upload_output .= &start_data_table_row().
+ ''.$embed_file.' '.
+ ''.&mt('Already exists').' '.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
+ if ($upload_output) {
+ $upload_output = &start_data_table().
+ $upload_output.
+ &end_data_table()."\n";
+ }
+ my $applies = 0;
+ if ($numremref) {
+ $applies ++;
+ }
+ if ($numinvalid) {
+ $applies ++;
+ }
+ if ($numexisting) {
+ $applies ++;
+ }
+ if ($num) {
+ $output = ''."\n";
+ } elsif ($numpathchg) {
+ my %pathchange = ();
+ $output .= &modify_html_form('pathchange',$actionurl,$state,\%pathchange,$pathchange_output);
+ if (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+ $output .= ''.&mt('or').'
';
+ }
+ }
+ return ($output,$num,$numpathchg);
+}
+
+sub embedded_file_element {
+ my ($context,$num,$embed_file,$mapping,$allfiles,$codebase) = @_;
+ return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
+ (ref($codebase) eq 'HASH'));
+ my $output;
+ if ($context eq 'upload_embedded') {
+ $output = ' '."\n";
+ }
+ $output .= ' ';
+ unless (($context eq 'upload_embedded') &&
+ ($mapping->{$embed_file} eq $embed_file)) {
+ $output .='
+ ';
+ }
+ my $attrib;
+ if (ref($allfiles->{$mapping->{$embed_file}}) eq 'ARRAY') {
+ $attrib = &escape(join(':',@{$allfiles->{$mapping->{$embed_file}}}));
+ }
+ $output .=
+ "\n\t\t".
+ ' ';
+ if (exists($codebase->{$mapping->{$embed_file}})) {
+ $output .=
+ "\n\t\t".
+ ' ';
+ }
+ return $output;
}
sub upload_embedded {
my ($context,$dirpath,$uname,$udom,$dir_root,$url_root,$group,$disk_quota,
- $current_disk_usage) = @_;
- my $output;
+ $current_disk_usage,$hiddenstate,$actionurl) = @_;
+ my (%pathchange,$output,$modifyform,$footer,$returnflag);
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});
+ foreach my $type ('orig','ref','attrib','codebase') {
+ if ($env{'form.embedded_'.$type.'_'.$i} ne '') {
+ $env{'form.embedded_'.$type.'_'.$i} =
+ &unescape($env{'form.embedded_'.$type.'_'.$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 '');
@@ -7115,12 +8734,12 @@ sub upload_embedded {
if ($group ne '') {
$port_path = "groups/$group/$port_path";
}
- ($state,$msg) = &check_for_upload($path,$fname,$group,'embedded_item_'.$i,
+ ($state,$msg) = &check_for_upload($env{'form.currentpath'}.$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' ) {
+ || $state eq 'file_locked') {
$output .= $msg;
next;
}
@@ -7134,31 +8753,53 @@ sub upload_embedded {
# 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);
+ $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);
+ $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);
+ $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);
+ my $result;
+ if ($state eq 'existingfile') {
+ $result=
+ &Apache::lonnet::userfileupload('embedded_item_'.$i,'existingfile',
+ $dirpath.$env{'form.currentpath'}.$path);
+ } else {
+ $result=
+ &Apache::lonnet::userfileupload('embedded_item_'.$i,'',
+ $dirpath.
+ $env{'form.currentpath'}.$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.' ').' ';
+ }
+ }
+ } elsif ($context eq 'coursedoc') {
+ my $result =
+ &Apache::lonnet::userfileupload('embedded_item_'.$i,'coursedoc',
+ $dirpath.'/'.$path);
if ($result !~ m|^/uploaded/|) {
$output .= ''
- .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
+ .&mt('An error occurred ([_1]) while trying to upload [_2] for embedded element [_3].'
,$result,$orig_uploaded_filename,$env{'form.embedded_orig_'.$i})
- .' ';
- next;
+ .' ';
+ next;
} else {
- $output .= ''.&mt('Uploaded [_1]',''.
- $path.$fname.' ').'
';
+ $output .= &mt('Uploaded [_1]',''.
+ $path.$fname.' ').' ';
}
} else {
# Save the file
@@ -7188,19 +8829,190 @@ sub upload_embedded {
&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.' ').' ';
+ $output .= &mt('Uploaded [_1]',''.
+ $url.' ').' ';
+ unless ($context eq 'testbank') {
+ $footer .= &mt('View embedded file: [_1]',
+ ''.$fname.' ').' ';
}
}
close($fh);
}
}
+ if ($env{'form.embedded_ref_'.$i}) {
+ $pathchange{$i} = 1;
+ }
+ }
+ if ($output) {
+ $output = ''.$output.'
';
+ }
+ $output .= &modify_html_form('upload_embedded',$actionurl,$hiddenstate,\%pathchange);
+ $returnflag = 'ok';
+ if (keys(%pathchange) > 0) {
+ if ($context eq 'portfolio') {
+ $output .= ''.&mt('or').'
';
+ } elsif ($context eq 'testbank') {
+ $output .= ''.&mt('Or [_1]continue[_2] the testbank import without modifying the reference(s).','',' ').'
';
+ $returnflag = 'modify_orightml';
+ }
+ }
+ return ($output.$footer,$returnflag);
+}
+
+sub modify_html_form {
+ my ($context,$actionurl,$hiddenstate,$pathchange,$pathchgtable) = @_;
+ my $end = 0;
+ my $modifyform;
+ if ($context eq 'upload_embedded') {
+ return unless (ref($pathchange) eq 'HASH');
+ if ($env{'form.number_embedded_items'}) {
+ $end += $env{'form.number_embedded_items'};
+ }
+ if ($env{'form.number_pathchange_items'}) {
+ $end += $env{'form.number_pathchange_items'};
+ }
+ if ($end) {
+ for (my $i=0; $i<$end; $i++) {
+ if ($i < $env{'form.number_embedded_items'}) {
+ next unless($pathchange->{$i});
+ }
+ $modifyform .=
+ &start_data_table_row().
+ ' '.
+ ''.$env{'form.embedded_ref_'.$i}.
+ ' '.
+ ' '.
+ ' '.
+ ''.$env{'form.embedded_orig_'.$i}.
+ ' '.
+ &end_data_table_row();
+ }
+ }
+ } else {
+ $modifyform = $pathchgtable;
+ if (($actionurl eq '/adm/upload') || ($actionurl eq '/adm/testbank')) {
+ $hiddenstate .= ' ';
+ } elsif (($actionurl eq '/adm/portfolio') || ($actionurl eq '/adm/coursegrp_portfolio')) {
+ $hiddenstate .= ' ';
+ }
+ }
+ if ($modifyform) {
+ return ''.&mt('Changes in content of HTML file required').' '."\n".
+ ''.&mt('Changes need to be made to the reference(s) used for one or more of the dependencies, if your HTML file is to work correctly:').'
'."\n".
+ ''.&mt('For consistency between the reference(s) and the location of the corresponding stored file within LON-CAPA.').' '."\n".
+ ''.&mt('To change absolute paths to relative paths, or replace directory traversal via "../" within the original reference.').' '."\n".
+ ' '."\n".''.
+ &mt('LON-CAPA can make the required changes to your HTML file.').'
'."\n".
+ ''."\n";
+ }
+ return;
+}
+
+sub modify_html_refs {
+ my ($context,$dirpath,$uname,$udom,$dir_root) = @_;
+ my $container;
+ if ($context eq 'portfolio') {
+ $container = $env{'form.container'};
+ } elsif ($context eq 'coursedoc') {
+ $container = $env{'form.primaryurl'};
+ } else {
+ $container = $env{'form.filename'};
+ $container =~ s{^/priv/(\Q$uname\E)/(.*)}{/home/$1/public_html/$2};
+ }
+ my (%allfiles,%codebase,$output,$content);
+ my @changes = &get_env_multiple('form.namechange');
+ return unless (@changes > 0);
+ if (($context eq 'portfolio') || ($context eq 'coursedoc')) {
+ return unless ($container =~ m{^/uploaded/\Q$udom\E/\Q$uname\E/});
+ $content = &Apache::lonnet::getfile($container);
+ return if ($content eq '-1');
+ } else {
+ return unless ($container =~ /^\Q$dir_root\E/);
+ if (open(my $fh,"<$container")) {
+ $content = join('', <$fh>);
+ close($fh);
+ } else {
+ return;
+ }
+ }
+ my ($count,$codebasecount) = (0,0);
+ my $mm = new File::MMagic;
+ my $mime_type = $mm->checktype_contents($content);
+ if ($mime_type eq 'text/html') {
+ my $parse_result =
+ &Apache::lonnet::extract_embedded_items($container,\%allfiles,
+ \%codebase,\$content);
+ if ($parse_result eq 'ok') {
+ foreach my $i (@changes) {
+ my $orig = &unescape($env{'form.embedded_orig_'.$i});
+ my $ref = &unescape($env{'form.embedded_ref_'.$i});
+ if ($allfiles{$ref}) {
+ my $newname = $orig;
+ my ($attrib_regexp,$codebase);
+ $attrib_regexp = &unescape($env{'form.embedded_attrib_'.$i});
+ if ($attrib_regexp =~ /:/) {
+ $attrib_regexp =~ s/\:/|/g;
+ }
+ if ($content =~ m{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}) {
+ my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
+ $count += $numchg;
+ }
+ if ($env{'form.embedded_codebase_'.$i} ne '') {
+ $codebase = &unescape($env{'form.embedded_codebase_'.$i});
+ my $numchg = ($content =~ s/(codebase\s*=\s*["']?)\Q$codebase\E(["']?)/$1.$2/i); #' stupid emacs
+ $codebasecount ++;
+ }
+ }
+ }
+ if ($count || $codebasecount) {
+ my $saveresult;
+ if ($context eq 'portfolio' || $context eq 'coursedoc') {
+ my $url = &Apache::lonnet::store_edited_file($container,$content,$udom,$uname,\$saveresult);
+ if ($url eq $container) {
+ my ($fname) = ($container =~ m{/([^/]+)$});
+ $output = ''.&mt('Updated [quant,_1,reference] in [_2].',
+ $count,''.
+ $fname.' ').'
';
+ } else {
+ $output = ''.
+ &mt('Error: update failed for: [_1].',
+ ''.
+ $container.' ').'
';
+ }
+ } else {
+ if (open(my $fh,">$container")) {
+ print $fh $content;
+ close($fh);
+ $output = ''.&mt('Updated [quant,_1,reference] in [_2].',
+ $count,''.
+ $container.' ').'
';
+ } else {
+ $output = ''.
+ &mt('Error: could not update [_1].',
+ ''.
+ $container.' ').'
';
+ }
+ }
+ }
+ } else {
+ &logthis('Failed to parse '.$container.
+ ' to modify references: '.$parse_result);
+ }
}
return $output;
}
@@ -7224,26 +9036,74 @@ sub check_for_existing {
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 $filesize = length($env{'form.'.$element});
+ if (!$filesize) {
+ my $msg = ''.
+ &mt('Unable to upload [_1]. (size = [_2] bytes)',
+ ''.$fname.' ',
+ $filesize).' '.
+ &mt('Either the file you attempted to upload was empty, or your web browser was unable to read its contents.').' '.
+ ' ';
+ return ('zero_bytes',$msg);
+ }
+ $filesize = $filesize/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;
+ my @lockers;
+ my $navmap;
+ if ($env{'request.course.id'}) {
+ $navmap = Apache::lonnavmaps::navmap->new();
+ }
foreach my $line (@dir_list) {
- my ($file_name)=split(/\&/,$line,2);
+ my ($file_name,$rest)=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 (&Apache::lonnet::is_locked($file_name,$udom,$uname,\@lockers) eq 'true') {
+ foreach my $lock (@lockers) {
+ if (ref($lock) eq 'ARRAY') {
+ my ($symb,$crsid) = @{$lock};
+ if ($crsid eq $env{'request.course.id'}) {
+ if (ref($navmap)) {
+ my $res = $navmap->getBySymb($symb);
+ foreach my $part (@{$res->parts()}) {
+ my ($slot_status,$slot_time,$slot_name)=$res->check_for_slot($part);
+ unless (($slot_status == $res->RESERVED) ||
+ ($slot_status == $res->RESERVED_LOCATION)) {
+ $locked_file = 1;
+ }
+ }
+ } else {
+ $locked_file = 1;
+ }
+ } else {
+ $locked_file = 1;
+ }
+ }
+ }
+ } else {
+ my @info = split(/\&/,$rest);
+ my $currsize = $info[6]/1000;
+ if ($currsize < $filesize) {
+ my $extra = $filesize - $currsize;
+ if (($current_disk_usage + $extra) > $disk_quota) {
+ my $msg = ''.
+ &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
+ ''.$fname.' ',$filesize,$currsize).' '.
+ ' '.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
+ $disk_quota,$current_disk_usage);
+ return ('will_exceed_quota',$msg);
+ }
+ }
}
}
}
- my $getpropath = 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).' '.
@@ -7258,15 +9118,162 @@ sub check_for_upload {
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 .= &mt(' A file by that name: [_1] 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);
+ return ('existingfile',$msg);
}
}
}
+sub check_for_traversal {
+ my ($path,$url,$toplevel) = @_;
+ my @parts=split(/\//,$path);
+ my $cleanpath;
+ my $fullpath = $url;
+ for (my $i=0;$i<@parts;$i++) {
+ next if ($parts[$i] eq '.');
+ if ($parts[$i] eq '..') {
+ $fullpath =~ s{([^/]+/)$}{};
+ } else {
+ $fullpath .= $parts[$i].'/';
+ }
+ }
+ if ($fullpath =~ /^\Q$url\E(.*)$/) {
+ $cleanpath = $1;
+ } elsif ($fullpath =~ /^\Q$toplevel\E(.*)$/) {
+ my $curr_toprel = $1;
+ my @parts = split(/\//,$curr_toprel);
+ my ($url_toprel) = ($url =~ /^\Q$toplevel\E(.*)$/);
+ my @urlparts = split(/\//,$url_toprel);
+ my $doubledots;
+ my $startdiff = -1;
+ for (my $i=0; $i<@urlparts; $i++) {
+ if ($startdiff == -1) {
+ unless ($urlparts[$i] eq $parts[$i]) {
+ $startdiff = $i;
+ $doubledots .= '../';
+ }
+ } else {
+ $doubledots .= '../';
+ }
+ }
+ if ($startdiff > -1) {
+ $cleanpath = $doubledots;
+ for (my $i=$startdiff; $i<@parts; $i++) {
+ $cleanpath .= $parts[$i].'/';
+ }
+ }
+ }
+ $cleanpath =~ s{(/)$}{};
+ return $cleanpath;
+}
+
+=pod
+
+=item * &get_turnedin_filepath()
+
+Determines path in a user's portfolio file for storage of files uploaded
+to a specific essayresponse or dropbox item.
+
+Inputs: 3 required + 1 optional.
+$symb is symb for resource, $uname and $udom are for current user (required).
+$caller is optional (can be "submission", if routine is called when storing
+an upoaded file when "Submit Answer" button was pressed).
+
+Returns array containing $path and $multiresp.
+$path is path in portfolio. $multiresp is 1 if this resource contains more
+than one file upload item. Callers of routine should append partid as a
+subdirectory to $path in cases where $multiresp is 1.
+
+Called by: homework/essayresponse.pm and homework/structuretags.pm
+
+=cut
+
+sub get_turnedin_filepath {
+ my ($symb,$uname,$udom,$caller) = @_;
+ my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb);
+ my $turnindir;
+ my %userhash = &Apache::lonnet::userenvironment($udom,$uname,'turnindir');
+ $turnindir = $userhash{'turnindir'};
+ my ($path,$multiresp);
+ if ($turnindir eq '') {
+ if ($caller eq 'submission') {
+ $turnindir = &mt('turned in');
+ $turnindir =~ s/\W+/_/g;
+ my %newhash = (
+ 'turnindir' => $turnindir,
+ );
+ &Apache::lonnet::put('environment',\%newhash,$udom,$uname);
+ }
+ }
+ if ($turnindir ne '') {
+ $path = '/'.$turnindir.'/';
+ my ($multipart,$turnin,@pathitems);
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (defined($navmap)) {
+ my $mapres = $navmap->getResourceByUrl($map);
+ if (ref($mapres)) {
+ my $pcslist = $mapres->map_hierarchy();
+ if ($pcslist ne '') {
+ foreach my $pc (split(/,/,$pcslist)) {
+ my $res = $navmap->getByMapPc($pc);
+ if (ref($res)) {
+ my $title = $res->compTitle();
+ $title =~ s/\W+/_/g;
+ if ($title ne '') {
+ push(@pathitems,$title);
+ }
+ }
+ }
+ }
+ my $maptitle = $mapres->compTitle();
+ $maptitle =~ s/\W+/_/g;
+ if ($maptitle ne '') {
+ push(@pathitems,$maptitle);
+ }
+ unless ($env{'request.state'} eq 'construct') {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ my $partlist = $res->parts();
+ my $totaluploads = 0;
+ if (ref($partlist) eq 'ARRAY') {
+ foreach my $part (@{$partlist}) {
+ my @types = $res->responseType($part);
+ my @ids = $res->responseIds($part);
+ for (my $i=0; $i < scalar(@ids); $i++) {
+ if ($types[$i] eq 'essay') {
+ my $partid = $part.'_'.$ids[$i];
+ if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') {
+ $totaluploads ++;
+ }
+ }
+ }
+ }
+ if ($totaluploads > 1) {
+ $multiresp = 1;
+ }
+ }
+ }
+ }
+ } else {
+ return;
+ }
+ } else {
+ return;
+ }
+ my $restitle=&Apache::lonnet::gettitle($symb);
+ $restitle =~ s/\W+/_/g;
+ if ($restitle eq '') {
+ $restitle = ($resurl =~ m{/[^/]+$});
+ if ($restitle eq '') {
+ $restitle = time;
+ }
+ }
+ push(@pathitems,$restitle);
+ $path .= join('/',@pathitems);
+ }
+ return ($path,$multiresp);
+}
=pod
@@ -7455,7 +9462,7 @@ sub upfile_select_html {
# xml => &mt('HTML/XML'),
);
my $Str = ' '.
- ' Type: ';
+ ' '.&mt('Type').': ';
foreach my $type (sort(keys(%Types))) {
$Str .= ''.$Types{$type}." \n";
}
@@ -7501,7 +9508,7 @@ sub csv_print_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(''.&mt('Column [_1]',($sample+1)).' '); }
$r->print(&end_data_table_header_row());
foreach my $hash (@$samples) {
$r->print(&start_data_table_row());
@@ -7543,9 +9550,9 @@ sub csv_print_select_table {
&end_data_table_header_row()."\n");
foreach my $array_ref (@$d) {
my ($value,$display,$defaultcol)=@{ $array_ref };
- $r->print(&start_data_table_row().''.$display.' ');
+ $r->print(&start_data_table_row().''.$display.' ');
- $r->print('print('');
$r->print(' ');
foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
@@ -8199,9 +10206,11 @@ sub restore_settings {
=item * &build_recipient_list()
-Build recipient lists for three types of e-mail:
-(a) Error Reports, (b) Package Updates, (c) Help requests, generated by
-lonerrorhandler.pm, CHECKRPMS and lonsupportreq.pm respectively.
+Build recipient lists for five types of e-mail:
+(a) Error Reports, (b) Package Updates, (c) lonstatus warnings/errors
+(d) Help requests, (e) Course requests needing approval, generated by
+lonerrorhandler.pm, CHECKRPMS, loncron, lonsupportreq.pm and
+loncoursequeueadmin.pm respectively.
Inputs:
defmail (scalar - email address of default recipient),
@@ -8225,23 +10234,29 @@ sub build_recipient_list {
my %domconfig =
&Apache::lonnet::get_dom('configuration',['contacts'],$defdom);
if (ref($domconfig{'contacts'}) eq 'HASH') {
- 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);
+ 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'};
}
- $otheremails = $domconfig{'contacts'}{$mailing}{'others'};
}
+ } elsif ($origmail ne '') {
+ push(@recipients,$origmail);
}
} elsif ($origmail ne '') {
push(@recipients,$origmail);
}
- if ($defmail ne '') {
- push(@recipients,$defmail);
+ if (defined($defmail)) {
+ if ($defmail ne '') {
+ push(@recipients,$defmail);
+ }
}
if ($otheremails) {
my @others;
@@ -8365,6 +10380,8 @@ sub extract_categories {
my $trailstr;
if ($name eq 'instcode') {
$trailstr = &mt('Official courses (with institutional codes)');
+ } elsif ($name eq 'communities') {
+ $trailstr = &mt('Communities');
} else {
$trailstr = $name;
}
@@ -8477,12 +10494,14 @@ cathash - reference to hash of categorie
currcat - scalar with an & separated list of categories assigned to a course.
+type - scalar contains course type (Course or Community).
+
Returns: $output (markup to be displayed)
=cut
sub assign_categories_table {
- my ($cathash,$currcat) = @_;
+ my ($cathash,$currcat,$type) = @_;
my $output;
if (ref($cathash) eq 'HASH') {
my (@cats,@trails,%allitems,%idx,@jsarray,@path,$maxdepth);
@@ -8491,33 +10510,47 @@ sub assign_categories_table {
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);
}
+ my $table;
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');
+ if ($type eq 'Community') {
+ next unless ($parent eq 'communities');
+ } else {
+ next if ($parent eq 'communities');
+ }
+ my $css_class = $itemcount%2?' class="LC_odd_row"':'';
my $item = &escape($parent).'::0';
my $checked = '';
if (@currcategories > 0) {
if (grep(/^\Q$item\E$/,@currcategories)) {
- $checked = ' checked="checked" ';
+ $checked = ' checked="checked"';
}
}
- $output .= ''
- .' '.$parent.' ';
+ my $parent_title = $parent;
+ if ($parent eq 'communities') {
+ $parent_title = &mt('Communities');
+ }
+ $table .= ''.
+ ' '.$parent_title.' '.
+ ' ';
my $depth = 1;
push(@path,$parent);
- $output .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);
+ $table .= &assign_category_rows($itemcount,\@cats,$depth,$parent,\@path,\@currcategories);
pop(@path);
- $output .= ' ';
+ $table .= ' ';
$itemcount ++;
}
- $output .= &Apache::loncommon::end_data_table();
+ if ($itemcount) {
+ $output = &Apache::loncommon::start_data_table().
+ $table.
+ &Apache::loncommon::end_data_table();
+ }
}
}
}
@@ -8569,13 +10602,15 @@ sub assign_category_rows {
if (ref($currcategories) eq 'ARRAY') {
if (@{$currcategories} > 0) {
if (grep(/^\Q$item\E$/,@{$currcategories})) {
- $checked = ' checked="checked" ';
+ $checked = ' checked="checked"';
}
}
}
$text .= ''.
' '.$name.' ';
+ $item.'"'.$checked.' />'.$name.''.
+ ' '.
+ ' ';
if (ref($path) eq 'ARRAY') {
push(@{$path},$name);
$text .= &assign_category_rows($itemcount,$cats,$deeper,$name,$path,$currcategories);
@@ -8760,12 +10795,26 @@ sub check_clone {
my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
my $clonemsg;
my $can_clone = 0;
-
+ my $lctype = lc($args->{'crstype'});
+ if ($lctype ne 'community') {
+ $lctype = 'course';
+ }
if ($clonehome eq 'no_host') {
- $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
+ if ($args->{'crstype'} eq 'Community') {
+ $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a non-existent community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
+ } else {
+ $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
+ }
} else {
my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1});
- if ($env{'request.role.domain'} eq $args->{'clonedomain'}) {
+ if ($args->{'crstype'} eq 'Community') {
+ if ($clonedesc{'type'} ne 'Community') {
+ $clonemsg = &mt('No new community created.').$linefeed.&mt('A new community could not be cloned from the specified original - [_1] - because it is a course not a community.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});
+ return ($can_clone, $clonemsg, $cloneid, $clonehome);
+ }
+ }
+ if (($env{'request.role.domain'} eq $args->{'clonedomain'}) &&
+ (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'}))) {
$can_clone = 1;
} else {
my %clonehash = &Apache::lonnet::get('environment',['cloners'],
@@ -8776,15 +10825,25 @@ sub check_clone {
} elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) {
$can_clone = 1;
} else {
+ my $ccrole = 'cc';
+ if ($args->{'crstype'} eq 'Community') {
+ $ccrole = 'co';
+ }
my %roleshash =
&Apache::lonnet::get_my_roles($args->{'ccuname'},
$args->{'ccdomain'},
- 'userroles',['active'],['cc'],
+ 'userroles',['active'],[$ccrole],
[$args->{'clonedomain'}]);
- if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
- $can_clone = 1;
- } else {
- $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
+ if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':'.$ccrole}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
+ $can_clone = 1;
+ } elsif (&Apache::lonnet::is_course_owner($args->{'clonedomain'},$args->{'clonecourse'},$args->{'ccuname'},$args->{'ccdomain'})) {
+ $can_clone = 1;
+ } else {
+ if ($args->{'crstype'} eq 'Community') {
+ $clonemsg = &mt('No new community created.').$linefeed.&mt('The new community could not be cloned from the existing community because the new community owner ([_1]) does not have cloning rights in the existing community ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
+ } else {
+ $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
+ }
}
}
}
@@ -8793,7 +10852,7 @@ sub check_clone {
}
sub construct_course {
- my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context) = @_;
+ my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context,$cnum,$category) = @_;
my $outcome;
my $linefeed = ' '."\n";
if ($context eq 'auto') {
@@ -8831,18 +10890,27 @@ sub construct_course {
$args->{'crscode'},
$args->{'ccuname'}.':'.
$args->{'ccdomain'},
- $args->{'crstype'});
+ $args->{'crstype'},
+ $cnum,$context,$category);
# Note: The testing routines depend on this being output; see
# Utils::Course. This needs to at least be output as a comment
# if anyone ever decides to not show this, and Utils::Course::new
# will need to be suitably modified.
$outcome .= &mt('New LON-CAPA [_1] ID: [_2]',$crstype,$$courseid).$linefeed;
+ if ($$courseid =~ /^error:/) {
+ return (0,$outcome);
+ }
+
#
# Check if created correctly
#
($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);
my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
+ if ($crsuhome eq 'no_host') {
+ $outcome .= &mt('Course creation failed, unrecognized course home server.').$linefeed;
+ return (0,$outcome);
+ }
$outcome .= &mt('Created on').': '.$crsuhome.$linefeed;
#
@@ -8861,6 +10929,10 @@ sub construct_course {
$cenv{'url'}=$oldcenv{'url'};
# Restore title
$cenv{'description'}=$oldcenv{'description'};
+# Restore creation date, creator and creation context.
+ $cenv{'internal.created'}=$oldcenv{'internal.created'};
+ $cenv{'internal.creator'}=$oldcenv{'internal.creator'};
+ $cenv{'internal.creationcontext'}=$oldcenv{'internal.creationcontext'};
# Mark as cloned
$cenv{'clonedfrom'}=$cloneid;
# Need to clone grading mode
@@ -8874,7 +10946,9 @@ sub construct_course {
'policy.email',
'comment.email',
'pch.users.denied',
- 'plc.users.denied'],
+ 'plc.users.denied',
+ 'hidefromcat',
+ 'categories'],
$$crsudom,$$crsunum);
}
@@ -9102,10 +11176,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('Table of Contents');
$url='/adm/navmaps';
}
@@ -9122,6 +11196,8 @@ sub construct_course {
############################################################
############################################################
+#SD
+# only Community and Course, or anything else?
sub course_type {
my ($cid) = @_;
if (!defined($cid)) {
@@ -9138,11 +11214,21 @@ sub group_term {
my $crstype = &course_type();
my %names = (
'Course' => 'group',
- 'Group' => 'team',
+ 'Community' => 'group',
);
return $names{$crstype};
}
+sub course_types {
+ my @types = ('official','unofficial','community');
+ my %typename = (
+ official => 'Official course',
+ unofficial => 'Unofficial course',
+ community => 'Community',
+ );
+ return (\@types,\%typename);
+}
+
sub icon {
my ($file)=@_;
my $curfext = lc((split(/\./,$file))[-1]);
@@ -9159,28 +11245,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 {
@@ -9216,7 +11288,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'};
@@ -9258,7 +11346,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
@@ -9270,40 +11358,22 @@ 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);
my ($tmp) = keys(%userenv);
if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
- # default remote control to off
- if ($userenv{'remote'} ne 'on') { $userenv{'remote'} = 'off'; }
} else {
undef(%userenv);
}
if (($userenv{'interface'}) && (!$form->{'interface'})) {
$form->{'interface'}=$userenv{'interface'};
}
- $env{'environment.remote'}=$userenv{'remote'};
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
@@ -9330,22 +11400,31 @@ sub init_user_environment {
$initial_env{"browser.localres"} = $form->{'localres'};
}
- if ($public) {
- $initial_env{"environment.remote"} = "off";
- }
if ($form->{'interface'}) {
$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";
- }
- }
}
+ my %is_adv = ( is_adv => $env{'user.adv'} );
+ my %domdef;
+ unless ($domain eq 'public') {
+ %domdef = &Apache::lonnet::get_domain_defaults($domain);
+ }
+
+ foreach my $tool ('aboutme','blog','portfolio') {
+ $userenv{'availabletools.'.$tool} =
+ &Apache::lonnet::usertools_access($username,$domain,$tool,'reload',
+ undef,\%userenv,\%domdef,\%is_adv);
+ }
+
+ foreach my $crstype ('official','unofficial','community') {
+ $userenv{'canrequest.'.$crstype} =
+ &Apache::lonnet::usertools_access($username,$domain,$crstype,
+ 'reload','requestcourses',
+ \%userenv,\%domdef,\%is_adv);
+ }
+
$env{'user.environment'} = "$lonids/$cookie.id";
if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",
@@ -9358,8 +11437,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: '.$!;
}
}
@@ -9373,12 +11452,84 @@ 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);
}
+sub build_release_hashes {
+ my ($checkparms,$checkresponsetypes,$checkcrstypes,$anonsurvey,$randomizetry) = @_;
+ return unless((ref($checkparms) eq 'HASH') && (ref($checkresponsetypes) eq 'HASH') &&
+ (ref($checkcrstypes) eq 'HASH') && (ref($anonsurvey) eq 'HASH') &&
+ (ref($randomizetry) eq 'HASH'));
+ foreach my $key (keys(%Apache::lonnet::needsrelease)) {
+ my ($item,$name,$value) = split(/:/,$key);
+ if ($item eq 'parameter') {
+ if (ref($checkparms->{$name}) eq 'ARRAY') {
+ unless(grep(/^\Q$name\E$/,@{$checkparms->{$name}})) {
+ push(@{$checkparms->{$name}},$value);
+ }
+ } else {
+ push(@{$checkparms->{$name}},$value);
+ }
+ } elsif ($item eq 'resourcetag') {
+ if ($name eq 'responsetype') {
+ $checkresponsetypes->{$value} = $Apache::lonnet::needsrelease{$key}
+ }
+ } elsif ($item eq 'course') {
+ if ($name eq 'crstype') {
+ $checkcrstypes->{$value} = $Apache::lonnet::needsrelease{$key};
+ }
+ }
+ }
+ ($anonsurvey->{major},$anonsurvey->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'});
+ ($randomizetry->{major},$randomizetry->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'});
+ return;
+}
=pod