add: Events in calendar Week view can now be ordered arbitrarily\

fix: Event Related Links are now proper collateral in their own table. The HTML area is parsed and the table populated accordingly. No more silly HTML Area.
This commit is contained in:
Doug Bell 2008-01-23 02:41:38 +00:00
parent fc732b5e19
commit 5292426cc5
7 changed files with 666 additions and 51 deletions

View file

@ -24,6 +24,10 @@
height, templateId); where assetId is the asset of the widget to
widgetize and templateId is the template for the widget itself. If
templateId isn't specified, uses ajaxInlineView.
- add: Events in the Calendar Week View can now be ordered
arbitrarily.
- fix: Event Related Links are now proper collateral in their own table
instead of a silly HTML area
7.4.21
- fix: Mails sent from WebGUI now wrap at 78 characters, as the SMTP

View file

@ -7,6 +7,13 @@ upgrading from one version to the next, or even between multiple
versions. Be sure to heed the warnings contained herein as they will
save you many hours of grief.
7.5.0
--------------------------------------------------------------------
* Event related links are now displayed using a template loop
rather than a template variable. See the default templates for
details.
Your custom Event Edit and Event View templates may need fixing.
7.4.12
--------------------------------------------------------------------
* Any customizations made to the Matrix default Search, Compare or

View file

@ -31,6 +31,11 @@ installGalleryAsset($session);
installGalleryAlbumAsset($session);
installPhotoAsset($session);
createEvent_relatedlinkTable($session);
updateRelatedLinkData($session);
alterEventTableForSequence($session);
populateSequenceNumbers($session);
finish($session); # this line required
@ -280,6 +285,244 @@ sub addIsExportable {
print "DONE!\n" unless $quiet;
}
#--------------------------------------------------------------------------
# Populate the initial sequence numbers
sub populateSequenceNumbers {
my $session = shift;
my $dbh = $session->db->dbh;
my $seed = 16384;
my $curr_seed = 32768;
my $sql =<<SQL_END;
SELECT DISTINCT Event.assetId
FROM Event
ORDER BY Event.startDate, Event.startTime, Event.endDate, Event.endTime, Event.assetId
SQL_END
my $ar_assetIds = $dbh->selectcol_arrayref($sql);
for my $assetId (@$ar_assetIds) {
my ($event) = $dbh->selectrow_hashref("SELECT revisionDate FROM Event WHERE assetId = ? ORDER BY revisionDate DESC LIMIT 1",undef,$assetId);
$dbh->do("UPDATE Event SET sequenceNumber = ? WHERE assetId = ? AND revisionDate = ?",{},$curr_seed,$assetId,$event->{revisionDate});
$curr_seed += $seed;
}
$dbh->do("UPDATE Calendar SET sortEventsBy = 'sequenceNumber'");
}
#--------------------------------------------------------------------------
# Create event relatedlink table
sub createEvent_relatedlinkTable {
my $session = shift;
print "\tCreate Event_relatedlink table.\n" unless $quiet;
my $sql =<<SQL_END;
CREATE TABLE Event_relatedlink (
eventlinkId VARCHAR(22) NOT NULL,
assetId VARCHAR(22) NOT NULL,
linkURL TINYTEXT,
linktext VARCHAR(80),
groupIdView VARCHAR(22) NOT NULL,
sequenceNumber BIGINT(20) DEFAULT NULL
)
SQL_END
$session->db->write($sql) or die "Failed to create Event_relatedlink table\n";
}
#-----------------------------------------------------------------------------
# Update the related links from the Event table to Event_relatedlink
sub updateRelatedLinkData {
my $session = shift;
use HTML::Parser;
my $p = HTML::Parser->new(api_version =>3);
print "\tConverting Related Links from Event table to Event_relatedlink table\n" unless $quiet;
my $sth = $session->db->read("SELECT Event.assetId,relatedLinks,groupIdView FROM Event,assetData WHERE Event.assetId = assetData.assetId order by Event.revisionDate desc");
$sth->execute;
my (%asset_used, %event_asset_of, %snippet_asset_of);
while (my ($assetId, $relatedLinks, $groupIdView) = $sth->array) {
if (defined $asset_used{$assetId}) {
# print "\tAlready defined\n";
# print "$assetId, $relatedLinks\n";
next;
}
# print "\n\tUsing\n";
# print "$assetId, $relatedLinks\n";
$asset_used{$assetId} = $groupIdView;
$event_asset_of{$assetId} = parse_html_to_link($p, $relatedLinks);
# print Dumper ( $event_asset_of{ $assetId } )."\n";
$p->eof;
}
# Scan all records for active AssetProxy macros and convert them to a
# Real url / display text pair.
#
for my $assetId (keys %event_asset_of) {
for my $hr (@{$event_asset_of{$assetId}}) {
next unless ($hr->{url} =~ /AssetProxy/);
$hr->{text} =~ s/^\///;
# print "*** NEW ***\n".$hr->{text}."\n";
my ($assetId_snippet, $groupIdView) = $session->db->quickArray("SELECT assetId, groupIdView FROM assetData WHERE url = ? ORDER BY revisionDate DESC LIMIT 1",[$hr->{text}]);
unless ($assetId_snippet) {
delete $event_asset_of{$assetId};
next;
}
$asset_used{$assetId_snippet} = $groupIdView;
my ($snippet) = $session->db->quickArray("SELECT snippet FROM snippet WHERE assetId = ? ORDER BY revisionDate DESC LIMIT 1",[$assetId_snippet]);
# print "\tsnippetId: ($assetId_snippet), assetId($assetId):\n$snippet\n";
my $links = parse_html_to_link($p, $snippet);
# print $assetId.":\n".Dumper ($links)."\n";
for (@$links) {
push @{$snippet_asset_of{$assetId}{$assetId_snippet}}, $_;
}
$hr = undef;
}
}
# Extracted data now stored as Event_relatedlink rows
my $sql =<<SQL_END;
INSERT INTO Event_relatedlink
(assetId,groupIdView,linkurl,linktext,sequenceNumber,eventlinkId)
VALUES (?,?,?,?,?,?)
SQL_END
for my $assetId (keys %event_asset_of) {
for my $a_idx (0..@{$event_asset_of{$assetId}}) {
my $eventlinkId = $session->id->generate();
next unless (defined (my $hr_link = $event_asset_of{$assetId}[$a_idx]));
my $groupToView = $asset_used{$assetId};
# printf "'%s', '%s', '%s', '%s', '%s', '%s'\n",$assetId,$groupToView,$hr_link->{url},$hr_link->{text},$a_idx+1,$eventlinkId;
$session->db->write($sql,[$assetId,$groupToView,$hr_link->{url},$hr_link->{text},$a_idx+1,$eventlinkId]);
}
}
# print "Snippets\n";
for my $assetId (keys %snippet_asset_of) {
my $hrs_asset_of = \%{$snippet_asset_of{$assetId}};
# print "\tEvent: $assetId\n";
# print Dumper ($hrs_asset_of)."\n";
for my $s_assetId (keys %$hrs_asset_of) {
# print "\t\tSnippet: $s_assetId\n";
for my $a_idx (0..@{$hrs_asset_of->{$s_assetId}}) {
# print "\t\t\tIDX: $a_idx\n";
my $eventlinkId = $session->id->generate();
next unless (defined (my $hr_link = $hrs_asset_of->{$s_assetId}[$a_idx]));
my $groupToView = $asset_used{$s_assetId};
# printf "'%s', '%s', '%s', '%s', '%s', '%s'\n",$assetId,$groupToView,$hr_link->{url},$hr_link->{text},$a_idx+1,$eventlinkId;
$session->db->write($sql,[$assetId,$groupToView,$hr_link->{url},$hr_link->{text},$a_idx+1,$eventlinkId]);
}
}
}
return;
}
#-----------------------------------------------------------------------------
# Alter the Event table to add the Sequence Number field
sub alterEventTableForSequence {
my $session = shift;
print "\tAdding sequenceNumber to Event table.\n" unless $quiet;
my $sql =<<SQL_END;
ALTER TABLE Event ADD sequenceNumber BIGINT(20) DEFAULT NULL
SQL_END
$session->db->write($sql) or die "Failed to modify Event table\n";
$sql =<<SQL_END;
ALTER TABLE Calendar ADD sortEventsBy ENUM('time','sequencenumber') DEFAULT 'time'
SQL_END
$session->db->write($sql) or die "Failed to modify Calendar table\n";
}
########
# Convert HTML::Parser output to something useful
# Results in a array of hashrefs with keys 'url' and 'text'
#
sub parse_html_to_link {
my ($p, $rl, $verbose) = @_;
$rl =~ s/<\/a\>\s*<a\s/<\/a\><br \/><a/gm;
my @result;
$p->handler( start => \@result, 'attr' );
$p->handler( text => \@result, 'text' );
$p->parse($rl."<br />");
if ($verbose) {
print "=========================================\n";
print Dumper (@result)."\n";
print "------\n";
}
my (@text, @links, $key);
for (@result) {
if (ref ($_->[0]) ne "HASH") {
if ($_->[0] =~ /^\^AssetProxy/) {
push @text, $_->[0];
push @links, link_to_hashref('', \@text);
}
elsif ($_->[0] =~ /\w/) {
push @text, $_->[0];
}
}
else {
if ($_->[0]->{href}) {
$key = $_->[0]->{href};
}
else {
push @links, link_to_hashref($key, \@text);
}
}
}
return \@links;
}
########
# Given a key (URL) and an array_ref containing strings
# build a hash value according to certain rules
#
sub link_to_hashref {
my ($key, $ar_text) = @_;
return unless $ar_text->[0];
my %h;
if ($key) {
# Both hash key and values provided
$h{url} = $key;
$h{text} = (join "&nbsp;",@$ar_text) || $key;
$key = '';
}
elsif ($ar_text->[0] =~ /^\//) {
# Only a file reference is provided
$h{url} = join "&nbsp;",@$ar_text;
$h{text} = join "&nbsp;",@$ar_text;
}
elsif ($ar_text->[0] =~ /^\^AssetProxy\(([^\)]+)\)/) {
# Snippet macro provided
$h{text} = $1;
$h{url} = 'AssetProxy';
}
# prevent surprise array expansion
@$ar_text = ();
return \%h;
}
# --------------- DO NOT EDIT BELOW THIS LINE --------------------------------
#----------------------------------------------------------------------------

View file

@ -91,10 +91,6 @@ sub definition {
defaultValue => undef,
},
'relatedLinks' => {
fieldType => "HTMLArea",
defaultValue => undef,
},
'location' => {
fieldType => "Text",
defaultValue => undef,
@ -115,6 +111,9 @@ sub definition {
'timeZone' => {
fieldType => 'TimeZone',
},
sequenceNumber => {
fieldType => 'hidden',
},
);
@ -400,6 +399,8 @@ sub getEventNext {
limit => 1,
});
return unless $events->[0];
return WebGUI::Asset->newByDynamicClass($self->session,$events->[0]);
}
@ -455,6 +456,7 @@ sub getEventPrev {
limit => 1,
});
return unless $events->[0];
return WebGUI::Asset->newByDynamicClass($self->session,$events->[0]);
}
@ -1140,13 +1142,26 @@ sub getRecurrenceFromForm {
=head2 getRelatedLinks
Gets an array of hashrefs of related links.
Gets an arrayref of hashrefs of related links.
=cut
sub getRelatedLinks {
my $self = shift;
my $sth
= $self->session->db->prepare(
"SELECT * FROM Event_relatedlink WHERE assetId=? ORDER BY sequenceNumber",
);
$sth->execute([ $self->getId ]);
my @links;
while ( my $link = $sth->hashRef ) {
next unless $self->session->user->isInGroup( $link->{ groupIdView } );
push @links, $link;
}
return \@links;
}
#-------------------------------------------------------------------
@ -1275,10 +1290,8 @@ sub getTemplateVars {
$var{ "urlSearch" } = $self->getParent->getSearchUrl;
# Related links
$var{ "relatedLinks" } = [];
push @{$var{"relatedLinks"}}, { "linkUrl" => $_ }
for ($self->getRelatedLinks);
$var{ relatedLinks } = $self->getRelatedLinks;
# Attachments
my $gotImage;
my $gotAttachment;
@ -1487,6 +1500,74 @@ sub processPropertiesFromFormPost {
});
}
my $top_val = $session->db->dbh->selectcol_arrayref("SELECT sequenceNumber FROM Event ORDER BY sequenceNumber desc LIMIT 1")->[0];
$top_val += 16384;
my $assetId = $self->get('assetId');
my $revisionDate = $self->get('revisionDate');
$session->db->write("UPDATE Event SET sequenceNumber =? WHERE assetId = ? AND revisionDate =?",[($form->param('sequenceNumber') || $top_val), $assetId, $revisionDate]);
# Pre-process Related Links and manage changes
# These parameters are the important ones
#
my @rel_keys = grep {/^rel_(?:delconfirm|url|text|group|seq)_/} $form->param;
# Organize results
my %rel_link_for;
for (@rel_keys) {
if (/^rel_group_id_(.+)$/) { # Group assignment
$rel_link_for{$1}{groupIdView} = $form->param($_);
}
elsif (/^rel_url_(.+)$/) {
my $eventlinkId = $1;
my $url = $form->param($_);
$url =~ s/^\s+//;
$url =~ s/\s+$//;
if (0 && $url && $url !~ /^http:\/\//) {
$url =~ s/ht+p[^\w]+//i;
$url = "http://$url";
}
$rel_link_for{$eventlinkId}{linkurl} = $url || '';
}
elsif (/^rel_seq_(.+)$/) {
$rel_link_for{$1}{sequenceNumber} = $form->param($_);
}
elsif (/^rel_text_(.+)$/) {
my $eventlinkId = $1;
my $text = $form->param($_);
$text =~ s/^\s+//;
$text =~ s/\s+$//;
$rel_link_for{$eventlinkId}{linktext} = $text;
}
elsif (/^rel_delconfirm_(.+)$/) {
$rel_link_for{$1}{delete} = $form->param($_);
}
}
# The database entries for this assetId are compared and
# then replaced by these (possibly new) values. Deletions
# are marked and passed on.
#
my @rel_link_saves;
for (keys %rel_link_for) {
if (!$rel_link_for{$_}{linkurl}) {
$rel_link_for{$_}{delete}++;
next;
}
if (/^new_/) {
$rel_link_for{$_}{eventlinkId} = $self->session->id->generate();
$rel_link_for{$_}{new_event}++;
}
else {
$rel_link_for{$_}{eventlinkId} = $_;
}
push @rel_link_saves, \%{$rel_link_for{$_}};
}
$self->setRelatedLinks(\@rel_link_saves);
# Determine if the pattern has changed
if ($form->param("recurType")) {
@ -1497,7 +1578,8 @@ sub processPropertiesFromFormPost {
# Set storable to canonical so that we can compare data structures
$Storable::canonical = 1;
local $Storable::canonical = 1;
# Pattern keys
if (nfreeze(\%recurrence_new) ne nfreeze(\%recurrence_old)) {
@ -1669,19 +1751,45 @@ sub setRecurrence {
####################################################################
=head2 setRelatedLinks ( @links )
=head2 setRelatedLinks ( links )
Sets the event's related links.
Sets the event's related links. C<links> is an array reference of
hash reference of links.
=cut
sub setRelatedLinks {
my $self = shift;
my @links = @_;
my $links = shift;
$self->update({
relatedLinks => join("\n", @links),
});
my $assetId = $self->getId;
# Don't make any changes unless asked, and then only change the known records
#
if (@$links) {
for my $hr (@{$links}) {
if ($hr->{new_event} && !$hr->{delete}) {
$self->session->db->write(
q{INSERT INTO Event_relatedlink (assetId,sequenceNumber,linkurl,linktext,groupIdView,eventlinkId) VALUES (?,?,?,?,?,?)},
[ $assetId, @{$hr}{('sequenceNumber','linkurl','linktext','groupIdView','eventlinkId')} ]
);
}
elsif ($hr->{delete}) {
$self->session->db->write(
q{DELETE FROM Event_relatedlink WHERE assetId = ? AND eventlinkId = ?},
[ $assetId, $hr->{eventlinkId} ],
);
}
else {
$self->session->db->write(
q{UPDATE Event_relatedlink set sequenceNumber=?,linkurl=?,linktext=?,groupIdView=? where eventlinkId = ?},
[ @{$hr}{('sequenceNumber','linkurl','linktext','groupIdView','eventlinkId')} ],
);
}
}
}
return;
}
####################################################################
@ -1782,6 +1890,10 @@ sub www_edit {
$var->{"formHeader"}
= WebGUI::Form::formHeader($session, {
action => $self->getUrl,
})
. WebGUI::Form::hidden($self->session, {
name => "sequenceNumber",
value => $self->get("sequenceNumber"),
});
}
@ -1971,13 +2083,34 @@ sub www_edit {
. q|<br/>Time Zone: |.$var->{formTimeZone}
. q|</div>|;
# related links
$var->{"formRelatedLinks"}
= WebGUI::Form::HTMLArea($session, {
name => "relatedLinks",
value => $form->process("relatedLinks") || $self->get("relatedLinks"),
});
###### related links
my $relatedLinks = $self->getRelatedLinks();
my $seqNum = 1;
for (@$relatedLinks) {
$_->{row_id} = "rel_row_".$_->{eventlinkId};
$_->{div_id} = "rel_div_".$_->{eventlinkId};
$_->{delete_name} = "rel_del_".$_->{eventlinkId};
$_->{delete_id} = "rel_del_id_".$_->{eventlinkId};
$_->{group_id} = WebGUI::Form::Group($session, {
name => "rel_group_id_".$_->{eventlinkId},
value => $form->process("rel_group_id_".$_->{eventlinkId}) || $_->{groupIdView} || $self->getParent->get("groupIdView"),
defaultValue => $self->getParent->get("groupIdView"),
});
$_->{seq_num_name} = "rel_seq_".$_->{eventlinkId};
$_->{seq_num_id} = "rel_seq_id_".$_->{eventlinkId};
$_->{seq_num_value} = $seqNum++;
}
$var->{"relatedLinks"} = $relatedLinks;
$var->{"genericGroup"} = WebGUI::Form::Group($session, {
name => "rel_group_id_ZZZZZZZZZZ",
value => $self->getParent->get("groupIdView"),
defaultValue => $self->getParent->get("groupIdView"),
});
chomp $var->{"genericGroup"};
###### Recurrence tab
@ -2142,11 +2275,11 @@ sub www_edit {
</div>
|;
# Include
# TODO!
# Exclude
# TODO!

View file

@ -62,8 +62,10 @@ sub definition {
first => $i18n->get("defaultDate value first"),
last => $i18n->get("defaultDate value last"),
);
tie (my %optionsEventSort, 'Tie::IxHash',
time => $i18n->get("sortEventsBy value time"),
sequencenumber => $i18n->get("sortEventsBy value sequencenumber"),
);
### Build properties hash ###
tie my %properties, 'Tie::IxHash';
@ -214,7 +216,15 @@ sub definition {
hoverHelp => $i18n->get('visitorCacheTimeout description'),
label => $i18n->get('visitorCacheTimeout label'),
},
sortEventsBy => {
fieldType => "SelectBox",
defaultValue => "time",
options => \%optionsEventSort,
tab => "display",
label => $i18n->get("sortEventsBy label"),
hoverHelp => $i18n->get("sortEventsBy description"),
},
# This doesn't function currently
#subscriberNotifyOffset => {
# fieldType => "integer",
@ -589,7 +599,7 @@ sub getEvent {
####################################################################
=head2 getEventsIn ( startDate, endDate )
=head2 getEventsIn ( startDate, endDate, options )
Returns a list of Event objects that fall between two dates, ordered by their
start date/time.
@ -601,17 +611,25 @@ user's time zone.
TODO: Allow WebGUI::DateTime objects to be passed as the parameters.
TODO: Allow for a hashref of options as the third parameter to specify such
things as a limit clause, or additional where clause, or something.
This is the main API method to get events from a calendar, so it must be flexible.
C<options> is a hash reference with the following keys:
order - The order to return the events. Will default to the
sortEventsBy asset property. Valid values are:
'time', 'sequenceNumber'
=cut
sub getEventsIn {
my $self = shift;
my $start = shift;
my $end = shift;
my $params = shift;
$params->{order} = '' if $params->{order} !~ /^(?:time|sequencenumber)/i;
my $order_by_type = $params->{order} ? lc($params->{order}) : $self->get('sortEventsBy');
my $tz = $self->session->user->profileField("timeZone");
# Warn and return if no startDate or endDate
@ -647,15 +665,20 @@ sub getEventsIn {
)
};
my $orderby
= join ',',
'Event.startDate',
my @order_priority
= ( 'Event.startDate',
'Event.startTime',
'Event.endDate',
'Event.endTime',
'assetData.title',
'assetData.assetId',
;
);
if ($order_by_type eq 'sequencenumber') {
unshift @order_priority, 'Event.sequenceNumber';
}
my $orderby = join ',', @order_priority;
my $events
= $self->getLineage(["descendants"], {
@ -933,12 +956,25 @@ sub view {
# Get the form parameters
my $params = {};
$params->{type} = $form->param("type");
$params->{type} = $form->param("type") || $self->get( 'defaultView' );
$params->{start} = $form->param("start");
### TODO: Parse user input for sanity.
# {start} must be of the form: YYYY-MM-DD%20HH:MM:SS
# {type} must be "month", "week", or "day"
# Validate type passed, or recover from session scratchpad
if ($params->{type} =~ /^(?:month|week|day)$/) {
$session->scratch->set('cal_view_type', $params->{'type'});
}
else {
$params->{type} = $session->scratch->get('cal_view_type') || $self->get( 'defaultView' ) || 'month';
$session->scratch->set('cal_view_type', $params->{'type'});
}
# Validate start passed or recover from session scratchpad
if ($params->{ start } =~ /^\d\d\d\d\-\d\d\-\d\d.+?\d\d\:\d\d\:\d\d$/) {
$session->scratch->set('cal_view_start', $params->{ start });
}
else {
$params->{ start } = $session->scratch->get('cal_view_start') || 0;
}
# Set defaults if necessary
if (!$params->{start}) {
@ -949,9 +985,8 @@ sub view {
? $self->getLastEvent->getDateTimeStart
: WebGUI::DateTime->new($session, time)->toUserTimeZone
;
}
if (!$params->{type}) {
$params->{type} = $self->get("defaultView") || "Month";
$session->scratch->set('cal_view_start', $params->{'start'});
}
# Get the template from the appropriate view* method
@ -971,7 +1006,7 @@ sub view {
# Event editor
if ($self->canAddEvent) {
$var->{'editor'} = 1;
$var->{"urlAdd"} = $self->getUrl("func=add;class=WebGUI::Asset::Event;start=$params->{start}");
$var->{"urlAdd"} = $self->getUrl("func=add;class=WebGUI::Asset::Event;type=".$params->{type}.";start=$params->{start}");
}
# URLs
@ -1283,12 +1318,165 @@ sub viewWeek {
$dt->subtract(days => $dt->day_of_week % 7 - $first_dow);
my $start = $dt->toMysql;
my $dtEnd = $dt->clone->add(days => 7);
my $dtEnd = $dt->clone->add(days => 7)->add( seconds => -1);
my $end = $dtEnd->toMysql; # Clone to prevent saving change
$dtEnd->add(seconds => -1);
my @events = $self->getEventsIn($start,$end);
my $sort_by_sequence++ if $self->get('sortEventsBy') eq 'sequencenumber';
my $can_edit_order++ if $self->canEdit && $sort_by_sequence;
my $reorder_request++ if $can_edit_order && $session->form->param( 'eventMove' ) =~ /^(?:UP|DOWN)$/;
if ($reorder_request) {
# Someone clicked an UP or DOWN request
#
my @events = $self->getEventsIn( $start, $end );
my (%event_asset_of, %seq_key_of, %week_day_of, @event_days);
# The events
for my $event ( @events ) {
next unless $event->canView();
my $event_asset_id = $event->get( 'assetId' );
# Add Event object use by assetId
$event_asset_of{ $event_asset_id }{ object } = $event;
# Get the week this event is in, and add it to that week in
# the template variables
my $dt_event_start = $event->getDateTimeStart;
my $dt_event_end = $event->getDateTimeEnd;
#Handle events that start before this week or end after this week.
if ($dt_event_start < $dt) {
$dt_event_start = $dt;
}
if ($dt_event_end > $dtEnd) {
$dt_event_end = $dtEnd;
}
my $start_dow = ($dt_event_start->day_of_week - $first_dow) % 7;
my $end_dow = ($dt_event_end->day_of_week - $first_dow) % 7;
my $sequence_number = $session->db->dbh->selectcol_arrayref("SELECT sequenceNumber FROM Event WHERE assetId
= ? ORDER BY revisionDate desc LIMIT 1",{},$event_asset_id)->[0];
foreach my $weekDay ($start_dow .. $end_dow) {
push @{ $event_days[ $weekDay ] }, $event;
my $event_day_pos = $#{ $event_days[ $weekDay ]};
# Monitor duplicates in sequence list;
push @{ $seq_key_of{ $sequence_number } }, $event_asset_id;
# Add find assetId by day/order pos
$week_day_of{ $weekDay }{ $event_day_pos } = $event_asset_id;
# Add find order pos by assetId and day
$event_asset_of{ $event_asset_id }{ $weekDay } = $event_day_pos;
}
}
# Process the event sequence change request
#
# Based upon binary values beginning at 16384 sequence
# number separtion. Collisions are expected, in fact,
# designed for, with the move increment divided by two
# repeatedly until a non-collision situation is detected and
# then used. In worst case behavior, this practice will
# fail at 16 repositions, but to cause this someone would
# have to be applying extremely abusive reorder behavior.
#
# Abusive consists of applying move-up or move-down between
# two select events, in a leap frog fashion, towards yet another
# event in the same time frame. This causes the increment to
# progressively be divided by two until it hits the value '1'.
# At that point, duplication of sequence number is inevitable,
# and the order list may behave in unexpected ways.
#
# CAVEAT: This service functions on a week view. This
# behavior could move the reprioritized event ahead or
# behind interventing events listed on other days. The
# logic to compensate for calendar events spanning to
# non-target weeks is ignored.
#
my $direction = $session->form->param( 'eventMove' );
my $event_asset_id = $session->form->param( 'assetId' );
my $event_day = $session->form->param( 'day' );
my $event_day_pos = $event_asset_of{ $event_asset_id }{ $event_day };
my $event_object = $event_asset_of{ $event_asset_id }{ object };
my $event_seq_num = $session->db->dbh->selectcol_arrayref("SELECT sequenceNumber FROM Event WHERE assetId = ? ORDER BY revisionDate desc LIMIT 1",{},$event_asset_id)->[0];
my @seq_list = sort keys %seq_key_of;
my $incr = 8192;
my $day_entries = \@{ $event_days[ $event_day ] };
# warn "@seq_list\n";
# warn "Moving assetId: $event_asset_id, seqNum: $event_seq_num, day: $event_day.$event_day_pos\n";
if ($direction eq 'UP' && $event_day_pos > 0) {
my $prev_asset_id = $week_day_of{ $event_day }{ $event_day_pos - 1 };
my $prev_day_pos = $event_asset_of{ $prev_asset_id }{ $event_day };
my $prev_event_object = $event_asset_of{ $prev_asset_id }{ object };
my $prev_seq_num = $session->db->dbh->selectcol_arrayref("SELECT sequenceNumber FROM Event WHERE assetId = ? ORDER BY revisionDate desc LIMIT 1",{},$prev_asset_id)->[0];
# warn "Before Asset: $prev_asset_id, seqNum: $prev_seq_num, day: $event_day.$prev_day_pos\n";
my $seq_idx;
for my $i (0..$#seq_list) {
next if $seq_list[ $i ] < $prev_seq_num;
$seq_idx = $i - 1;
last;
}
# warn "\tmove between: $seq_list[ $seq_idx] and $prev_seq_num\n";
if ($seq_idx >= 0) {
while ($prev_seq_num - $incr <= $seq_list[ $seq_idx ] && $incr > 1) {
$incr /= 2;
}
}
$session->db->dbh->do
("UPDATE Event SET sequenceNumber = ? WHERE assetId = ? AND revisionDate = ?",{},
$prev_seq_num-$incr, $event_asset_id, $event_object->get( 'revisionDate' )
);
# warn "Moved Asset New Seq Num: ".($prev_seq_num - $incr)." by $incr\n";
}
elsif ($direction eq 'DOWN' && $event_day_pos < $#{ $day_entries }) {
my $next_asset_id = $week_day_of{ $event_day }{ $event_day_pos + 1 };
my $next_day_pos = $event_asset_of{ $next_asset_id }{ $event_day };
my $next_event_object = $event_asset_of{ $next_asset_id }{ object };
my $next_seq_num = $session->db->dbh->selectcol_arrayref("SELECT sequenceNumber FROM Event WHERE assetId = ? ORDER BY revisionDate desc LIMIT 1",{},$next_asset_id)->[0];
# warn "After Asset: $next_asset_id, seqNum: $next_seq_num, day: $event_day.$next_day_pos\n";
my $seq_idx;
for my $i (0..$#seq_list) {
next if $seq_list[ $i ] < $next_seq_num;
$seq_idx = $i;
last;
}
# warn "\tmove between: $next_seq_num and $seq_list[ $seq_idx]\n";
if ($seq_idx <= $#seq_list) {
while ($next_seq_num + $incr >= $seq_list[ $seq_idx + 1 ] && $incr > 1) {
$incr /= 2;
}
}
$session->db->dbh->do
("UPDATE Event SET sequenceNumber = ? WHERE assetId = ? AND revisionDate = ?",{},
$next_seq_num + $incr, $event_asset_id, $event_object->get( 'revisionDate' )
);
# warn "Moved Asset New Seq Num: ".($next_seq_num + $incr)." by $incr\n";
}
}
#### Create the template parameters
# Some friendly dates
@ -1316,9 +1504,9 @@ sub viewWeek {
}
# The events
EVENT: for my $event (@events) {
next EVENT unless $event->canView();
my @events = $self->getEventsIn( $start, $end );
for my $event ( @events ) {
next unless $event->canView();
# Get the week this event is in, and add it to that week in
# the template variables
my $dt_event_start = $event->getDateTimeStart;
@ -1339,7 +1527,24 @@ sub viewWeek {
my %eventTemplateVariables = $self->getEventVars($event);
foreach my $weekDay ($start_dow .. $end_dow) {
push @{$var->{days}->[$weekDay]->{events}}, \%eventTemplateVariables;
my $eventAssetId = $event->get( 'assetId' );
my %hash = %eventTemplateVariables;
if ($sort_by_sequence && $can_edit_order) {
if (1) {
$hash{ iconCallbackUP }
= $session->icon->moveUp( qq|eventMove=UP;day=$weekDay;assetId=$eventAssetId;type=week;start=|.$params->{start} );
$hash{ iconCallbackDOWN }
= $session->icon->moveDown( qq|eventMove=DOWN;day=$weekDay;assetId=$eventAssetId;type=week;start=|.$params->{start} );
}
else {
$hash{ callbackUP } = "day=$weekDay;eventMove=UP;assetId=$eventAssetId;type=week;start=".$params->{start};
$hash{ callbackDOWN } = "day=$weekDay;eventMove=DOWN;assetId=$eventAssetId;type=week;start=".$params->{start};
}
}
push @{ $var->{ days }->[ $weekDay ]->{ events }}, \%hash;
}
}

View file

@ -104,6 +104,29 @@ our $I18N = {
},
##### Default Daily Event Sort Order #####
'sortEventsBy label' => {
message => q{Daily Events Sort Order},
lastUpdated => 0,
context => q{A specification for determining daily Event display order.},
},
'sortEventsBy description' => {
message => q{The order in which daily Events are displayed.},
lastUpdated => 0,
context => q{Hover Help for the Daily Events Sort Order field.},
},
'sortEventsBy value time' => {
message => q{Order by Start Date/End Date.},
lastUpdated => 0,
context => q{A value for the Daily Event Sort Order field.},
},
'sortEventsBy value sequencenumber' => {
message => q{Order by Sequence Number.},
lastUpdated => 0,
context => q{A value for the Daily Events Sort Order field.},
},