File:  [LON-CAPA] / loncom / interface / lonannounce.pm
Revision 1.77: download - view: text, annotated - select for diffs
Thu Feb 26 16:17:29 2009 UTC (15 years, 2 months ago) by schafran
Branches: MAIN
CVS tags: HEAD
Box title is now the main title of the next page and the link text or the former page title will be set to the subtitle in the near future.
Group: consistent wording

# The LearningOnline Network
# Announce
#
# $Id: lonannounce.pm,v 1.77 2009/02/26 16:17:29 schafran Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#

package Apache::lonannounce;

use strict;
use Apache::Constants qw(:common);
use Apache::loncommon;
use Apache::lonhtmlcommon();
use Apache::lonlocal;
use Apache::lonnavmaps();
use Apache::lonrss();
use Apache::lonnet;
use HTML::Entities();
use LONCAPA qw(:match);
use DateTime;
use DateTime::TimeZone;

my %todayhash;
my %showedcheck;

sub editfield {
    my ($r,$start,$end,$text)=@_;
    # Deal with date forms
    my $startdateform = &Apache::lonhtmlcommon::date_setter('anno',
                                                            'startdate',
                                                            $start);
    my $enddateform = &Apache::lonhtmlcommon::date_setter('anno',
                                                          'enddate',
                                                          $end);
    #my $help=&Apache::loncommon::help_open_menu('Calendar Add Announcement','Calendar_Add_Announcement',274,'Communication Tools');
    my $help=&Apache::loncommon::help_open_topic('Calendar_Add_Announcement');
    
    my %lt=&Apache::lonlocal::texthash('annon' => 'Course Announcements',
                                       'post' => 'Post Announcement',
				       'start' => 'Starting date',
				       'end' => 'Ending date',
				       'incrss' => 'Include in course RSS newsfeed');

    $r->print(<<ENDFORM);
<h2>$lt{'annon'} $help</h2>
<form name="anno" method="post">
<input type="hidden" value='' name="action" />
<table><tr><td>$lt{'start'}:</td><td>$startdateform</td></tr>
<tr><td>$lt{'end'}:</td><td>$enddateform</td></tr></table>
<textarea name="msg" rows="4" cols="60">$text</textarea>
<br />
<label><input type="checkbox" name="rsspost" /> $lt{'incrss'}</label>
<br /><input type="button" onClick="trysubmit()" value="$lt{'post'}" /><hr />
ENDFORM
}

sub readcalendar {
    my $courseid=shift;
    my $coursenum=$env{'course.'.$courseid.'.num'};
    my $coursedom=$env{'course.'.$courseid.'.domain'};
    if ($coursenum eq '' || $coursedom eq '') {
        my %courseinfo=&Apache::lonnet::coursedescription($courseid);
        if ($coursenum eq '' && exists($courseinfo{'num'})) {
            $coursenum = $courseinfo{'num'};
        }
        if ($coursedom eq '' && exists($courseinfo{'domain'})) {
            $coursedom = $courseinfo{'domain'};
        }
    }

    my %thiscal=&Apache::lonnet::dump('calendar',$coursedom,$coursenum);
    my %returnhash=();
    foreach my $item (keys(%thiscal)) {
        unless (($item=~/^error\:/) || ($thiscal{$item}=~/^error\:/)) {
	    my ($start,$end)=split('_',$item);
	    $returnhash{join("\0",$courseid,$start,$end)}=$thiscal{$item};
        }
    }
    my $can_see_hidden = ($env{'request.role.adv'} &&
			  ($courseid eq $env{'request.course.id'}));
    
    my $navmap;
    if ($courseid eq $env{'request.course.id'}) {
	$navmap = Apache::lonnavmaps::navmap->new();
    }

    my $resourcedata=
	&Apache::lonnet::get_courseresdata($coursenum,$coursedom);
    if (ref($resourcedata) ne 'HASH') {
        return %returnhash;
    } 
    foreach my $thiskey (keys(%$resourcedata)) {
	if ($resourcedata->{$thiskey.'.type'}=~/^date/) {
	    my ($course,$middle,$part,$name)=
		($thiskey=~/^(\Q$courseid\E)\.(?:(.+)\.)*([\w\s]+)\.(\w+)$/);

	    my %data = ( 'section' => &mt('All Students'));
	    if ($middle=~/^\[(.*)\]\./) {
		my $sec=$1;
		# if we have a section don't show ones that aren't ours
		if ($env{'request.course.sec'} &&
		    $env{'request.course.sec'} ne $sec) { next; }
		# if a student without a section don't show any section ones
		if (!$env{'request.role.adv'} &&
		    !$env{'request.course.sec'}) { next; }
		$data{'section'}=&mt('Group/Section').': '.$1;
		$middle=~s/^\[(.*)\]\.//;
	    }
	    $middle=~s/\.$//;
	    $data{'realm'}=&mt('All Resources');
	    if ($middle eq '___(all)') {
		if (!$can_see_hidden && !$navmap) {
		    next;
		}
	    } elsif ($middle=~/^(.+)\_\_\_\(all\)$/) {
		my $map_url=$1;
		if (!$can_see_hidden && !$navmap) {
		    next;
		}
		if (!$can_see_hidden) {
		    my $res = $navmap->getResourceByUrl($map_url);
		    if ($res && $res->randomout()) {
			next;
		    }
		}
		$data{'realm'}=&mt('Folder/Map');
		$data{'url'} = $map_url;
	    } elsif ($middle) {
		if (!$can_see_hidden && !$navmap) {
		    next;
		}
		if (!$can_see_hidden) {
		    my $res = $navmap->getBySymb($middle);
		    if ($res && $res->randomout()) {
			next;
		    }
		}
		$data{'realm'} = &mt('Resource');
		$data{'symb'} = $middle;
	    }
	    $data{'datetype'} = $name;
	    if ($name eq 'duedate') { 
		$data{'datetype'} = &mt('Due'); 
# see if accidentally answerdate is before duedate
		my $answerkey=$thiskey;
		$answerkey=~s/duedate$/answerdate/;
		if ($resourcedata->{$thiskey}>$resourcedata->{$answerkey}) {
		    $data{'datetype'} = &mt('Due and Answer Available');
		}
	    }
	    if ($name eq 'opendate' 
		|| $name eq 'contentopen' ) {
		$data{'datetype'}=&mt('Opening');
	    }
	    if ($name eq 'contentclose') {
		$data{'datetype'}=&mt('Closing');
	    }
	    if ($name eq 'answerdate') {
# see if accidentally answerdate is before duedate
		my $duekey=$thiskey;
		$duekey=~s/answerdate$/duedate/;
		if ($resourcedata->{$duekey}>$resourcedata->{$thiskey}) {
# forget it
		    next;
		} 
		$data{'datetype'}=&mt('Answer Available'); 
	    }
	    $returnhash{join("\0",$courseid,
			     $resourcedata->{$thiskey},
			     $resourcedata->{$thiskey})}=\%data;
	}
    }
    return %returnhash;
}

sub emptycell {
    return '<td class="LC_calendar_day_empty">&nbsp;</td>';
}

sub normalcell {
    my ($day,$month,$year,$items_ref)=@_;
    my $output;
    my @items=&order($items_ref);
    foreach my $item (@items) {
        if ($item) {
	    my ($courseid,$start,$end,$msg)=@$item;
	    my $internalflag= (ref($msg)) ? 1 : 0;
	    $msg = &display_msg($msg);
            my $fullmsg=&mt('Calendar Announcement for ').$env{'course.'.$courseid.'.description'}.
		'\n'.&Apache::lonlocal::locallocaltime($start);
	    if ($start!=$end) {
		$fullmsg.=' - '.&Apache::lonlocal::locallocaltime($end);
	    }
	    $fullmsg.=':\n'.$msg;
	    $fullmsg=~s/[\n\r]/\\n/gs;
            $fullmsg=&HTML::Entities::encode($fullmsg,'<>&"\'');
            $fullmsg=~s/&/\\&/g;
	    my $short_msg = substr($msg,0,20).((length($msg) > 20)?'...':'');
	    if (defined($output)) { $output.='<br />'; }
            if ($courseid eq $env{'request.course.id'}) {
              if ((&Apache::lonnet::allowed('srm',$env{'request.course.id'}))
               && (!$showedcheck{$start.'_'.$end})
	       && ($env{'form.pickdate'} ne 'yes')
	       && (!$internalflag)) {
               $output.='<input type="checkbox" name="remove_'.$start.'_'.
		   $end.'">';
               $showedcheck{$start.'_'.$end}=1;
	      }
	    }
            $output.='<a href="javascript:alert('."'$fullmsg'".')">'.
	       $short_msg.'</a>';
       }
    }
    return '<td class="LC_calendar_day'.
	((($day eq $todayhash{'day'}) &&
          ($month eq $todayhash{'month'}) &&
          ($year eq $todayhash{'year'}))?'_current':'').
           '" ><b>'.&picklink($day,$day,$month,$year).'</b><br />'.$output.'</td>';
}

sub plaincell {
    my ($items_ref)=@_;
    my $output;
    my @items=&order($items_ref);
    foreach my $item (@items) {
        if (ref($item)) {
	    my ($courseid,$start,$end,$msg)=@$item;
            my $fullmsg=&mt('Calendar Announcement for ').$env{'course.'.$courseid.'.description'}.
		'\n'.&Apache::lonlocal::locallocaltime($start);
	    if ($start!=$end) {
		$fullmsg.=' - '.&Apache::lonlocal::locallocaltime($end);
	    }
	    $msg = &display_msg($msg);
	    $fullmsg.=':\n'.$msg;
 	    $fullmsg=~s/[\n\r]/\\n/gs;
            $fullmsg=&HTML::Entities::encode($fullmsg,'<>&"\'');
            $fullmsg=~s/&/\\&/g;
	    my $short_msg = substr($msg,0,80).((length($msg) > 80)?'...':'');
	    if (defined($output)) { $output.='<br />'; }
            $output.='<a href="javascript:alert('."'$fullmsg'".')">'.
	       $short_msg.'</a>';
       }
    }
    return $output;
}

sub listcell {
    my ($items_ref)=@_;
    my $output='';
    my @items=&order($items_ref);
    foreach my $item (@items) {
        if (ref($item)) {
	    my ($courseid,$start,$end,$msg)=@$item;
	    my $fullmsg=&Apache::lonlocal::locallocaltime($start);
	    if ($start!=$end) {
		$fullmsg.=&mt(' to ').
		    &Apache::lonlocal::locallocaltime($end);
	    }
            $fullmsg.=':<br /><b>'.&display_msg($msg).'</b>';
            $output.='<li>'.$fullmsg.'</li>';
       }
    }
    return $output;
}

sub order {
    my ($items)=@_;
    return sort {
	my ($astart,$aend)=$a->[1,2];
	my ($bstart,$bend)=$b->[1,2];
	if ($astart != $bstart) {
	    return $astart <=> $bstart;
	}
	return $aend <=> $bend;
    } @$items;
}

sub nextday {
    my ($tk,%th)=@_;
    my ($incmonth,$incyear);
    if ($th{'day'} > 27) {
        if ($th{'month'} == 2) {
            if ($th{'day'} == 29) { 
                $incmonth = 1;
            } elsif ($th{'day'} == 28) {
                if (!&is_leap_year($tk)) {
                   $incmonth = 1;
                }
            }
        } elsif (($th{'month'} == 4) || ($th{'month'} == 6) || 
                 ($th{'month'} == 9) || ($th{'month'} == 11)) {
            if ($th{'day'} == 30) {
                $incmonth = 1;
            }
        } elsif ($th{'day'} == 31) {
            if ($th{'month'} == 12) {
                $incyear = 1;
            } else {
                $incmonth = 1;
            }
        }
        if ($incyear) {
            $th{'day'} = 1;
            $th{'month'} = 1;
            $th{'year'}++;
        } elsif ($incmonth) {
            $th{'day'} = 1;
            $th{'month'}++;
        } else {
            $th{'day'}++;
        }
    } else {
        $th{'day'}++;
    }
    return (&Apache::loncommon::maketime(%th),$th{'month'});
}

sub is_leap_year {
    my ($thistime) = @_;
    my ($is_leap,$timezone,$dt);
    $timezone = &Apache::lonlocal::gettimezone();
    eval {
        $dt = DateTime->from_epoch(epoch => $thistime)
                      ->set_time_zone($timezone);
    };
    if (!$@) {
        $is_leap = $dt->is_leap_year;
    }
    return $is_leap;
}

sub display_msg {
    my ($msg) = @_;

    # if it's not a ref, it's an instructor provided message
    return $msg if (!ref($msg));

    my $output = $msg->{'datetype'}. ': '.$msg->{'realm'};
    if (exists($msg->{'url'})) {
	my $displayurl=&Apache::lonnet::gettitle($msg->{'url'});
	if ($msg->{'url'}!~/\Q$displayurl\E$/) {
	    $output .= ' - '.$displayurl;
	}
    }
    if (exists($msg->{'symb'})) {
	my $displaysymb=&Apache::lonnet::gettitle($msg->{'symb'});
	if ($msg->{'symb'}!~/\Q$displaysymb\E$/) {
	    $output .= ' - '.$displaysymb;
	}
    }
    $output .= ' ('.$msg->{'section'}.') ';
    return $output;
}

sub showday {
    my ($tk,$mode,%allcal)=@_;
    my %th=&Apache::loncommon::timehash($tk);
    my ($nextday,$nextmonth)=&nextday($tk,%th);
    my @outp;
    if ($mode) {
	my $oneday=24*3600;
	$tk-=$oneday;
	$nextday+=$oneday;
    }
    foreach my $item (keys(%allcal)) {
	my ($courseid,$startdate,$enddate)= split("\0",$item);
	if (($startdate<$nextday) && ($enddate>=$tk))  {
	    push(@outp,[$courseid,$startdate,$enddate,$allcal{$item}]);
        }
    }
    unless ($mode) {
       return ($nextday,$nextmonth,&normalcell(
               $th{'day'},$th{'month'},$th{'year'},\@outp));
   } elsif (@outp) {
       if ($mode==1) {
          return '<br />'.&plaincell(\@outp);
      } else {
          return '<ul>'.&listcell(\@outp).'</ul>';
      }
   } else {
       return '';
   }
}

sub picklink {
    my ($text,$day,$month,$year)=@_;
    if ($env{'form.pickdate'} eq 'yes') {
	return '<a href="javascript:dialin('.$day.','.$month.','.$year.')">'.
	    $text.'</a>';
    } else {
	return $text;
    }
}

sub dialscript {
    return (<<ENDDIA);
<script language="Javascript">
function dialin(day,month,year) {
	opener.document.$env{'form.formname'}.$env{'form.element'}\_year.value=year;
    var slct=opener.document.$env{'form.formname'}.$env{'form.element'}\_month;
    var i;
    for (i=0;i<slct.length;i++) {
        if (slct.options[i].value==month) { slct.selectedIndex=i; }
    }
    opener.document.$env{'form.formname'}.$env{'form.element'}\_day.value=day;
    opener.$env{'form.element'}\_checkday();
    self.close();
}
</script>
ENDDIA
}
# ----------------------------------------------------- Summarize all calendars
sub get_all_calendars {
    my %allcal=();
    my %courses = &Apache::loncommon::findallcourses();
    foreach my $course (sort(keys(%courses))) {
	%allcal=(%allcal,&readcalendar($course));
    }
    return %allcal;
}

sub output_ics_file {
    my ($r)=@_;
# RFC 2445 wants CRLF
    my $crlf="\015\012";
# Header
    $r->print("BEGIN:VCALENDAR$crlf");
    $r->print("VERSION:2.0$crlf");
    $r->print("PRODID:-//LONCAPA//LONCAPA Calendar Output//EN$crlf");
    my %allcal=&get_all_calendars();
    foreach my $event (keys(%allcal)) {
	my ($courseid,$startdate,$enddate)= split('\0',$event);
	my $uid=$event;
	$uid=~s/[\W\_]/-/gs;
	$uid.='@loncapa';
	my $summary=&display_msg($allcal{$event});
	$summary=~s/\s+/ /gs;
        $summary=$env{'course.'.$courseid.'.description'}.': '.$summary;
	$r->print("BEGIN:VEVENT$crlf");
	$r->print("DTSTART:".&Apache::loncommon::utc_string($startdate).$crlf);
	$r->print("DTEND:".&Apache::loncommon::utc_string($enddate).$crlf);
	$r->print("SUMMARY:$summary$crlf");
	$r->print("UID:$uid$crlf");
	$r->print("END:VEVENT$crlf");
    }
# Footer
    $r->print("END:VCALENDAR$crlf");
}

sub show_timezone {
    my $tzone = &Apache::lonlocal::gettimezone();
    my $dt = DateTime->now();
    my $tz = DateTime::TimeZone->new( name => $tzone );
    return &mt('([_1] time zone)',$tz->short_name_for_datetime($dt));
}

sub handler {
    my $r = shift;
    if ($r->uri=~/\.(ics|ical)$/) {
        &Apache::loncommon::content_type($r,'text/calendar');
	&output_ics_file($r);
	return OK;
    }
    &Apache::loncommon::content_type($r,'text/html');
    $r->send_http_header;
    return OK if $r->header_only;

# ---------------------------------------------------------- Get time right now
    my $today=time;
    %todayhash=&Apache::loncommon::timehash($today);
# ----------------------------------------------------------------- Check marks
    undef(%showedcheck);
# ---------------------------------------------------------- Get month and year
    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                             ['month','year','pickdate','formname','element']);
# --------------------------------------------------- Decide what month to show
    my $year=$todayhash{'year'};
    if ($env{'form.year'}) { $year=$env{'form.year'}; }
    my $month=$todayhash{'month'};
    if ($env{'form.month'}) { $month=$env{'form.month'}; }

# ---------------------------------------------- See if we are in pickdate mode
    my $pickdatemode=($env{'form.pickdate'} eq 'yes');
    my $pickinfo='&pickdate=yes&formname='.$env{'form.formname'}.
	'&element='.$env{'form.element'};
# --------------------------------------------- Find out first day of the month

    my $tk = &Apache::loncommon::maketime( 'day' => 1,
                                           'month'=> $month,
                                           'year' => $year, 
                                           'hour' => 0,
				           'minute' => 0, 
                                           'second' => 0);
    my %firstday = &Apache::loncommon::timehash($tk);
    my $weekday=$firstday{'weekday'};

# ------------------------------------------------------------ Print the screen
    my $js = <<ENDDOCUMENT;
<script type="text/javascript">

    function trysubmit() {
        document.anno.action.value="new";
	document.anno.submit();
    }

    function removesub() {
        document.anno.action.value="del";
	document.anno.submit();
    }
</script>
ENDDOCUMENT

    if ($pickdatemode) {
# no big header in pickdate mode
	$r->print(&Apache::loncommon::start_page("Pick a Date",$js,
						 {'only_body' => 1,}).
		  &dialscript().
		  '<font size="1">');
    } else {
        my $brcrum = [{href=>"/adm/announcements",text=>"Announcements and Calendar"}];
        $r->print(&Apache::loncommon::start_page("Communication",$js,{'bread_crumbs' => $brcrum}));
    }
# does this user have privileges to post, etc?
    my $allowed=0;
    if ($env{'request.course.id'}) {
       $allowed=&Apache::lonnet::allowed('srm',$env{'request.course.id'});
    }
# does this user have privileges to post to servers?
    my $serverpost=0;
    if ($env{'request.role.domain'}) {
	$serverpost=&Apache::lonnet::allowed('psa',
					     $env{'request.role.domain'});
    } else {
	$serverpost=&Apache::lonnet::allowed('psa','/');
    }
# -------------------------------- BUT: do no fancy stuff when in pickdate mode
    if ($pickdatemode) { 
	$serverpost=0; 
	$allowed=0;
    }
# ------------------------------------------------------------ Process commands
    if ($serverpost) {
	if ($env{'form.serveraction'}) {
	    foreach my $key (keys(%env)) {
		if ($key=~/^form\.postto\_(\w+)/) {
		    $r->print( 
			'<br />Posting '.$1.': '.&Apache::lonnet::postannounce
			($1,$env{'form.serverannnounce'}));
		}
	    }
	}
	$r->print('<form name="serveranno" method="post">'
                 .'<h2>'.&mt('Post Server Announcements').'</h2>'
                 .&mt('Post announcements to the system login and roles screen').'<br />'
                 .'<i>'.&mt('(leave blank to delete announcement)').'</i><br />'
                 .'<textarea name="serverannnounce" cols="60" rows="5"></textarea><br />'
                 .&mt('Check machines:').'<br />'
        );
# list servers
    my %hostname = &Apache::lonnet::all_hostnames();
    foreach my $host (sort(keys(%hostname))) {
	if (&Apache::lonnet::allowed('psa',
				     &Apache::lonnet::host_domain($host))) {
	    $r->print ('<label><input type="checkbox" name="postto_'.$host.'" /> '.
		       $host.' <tt>'.$hostname{$host}.'</tt> '.
		       '</label><a href="http://'.$hostname{$host}.
		       '/announcement.txt?time='.time.'" target="annowin">'.
                       &mt('Current Announcement').'</a><br />');
	}
    }
    $r->print(
  '<br /><input type="submit" name="serveraction" value="'.&mt('Post').'"></form><hr />');
    }
    if ($allowed) {
        my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
        my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
# ----------------------------------------------------- Store new submitted one
        if ($env{'form.action'} eq 'new') {
	    my $startdate = 
		&Apache::lonhtmlcommon::get_date_from_form('startdate');
	    my $enddate   = 
		&Apache::lonhtmlcommon::get_date_from_form('enddate');
	    unless ($startdate=~/^\d+$/) { $startdate=time; }
            unless ($enddate=~/^\d+$/) { $enddate=$startdate+1; }
            if ($startdate>$enddate) {
		my $buffer=$startdate;
		$startdate=$enddate;
		$enddate=$buffer;
            }
	    &Apache::lonnet::put('calendar',{ 
		$startdate.'_'.$enddate => 
		    $env{'form.msg'} },$coursedom,$coursenum);
	    if ($env{'form.rsspost'}) {
               &Apache::lonrss::addentry($coursenum,$coursedom,'Course_Announcements',
					 &mt('Event from [_1] to [_2]',
					     &Apache::lonlocal::locallocaltime($startdate),
					     &Apache::lonlocal::locallocaltime($enddate)),
					 $env{'form.msg'},'/adm/announcements','public');
	   }
        }
# ---------------------------------------------------------------- Remove items
        if ($env{'form.action'} eq 'del') {
	    my @delwhich=();
            foreach my $key (keys(%env)) {
		if ($key=~/^form\.remove\_(.+)$/) {
		    push(@delwhich,$1);
                }
            }
            &Apache::lonnet::del('calendar',\@delwhich,$coursedom,$coursenum);
        }
# -------------------------------------------------------- Form to post new one
        my %tomorrowhash=%todayhash;
        $tomorrowhash{'day'}++;
        my $tomorrow=&Apache::loncommon::maketime(%tomorrowhash);
        
        &editfield($r,$today,$tomorrow,'');
    }
# ----------------------------------------------------- Summarize all calendars
    my %allcal=&get_all_calendars();
# ------------------------------- Initialize table and forward backward buttons
    my ($pm,$py,$fm,$fy)=($month-1,$year,$month+1,$year);
    if ($pm<1) { ($pm,$py)=(12,$year-1); }
    if ($fm>12){ ($fm,$fy)=(1,$year+1); }

    $r->print('<h2>'.&mt('Calendar').'</h2>'
             .'<h3>'.('',&mt('January'),&mt('February'),&mt('March'),
		      &mt('April'),&mt('May'),
		      &mt('June'),&mt('July'),&mt('August'),
                      &mt('September'),&mt('October'),
                      &mt('November'),&mt('December'))[$month].' '.
	              $year.' '.&show_timezone().'</h3>');
# Reached the end of times, give up
    if (($year<1970) || ($year>2037)) {
	$r->print('<p class="LC_warning">'
                 .&mt('No calendar available for this date.')
                 .'</p>'
                 .'<a href="/adm/announcements?month='.$todayhash{'month'}
                 .'&year='.$todayhash{'year'}.'">'.&mt('Current Month').'</a>'
		 .&Apache::loncommon::end_page());
	return OK;
    }

    my $class = "LC_calendar";
    if ($env{'form.pickdate'} eq 'yes') {
	$class .= " LC_calendar_pickdate";
    }
# ------------------------------------------------ Determine first day of a week
    my $datelocale =  &Apache::lonlocal::getdatelocale();
    my $days_in_week = 7;
    my $startweek = 0;
    if (ref($datelocale)) {
        $startweek = $datelocale->first_day_of_week();
        if ($startweek == $days_in_week)  { $startweek = 0; }
    }
    my @days = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
    my @localdays;
    if ($startweek == 0) {
        @localdays = @days;
    } else {
        my $endday = $days_in_week - $startweek;
        for (my $i=0; $i<$days_in_week; $i++) {
            if ($i < $endday) {
                $localdays[$i] = $days[$i+$startweek];
            } else {
                $localdays[$i] = $days[$i-$endday];
            }
        }
    }

# ----------------------------------------------------------- Weekday in locale
    my $loc_weekday = $weekday - $startweek;
    if ($loc_weekday < 0) {
        $loc_weekday += $days_in_week; 
    }

    $r->print(
 '<a href="/adm/announcements?month='.$pm.'&year='.$py.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Previous Month').'</a> '.
 '<a href="/adm/announcements?month='.$fm.'&year='.$fy.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Next Month').'</a>'.
 '&nbsp;&nbsp;&nbsp;<a href="/adm/announcements?month='.$todayhash{'month'}.
 '&year='.$todayhash{'year'}.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Current Month').'</a><p>'.
        '<table class="'.$class.'" cols="7" rows="5"><tr>');
    for (my $i=0; $i<@localdays; $i++) {
        $r->print('<th>'.&mt($localdays[$i]).'</th>');
    }
    $r->print('</tr>');

    my $outp;
    my $nm;

# ---------------------------------------------------------------- Actual table
    $r->print('<tr>');
    for (my $i=0;$i<$loc_weekday;$i++) { $r->print(&emptycell); }
    for (my $i=$loc_weekday;$i<=6;$i++) {
        ($tk,$nm,$outp)=&showday($tk,0,%allcal);
        $r->print($outp);
    }
    $r->print('</tr>');

    my $lastrow = 0;
    my $lastday = 0;
    for (my $k=0;$k<=4;$k++) {
        if (!$lastrow) {
            $r->print('<tr>');
            for (my $i=0;$i<=6;$i++) {
                if ($lastday) {
                    $outp = &emptycell();
                } else {
                    my $currtk = $tk;
                    ($tk,$nm,$outp)=&showday($tk,0,%allcal);
                    if ($month!=$nm) { $lastday = 1; }
                }
                $r->print($outp);
            }
            if ($lastday) {
                $lastrow = 1;
            }
            $r->print('</tr>');
        }
    }
# ------------------------------------------------------------------- End table
    $r->print('</table>');
# ----------------------------------------------------------------- Check marks
    undef(%showedcheck);
# --------------------------------------------------------------- Remove button
    if ($allowed) { $r->print('<br /><input type="button" onClick="removesub()" value="'.&mt('Remove Checked Entries').'">'.
			      &Apache::loncommon::help_open_topic('Calendar_Remove_Announcement').'</form>'); }
    $r->print('<p>'.
 '<a href="/adm/announcements?month='.$pm.'&year='.$py.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Previous Month').'</a> '.
 '<a href="/adm/announcements?month='.$fm.'&year='.$fy.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Next Month').'</a>'.
 '&nbsp;&nbsp;&nbsp;<a href="/adm/announcements?month='.$todayhash{'month'}.
 '&year='.$todayhash{'year'}.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Current Month').'</a></p>'.
 ($pickdatemode?'</font>':'').&Apache::loncommon::end_page());
    $r->print('<a href="/adm/announcements.ics">'.&mt('Download your Calendar as iCalendar File').'</a>');
    return OK;
} 

1;
__END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>