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, 4 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

    1: # The LearningOnline Network
    2: # Announce
    3: #
    4: # $Id: lonannounce.pm,v 1.77 2009/02/26 16:17:29 schafran Exp $
    5: #
    6: # Copyright Michigan State University Board of Trustees
    7: #
    8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    9: #
   10: # LON-CAPA is free software; you can redistribute it and/or modify
   11: # it under the terms of the GNU General Public License as published by
   12: # the Free Software Foundation; either version 2 of the License, or
   13: # (at your option) any later version.
   14: #
   15: # LON-CAPA is distributed in the hope that it will be useful,
   16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18: # GNU General Public License for more details.
   19: #
   20: # You should have received a copy of the GNU General Public License
   21: # along with LON-CAPA; if not, write to the Free Software
   22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23: #
   24: # /home/httpd/html/adm/gpl.txt
   25: #
   26: # http://www.lon-capa.org/
   27: #
   28: 
   29: package Apache::lonannounce;
   30: 
   31: use strict;
   32: use Apache::Constants qw(:common);
   33: use Apache::loncommon;
   34: use Apache::lonhtmlcommon();
   35: use Apache::lonlocal;
   36: use Apache::lonnavmaps();
   37: use Apache::lonrss();
   38: use Apache::lonnet;
   39: use HTML::Entities();
   40: use LONCAPA qw(:match);
   41: use DateTime;
   42: use DateTime::TimeZone;
   43: 
   44: my %todayhash;
   45: my %showedcheck;
   46: 
   47: sub editfield {
   48:     my ($r,$start,$end,$text)=@_;
   49:     # Deal with date forms
   50:     my $startdateform = &Apache::lonhtmlcommon::date_setter('anno',
   51:                                                             'startdate',
   52:                                                             $start);
   53:     my $enddateform = &Apache::lonhtmlcommon::date_setter('anno',
   54:                                                           'enddate',
   55:                                                           $end);
   56:     #my $help=&Apache::loncommon::help_open_menu('Calendar Add Announcement','Calendar_Add_Announcement',274,'Communication Tools');
   57:     my $help=&Apache::loncommon::help_open_topic('Calendar_Add_Announcement');
   58:     
   59:     my %lt=&Apache::lonlocal::texthash('annon' => 'Course Announcements',
   60:                                        'post' => 'Post Announcement',
   61: 				       'start' => 'Starting date',
   62: 				       'end' => 'Ending date',
   63: 				       'incrss' => 'Include in course RSS newsfeed');
   64: 
   65:     $r->print(<<ENDFORM);
   66: <h2>$lt{'annon'} $help</h2>
   67: <form name="anno" method="post">
   68: <input type="hidden" value='' name="action" />
   69: <table><tr><td>$lt{'start'}:</td><td>$startdateform</td></tr>
   70: <tr><td>$lt{'end'}:</td><td>$enddateform</td></tr></table>
   71: <textarea name="msg" rows="4" cols="60">$text</textarea>
   72: <br />
   73: <label><input type="checkbox" name="rsspost" /> $lt{'incrss'}</label>
   74: <br /><input type="button" onClick="trysubmit()" value="$lt{'post'}" /><hr />
   75: ENDFORM
   76: }
   77: 
   78: sub readcalendar {
   79:     my $courseid=shift;
   80:     my $coursenum=$env{'course.'.$courseid.'.num'};
   81:     my $coursedom=$env{'course.'.$courseid.'.domain'};
   82:     if ($coursenum eq '' || $coursedom eq '') {
   83:         my %courseinfo=&Apache::lonnet::coursedescription($courseid);
   84:         if ($coursenum eq '' && exists($courseinfo{'num'})) {
   85:             $coursenum = $courseinfo{'num'};
   86:         }
   87:         if ($coursedom eq '' && exists($courseinfo{'domain'})) {
   88:             $coursedom = $courseinfo{'domain'};
   89:         }
   90:     }
   91: 
   92:     my %thiscal=&Apache::lonnet::dump('calendar',$coursedom,$coursenum);
   93:     my %returnhash=();
   94:     foreach my $item (keys(%thiscal)) {
   95:         unless (($item=~/^error\:/) || ($thiscal{$item}=~/^error\:/)) {
   96: 	    my ($start,$end)=split('_',$item);
   97: 	    $returnhash{join("\0",$courseid,$start,$end)}=$thiscal{$item};
   98:         }
   99:     }
  100:     my $can_see_hidden = ($env{'request.role.adv'} &&
  101: 			  ($courseid eq $env{'request.course.id'}));
  102:     
  103:     my $navmap;
  104:     if ($courseid eq $env{'request.course.id'}) {
  105: 	$navmap = Apache::lonnavmaps::navmap->new();
  106:     }
  107: 
  108:     my $resourcedata=
  109: 	&Apache::lonnet::get_courseresdata($coursenum,$coursedom);
  110:     if (ref($resourcedata) ne 'HASH') {
  111:         return %returnhash;
  112:     } 
  113:     foreach my $thiskey (keys(%$resourcedata)) {
  114: 	if ($resourcedata->{$thiskey.'.type'}=~/^date/) {
  115: 	    my ($course,$middle,$part,$name)=
  116: 		($thiskey=~/^(\Q$courseid\E)\.(?:(.+)\.)*([\w\s]+)\.(\w+)$/);
  117: 
  118: 	    my %data = ( 'section' => &mt('All Students'));
  119: 	    if ($middle=~/^\[(.*)\]\./) {
  120: 		my $sec=$1;
  121: 		# if we have a section don't show ones that aren't ours
  122: 		if ($env{'request.course.sec'} &&
  123: 		    $env{'request.course.sec'} ne $sec) { next; }
  124: 		# if a student without a section don't show any section ones
  125: 		if (!$env{'request.role.adv'} &&
  126: 		    !$env{'request.course.sec'}) { next; }
  127: 		$data{'section'}=&mt('Group/Section').': '.$1;
  128: 		$middle=~s/^\[(.*)\]\.//;
  129: 	    }
  130: 	    $middle=~s/\.$//;
  131: 	    $data{'realm'}=&mt('All Resources');
  132: 	    if ($middle eq '___(all)') {
  133: 		if (!$can_see_hidden && !$navmap) {
  134: 		    next;
  135: 		}
  136: 	    } elsif ($middle=~/^(.+)\_\_\_\(all\)$/) {
  137: 		my $map_url=$1;
  138: 		if (!$can_see_hidden && !$navmap) {
  139: 		    next;
  140: 		}
  141: 		if (!$can_see_hidden) {
  142: 		    my $res = $navmap->getResourceByUrl($map_url);
  143: 		    if ($res && $res->randomout()) {
  144: 			next;
  145: 		    }
  146: 		}
  147: 		$data{'realm'}=&mt('Folder/Map');
  148: 		$data{'url'} = $map_url;
  149: 	    } elsif ($middle) {
  150: 		if (!$can_see_hidden && !$navmap) {
  151: 		    next;
  152: 		}
  153: 		if (!$can_see_hidden) {
  154: 		    my $res = $navmap->getBySymb($middle);
  155: 		    if ($res && $res->randomout()) {
  156: 			next;
  157: 		    }
  158: 		}
  159: 		$data{'realm'} = &mt('Resource');
  160: 		$data{'symb'} = $middle;
  161: 	    }
  162: 	    $data{'datetype'} = $name;
  163: 	    if ($name eq 'duedate') { 
  164: 		$data{'datetype'} = &mt('Due'); 
  165: # see if accidentally answerdate is before duedate
  166: 		my $answerkey=$thiskey;
  167: 		$answerkey=~s/duedate$/answerdate/;
  168: 		if ($resourcedata->{$thiskey}>$resourcedata->{$answerkey}) {
  169: 		    $data{'datetype'} = &mt('Due and Answer Available');
  170: 		}
  171: 	    }
  172: 	    if ($name eq 'opendate' 
  173: 		|| $name eq 'contentopen' ) {
  174: 		$data{'datetype'}=&mt('Opening');
  175: 	    }
  176: 	    if ($name eq 'contentclose') {
  177: 		$data{'datetype'}=&mt('Closing');
  178: 	    }
  179: 	    if ($name eq 'answerdate') {
  180: # see if accidentally answerdate is before duedate
  181: 		my $duekey=$thiskey;
  182: 		$duekey=~s/answerdate$/duedate/;
  183: 		if ($resourcedata->{$duekey}>$resourcedata->{$thiskey}) {
  184: # forget it
  185: 		    next;
  186: 		} 
  187: 		$data{'datetype'}=&mt('Answer Available'); 
  188: 	    }
  189: 	    $returnhash{join("\0",$courseid,
  190: 			     $resourcedata->{$thiskey},
  191: 			     $resourcedata->{$thiskey})}=\%data;
  192: 	}
  193:     }
  194:     return %returnhash;
  195: }
  196: 
  197: sub emptycell {
  198:     return '<td class="LC_calendar_day_empty">&nbsp;</td>';
  199: }
  200: 
  201: sub normalcell {
  202:     my ($day,$month,$year,$items_ref)=@_;
  203:     my $output;
  204:     my @items=&order($items_ref);
  205:     foreach my $item (@items) {
  206:         if ($item) {
  207: 	    my ($courseid,$start,$end,$msg)=@$item;
  208: 	    my $internalflag= (ref($msg)) ? 1 : 0;
  209: 	    $msg = &display_msg($msg);
  210:             my $fullmsg=&mt('Calendar Announcement for ').$env{'course.'.$courseid.'.description'}.
  211: 		'\n'.&Apache::lonlocal::locallocaltime($start);
  212: 	    if ($start!=$end) {
  213: 		$fullmsg.=' - '.&Apache::lonlocal::locallocaltime($end);
  214: 	    }
  215: 	    $fullmsg.=':\n'.$msg;
  216: 	    $fullmsg=~s/[\n\r]/\\n/gs;
  217:             $fullmsg=&HTML::Entities::encode($fullmsg,'<>&"\'');
  218:             $fullmsg=~s/&/\\&/g;
  219: 	    my $short_msg = substr($msg,0,20).((length($msg) > 20)?'...':'');
  220: 	    if (defined($output)) { $output.='<br />'; }
  221:             if ($courseid eq $env{'request.course.id'}) {
  222:               if ((&Apache::lonnet::allowed('srm',$env{'request.course.id'}))
  223:                && (!$showedcheck{$start.'_'.$end})
  224: 	       && ($env{'form.pickdate'} ne 'yes')
  225: 	       && (!$internalflag)) {
  226:                $output.='<input type="checkbox" name="remove_'.$start.'_'.
  227: 		   $end.'">';
  228:                $showedcheck{$start.'_'.$end}=1;
  229: 	      }
  230: 	    }
  231:             $output.='<a href="javascript:alert('."'$fullmsg'".')">'.
  232: 	       $short_msg.'</a>';
  233:        }
  234:     }
  235:     return '<td class="LC_calendar_day'.
  236: 	((($day eq $todayhash{'day'}) &&
  237:           ($month eq $todayhash{'month'}) &&
  238:           ($year eq $todayhash{'year'}))?'_current':'').
  239:            '" ><b>'.&picklink($day,$day,$month,$year).'</b><br />'.$output.'</td>';
  240: }
  241: 
  242: sub plaincell {
  243:     my ($items_ref)=@_;
  244:     my $output;
  245:     my @items=&order($items_ref);
  246:     foreach my $item (@items) {
  247:         if (ref($item)) {
  248: 	    my ($courseid,$start,$end,$msg)=@$item;
  249:             my $fullmsg=&mt('Calendar Announcement for ').$env{'course.'.$courseid.'.description'}.
  250: 		'\n'.&Apache::lonlocal::locallocaltime($start);
  251: 	    if ($start!=$end) {
  252: 		$fullmsg.=' - '.&Apache::lonlocal::locallocaltime($end);
  253: 	    }
  254: 	    $msg = &display_msg($msg);
  255: 	    $fullmsg.=':\n'.$msg;
  256:  	    $fullmsg=~s/[\n\r]/\\n/gs;
  257:             $fullmsg=&HTML::Entities::encode($fullmsg,'<>&"\'');
  258:             $fullmsg=~s/&/\\&/g;
  259: 	    my $short_msg = substr($msg,0,80).((length($msg) > 80)?'...':'');
  260: 	    if (defined($output)) { $output.='<br />'; }
  261:             $output.='<a href="javascript:alert('."'$fullmsg'".')">'.
  262: 	       $short_msg.'</a>';
  263:        }
  264:     }
  265:     return $output;
  266: }
  267: 
  268: sub listcell {
  269:     my ($items_ref)=@_;
  270:     my $output='';
  271:     my @items=&order($items_ref);
  272:     foreach my $item (@items) {
  273:         if (ref($item)) {
  274: 	    my ($courseid,$start,$end,$msg)=@$item;
  275: 	    my $fullmsg=&Apache::lonlocal::locallocaltime($start);
  276: 	    if ($start!=$end) {
  277: 		$fullmsg.=&mt(' to ').
  278: 		    &Apache::lonlocal::locallocaltime($end);
  279: 	    }
  280:             $fullmsg.=':<br /><b>'.&display_msg($msg).'</b>';
  281:             $output.='<li>'.$fullmsg.'</li>';
  282:        }
  283:     }
  284:     return $output;
  285: }
  286: 
  287: sub order {
  288:     my ($items)=@_;
  289:     return sort {
  290: 	my ($astart,$aend)=$a->[1,2];
  291: 	my ($bstart,$bend)=$b->[1,2];
  292: 	if ($astart != $bstart) {
  293: 	    return $astart <=> $bstart;
  294: 	}
  295: 	return $aend <=> $bend;
  296:     } @$items;
  297: }
  298: 
  299: sub nextday {
  300:     my ($tk,%th)=@_;
  301:     my ($incmonth,$incyear);
  302:     if ($th{'day'} > 27) {
  303:         if ($th{'month'} == 2) {
  304:             if ($th{'day'} == 29) { 
  305:                 $incmonth = 1;
  306:             } elsif ($th{'day'} == 28) {
  307:                 if (!&is_leap_year($tk)) {
  308:                    $incmonth = 1;
  309:                 }
  310:             }
  311:         } elsif (($th{'month'} == 4) || ($th{'month'} == 6) || 
  312:                  ($th{'month'} == 9) || ($th{'month'} == 11)) {
  313:             if ($th{'day'} == 30) {
  314:                 $incmonth = 1;
  315:             }
  316:         } elsif ($th{'day'} == 31) {
  317:             if ($th{'month'} == 12) {
  318:                 $incyear = 1;
  319:             } else {
  320:                 $incmonth = 1;
  321:             }
  322:         }
  323:         if ($incyear) {
  324:             $th{'day'} = 1;
  325:             $th{'month'} = 1;
  326:             $th{'year'}++;
  327:         } elsif ($incmonth) {
  328:             $th{'day'} = 1;
  329:             $th{'month'}++;
  330:         } else {
  331:             $th{'day'}++;
  332:         }
  333:     } else {
  334:         $th{'day'}++;
  335:     }
  336:     return (&Apache::loncommon::maketime(%th),$th{'month'});
  337: }
  338: 
  339: sub is_leap_year {
  340:     my ($thistime) = @_;
  341:     my ($is_leap,$timezone,$dt);
  342:     $timezone = &Apache::lonlocal::gettimezone();
  343:     eval {
  344:         $dt = DateTime->from_epoch(epoch => $thistime)
  345:                       ->set_time_zone($timezone);
  346:     };
  347:     if (!$@) {
  348:         $is_leap = $dt->is_leap_year;
  349:     }
  350:     return $is_leap;
  351: }
  352: 
  353: sub display_msg {
  354:     my ($msg) = @_;
  355: 
  356:     # if it's not a ref, it's an instructor provided message
  357:     return $msg if (!ref($msg));
  358: 
  359:     my $output = $msg->{'datetype'}. ': '.$msg->{'realm'};
  360:     if (exists($msg->{'url'})) {
  361: 	my $displayurl=&Apache::lonnet::gettitle($msg->{'url'});
  362: 	if ($msg->{'url'}!~/\Q$displayurl\E$/) {
  363: 	    $output .= ' - '.$displayurl;
  364: 	}
  365:     }
  366:     if (exists($msg->{'symb'})) {
  367: 	my $displaysymb=&Apache::lonnet::gettitle($msg->{'symb'});
  368: 	if ($msg->{'symb'}!~/\Q$displaysymb\E$/) {
  369: 	    $output .= ' - '.$displaysymb;
  370: 	}
  371:     }
  372:     $output .= ' ('.$msg->{'section'}.') ';
  373:     return $output;
  374: }
  375: 
  376: sub showday {
  377:     my ($tk,$mode,%allcal)=@_;
  378:     my %th=&Apache::loncommon::timehash($tk);
  379:     my ($nextday,$nextmonth)=&nextday($tk,%th);
  380:     my @outp;
  381:     if ($mode) {
  382: 	my $oneday=24*3600;
  383: 	$tk-=$oneday;
  384: 	$nextday+=$oneday;
  385:     }
  386:     foreach my $item (keys(%allcal)) {
  387: 	my ($courseid,$startdate,$enddate)= split("\0",$item);
  388: 	if (($startdate<$nextday) && ($enddate>=$tk))  {
  389: 	    push(@outp,[$courseid,$startdate,$enddate,$allcal{$item}]);
  390:         }
  391:     }
  392:     unless ($mode) {
  393:        return ($nextday,$nextmonth,&normalcell(
  394:                $th{'day'},$th{'month'},$th{'year'},\@outp));
  395:    } elsif (@outp) {
  396:        if ($mode==1) {
  397:           return '<br />'.&plaincell(\@outp);
  398:       } else {
  399:           return '<ul>'.&listcell(\@outp).'</ul>';
  400:       }
  401:    } else {
  402:        return '';
  403:    }
  404: }
  405: 
  406: sub picklink {
  407:     my ($text,$day,$month,$year)=@_;
  408:     if ($env{'form.pickdate'} eq 'yes') {
  409: 	return '<a href="javascript:dialin('.$day.','.$month.','.$year.')">'.
  410: 	    $text.'</a>';
  411:     } else {
  412: 	return $text;
  413:     }
  414: }
  415: 
  416: sub dialscript {
  417:     return (<<ENDDIA);
  418: <script language="Javascript">
  419: function dialin(day,month,year) {
  420: 	opener.document.$env{'form.formname'}.$env{'form.element'}\_year.value=year;
  421:     var slct=opener.document.$env{'form.formname'}.$env{'form.element'}\_month;
  422:     var i;
  423:     for (i=0;i<slct.length;i++) {
  424:         if (slct.options[i].value==month) { slct.selectedIndex=i; }
  425:     }
  426:     opener.document.$env{'form.formname'}.$env{'form.element'}\_day.value=day;
  427:     opener.$env{'form.element'}\_checkday();
  428:     self.close();
  429: }
  430: </script>
  431: ENDDIA
  432: }
  433: # ----------------------------------------------------- Summarize all calendars
  434: sub get_all_calendars {
  435:     my %allcal=();
  436:     my %courses = &Apache::loncommon::findallcourses();
  437:     foreach my $course (sort(keys(%courses))) {
  438: 	%allcal=(%allcal,&readcalendar($course));
  439:     }
  440:     return %allcal;
  441: }
  442: 
  443: sub output_ics_file {
  444:     my ($r)=@_;
  445: # RFC 2445 wants CRLF
  446:     my $crlf="\015\012";
  447: # Header
  448:     $r->print("BEGIN:VCALENDAR$crlf");
  449:     $r->print("VERSION:2.0$crlf");
  450:     $r->print("PRODID:-//LONCAPA//LONCAPA Calendar Output//EN$crlf");
  451:     my %allcal=&get_all_calendars();
  452:     foreach my $event (keys(%allcal)) {
  453: 	my ($courseid,$startdate,$enddate)= split('\0',$event);
  454: 	my $uid=$event;
  455: 	$uid=~s/[\W\_]/-/gs;
  456: 	$uid.='@loncapa';
  457: 	my $summary=&display_msg($allcal{$event});
  458: 	$summary=~s/\s+/ /gs;
  459:         $summary=$env{'course.'.$courseid.'.description'}.': '.$summary;
  460: 	$r->print("BEGIN:VEVENT$crlf");
  461: 	$r->print("DTSTART:".&Apache::loncommon::utc_string($startdate).$crlf);
  462: 	$r->print("DTEND:".&Apache::loncommon::utc_string($enddate).$crlf);
  463: 	$r->print("SUMMARY:$summary$crlf");
  464: 	$r->print("UID:$uid$crlf");
  465: 	$r->print("END:VEVENT$crlf");
  466:     }
  467: # Footer
  468:     $r->print("END:VCALENDAR$crlf");
  469: }
  470: 
  471: sub show_timezone {
  472:     my $tzone = &Apache::lonlocal::gettimezone();
  473:     my $dt = DateTime->now();
  474:     my $tz = DateTime::TimeZone->new( name => $tzone );
  475:     return &mt('([_1] time zone)',$tz->short_name_for_datetime($dt));
  476: }
  477: 
  478: sub handler {
  479:     my $r = shift;
  480:     if ($r->uri=~/\.(ics|ical)$/) {
  481:         &Apache::loncommon::content_type($r,'text/calendar');
  482: 	&output_ics_file($r);
  483: 	return OK;
  484:     }
  485:     &Apache::loncommon::content_type($r,'text/html');
  486:     $r->send_http_header;
  487:     return OK if $r->header_only;
  488: 
  489: # ---------------------------------------------------------- Get time right now
  490:     my $today=time;
  491:     %todayhash=&Apache::loncommon::timehash($today);
  492: # ----------------------------------------------------------------- Check marks
  493:     undef(%showedcheck);
  494: # ---------------------------------------------------------- Get month and year
  495:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
  496:                              ['month','year','pickdate','formname','element']);
  497: # --------------------------------------------------- Decide what month to show
  498:     my $year=$todayhash{'year'};
  499:     if ($env{'form.year'}) { $year=$env{'form.year'}; }
  500:     my $month=$todayhash{'month'};
  501:     if ($env{'form.month'}) { $month=$env{'form.month'}; }
  502: 
  503: # ---------------------------------------------- See if we are in pickdate mode
  504:     my $pickdatemode=($env{'form.pickdate'} eq 'yes');
  505:     my $pickinfo='&pickdate=yes&formname='.$env{'form.formname'}.
  506: 	'&element='.$env{'form.element'};
  507: # --------------------------------------------- Find out first day of the month
  508: 
  509:     my $tk = &Apache::loncommon::maketime( 'day' => 1,
  510:                                            'month'=> $month,
  511:                                            'year' => $year, 
  512:                                            'hour' => 0,
  513: 				           'minute' => 0, 
  514:                                            'second' => 0);
  515:     my %firstday = &Apache::loncommon::timehash($tk);
  516:     my $weekday=$firstday{'weekday'};
  517: 
  518: # ------------------------------------------------------------ Print the screen
  519:     my $js = <<ENDDOCUMENT;
  520: <script type="text/javascript">
  521: 
  522:     function trysubmit() {
  523:         document.anno.action.value="new";
  524: 	document.anno.submit();
  525:     }
  526: 
  527:     function removesub() {
  528:         document.anno.action.value="del";
  529: 	document.anno.submit();
  530:     }
  531: </script>
  532: ENDDOCUMENT
  533: 
  534:     if ($pickdatemode) {
  535: # no big header in pickdate mode
  536: 	$r->print(&Apache::loncommon::start_page("Pick a Date",$js,
  537: 						 {'only_body' => 1,}).
  538: 		  &dialscript().
  539: 		  '<font size="1">');
  540:     } else {
  541:         my $brcrum = [{href=>"/adm/announcements",text=>"Announcements and Calendar"}];
  542:         $r->print(&Apache::loncommon::start_page("Communication",$js,{'bread_crumbs' => $brcrum}));
  543:     }
  544: # does this user have privileges to post, etc?
  545:     my $allowed=0;
  546:     if ($env{'request.course.id'}) {
  547:        $allowed=&Apache::lonnet::allowed('srm',$env{'request.course.id'});
  548:     }
  549: # does this user have privileges to post to servers?
  550:     my $serverpost=0;
  551:     if ($env{'request.role.domain'}) {
  552: 	$serverpost=&Apache::lonnet::allowed('psa',
  553: 					     $env{'request.role.domain'});
  554:     } else {
  555: 	$serverpost=&Apache::lonnet::allowed('psa','/');
  556:     }
  557: # -------------------------------- BUT: do no fancy stuff when in pickdate mode
  558:     if ($pickdatemode) { 
  559: 	$serverpost=0; 
  560: 	$allowed=0;
  561:     }
  562: # ------------------------------------------------------------ Process commands
  563:     if ($serverpost) {
  564: 	if ($env{'form.serveraction'}) {
  565: 	    foreach my $key (keys(%env)) {
  566: 		if ($key=~/^form\.postto\_(\w+)/) {
  567: 		    $r->print( 
  568: 			'<br />Posting '.$1.': '.&Apache::lonnet::postannounce
  569: 			($1,$env{'form.serverannnounce'}));
  570: 		}
  571: 	    }
  572: 	}
  573: 	$r->print('<form name="serveranno" method="post">'
  574:                  .'<h2>'.&mt('Post Server Announcements').'</h2>'
  575:                  .&mt('Post announcements to the system login and roles screen').'<br />'
  576:                  .'<i>'.&mt('(leave blank to delete announcement)').'</i><br />'
  577:                  .'<textarea name="serverannnounce" cols="60" rows="5"></textarea><br />'
  578:                  .&mt('Check machines:').'<br />'
  579:         );
  580: # list servers
  581:     my %hostname = &Apache::lonnet::all_hostnames();
  582:     foreach my $host (sort(keys(%hostname))) {
  583: 	if (&Apache::lonnet::allowed('psa',
  584: 				     &Apache::lonnet::host_domain($host))) {
  585: 	    $r->print ('<label><input type="checkbox" name="postto_'.$host.'" /> '.
  586: 		       $host.' <tt>'.$hostname{$host}.'</tt> '.
  587: 		       '</label><a href="http://'.$hostname{$host}.
  588: 		       '/announcement.txt?time='.time.'" target="annowin">'.
  589:                        &mt('Current Announcement').'</a><br />');
  590: 	}
  591:     }
  592:     $r->print(
  593:   '<br /><input type="submit" name="serveraction" value="'.&mt('Post').'"></form><hr />');
  594:     }
  595:     if ($allowed) {
  596:         my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
  597:         my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
  598: # ----------------------------------------------------- Store new submitted one
  599:         if ($env{'form.action'} eq 'new') {
  600: 	    my $startdate = 
  601: 		&Apache::lonhtmlcommon::get_date_from_form('startdate');
  602: 	    my $enddate   = 
  603: 		&Apache::lonhtmlcommon::get_date_from_form('enddate');
  604: 	    unless ($startdate=~/^\d+$/) { $startdate=time; }
  605:             unless ($enddate=~/^\d+$/) { $enddate=$startdate+1; }
  606:             if ($startdate>$enddate) {
  607: 		my $buffer=$startdate;
  608: 		$startdate=$enddate;
  609: 		$enddate=$buffer;
  610:             }
  611: 	    &Apache::lonnet::put('calendar',{ 
  612: 		$startdate.'_'.$enddate => 
  613: 		    $env{'form.msg'} },$coursedom,$coursenum);
  614: 	    if ($env{'form.rsspost'}) {
  615:                &Apache::lonrss::addentry($coursenum,$coursedom,'Course_Announcements',
  616: 					 &mt('Event from [_1] to [_2]',
  617: 					     &Apache::lonlocal::locallocaltime($startdate),
  618: 					     &Apache::lonlocal::locallocaltime($enddate)),
  619: 					 $env{'form.msg'},'/adm/announcements','public');
  620: 	   }
  621:         }
  622: # ---------------------------------------------------------------- Remove items
  623:         if ($env{'form.action'} eq 'del') {
  624: 	    my @delwhich=();
  625:             foreach my $key (keys(%env)) {
  626: 		if ($key=~/^form\.remove\_(.+)$/) {
  627: 		    push(@delwhich,$1);
  628:                 }
  629:             }
  630:             &Apache::lonnet::del('calendar',\@delwhich,$coursedom,$coursenum);
  631:         }
  632: # -------------------------------------------------------- Form to post new one
  633:         my %tomorrowhash=%todayhash;
  634:         $tomorrowhash{'day'}++;
  635:         my $tomorrow=&Apache::loncommon::maketime(%tomorrowhash);
  636:         
  637:         &editfield($r,$today,$tomorrow,'');
  638:     }
  639: # ----------------------------------------------------- Summarize all calendars
  640:     my %allcal=&get_all_calendars();
  641: # ------------------------------- Initialize table and forward backward buttons
  642:     my ($pm,$py,$fm,$fy)=($month-1,$year,$month+1,$year);
  643:     if ($pm<1) { ($pm,$py)=(12,$year-1); }
  644:     if ($fm>12){ ($fm,$fy)=(1,$year+1); }
  645: 
  646:     $r->print('<h2>'.&mt('Calendar').'</h2>'
  647:              .'<h3>'.('',&mt('January'),&mt('February'),&mt('March'),
  648: 		      &mt('April'),&mt('May'),
  649: 		      &mt('June'),&mt('July'),&mt('August'),
  650:                       &mt('September'),&mt('October'),
  651:                       &mt('November'),&mt('December'))[$month].' '.
  652: 	              $year.' '.&show_timezone().'</h3>');
  653: # Reached the end of times, give up
  654:     if (($year<1970) || ($year>2037)) {
  655: 	$r->print('<p class="LC_warning">'
  656:                  .&mt('No calendar available for this date.')
  657:                  .'</p>'
  658:                  .'<a href="/adm/announcements?month='.$todayhash{'month'}
  659:                  .'&year='.$todayhash{'year'}.'">'.&mt('Current Month').'</a>'
  660: 		 .&Apache::loncommon::end_page());
  661: 	return OK;
  662:     }
  663: 
  664:     my $class = "LC_calendar";
  665:     if ($env{'form.pickdate'} eq 'yes') {
  666: 	$class .= " LC_calendar_pickdate";
  667:     }
  668: # ------------------------------------------------ Determine first day of a week
  669:     my $datelocale =  &Apache::lonlocal::getdatelocale();
  670:     my $days_in_week = 7;
  671:     my $startweek = 0;
  672:     if (ref($datelocale)) {
  673:         $startweek = $datelocale->first_day_of_week();
  674:         if ($startweek == $days_in_week)  { $startweek = 0; }
  675:     }
  676:     my @days = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
  677:     my @localdays;
  678:     if ($startweek == 0) {
  679:         @localdays = @days;
  680:     } else {
  681:         my $endday = $days_in_week - $startweek;
  682:         for (my $i=0; $i<$days_in_week; $i++) {
  683:             if ($i < $endday) {
  684:                 $localdays[$i] = $days[$i+$startweek];
  685:             } else {
  686:                 $localdays[$i] = $days[$i-$endday];
  687:             }
  688:         }
  689:     }
  690: 
  691: # ----------------------------------------------------------- Weekday in locale
  692:     my $loc_weekday = $weekday - $startweek;
  693:     if ($loc_weekday < 0) {
  694:         $loc_weekday += $days_in_week; 
  695:     }
  696: 
  697:     $r->print(
  698:  '<a href="/adm/announcements?month='.$pm.'&year='.$py.
  699:  ($pickdatemode?$pickinfo:'').'">'.&mt('Previous Month').'</a> '.
  700:  '<a href="/adm/announcements?month='.$fm.'&year='.$fy.
  701:  ($pickdatemode?$pickinfo:'').'">'.&mt('Next Month').'</a>'.
  702:  '&nbsp;&nbsp;&nbsp;<a href="/adm/announcements?month='.$todayhash{'month'}.
  703:  '&year='.$todayhash{'year'}.
  704:  ($pickdatemode?$pickinfo:'').'">'.&mt('Current Month').'</a><p>'.
  705:         '<table class="'.$class.'" cols="7" rows="5"><tr>');
  706:     for (my $i=0; $i<@localdays; $i++) {
  707:         $r->print('<th>'.&mt($localdays[$i]).'</th>');
  708:     }
  709:     $r->print('</tr>');
  710: 
  711:     my $outp;
  712:     my $nm;
  713: 
  714: # ---------------------------------------------------------------- Actual table
  715:     $r->print('<tr>');
  716:     for (my $i=0;$i<$loc_weekday;$i++) { $r->print(&emptycell); }
  717:     for (my $i=$loc_weekday;$i<=6;$i++) {
  718:         ($tk,$nm,$outp)=&showday($tk,0,%allcal);
  719:         $r->print($outp);
  720:     }
  721:     $r->print('</tr>');
  722: 
  723:     my $lastrow = 0;
  724:     my $lastday = 0;
  725:     for (my $k=0;$k<=4;$k++) {
  726:         if (!$lastrow) {
  727:             $r->print('<tr>');
  728:             for (my $i=0;$i<=6;$i++) {
  729:                 if ($lastday) {
  730:                     $outp = &emptycell();
  731:                 } else {
  732:                     my $currtk = $tk;
  733:                     ($tk,$nm,$outp)=&showday($tk,0,%allcal);
  734:                     if ($month!=$nm) { $lastday = 1; }
  735:                 }
  736:                 $r->print($outp);
  737:             }
  738:             if ($lastday) {
  739:                 $lastrow = 1;
  740:             }
  741:             $r->print('</tr>');
  742:         }
  743:     }
  744: # ------------------------------------------------------------------- End table
  745:     $r->print('</table>');
  746: # ----------------------------------------------------------------- Check marks
  747:     undef(%showedcheck);
  748: # --------------------------------------------------------------- Remove button
  749:     if ($allowed) { $r->print('<br /><input type="button" onClick="removesub()" value="'.&mt('Remove Checked Entries').'">'.
  750: 			      &Apache::loncommon::help_open_topic('Calendar_Remove_Announcement').'</form>'); }
  751:     $r->print('<p>'.
  752:  '<a href="/adm/announcements?month='.$pm.'&year='.$py.
  753:  ($pickdatemode?$pickinfo:'').'">'.&mt('Previous Month').'</a> '.
  754:  '<a href="/adm/announcements?month='.$fm.'&year='.$fy.
  755:  ($pickdatemode?$pickinfo:'').'">'.&mt('Next Month').'</a>'.
  756:  '&nbsp;&nbsp;&nbsp;<a href="/adm/announcements?month='.$todayhash{'month'}.
  757:  '&year='.$todayhash{'year'}.
  758:  ($pickdatemode?$pickinfo:'').'">'.&mt('Current Month').'</a></p>'.
  759:  ($pickdatemode?'</font>':'').&Apache::loncommon::end_page());
  760:     $r->print('<a href="/adm/announcements.ics">'.&mt('Download your Calendar as iCalendar File').'</a>');
  761:     return OK;
  762: } 
  763: 
  764: 1;
  765: __END__

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