File:  [LON-CAPA] / loncom / interface / lonannounce.pm
Revision 1.88: download - view: text, annotated - select for diffs
Thu Feb 16 18:17:49 2017 UTC (7 years, 10 months ago) by damieng
Branches: MAIN
CVS tags: version_2_12_X, version_2_11_X, version_2_11_5_msu, version_2_11_5, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, HEAD
fixed bug 6846 (bad regexp to match part id)

# The LearningOnline Network
# Announce
#
# $Id: lonannounce.pm,v 1.88 2017/02/16 18:17:49 damieng 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,$crstype)=@_;
    # 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');
    if ($crstype eq 'Community') {
        $lt{'annon'} = &mt('Community Announcements');
        $lt{'incrss'} = &mt('Include in community RSS newsfeed');
    }

    $r->print(<<ENDFORM);
<h2>$lt{'annon'} $help</h2>
<form name="anno" method="post" action="">
<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 type="text/javascript" language="JavaScript">
// <![CDATA[
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='&amp;pickdate=yes&amp;formname='.$env{'form.formname'}.
	'&amp;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" language="JavaScript">
// <![CDATA[

    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'}) {
            my $rc;
            my $message;
            foreach my $key (keys(%env)) {
                if ($key=~/^form\.postto\_(\w+[\w\-]*)/) {
                     $rc = &Apache::lonnet::postannounce
                           ($1,$env{'form.serverannnounce'});
                    if ($rc eq 'ok') {
                        $message .= 
                            &Apache::lonhtmlcommon::confirm_success(
                                &mt('Announcement posted to [_1]',$1))
                               .'<br />';
                    } else {
                        $message .=
                            &Apache::lonhtmlcommon::confirm_success(
                                &mt('Posting announcement to [_1] failed: [_2]'
                                    ,$1,$rc), 1)
                               .'<br />';
                    }
                }
            }
            $r->print(&Apache::loncommon::confirmwrapper($message));
        }
	$r->print('<form name="serveranno" method="post" action="">'
                 .'<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'};
        my $crstype = &Apache::loncommon::course_type();
# ----------------------------------------------------- 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'}) {
               my $feed;
               if ($crstype eq 'Community') {
                   $feed = 'Community_Announcements';
               } else {
                   $feed = 'Course_Announcements';
               }
               &Apache::lonrss::addentry($coursenum,$coursedom,$feed,
					 &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,'',$crstype);
    }
# ----------------------------------------------------- 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'}
                 .'&amp;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.'&amp;year='.$py.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Previous Month').'</a> '.
 '<a href="/adm/announcements?month='.$fm.'&amp;year='.$fy.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Next Month').'</a>'.
 '&nbsp;&nbsp;&nbsp;<a href="/adm/announcements?month='.$todayhash{'month'}.
 '&amp;year='.$todayhash{'year'}.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Current Month').'</a><div>'.
        '<table class="'.$class.'"><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></div>');
# ----------------------------------------------------------------- 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.'&amp;year='.$py.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Previous Month').'</a> '.
 '<a href="/adm/announcements?month='.$fm.'&amp;year='.$fy.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Next Month').'</a>'.
 '&nbsp;&nbsp;&nbsp;<a href="/adm/announcements?month='.$todayhash{'month'}.
 '&amp;year='.$todayhash{'year'}.
 ($pickdatemode?$pickinfo:'').'">'.&mt('Current Month').'</a></p>'.
 ($pickdatemode?'</font>':'').
 '<a href="/adm/announcements.ics">'.&mt('Download your Calendar as iCalendar File').'</a>'.
    &Apache::loncommon::end_page());
    return OK;
} 

1;
__END__

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