[Bps-public-commit] rtx-calendar branch allow-custom-field-based-events created. 1.05-19-g0aa12ac
BPS Git Server
git at git.bestpractical.com
Fri Aug 25 14:36:31 UTC 2023
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rtx-calendar".
The branch, allow-custom-field-based-events has been created
at 0aa12acec559221cf32a7679ed1feff847a95c59 (commit)
- Log -----------------------------------------------------------------
commit 0aa12acec559221cf32a7679ed1feff847a95c59
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Fri Aug 25 11:22:51 2023 -0300
Add information about how add Custom Field dates to the Calendar
Since we support Custom Field dates in the Calendar, we add a note
about it in the Calendar Help section.
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index 4633bfb..59406cd 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -217,12 +217,14 @@ and add something to the Query like that:
<&|/l_unsafe, qq{<a href="$RT::WebPath/Search/Build.html">} . loc("Query Builder") . '</a>'&>
By default RTx::Calendar display Due and Starts dates. You can select other
kind of events you want with the Display Columns section in the [_1].
-The following one will display the two latter and LastUpdated dates:
+The following one will display the two latter, LastUpdated and an additional
+date from a custom field called Maintenance Date:
</&>
<pre>
'<small>__Due__</small>',
'<small>__Starts__</small>',
- '<small>__LastUpdated__</small>'
+ '<small>__LastUpdated__</small>',
+ '<small>__CustomField.{Maintenance Date}__</small>'
</pre>
</p>
commit bb3e52dadb8bcfa4008f799c99ebdd8a1a57ec30
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Fri Aug 25 09:56:29 2023 -0300
Refactor Event Color per Status feature
Rename it from CalendarColorStatusMap to CalendarStatusColorMap.
Create a default configuration for it in etc/RTxCalendar_Config.pm and
refactor the code removing some unnecessary if statements.
Move the event html style code to Mason template, where it's rendered
for better readability of the code.
Update POD with more info about the accepted colors on the configuration.
diff --git a/etc/RTxCalendar_Config.pm b/etc/RTxCalendar_Config.pm
index 35d9ccf..ad5d47f 100644
--- a/etc/RTxCalendar_Config.pm
+++ b/etc/RTxCalendar_Config.pm
@@ -10,4 +10,12 @@ Set(%CalendarIcons, (
'LastUpdated' => 'updated.png',
));
+Set(%CalendarStatusColorMap, (
+ 'new' => '#87873c',
+ 'open' => '#5555f8',
+ 'rejected' => '#FF0000',
+ 'resolved' => '#72b872',
+ 'stalled' => '#FF0000',
+));
+
1;
diff --git a/html/Elements/CalendarEvent b/html/Elements/CalendarEvent
index a125970..61a22a9 100644
--- a/html/Elements/CalendarEvent
+++ b/html/Elements/CalendarEvent
@@ -7,7 +7,11 @@ $DateTypes => undef
<small>
<% RTx::Calendar::GetEventImg($Object, $today, $DateTypes, $IsReminder)|n %>
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>" <% $StatusColor|n %>>
+ <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>"
+% if ( $CalendarStatusColorMap{$status} ) {
+ style="color: <%$CalendarStatusColorMap{$status}%>;"
+% }
+ >
<% $Object->QueueObj->Name %> #<% $TicketId %>
<% $display_owner ? 'by ' . $Object->OwnerObj->Name : '' %>
<% length($Object->Subject) > 80 ? substr($Object->Subject, 0, 77) . "..." : $Object->Subject %></a></small><br />
@@ -66,15 +70,7 @@ if ($Object->Type eq 'reminder') {
$status = $Object->Status;
}
-# Colors per status
-my %CalendarColorStatusMap;
-if (RT->Config->Get('CalendarColorStatusMap')) {
- %CalendarColorStatusMap = RT->Config->Get('CalendarColorStatusMap');
-}
-my $StatusColor = '';
-if ($CalendarColorStatusMap{$status}) {
- $StatusColor ='style="color: '.$CalendarColorStatusMap{$status}.'"';
-}
+my %CalendarStatusColorMap = RT->Config->Get('CalendarStatusColorMap');
my $display_owner = $RT::CalendarDisplayOwner;
$display_owner ||= RT->Config->Get('CalendarDisplayOwner')
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index efe4a51..4633bfb 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -188,13 +188,11 @@ foreach my $TranslatedLegend (sort keys %CalendarIconsTranslated) {
% }
</div>
<div class="col-6">
-% if (RT->Config->Get('CalendarColorStatusMap')) {
<b><&|/l&>State Colors</&></b><br />
-% my %ColorStatusMap = RT->Config->Get('CalendarColorStatusMap');
+% my %ColorStatusMap = RT->Config->Get('CalendarStatusColorMap');
% foreach my $Status (sort { lc($a) cmp lc($b) } keys %ColorStatusMap) {
<span style="color: <% $ColorStatusMap{$Status} %>"><% $Status %><span><br />
% }
-% }
</div>
</div>
</div>
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 53d9348..c3dbff7 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -313,9 +313,9 @@ The following example sorts the events by status:
=head3 Event colors
It's also possible to change the color of the events in the calendar by
-adding the C<$CalendarColorStatusMap> setting to your F<etc/RT_SiteConfig.pm>:
+adding the C<$CalendarStatusColorMap> setting to your F<etc/RT_SiteConfig.pm>:
- Set(%CalendarColorStatusMap, (
+ Set(%CalendarStatusColorMap, (
'new' => 'blue',
'open' => 'blue',
'approved' => 'green',
@@ -323,6 +323,9 @@ adding the C<$CalendarColorStatusMap> setting to your F<etc/RT_SiteConfig.pm>:
'resolved' => '#aaa',
));
+You can use any color declaration that CSS supports, including hex codes,
+color names, and RGB values.
+
=head3 Custom icons
Custom Icons can be defined for the events in the calendar by adding the
commit 1bc3d5cd10fb6a426af7afdd44bc8964d8550af6
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 19:31:57 2023 -0300
Refactor Custom Icon feature
Renamed the method from GetEventIcon to GetEventImg and sticked it to
only allow image files and not html code.
Also, since all the Icons can be customized, we created a default setting
for all the core Dates icons.
Also renamed the Icon setting from CalendarCustomIcons to CalendarIcons,
since it's not only for custom icons anymore.
Add an extra loop to the icon get feature to treat icons that are the
reflection of combined dates.
Update POD mentioning where to place the custom images.
Remove unnecessary Legend variable.
diff --git a/etc/RTxCalendar_Config.pm b/etc/RTxCalendar_Config.pm
new file mode 100644
index 0000000..35d9ccf
--- /dev/null
+++ b/etc/RTxCalendar_Config.pm
@@ -0,0 +1,13 @@
+Set(%CalendarIcons, (
+ 'Reminder' => 'reminder.png',
+ 'Resolved' => 'resolved.png',
+ 'Starts, Due' => 'starts_due.png',
+ 'Created, Due' => 'created_due.png',
+ 'Created' => 'created.png',
+ 'Due' => 'due.png',
+ 'Starts' => 'starts.png',
+ 'Started' => 'started.png',
+ 'LastUpdated' => 'updated.png',
+));
+
+1;
diff --git a/html/Elements/CalendarEvent b/html/Elements/CalendarEvent
index f684aa0..a125970 100644
--- a/html/Elements/CalendarEvent
+++ b/html/Elements/CalendarEvent
@@ -6,7 +6,7 @@ $DateTypes => undef
<div class="day">
<small>
- <% RTx::Calendar::GetEventIcon($Object, $today, $DateTypes, $IsReminder)|n %>
+ <% RTx::Calendar::GetEventImg($Object, $today, $DateTypes, $IsReminder)|n %>
<a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>" <% $StatusColor|n %>>
<% $Object->QueueObj->Name %> #<% $TicketId %>
<% $display_owner ? 'by ' . $Object->OwnerObj->Name : '' %>
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index fe64d11..efe4a51 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -156,34 +156,35 @@ $FilterOnStatusClear => undef
<div class="col-2 pl-1 pr-1"> </div>
<div class="col-auto text-left pl-1 pr-1"><b><&|/l&>Event Types</&></b></div>
</div>
-% foreach my $legend (sort keys %legend) {
- <div class="row">
- <div class="col-3 text-right pl-1 pr-1">
- <img src="<%$RT::WebImagesURL%>/<%$legend%>.png" />
- </div>
- <div class="col text-left pl-1 pr-1">
-% my $more = 0;
-% foreach ( @{$legend{$legend}} ) {
- <% $more++ ? ', ' : '' %>
- <&|/l&><% $_ %></&>
-% }
- </div>
- </div>
-% }
-% if (RT->Config->Get('CalendarCustomIcons')) {
-% my %CalendarCustomIcons = RT->Config->Get('CalendarCustomIcons');
-% foreach my $legend (sort keys %CalendarCustomIcons) {
-% my $legendLabel = $legend;
-% $legendLabel =~ s/^CF\.\{(.*)\}/$1/;
+<%perl>
+my %CalendarIcons = RT->Config->Get('CalendarIcons');
+# Sort the legend after translation
+my %CalendarIconsTranslated;
+my $LegendLabel;
+foreach my $legend (sort { lc($a) cmp lc($b) } keys %CalendarIcons) {
+ my @LegendLabels = split ',', $legend;
+ $LegendLabel = join ', ',
+ map {
+ $_ =~ s/^\s+|\s+$//g;
+ $_ =~ s/^CF\.\{(.*)\}/$1/;
+ $_ = 'Last Updated' if $_ eq 'LastUpdated';
+ loc($_)
+ } @LegendLabels;
+ $CalendarIconsTranslated{$LegendLabel} = $legend;
+}
+foreach my $TranslatedLegend (sort keys %CalendarIconsTranslated) {
+</%perl>
<div class="row">
<div class="col-3 text-right pl-1 pr-1">
- <span class="tip"><% $CalendarCustomIcons{$legend}|n %></span>
+ <span class="tip">
+ <img
+ src="<% $RT::WebImagesURL %>/<%
+ $CalendarIcons{$CalendarIconsTranslated{$TranslatedLegend}}|n %>" /></span>
</div>
<div class="col text-left pl-1 pr-1">
- <&|/l&><% $legendLabel %></&>
+ <% $TranslatedLegend %>
</div>
</div>
-% }
% }
</div>
<div class="col-6">
@@ -237,20 +238,6 @@ portlet by saving a query with the name <code>calendar</code> in the [_1].
</&>
-<%ONCE>
-
-my %legend = (
- 'created' => ['Created'],
- 'due' => ['Due'],
- 'resolved' => ['Resolved'],
- 'updated' => ['Last Updated'],
- 'created_due' => ['Created','Due'],
- 'reminder' => ['Reminders'],
- 'started' => ['Started'],
- 'starts_due' => ['Starts','Due'],
-);
-
-</%ONCE>
<%INIT>
if ($FilterOnStatusClear) {
$Query = $BaseQuery if $BaseQuery;
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 780e59f..53d9348 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -160,71 +160,57 @@ sub SearchDefaultCalendar {
}
}
-sub GetEventIcon {
- my $Object = shift;
+sub GetEventImg {
+ my $Object = shift;
my $CurrentDate = shift;
- my $DateTypes = shift;
+ my $DateTypes = shift;
my $IsReminder = shift;
my $EventIcon;
- if (RT->Config->Get('CalendarCustomIcons')) {
- my %CalendarCustomIcons = RT->Config->Get('CalendarCustomIcons');
- for my $DateField (keys %CalendarCustomIcons) {
- my $DateValue;
- if ($DateField =~ /^CF\./){
+ my %CalendarIcons = RT->Config->Get('CalendarIcons');
+CALENDAR_ICON:
+ for my $DateField ( keys %CalendarIcons ) {
+
+ # Icon can be a combination of two dates such as Due-Created,
+ # or CF.{Date Field}-Created. It can be also single date such as Created
+ my @DatesToCompare = split( /,/, $DateField );
+ DATE_COMPARE:
+ for my $ComparedDate (@DatesToCompare) {
+ # trim spaces
+ $ComparedDate =~ s/^\s+|\s+$//g;
+ if ( $DateField eq 'Reminder' ) {
+ if ( $IsReminder
+ && RTx::Calendar::LocalDate( $Object->DueObj->Unix ) eq
+ $CurrentDate )
+ {
+ $EventIcon = 'reminder.png';
+ last CALENDAR_ICON;
+ }
+ } elsif ( $DateField =~ /^CF\./ ) {
my $cf = $DateField;
$cf =~ s/^CF\.\{(.*)\}/$1/;
- $DateValue = $Object->FirstCustomFieldValue($cf);
- next unless $DateValue;
+ my $DateValue = $Object->FirstCustomFieldValue($cf);
+ next CALENDAR_ICON unless $DateValue;
$DateValue =~ s/(.*) (.*)/$1/;
+ next CALENDAR_ICON unless $DateValue eq $CurrentDate;
} else {
- my $DateObj = $DateField . "Obj";
- $DateValue = LocalDate( $Object->$DateObj->Unix );
- }
- if ($DateValue eq $CurrentDate) {
- $EventIcon = $CalendarCustomIcons{$DateField};
- return $EventIcon;
+ my $DateObj = $ComparedDate . "Obj";
+ my $DateValue
+ = RTx::Calendar::LocalDate( $Object->$DateObj->Unix );
+ next CALENDAR_ICON unless $DateValue eq $CurrentDate;
}
+
+ # If we are here, it means that all comparissons are true
+ $EventIcon = $CalendarIcons{$DateField};
}
}
- if ($IsReminder and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/reminder.png" />';
-
- } elsif ($DateTypes->{Resolved}
- and RTx::Calendar::LocalDate($Object->ResolvedObj->Unix) eq $CurrentDate) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/resolved.png" />';
-
- } elsif ($DateTypes->{Starts} and $DateTypes->{Due}
- and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $CurrentDate and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate ) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/starts_due.png" />';
-
- } elsif ($DateTypes->{Due} and $DateTypes->{Created}
- and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $CurrentDate ) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/created_due.png" />';
-
- } elsif ($DateTypes->{Starts}
- and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $CurrentDate) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/starts.png" />';
-
- } elsif ($DateTypes->{Due}
- and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/due.png" />';
-
- } elsif ($DateTypes->{Created}
- and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $CurrentDate) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/created.png" />';
-
- } elsif ($DateTypes->{Started}
- and RTx::Calendar::LocalDate($Object->StartedObj->Unix) eq $CurrentDate) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/started.png" />';
-
- } elsif ($DateTypes->{LastUpdated}
- and RTx::Calendar::LocalDate($Object->LastUpdatedObj->Unix) eq $CurrentDate) {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/updated.png" />';
-
+ if ($EventIcon) {
+ return '<img src="' . $RT::WebImagesURL . '/' . $EventIcon . '" />';
+ } else {
+ return '';
}
- return $EventIcon;
}
+
1;
__END__
@@ -340,13 +326,15 @@ adding the C<$CalendarColorStatusMap> setting to your F<etc/RT_SiteConfig.pm>:
=head3 Custom icons
Custom Icons can be defined for the events in the calendar by adding the
-C<$CalendarCustomIcons> setting to your F<etc/RT_SiteConfig.pm>:
+C<$CalendarIcons> setting to your F<etc/RT_SiteConfig.pm>:
- Set(%CalendarCustomIcons, (
+ Set(%CalendarIcons, (
'CF.{Maintenance Estimated Start Date/Time - ET}'
- => '<small class="ml-1"><i class="fas fa-cog"></i></small>'
+ => 'maint.png',
));
+The images should be placed on F<local/static/images>.
+
=head1 USAGE
A small help section is available in /Search/Calendar.html
commit 72650586f5057a7da712c9c3324603d1036387e4
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 16:03:46 2023 -0300
Update custom color feature to use reminder status
It was coloring the event based on the associated ticket status, but
the status of the reminder is more important.
diff --git a/html/Elements/CalendarEvent b/html/Elements/CalendarEvent
index 9a6750f..f684aa0 100644
--- a/html/Elements/CalendarEvent
+++ b/html/Elements/CalendarEvent
@@ -58,7 +58,7 @@ if ($Object->Type eq 'reminder') {
$ticket = $Object->RefersTo->First->TargetObj;
$TicketId = $ticket->Id;
$subject = $Object->Subject . " (" . $ticket->Subject . ")";
- $status = $ticket->Status;
+ $status = $Object->Status;
}
} else {
$TicketId = $Object->Id;
commit db7281db5587192bd92c0566daccba98e1badfd8
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 14:54:21 2023 -0300
Update CalendarSortEvents setting documentation
Describe that the setting is a subroutine reference, and what it
expects and returns.
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index faef4ac..780e59f 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -311,8 +311,12 @@ mouse over a date in F<etc/RT_SiteConfig.pm>:
=head3 Event sorting
You can set the order that the events will presented in the day cell with
-the C<$CalendarSortEvents> setting. The following example sorts
-the events by status:
+the C<$CalendarSortEvents> setting.
+
+This setting takes a subroutine reference that will receive an array of
+L<RT::Ticket> objects and should return a sorted array of L<RT::Ticket>.
+
+The following example sorts the events by status:
Set($CalendarSortEvents, sub {
my @Tickets = @_;
commit 1525452251653329e8249b83ee2bca7105588c1f
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 14:51:10 2023 -0300
Update POD organization
Add third level headings to organize display configurations and
make it easier to describe each feature.
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 17c154c..faef4ac 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -294,16 +294,22 @@ C<$HomepageComponents> in F<etc/RT_SiteConfig.pm>:
=head2 Display configuration
+=head3 Displaying the owner
+
You can show the owner in each day box by adding this line to your
F<etc/RT_SiteConfig.pm>:
Set($CalendarDisplayOwner, 1);
+=head3 Displaying custom fields
+
You can change which fields show up in the popup display when you
mouse over a date in F<etc/RT_SiteConfig.pm>:
Set(@CalendarPopupFields, ('Status', 'OwnerObj->Name', 'DueObj->ISO'));
+=head3 Event sorting
+
You can set the order that the events will presented in the day cell with
the C<$CalendarSortEvents> setting. The following example sorts
the events by status:
@@ -314,6 +320,8 @@ the events by status:
return @SortedTickets;
});
+=head3 Event colors
+
It's also possible to change the color of the events in the calendar by
adding the C<$CalendarColorStatusMap> setting to your F<etc/RT_SiteConfig.pm>:
@@ -325,6 +333,8 @@ adding the C<$CalendarColorStatusMap> setting to your F<etc/RT_SiteConfig.pm>:
'resolved' => '#aaa',
));
+=head3 Custom icons
+
Custom Icons can be defined for the events in the calendar by adding the
C<$CalendarCustomIcons> setting to your F<etc/RT_SiteConfig.pm>:
commit 8c18c89aa77ae6cb939d0c9c5a2d31419d309bc6
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 14:46:17 2023 -0300
Update Calendar sorting config name
Update the config name from CalendarSortCalendarEvents to
CalendarSortEvents.
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index b037886..fe64d11 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -366,7 +366,7 @@ for my $Dates (keys %Tickets) {
my $SortCalendarEvents = sub {
return @_;
};
-if (RT->Config->Get("CalendarSortCalendarEvents")) {
- $SortCalendarEvents = RT->Config->Get("CalendarSortCalendarEvents");
+if (RT->Config->Get("CalendarSortEvents")) {
+ $SortCalendarEvents = RT->Config->Get("CalendarSortEvents");
}
</%INIT>
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index dd3a6fd..17c154c 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -305,10 +305,10 @@ mouse over a date in F<etc/RT_SiteConfig.pm>:
Set(@CalendarPopupFields, ('Status', 'OwnerObj->Name', 'DueObj->ISO'));
You can set the order that the events will presented in the day cell with
-the C<$CalendarSortCalendarEvents> setting. The following example sorts
+the C<$CalendarSortEvents> setting. The following example sorts
the events by status:
- Set($CalendarSortCalendarEvents, sub {
+ Set($CalendarSortEvents, sub {
my @Tickets = @_;
my @SortedTickets = sort { lc($a->Status) cmp lc($b->Status) } @Tickets;
return @SortedTickets;
commit 7b22f4f1274e65c3ad6a3eba6ee703c7b11431f7
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 14:36:36 2023 -0300
Small code formatting for better readability
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index b0eb038..dd3a6fd 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -100,6 +100,7 @@ sub FindTickets {
my $DateObj = $Date . "Obj";
$dateindex = LocalDate( $Ticket->$DateObj->Unix );
}
+
push @{ $Tickets{$dateindex } },
$Ticket
commit 6207d7547be40a154b30a01ec05f2aca291a5e22
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 14:18:47 2023 -0300
Refactor Custom Field checking for the Calendar
Remove pre-loading of all Custom Fields, and instead only load the
Custom Fields that are used by the Calendar, declared on the Format
attribute.
Also, update the way that the date content of the custom field was parsed
for consistency. Instead of using regex, we now load it to a Date Object
and parse it with LocalDate.
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index cbd1903..b0eb038 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -79,9 +79,23 @@ sub FindTickets {
if ($Date =~ /^CF\./){
my $cf = $Date;
$cf =~ s/^CF\.\{(.*)\}/$1/;
- $dateindex = $Ticket->FirstCustomFieldValue($cf);
- next unless $dateindex;
- $dateindex =~ s/(.*) (.*)/$1/;
+
+ my $CFDateValue = $Ticket->FirstCustomFieldValue($cf);
+ next unless $CFDateValue;
+ my $CustomFieldObj = RT::CustomField->new($CurrentUser);
+ $CustomFieldObj->LoadByName( Name => $cf );
+ my $CustomFieldObjType = $CustomFieldObj->Type;
+ my $DateObj = RT::Date->new($CurrentUser);
+ if ( $CustomFieldObjType eq 'Date' ) {
+ $DateObj->Set(
+ Format => 'unknown',
+ Value => $CFDateValue,
+ Timezone => 'utc'
+ );
+ } else {
+ $DateObj->Set( Format => 'ISO', Value => $CFDateValue );
+ }
+ $dateindex = LocalDate( $DateObj->Unix );
} else {
my $DateObj = $Date . "Obj";
$dateindex = LocalDate( $Ticket->$DateObj->Unix );
commit 262d72628e5d4cbe0d06b7e147afc667ae2d074c
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 24 14:05:03 2023 -0300
Add comment about $dateindex to explain how it's used
When we added the date and date time Custom Field support to the
calendar, we added a bit of complexity to the code and needed to
add use of a new variable, $dateindex, to extract the correct date
from the Custom Field value and index the Ticket into the correct
date bucket.
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index e0b9390..cbd1903 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -71,6 +71,10 @@ sub FindTickets {
# How to find the LastContacted date ?
for my $Date (@$Dates) {
+
+ # $dateindex is the date to use as key in the Tickets Hash
+ # in the YYYY-MM-DD format
+ # Tickets are then groupd by date in the %Tickets hash
my $dateindex;
if ($Date =~ /^CF\./){
my $cf = $Date;
commit 43140bd7ab6cd151d3ab5ec8b96b43d29f03136b
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Wed Aug 23 17:14:10 2023 -0300
Add Date Custom Field support to the calendar
Only Date Time custom fields were supported in the calendar. This patch
adds support for Date custom fields.
Also, change the way we check for the Custom Field type, allowing loading
all Date and Date Time custom fields even if they are not in the Format
attribute.
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index 2f7a599..b037886 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -261,17 +261,6 @@ my $title = loc("Calendar");
my @DateTypes = qw/Created Starts Started Due LastUpdated Resolved/;
-# push Date Time CFs to DateTypes
-my $CFs = RT::CustomFields->new($session{'CurrentUser'});
-$CFs->Limit(
- FIELD => 'Type',
- VALUE => 'DateTime',
-);
-
-while ( my $CF = $CFs->Next ) {
- push @DateTypes, 'CustomField.{' . $CF->Name . '}';
-}
-
my $rtdate = RT::Date->new($session{'CurrentUser'});
my $weekstart = 'Sunday'; #RT::SiteConfig? user pref?
@@ -329,12 +318,22 @@ $TempQuery = $Query if $Query;
$TempFormat = $Format if $Format;
# we search all date types in Format string
-my @Dates = grep {
- my $LintField=${_};
- $LintField=~s/(\{|\})/\\$1/;
- $TempFormat =~ m/__$LintField(Relative)?__/
-} @DateTypes;
+my @CoreDates = grep { $TempFormat =~ m/__${_}(Relative)?__/ } @DateTypes;
+my @CustomFields = ( $TempFormat =~ /__(CustomField\.\{.*\})__/g );
+my @DateCustomFields;
+
+for my $CustomField (@CustomFields) {
+ my $LintCustomField = $CustomField;
+ $LintCustomField =~ s/CustomField\.\{(.*)\}/$1/;
+ my $CustomFieldObj = RT::CustomField->new( RT->SystemUser );
+ $CustomFieldObj->LoadByName( Name => $LintCustomField );
+ push @DateCustomFields, $CustomField
+ if $CustomFieldObj->id
+ && ( $CustomFieldObj->Type eq 'Date'
+ || $CustomFieldObj->Type eq 'DateTime' );
+}
+my @Dates = (@CoreDates, @DateCustomFields);
@Dates = map { $_ =~ s/^CustomField\.(.*)$/CF.$1/; $_ } @Dates;
# used to display or not a date in Element/CalendarEvent
commit b5488423f7aa9591613b08a07836f126357d9da5
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Wed Aug 23 16:15:26 2023 -0300
Remove general icon from non match events
If custom icon is not set to a Custom Field based event, then we will
not show a standard icon for that.
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 5ebd0f9..e0b9390 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -202,8 +202,6 @@ sub GetEventIcon {
and RTx::Calendar::LocalDate($Object->LastUpdatedObj->Unix) eq $CurrentDate) {
$EventIcon = '<img src="' . $RT::WebImagesURL . '/updated.png" />';
- } else {
- $EventIcon = '<img src="' . $RT::WebImagesURL . '/reminder.png" />';
}
return $EventIcon;
}
commit 8299ab50c7e1647b587bd3f554f7a4120ca15188
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Tue Aug 22 14:44:21 2023 -0300
Add button to Download Calendar events
Add button that download the events of the calendar that are shown in the
current view.
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index 3ccc107..2f7a599 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -56,12 +56,14 @@ $FilterOnStatusClear => undef
% }
</select>
</div>
- <div class="col-2 text-left">
+ <div class="col text-left">
% if ($FilterOnStatus[0]) {
<button type="submit" id="FilterOnStatusClear" name="FilterOnStatusClear"
value="1" class="button btn btn-primary"><% loc('Clear') %></button>
% }
<input type="submit" value="<% loc('Filter') %>" class="button btn btn-primary" />
+ <a href="<%$RT::WebPath%>/Search/Results.tsv?<%$DownloadQueryString%>"
+ class="button btn btn-primary ml-2"><% loc('Download as Spreadsheet') %></a>
</div>
</div>
</div>
@@ -344,6 +346,15 @@ $m->callback( CallbackName => 'BeforeFindTickets', ARGSRef => \%ARGS, QueryRef =
my %Tickets = RTx::Calendar::FindTickets($session{'CurrentUser'}, $TempQuery, \@Dates, $date->strftime("%F"), $end->strftime("%F"));
+my $DownloadQueryString =
+ $m->comp(
+ '/Elements/QueryString',
+ Query => $TempQuery,
+ Format => $Format,
+ Order => $Order,
+ OrderBy => $OrderBy,
+ );
+
my %StatusesAvailable;
for my $Dates (keys %Tickets) {
my $TicketsOnTheDate = $Tickets{$Dates};
commit e950a511ea92100b33a002f1bba0078f2e206e3a
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Tue Aug 22 14:17:11 2023 -0300
Add Status Filter to Calendar
Allow user to filter events by status.
Also update the table header to be a bootstrap div container instead
of a table, so it can accommodate the new filter better.
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index 71ea271..3ccc107 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -7,6 +7,9 @@ $Order => undef
$OrderBy => undef
$RowsPerPage => undef
$NewQuery => 0
+ at FilterOnStatus => undef
+$BaseQuery => undef
+$FilterOnStatusClear => undef
</%args>
<& /Elements/Header, Title => $title &>
@@ -22,29 +25,57 @@ $NewQuery => 0
<&| /Widgets/TitleBox,
title => loc('Calendar for [_1] [_2]', $rtdate->GetMonth($Month), $Year) &>
-<table width="100%">
-<tr>
-<td align="left">
+<form id="FilterOnStatusForm"
+ action="<%$RT::WebPath%>/Search/Calendar.html?<%$QueryString%>" method="post">
+ <input type="hidden" name="BaseQuery" value="<%$BaseQuery%>" />
+ <div class="container col-12 mt-1 mb-1">
+ <div class="row align-items-center">
+ <div class="col-1 text-left">
% my ($PMonth, $PYear) = ($Month - 1, $Year);
% if ($PMonth < 0) {
% $PYear--;
% $PMonth = 11;
% }
-<a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">« <%$rtdate->GetMonth($PMonth)%></a>
-</td>
-<th align="center">
- <font size="+1"><% $rtdate->GetMonth($Month). " $Year" %></font>
-</th>
-<td align="right">
+ <a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$PMonth%>&Year=<%$PYear%>&<%$QueryString%>">« <%$rtdate->GetMonth($PMonth)%></a>
+ </div>
+ <div class="col text-center">
+ <div class="row">
+ <div class="col-2">
+ <font size="+1"><% $rtdate->GetMonth($Month). " $Year" %></font>
+ </div>
+ <div class="col-2 label"><% loc( 'Filter on [_1]', loc('Status') ) %>:</div>
+ <div class="col-3">
+ <select name="FilterOnStatus" id="FilterOnStatus"
+ class="selectpicker form-control tall" multiple="multiple" size="6">
+% for my $Status (sort keys %StatusesAvailable) {
+ <option value="<% $Status %>"
+% if (@FilterOnStatus && $FilterOnStatus[0]) {
+ <% (grep { $Status eq $_ } @FilterOnStatus) ? 'selected="selected"':''%>
+% }
+ ><% loc($Status) %></option>
+% }
+ </select>
+ </div>
+ <div class="col-2 text-left">
+% if ($FilterOnStatus[0]) {
+ <button type="submit" id="FilterOnStatusClear" name="FilterOnStatusClear"
+ value="1" class="button btn btn-primary"><% loc('Clear') %></button>
+% }
+ <input type="submit" value="<% loc('Filter') %>" class="button btn btn-primary" />
+ </div>
+ </div>
+ </div>
+ <div class="col-1 text-right">
% my ($NMonth, $NYear) = ($Month + 1, $Year);
% if ($NMonth > 11) {
% $NYear++;
% $NMonth = 0;
% }
-<a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%> »</a>
-</td>
-</tr>
-</table>
+ <a href="<%$RT::WebPath%>/Search/Calendar.html?Month=<%$NMonth%>&Year=<%$NYear%>&<%$QueryString%>"><%$rtdate->GetMonth($NMonth)%> »</a>
+ </div>
+ </div>
+</div>
+</form>
<table class="rtxcalendar">
@@ -219,6 +250,11 @@ my %legend = (
</%ONCE>
<%INIT>
+if ($FilterOnStatusClear) {
+ $Query = $BaseQuery if $BaseQuery;
+ @FilterOnStatus = ();
+}
+$BaseQuery ||= $Query;
my $title = loc("Calendar");
my @DateTypes = qw/Created Starts Started Due LastUpdated Resolved/;
@@ -256,10 +292,16 @@ my $set = DateTime::Set->from_recurrence(
next => sub { $_[0]->truncate( to => 'day' )->add( days => 1 ) }
);
+if ($FilterOnStatus[0]) {
+ my $StatusClause = join " OR ", map { "Status = '$_'" } @FilterOnStatus;
+ $Query .= " AND " if $Query;
+ $Query .= "($StatusClause)";
+}
+
my $QueryString =
$m->comp(
'/Elements/QueryString',
- Query => $Query,
+ Query => $BaseQuery,
Format => $Format,
Order => $Order,
OrderBy => $OrderBy,
@@ -302,6 +344,15 @@ $m->callback( CallbackName => 'BeforeFindTickets', ARGSRef => \%ARGS, QueryRef =
my %Tickets = RTx::Calendar::FindTickets($session{'CurrentUser'}, $TempQuery, \@Dates, $date->strftime("%F"), $end->strftime("%F"));
+my %StatusesAvailable;
+for my $Dates (keys %Tickets) {
+ my $TicketsOnTheDate = $Tickets{$Dates};
+ for my $Ticket (@$TicketsOnTheDate) {
+ my $Status = $Ticket->Status;
+ $StatusesAvailable{$Status}++;
+ }
+}
+
my $SortCalendarEvents = sub {
return @_;
};
commit 5c6a9fd71ac85a15a869b1b821586fccb3949abf
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 17 15:44:01 2023 -0300
Update the legend of the Calendar
Upgrade the code of the legend area to match bootstrap 4.
Added the custom icons to the legend.
Added the custom colors and their statuses to the legend.
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index 5225cca..71ea271 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -116,23 +116,54 @@ $NewQuery => 0
</tr>
</table>
-<table width="100%">
-% foreach my $legend (sort keys %legend) {
- <tr>
- <td align="right">
- <img src="<%$RT::WebImagesURL%>/<%$legend%>.png" />
- </td>
- <td align="left">
-% my $more = 0;
-% foreach ( @{$legend{$legend}} ) {
- <% $more++ ? ', ' : '' %>
- <&|/l&><% $_ %></&>
+<div class="container mt-4">
+ <div class="row">
+ <div class="col-6">
+ <div class="row">
+ <div class="col-2 pl-1 pr-1"> </div>
+ <div class="col-auto text-left pl-1 pr-1"><b><&|/l&>Event Types</&></b></div>
+ </div>
+% foreach my $legend (sort keys %legend) {
+ <div class="row">
+ <div class="col-3 text-right pl-1 pr-1">
+ <img src="<%$RT::WebImagesURL%>/<%$legend%>.png" />
+ </div>
+ <div class="col text-left pl-1 pr-1">
+% my $more = 0;
+% foreach ( @{$legend{$legend}} ) {
+ <% $more++ ? ', ' : '' %>
+ <&|/l&><% $_ %></&>
+% }
+ </div>
+ </div>
+% }
+% if (RT->Config->Get('CalendarCustomIcons')) {
+% my %CalendarCustomIcons = RT->Config->Get('CalendarCustomIcons');
+% foreach my $legend (sort keys %CalendarCustomIcons) {
+% my $legendLabel = $legend;
+% $legendLabel =~ s/^CF\.\{(.*)\}/$1/;
+ <div class="row">
+ <div class="col-3 text-right pl-1 pr-1">
+ <span class="tip"><% $CalendarCustomIcons{$legend}|n %></span>
+ </div>
+ <div class="col text-left pl-1 pr-1">
+ <&|/l&><% $legendLabel %></&>
+ </div>
+ </div>
% }
- </td>
- </tr>
-% }
-
-</table>
+% }
+ </div>
+ <div class="col-6">
+% if (RT->Config->Get('CalendarColorStatusMap')) {
+ <b><&|/l&>State Colors</&></b><br />
+% my %ColorStatusMap = RT->Config->Get('CalendarColorStatusMap');
+% foreach my $Status (sort { lc($a) cmp lc($b) } keys %ColorStatusMap) {
+ <span style="color: <% $ColorStatusMap{$Status} %>"><% $Status %><span><br />
+% }
+% }
+ </div>
+ </div>
+</div>
</&>
commit 3a7a63e931398674a710c6a6d4649302e8f1c2eb
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 17 15:43:46 2023 -0300
Add feature to customize Icon of events on the calendar
Since we allow now to add custom fields to the calendar, we need to
allow to customize the icon of the event based on its type.
diff --git a/html/Elements/CalendarEvent b/html/Elements/CalendarEvent
index ca374f7..9a6750f 100644
--- a/html/Elements/CalendarEvent
+++ b/html/Elements/CalendarEvent
@@ -6,45 +6,7 @@ $DateTypes => undef
<div class="day">
<small>
-% if ($IsReminder and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today) {
- <img src="<%$RT::WebImagesURL%>/reminder.png" />
-
-% } elsif ($DateTypes->{Resolved}
-% and RTx::Calendar::LocalDate($Object->ResolvedObj->Unix) eq $today) {
- <img src="<%$RT::WebImagesURL%>/resolved.png" />
-
-% } elsif ($DateTypes->{Starts} and $DateTypes->{Due}
-% and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $today and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today ) {
- <img src="<%$RT::WebImagesURL%>/starts_due.png" />
-
-% } elsif ($DateTypes->{Due} and $DateTypes->{Created}
-% and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $today ) {
- <img src="<%$RT::WebImagesURL%>/created_due.png" />
-
-% } elsif ($DateTypes->{Starts}
-% and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $today) {
- <img src="<%$RT::WebImagesURL%>/starts.png" />
-
-% } elsif ($DateTypes->{Due}
-% and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $today) {
- <img src="<%$RT::WebImagesURL%>/due.png" />
-
-% } elsif ($DateTypes->{Created}
-% and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $today) {
- <img src="<%$RT::WebImagesURL%>/created.png" />
-
-% } elsif ($DateTypes->{Started}
-% and RTx::Calendar::LocalDate($Object->StartedObj->Unix) eq $today) {
- <img src="<%$RT::WebImagesURL%>/started.png" />
-
-% } elsif ($DateTypes->{LastUpdated}
-% and RTx::Calendar::LocalDate($Object->LastUpdatedObj->Unix) eq $today) {
- <img src="<%$RT::WebImagesURL%>/updated.png" />
-
-% } else {
- <img src="<%$RT::WebImagesURL%>/reminder.png" />
-% }
-
+ <% RTx::Calendar::GetEventIcon($Object, $today, $DateTypes, $IsReminder)|n %>
<a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>" <% $StatusColor|n %>>
<% $Object->QueueObj->Name %> #<% $TicketId %>
<% $display_owner ? 'by ' . $Object->OwnerObj->Name : '' %>
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 61eeb5d..5ebd0f9 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -141,6 +141,73 @@ sub SearchDefaultCalendar {
}
}
+sub GetEventIcon {
+ my $Object = shift;
+ my $CurrentDate = shift;
+ my $DateTypes = shift;
+ my $IsReminder = shift;
+ my $EventIcon;
+ if (RT->Config->Get('CalendarCustomIcons')) {
+ my %CalendarCustomIcons = RT->Config->Get('CalendarCustomIcons');
+ for my $DateField (keys %CalendarCustomIcons) {
+ my $DateValue;
+ if ($DateField =~ /^CF\./){
+ my $cf = $DateField;
+ $cf =~ s/^CF\.\{(.*)\}/$1/;
+ $DateValue = $Object->FirstCustomFieldValue($cf);
+ next unless $DateValue;
+ $DateValue =~ s/(.*) (.*)/$1/;
+ } else {
+ my $DateObj = $DateField . "Obj";
+ $DateValue = LocalDate( $Object->$DateObj->Unix );
+ }
+ if ($DateValue eq $CurrentDate) {
+ $EventIcon = $CalendarCustomIcons{$DateField};
+ return $EventIcon;
+ }
+ }
+ }
+ if ($IsReminder and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/reminder.png" />';
+
+ } elsif ($DateTypes->{Resolved}
+ and RTx::Calendar::LocalDate($Object->ResolvedObj->Unix) eq $CurrentDate) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/resolved.png" />';
+
+ } elsif ($DateTypes->{Starts} and $DateTypes->{Due}
+ and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $CurrentDate and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate ) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/starts_due.png" />';
+
+ } elsif ($DateTypes->{Due} and $DateTypes->{Created}
+ and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $CurrentDate ) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/created_due.png" />';
+
+ } elsif ($DateTypes->{Starts}
+ and RTx::Calendar::LocalDate($Object->StartsObj->Unix) eq $CurrentDate) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/starts.png" />';
+
+ } elsif ($DateTypes->{Due}
+ and RTx::Calendar::LocalDate($Object->DueObj->Unix) eq $CurrentDate) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/due.png" />';
+
+ } elsif ($DateTypes->{Created}
+ and RTx::Calendar::LocalDate($Object->CreatedObj->Unix) eq $CurrentDate) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/created.png" />';
+
+ } elsif ($DateTypes->{Started}
+ and RTx::Calendar::LocalDate($Object->StartedObj->Unix) eq $CurrentDate) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/started.png" />';
+
+ } elsif ($DateTypes->{LastUpdated}
+ and RTx::Calendar::LocalDate($Object->LastUpdatedObj->Unix) eq $CurrentDate) {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/updated.png" />';
+
+ } else {
+ $EventIcon = '<img src="' . $RT::WebImagesURL . '/reminder.png" />';
+ }
+ return $EventIcon;
+}
+
1;
__END__
@@ -241,6 +308,14 @@ adding the C<$CalendarColorStatusMap> setting to your F<etc/RT_SiteConfig.pm>:
'resolved' => '#aaa',
));
+Custom Icons can be defined for the events in the calendar by adding the
+C<$CalendarCustomIcons> setting to your F<etc/RT_SiteConfig.pm>:
+
+ Set(%CalendarCustomIcons, (
+ 'CF.{Maintenance Estimated Start Date/Time - ET}'
+ => '<small class="ml-1"><i class="fas fa-cog"></i></small>'
+ ));
+
=head1 USAGE
A small help section is available in /Search/Calendar.html
commit d280bf44f1f9c0cafbec71303b726c82b3beaebf
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Thu Aug 17 15:32:18 2023 -0300
Add feature to customize color of events on the calendar
diff --git a/html/Elements/CalendarEvent b/html/Elements/CalendarEvent
index 0f891b1..ca374f7 100644
--- a/html/Elements/CalendarEvent
+++ b/html/Elements/CalendarEvent
@@ -45,7 +45,7 @@ $DateTypes => undef
<img src="<%$RT::WebImagesURL%>/reminder.png" />
% }
- <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>">
+ <a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>" <% $StatusColor|n %>>
<% $Object->QueueObj->Name %> #<% $TicketId %>
<% $display_owner ? 'by ' . $Object->OwnerObj->Name : '' %>
<% length($Object->Subject) > 80 ? substr($Object->Subject, 0, 77) . "..." : $Object->Subject %></a></small><br />
@@ -88,17 +88,30 @@ my $TicketId;
my $ticket;
my $subject;
my $IsReminder;
+my $status;
if ($Object->Type eq 'reminder') {
$IsReminder = 1;
if ($Object->RefersTo->First) {
- $ticket = $Object->RefersTo->First->TargetObj;
- $TicketId = $ticket->Id;
- $subject = $Object->Subject . " (" . $ticket->Subject . ")";
+ $ticket = $Object->RefersTo->First->TargetObj;
+ $TicketId = $ticket->Id;
+ $subject = $Object->Subject . " (" . $ticket->Subject . ")";
+ $status = $ticket->Status;
}
} else {
$TicketId = $Object->Id;
$subject = $Object->Subject;
+ $status = $Object->Status;
+}
+
+# Colors per status
+my %CalendarColorStatusMap;
+if (RT->Config->Get('CalendarColorStatusMap')) {
+ %CalendarColorStatusMap = RT->Config->Get('CalendarColorStatusMap');
+}
+my $StatusColor = '';
+if ($CalendarColorStatusMap{$status}) {
+ $StatusColor ='style="color: '.$CalendarColorStatusMap{$status}.'"';
}
my $display_owner = $RT::CalendarDisplayOwner;
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 6413b9c..61eeb5d 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -230,6 +230,17 @@ the events by status:
return @SortedTickets;
});
+It's also possible to change the color of the events in the calendar by
+adding the C<$CalendarColorStatusMap> setting to your F<etc/RT_SiteConfig.pm>:
+
+ Set(%CalendarColorStatusMap, (
+ 'new' => 'blue',
+ 'open' => 'blue',
+ 'approved' => 'green',
+ 'rejected' => 'red',
+ 'resolved' => '#aaa',
+ ));
+
=head1 USAGE
A small help section is available in /Search/Calendar.html
commit 46b06b2cd10ef5a79c408abdf20bb3b6623d8916
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Wed Aug 16 11:45:20 2023 -0300
Add setting to allow customize the sort order of the events
Add $CalendarSortCalendarEvents setting to allow customize the sort order
of the events in a day cell of the calendar. This is a sub that takes
the Objects list (that can be tickets or reminders) and returns a sorted
list of the objects.
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index 00caeff..5225cca 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -68,7 +68,7 @@ $NewQuery => 0
<td class="<% @classes %>"><div class="inside-day">
<div class="calendardate"><%$date->day%></div>
-% for my $t ( @{ $Tickets{$date->strftime("%F")} } ) {
+% for my $t ( $SortCalendarEvents->( @{ $Tickets{ $date->strftime("%F") } || [] } )) {
<& /Elements/CalendarEvent, Object => $t, Date => $date, DateTypes => \%DateTypes &>
% }
@@ -271,4 +271,10 @@ $m->callback( CallbackName => 'BeforeFindTickets', ARGSRef => \%ARGS, QueryRef =
my %Tickets = RTx::Calendar::FindTickets($session{'CurrentUser'}, $TempQuery, \@Dates, $date->strftime("%F"), $end->strftime("%F"));
+my $SortCalendarEvents = sub {
+ return @_;
+};
+if (RT->Config->Get("CalendarSortCalendarEvents")) {
+ $SortCalendarEvents = RT->Config->Get("CalendarSortCalendarEvents");
+}
</%INIT>
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 3f03c77..6413b9c 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -220,6 +220,16 @@ mouse over a date in F<etc/RT_SiteConfig.pm>:
Set(@CalendarPopupFields, ('Status', 'OwnerObj->Name', 'DueObj->ISO'));
+You can set the order that the events will presented in the day cell with
+the C<$CalendarSortCalendarEvents> setting. The following example sorts
+the events by status:
+
+ Set($CalendarSortCalendarEvents, sub {
+ my @Tickets = @_;
+ my @SortedTickets = sort { lc($a->Status) cmp lc($b->Status) } @Tickets;
+ return @SortedTickets;
+ });
+
=head1 USAGE
A small help section is available in /Search/Calendar.html
commit 20a529c4f13e061592d8c0391a674a0df4d900a8
Author: Ronaldo Richieri <ronaldo at bestpractical.com>
Date: Fri Jul 28 16:10:17 2023 -0300
Allow date time Custom Fields to be used in Calendar
It's possible now to add __CustomField.{Custom Field Name}__ to search
format so it will appear on calendar.
diff --git a/html/Elements/CalendarEvent b/html/Elements/CalendarEvent
index 5b8a6c5..0f891b1 100644
--- a/html/Elements/CalendarEvent
+++ b/html/Elements/CalendarEvent
@@ -41,6 +41,8 @@ $DateTypes => undef
% and RTx::Calendar::LocalDate($Object->LastUpdatedObj->Unix) eq $today) {
<img src="<%$RT::WebImagesURL%>/updated.png" />
+% } else {
+ <img src="<%$RT::WebImagesURL%>/reminder.png" />
% }
<a href="<%$RT::WebPath%>/Ticket/Display.html?id=<%$TicketId%>">
@@ -60,6 +62,9 @@ $DateTypes => undef
%
% if ($attr =~ /(.*)->ISO$/ and $Object->$1->Unix <= 0) {
% $value = '-';
+% } elsif ($attr =~ /CustomField\.\{(.*)\}$/) {
+% my $cf = $1;
+% $value = $Object->FirstCustomFieldValue($cf);
% } else {
% my $method = '$Object->'.$attr.'()';
% $method =~ s/->ISO\(\)$/->ISO( Timezone => 'user' )/;
@@ -123,6 +128,7 @@ for my $field (@display_fields) {
my $label = $field;
$label =~ s'Obj-.(?:AsString|Name|ISO)''g;
$label =~ s'-\>MemberEmailAddressesAsString''g;
+ $label =~ s/CustomField\.\{(.*)\}/$1/g;
$label_of{$field} = $label;
}
diff --git a/html/Search/Calendar.html b/html/Search/Calendar.html
index 9c5e71e..00caeff 100644
--- a/html/Search/Calendar.html
+++ b/html/Search/Calendar.html
@@ -192,6 +192,17 @@ my $title = loc("Calendar");
my @DateTypes = qw/Created Starts Started Due LastUpdated Resolved/;
+# push Date Time CFs to DateTypes
+my $CFs = RT::CustomFields->new($session{'CurrentUser'});
+$CFs->Limit(
+ FIELD => 'Type',
+ VALUE => 'DateTime',
+);
+
+while ( my $CF = $CFs->Next ) {
+ push @DateTypes, 'CustomField.{' . $CF->Name . '}';
+}
+
my $rtdate = RT::Date->new($session{'CurrentUser'});
my $weekstart = 'Sunday'; #RT::SiteConfig? user pref?
@@ -243,7 +254,13 @@ $TempQuery = $Query if $Query;
$TempFormat = $Format if $Format;
# we search all date types in Format string
-my @Dates = grep { $TempFormat =~ m/__${_}(Relative)?__/ } @DateTypes;
+my @Dates = grep {
+ my $LintField=${_};
+ $LintField=~s/(\{|\})/\\$1/;
+ $TempFormat =~ m/__$LintField(Relative)?__/
+} @DateTypes;
+
+ at Dates = map { $_ =~ s/^CustomField\.(.*)$/CF.$1/; $_ } @Dates;
# used to display or not a date in Element/CalendarEvent
my %DateTypes = map { $_ => 1 } @Dates;
diff --git a/lib/RTx/Calendar.pm b/lib/RTx/Calendar.pm
index 9bb375d..3f03c77 100644
--- a/lib/RTx/Calendar.pm
+++ b/lib/RTx/Calendar.pm
@@ -71,14 +71,24 @@ sub FindTickets {
# How to find the LastContacted date ?
for my $Date (@$Dates) {
- my $DateObj = $Date . "Obj";
- push @{ $Tickets{ LocalDate( $Ticket->$DateObj->Unix ) } },
+ my $dateindex;
+ if ($Date =~ /^CF\./){
+ my $cf = $Date;
+ $cf =~ s/^CF\.\{(.*)\}/$1/;
+ $dateindex = $Ticket->FirstCustomFieldValue($cf);
+ next unless $dateindex;
+ $dateindex =~ s/(.*) (.*)/$1/;
+ } else {
+ my $DateObj = $Date . "Obj";
+ $dateindex = LocalDate( $Ticket->$DateObj->Unix );
+ }
+ push @{ $Tickets{$dateindex } },
$Ticket
# if reminder, check it's refering to a ticket
unless ( $Ticket->Type eq 'reminder'
and not $Ticket->RefersTo->First )
- or $AlreadySeen{ LocalDate( $Ticket->$DateObj->Unix ) }
+ or $AlreadySeen{ $dateindex }
{$Ticket}++;
}
}
-----------------------------------------------------------------------
hooks/post-receive
--
rtx-calendar
More information about the Bps-public-commit
mailing list