|
Server : Apache/2.4.62 System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64 User : www ( 80) PHP Version : 8.3.8 Disable Function : NONE Directory : /domains/compasssysweb/calendar/CalciumDir39/Calendar/ |
Upload File : |
# Copyright 2001-2003, Fred Steinberg, Brown Bear Software
# Display events for single day for multiple calendars
package DayPlanner;
use strict;
use CGI;
use Calendar::Date;
use Calendar::Event;
use Calendar::Preferences;
use Calendar::Permissions;
use Calendar::TimeBlock; # for _dayViewControls
use Calendar::Javascript;
sub new {
my $class = shift;
my ($op, $startDate, $endDate) = @_;
my $self = {};
bless $self, $class;
my $cgi = CGI->new;
my $i18n = $op->I18N;
my $prefs = $op->prefs;
my $milTime = $prefs->MilitaryTime;
my ($startHour, $numHours) = $op->getParams (qw (DayViewStart
DayViewHours));
my ($filterCategories, $filterText, $filterIn) = $op->ParseFilterSpecs;
# Get prefs we need
$numHours = $prefs->DayViewHours || 8 unless defined $numHours;
$startHour = $prefs->DayViewStart unless defined $startHour;
$startHour = 9 unless defined $startHour;
# if > 12, numhours must be mult. of 2
if ($numHours > 12) {
$numHours += $numHours % 2;
}
if ($startHour + $numHours > 24) {
$startHour = 24 - $numHours;
} elsif ($startHour < 0) {
$startHour = 0;
}
my $minsPerCell = $numHours > 12 ? 10 : 5; # num minutes per table cell
my $displayStartTime = $startHour * 60;
my $displayEndTime = ($startHour + $numHours) * 60;
# Colors and Fonts
my (%colors, %fonts);
$colors{Header} = [$prefs->color ('WeekHeaderBG') || '',
$prefs->color ('WeekHeaderFG') || ''];
$fonts{Header} = [$prefs->font ('BlockDayOfWeek')];
$colors{Name} = [$prefs->color ('DayHeaderBG') || '',
$prefs->color ('DayHeaderFG') || ''];
$fonts{Name} = [$prefs->font ('BlockDayOfWeek')];
$fonts{Event} = [$prefs->font ('BlockEvent')];
$fonts{Time} = [$prefs->font ('BlockEventTime')];
$fonts{Category} = [$prefs->font ('BlockCategory')];
# Cellsize must be factor or multiple of 60
if ($minsPerCell !~ /^(1|2|3|5|6|10|12|15|20|30|60|120)$/) {
$minsPerCell = 10;
}
# number cols in hour display portion of table (there is actually 1
# extra column at left for cal names
my $numColumns = $numHours * 60 / $minsPerCell;
my $mainCal = $op->calendarName;
my @calNames = sort {lc($a) cmp lc($b)} $prefs->getIncludedCalendarNames;
unless ($prefs->PlannerHideSelf) {
unshift @calNames, $mainCal;
}
# First row is for hour headers, but if we have multi-hour blocks, use
# fewer headers
my @hours;
my $headHours;
if ($numHours < 13) {
$headHours = 1;
@hours = ($startHour .. ($startHour + $numHours - 1));
} else {
$headHours = 2;
for (my $i=0; $i<$numHours; $i+=2) {
push @hours, $startHour + $i;
}
}
# Convert integer hours to hour strings
@hours = map {_timeLabel ($_, $milTime)} @hours;
my $colWidthPercent = 100 / ($numHours + 1);
my $row = $cgi->Tr ({-bgcolor => $colors{Header}->[0]},
$cgi->td ({-align => 'left'},
$cgi->font ({-color => $colors{Header}->[1],
-face => $fonts{Header}->[0],
-size => $fonts{Header}->[1]},
$i18n->get ('Calendar'))),
(map {$cgi->td ({-colSpan =>
$numColumns * $headHours / $numHours,
# -width => $colWidthPercent . '%'},
},
$cgi->font ({-color =>
$colors{Header}->[1],
-face =>
$fonts{Header}->[0],
-size =>
$fonts{Header}->[1]},
$_))} @hours));
my @theRows = ($row);
# Each calendar gets at least one row; might be more if there are
# overlapping events. Ignore untimed events for now - FIXME
foreach my $thisCal (@calNames) {
my $db = Database->new ($thisCal);
my $pref = Preferences->new ($db);
$pref->Timezone ($prefs->Timezone); # set timezone from user pref
my @events = $db->getApplicableEvents ($startDate, $pref, 'yesterday');
# First, eliminate Tentative events we don't have Edit perm for
@events = $op->removeTentatives (\@events); # op is a ShowIt
# Filter out included events, privacy issues
my @keepers;
foreach my $event (@events) {
next unless defined $event;
# skip included events
next if defined $event->includedFrom
and $event->includedFrom ne $thisCal;
# if not main cal, check for Privacy
if ($thisCal ne $mainCal) {
next if $event->private;
$event->includedFrom ($thisCal . ' ');
}
push @keepers, $event;
}
@events = @keepers;
# Filter out events we don't want, maybe
if ($filterCategories or defined $filterText) {
my @keepers;
foreach my $event (@events) {
next unless defined $event;
next if ($filterCategories and
!$event->inCategory ($filterCategories));
next if (defined $filterText and
!$event->matchesText ($filterText, $filterIn));
push @keepers, $event;
}
@events = @keepers;
}
# Try putting each event in the row. If it conflcts with any events
# already in the row, go to next row.
my @rows = ([]);
foreach my $event (@events) {
next unless (defined $event->startTime);
my $startTime = $event->startTime;
my $endTime = defined $event->endTime ? $event->endTime
: $startTime;
$endTime = 1440 if ($endTime < $startTime); # it ends on next day
next if ($startTime >= $displayEndTime or
$endTime <= $displayStartTime);
my $addedIt;
foreach my $thisRow (@rows) {
next if _conflicts ($event, $thisRow);
push @$thisRow, $event;
$addedIt++;
last;
}
unless ($addedIt) {
my $newRow = [];
push @$newRow, $event;
push @rows, $newRow;
}
}
# Now we have array of rows for this calendar. Make them into Trs
my $numRows = @rows;
my $firstRow = 1;
my @trs;
foreach my $thisRow (@rows) {
my $lastCol = 0;
my @tds;
# Make sure events in the row are sorted by time!
$thisRow = [sort {$a->startTime <=> $b->startTime} @$thisRow];
foreach my $event (@$thisRow) {
my ($start, $span, $blah);
my $startTime = $event->startTime;
my $endTime = $event->endTime;
$endTime = 1440 if (defined $endTime and
$endTime < $startTime); # ends on next day
$endTime ||= $startTime;
$start = int (($startTime - $startHour * 60) / $minsPerCell);
$blah = ($endTime - $startTime) / $minsPerCell;
$span = int ($blah);
$span++ unless ($span == $blah);
if ($lastCol < $start) {
push @tds, $cgi->td ({-colSpan => $start - $lastCol},
' ');
$lastCol = $start;
}
# See where we really started
if ($start < $lastCol) {
$span -= $lastCol - $start;
$start = $lastCol;
}
# Don't go past the edge
if ($lastCol + $span > $numColumns) {
$span = $numColumns - $lastCol;
}
my ($fg, $bg) = $event->colors ($thisCal, $prefs);
my %eventSettings = (calName => $thisCal,
date => $startDate,
prefs => $prefs,
i18n => $i18n,
textFG => $fg,
eventFace => $fonts{Event}->[0],
eventSize => $fonts{Event}->[1],
timeFace => $fonts{Time}->[0],
timeSize => $fonts{Time}->[1],
categoryFace => $fonts{Category}->[0],
categorySize => $fonts{Category}->[1]);
my $td = $cgi->td ({-align => 'center',
-colSpan => $span,
-bgColor => $bg},
$event->getHTML (\%eventSettings));
$lastCol += $span;
push @tds, $td;
}
if ($lastCol < $numColumns) {
push @tds, $cgi->td ({-colSpan => $numColumns - $lastCol},
' ');
}
my $calName = '';
if ($firstRow) {
my $data = $cgi->font ({-color => $colors{Name}->[1],
-size => $fonts{Name}->[1],
-face => $fonts{Name}->[0]},
$thisCal);
if (Permissions->new ($thisCal)->permitted ($op->getUsername,
'Add')) {
$data = $cgi->a ({-href =>
$op->makeURL ({Op => 'ShowDay',
Date => $startDate,
ViewCal => $mainCal,
CalendarName=>$thisCal})},
$data);
}
$calName = $cgi->td ({-rowSpan => $numRows,
-bgcolor => $colors{Name}->[0],
-width => '10%'}, $data);
undef $firstRow;
}
push @theRows, $cgi->Tr ($calName, @tds);
}
}
sub _conflicts {
my ($event, $row) = @_;
my ($start, $end) = ($event->startTime, $event->endTime);
if (!defined $end) {
$end = $start + 60;
} elsif ($end < $start) {
$end = 1440; # if it ends tommorrow
}
foreach my $ev (@$row) {
my ($evStart, $evEnd) = ($ev->startTime, $ev->endTime);
if (!defined $evEnd) {
$evEnd = $evStart + 60;
} elsif ($evEnd < $evStart) {
$evEnd = 1440; # if it ends tommorrow
}
next if ($start >= $evEnd);
next if ($end <= $evStart);
return 1;
}
return undef;
}
my $bgcolor = $prefs->inBWPrintMode ? 'white' : 'gray';
# First, the javascript code we'll need
$self->{html} = Javascript->PopupWindow ($op);
$self->{html} .= $cgi->table ({align => 'center',
border => 1,
cellpadding => 2,
cellspacing => 1,
bgcolor => $bgcolor,
width => '100%'},
@theRows);
# Controls
my $tb = TimeBlock->new (cgi => $cgi,
op => $op);
$self->{html} .= '<br>' . $tb->hourControls;
$self;
}
sub _timeLabel {
my ($hour, $milTime) = @_;
my $amPm = '';
if (!$milTime) {
$amPm = $hour < 12 ? 'am ' : 'pm ';
$hour = 12 if $hour == 0;
$hour -= 12 if ($hour > 12);
}
return "$hour:00" . $amPm;
}
sub getHTML {
my $self = shift;
$self->{html};
}
1;