View Issue Details

IDProjectCategoryView StatusLast Update
0000087SOGoBackend Calendarpublic2010-04-19 21:18
Reporterfsayd Assigned Tofrancis  
PrioritynormalSeverityfeatureReproducibilityalways
Status resolvedResolutionfixed 
Product Version1.0.3 
Target Version1.2.2Fixed in Version1.2.2 
Summary0000087: Add support to recurrent events of type "First Monday of month"
Description

In the web calendar when the recurrence is set to custom of type
'1st [Monday, Tuesday, etc.] of month', the web interface say: "This type of recurrence is currently unsupported."
Some users of our organization need this feature.
It is possible to add this feature?

Thanks

TagsNo tags attached.

Relationships

parent of 0000577 resolvedfrancis Cannot edit this event in Month View 
has duplicate 0000401 resolvedfrancis Custom repeating event shows incorrectly on the web version 

Activities

mstucky

mstucky

2009-09-04 13:19

reporter   ~0000116

This is a serious problem for us as well. Also, when this type of event is added in Lightning, the web interface shows the event as being every Monday, instead of the "first Monday" of the month.

kameleon

kameleon

2010-03-25 19:30

reporter   ~0000802

This is needed here also. While a workaround is to manually add the event on each date needed, the feature should work.

2010-04-02 14:51

 

monthly-recurrence.diff (10,397 bytes)   
#
# old_revision [2a48eee9ca61b361fdcea65d94dfa403aad3388f]
#
# patch "SOPE/NGCards/iCalDailyRecurrenceCalculator.m"
#  from [f4abeb2c617d8ffdccd8044b6dba57360cc16168]
#    to [dd01d13e5d98da301110bee1c641706c77371d68]
# 
# patch "SOPE/NGCards/iCalRecurrenceRule.h"
#  from [77406b397c6aba6d5b0e9aab2d3d453e8e478aed]
#    to [d59c3197244bfc225bcf33d2190906639ffa8085]
# 
# patch "SOPE/NGCards/iCalRecurrenceRule.m"
#  from [9fc9d136f8eb901c30cfe0722a4d5984c92187ec]
#    to [48256c8bf3395d83fb88c1a29d5bc1d35a18d03f]
# 
# patch "UI/Scheduler/UIxComponentEditor.m"
#  from [feff5835f0974c20aa318a011590e6f077088c12]
#    to [edd1145aae23402f52cd8b13d812a1161055ae3e]
# 
# patch "UI/WebServerResources/UIxRecurrenceEditor.js"
#  from [bfe8647fac9f61e394b0ffa75de78d84e6770c81]
#    to [7a8a784805e38ccb8f56ecfb264ca574e60e8c11]
#
============================================================
--- SOPE/NGCards/iCalDailyRecurrenceCalculator.m	f4abeb2c617d8ffdccd8044b6dba57360cc16168
+++ SOPE/NGCards/iCalDailyRecurrenceCalculator.m	dd01d13e5d98da301110bee1c641706c77371d68
@@ -29,6 +29,7 @@
 
 #import "iCalRecurrenceCalculator.h"
 #import "iCalRecurrenceRule.h"
+#import "iCalByDayMask.h"
 
 @interface iCalDailyRecurrenceCalculator : iCalRecurrenceCalculator
 @end
@@ -90,24 +91,17 @@
       if ([startDate compare: currentStartDate] == NSOrderedAscending ||
 	  [startDate compare: currentStartDate] == NSOrderedSame)
 	{
-	  BOOL wrongDay = NO;
-	  unsigned int mask;
 	  NGCalendarDateRange *r;
+          iCalByDayMask *mask;
 
-	  if ([rrule byDayMask])
-	    {
-	      mask = ([currentStartDate dayOfWeek]
-		      ? (unsigned int) 1 << ([currentStartDate dayOfWeek])
-		      : iCalWeekDaySunday);
-	      if (([rrule byDayMask] & mask) != mask)
-		wrongDay = YES;
-	    }
-
-	  if (wrongDay == NO)
-	    {
-	      currentEndDate = [currentStartDate addTimeInterval: [firstRange duration]];
-	      r = [NGCalendarDateRange calendarDateRangeWithStartDate: currentStartDate
-				       endDate: currentEndDate];
+          mask = [rrule byDayMask];
+	  if (!mask || [mask occursOnDay: [currentStartDate dayOfWeek]])
+            {
+	      currentEndDate
+                = [currentStartDate addTimeInterval: [firstRange duration]];
+	      r = [NGCalendarDateRange
+                    calendarDateRangeWithStartDate: currentStartDate
+                                           endDate: currentEndDate];
 	      if ([_r containsDateRange: r])
 		[ranges addObject: r];
 	    }
============================================================
--- SOPE/NGCards/iCalRecurrenceRule.h	77406b397c6aba6d5b0e9aab2d3d453e8e478aed
+++ SOPE/NGCards/iCalRecurrenceRule.h	d59c3197244bfc225bcf33d2190906639ffa8085
@@ -45,18 +45,22 @@ typedef enum {
   iCalRecurrenceFrequenceYearly   = 7,
 } iCalRecurrenceFrequency;
 
+extern NSString *iCalWeekDayString[];
+
 typedef enum {
-  iCalWeekDaySunday    = 1,
-  iCalWeekDayMonday    = 2,
-  iCalWeekDayTuesday   = 4,
-  iCalWeekDayWednesday = 8,
-  iCalWeekDayThursday  = 16,
-  iCalWeekDayFriday    = 32,
-  iCalWeekDaySaturday  = 64,
+  iCalWeekDaySunday    = 0,
+  iCalWeekDayMonday    = 1,
+  iCalWeekDayTuesday   = 2,
+  iCalWeekDayWednesday = 3,
+  iCalWeekDayThursday  = 4,
+  iCalWeekDayFriday    = 5,
+  iCalWeekDaySaturday  = 6,
 } iCalWeekDay;
 
 @class NSString, NSCalendarDate, NGCalendarDateRange, NSArray;
 
+@class iCalByDayMask;
+
 @interface iCalRecurrenceRule : CardElement
 // {
 //   iCalRecurrenceFrequency frequency;
@@ -92,12 +96,14 @@ typedef enum {
 - (void) setWeekStart: (iCalWeekDay) _weekStart;
 - (iCalWeekDay) weekStart;
 
-- (void) setByDayMask: (unsigned int) _mask;
-- (unsigned int) byDayMask;
-- (int) byDayOccurence1;
+- (void) setByDay: (NSString *) newByDay;
+- (NSString *) byDay;
 
+- (void) setByDayMask: (iCalByDayMask *) newMask;
+- (iCalByDayMask *) byDayMask;
+
 - (NSArray *) byMonthDay;
-  
+
 /* count and untilDate are mutually exclusive */
 
 - (void) setRepeatCount: (int) _repeatCount;
============================================================
--- SOPE/NGCards/iCalRecurrenceRule.m	9fc9d136f8eb901c30cfe0722a4d5984c92187ec
+++ SOPE/NGCards/iCalRecurrenceRule.m	48256c8bf3395d83fb88c1a29d5bc1d35a18d03f
@@ -27,13 +27,16 @@
 
 #import <ctype.h>
 
+#import "iCalByDayMask.h"
 #import "NSCalendarDate+NGCards.h"
+#import "NSCalendarDate+ICal.h"
 #import "NSString+NGCards.h"
 
-#import "NSCalendarDate+ICal.h"
-
 #import "iCalRecurrenceRule.h"
 
+NSString *iCalWeekDayString[] = { @"SU", @"MO", @"TU", @"WE", @"TH", @"FR",
+                                  @"SA" };
+
 /*
   freq       = rrFreq;
   until      = rrUntil;
@@ -273,56 +276,56 @@
   return [self weekDayFromICalRepresentation: [self wkst]];
 }
 
-- (void) setByDayMask: (unsigned) _mask
+- (void) setByDay: (NSString *) newByDay
 {
-  NSMutableArray *days;
-  unsigned int count;
-  unsigned char maskDays[] = { iCalWeekDaySunday, iCalWeekDayMonday,
-			       iCalWeekDayTuesday, iCalWeekDayWednesday,
-			       iCalWeekDayThursday, iCalWeekDayFriday,
-			       iCalWeekDaySaturday };
-  days = [NSMutableArray arrayWithCapacity: 7];
-  if (_mask)
-    {
-      for (count = 0; count < 7; count++)
-        if (_mask & maskDays[count])
-          [days addObject:
-                  [self iCalRepresentationForWeekDay: maskDays[count]]];
-    }
+  [self setNamedValue: @"byday" to: newByDay];
+}
 
-  [self setNamedValue: @"byday" to: [days componentsJoinedByString: @","]];
+- (NSString *) byDay
+{
+  return [self namedValue: @"byday"];
 }
 
-- (unsigned int) byDayMask
+- (void) setByDayMask: (iCalByDayMask *) newByDayMask
 {
-  NSArray *days;
-  unsigned int mask, count, max;
-  NSString *day, *value;
+  [self setByDay: [newByDayMask asRuleString]];
+}
 
-  mask = 0;
+- (iCalByDayMask *) byDayMask
+{
+  return [iCalByDayMask byDayMaskWithRuleString: [self byDay]];
+}
 
-  value = [self namedValue: @"byday"];
-  if ([value length] > 0)
-    {
-      days = [value componentsSeparatedByString: @","];
-      max = [days count];
-      for (count = 0; count < max; count++)
-	{
-	  day = [days objectAtIndex: count];
-	  mask |= [self weekDayFromICalRepresentation: day];
-	}
-    }
+// - (unsigned int) byDayMask
+// {
+//   NSArray *days;
+//   unsigned int mask, count, max;
+//   NSString *day, *value;
 
-  return mask;
-}
+//   mask = 0;
 
-#warning this is bad
-- (int) byDayOccurence1
-{
-  return 0;
-//   return byDayOccurence1;
-}
+//   value = [self namedValue: @"byday"];
+//   if ([value length] > 0)
+//     {
+//       days = [value componentsSeparatedByString: @","];
+//       max = [days count];
+//       for (count = 0; count < max; count++)
+// 	{
+// 	  day = [days objectAtIndex: count];
+// 	  mask |= [self weekDayFromICalRepresentation: day];
+// 	}
+//     }
 
+//   return mask;
+// }
+
+// #warning this is bad
+// - (int) byDayOccurence1
+// {
+//   return 0;
+// //   return byDayOccurence1;
+// }
+
 - (NSArray *) byMonthDay
 {
   NSArray *byMonthDay;
============================================================
--- UI/Scheduler/UIxComponentEditor.m	feff5835f0974c20aa318a011590e6f077088c12
+++ UI/Scheduler/UIxComponentEditor.m	edd1145aae23402f52cd8b13d812a1161055ae3e
@@ -1731,15 +1731,22 @@ RANGE(2);
 	    [theRule setInterval: [self repeat1]];
 
 	    // We recur on specific days...
-	    if ([[self repeat2] intValue] == 1
-		&& [[self repeat5] intValue] > 0)
-	      {
-		[theRule setNamedValue: @"bymonthday" to: [self repeat5]];
+	    if ([[self repeat2] intValue] == 0)
+              {
+                NSString *day;
+                int weekDayNumber;
+
+                day = [theRule iCalRepresentationForWeekDay: [[self repeat4] intValue]];
+                weekDayNumber = [[self repeat3] intValue] + 1;
+                [theRule setNamedValue: @"byday"
+                                    to: [NSString stringWithFormat: @"%d%@",
+                                                  weekDayNumber, day]];
+              }
+            else
+              {
+                if ([[self repeat5] intValue] > 0)
+                  [theRule setNamedValue: @"bymonthday" to: [self repeat5]];
 	      }
-	    else
-	      {
-		// TODO
-	      }
 	  }
       }
       break;
============================================================
--- UI/WebServerResources/UIxRecurrenceEditor.js	bfe8647fac9f61e394b0ffa75de78d84e6770c81
+++ UI/WebServerResources/UIxRecurrenceEditor.js	7a8a784805e38ccb8f56ecfb264ca574e60e8c11
@@ -241,31 +241,31 @@ function handleMonthlyRecurrence() {
 
     var radioValue = $('recurrence_form').getRadioValue('monthlyRadioButtonName');
 
-    // FIXME - right now we do not support rules
-    //         such as The Second Tuesday...
-    if (radioValue == 0)
-        window.alert(recurrenceUnsupported);
-    else {
-        // We check if the monthlyMonthsField really contains an integer
-        var showError = true;
+    /* Xth day of the month:
+     repeat1: tous les X mois
+     repeat2: 0
+     repeat3: Xième jour Y du moins:
+     repeat4: jour Y: */
 
-        var fieldValue = "" + $('monthlyMonthsField').value;
-        if (fieldValue.length > 0) {
-            var v = parseInt(fieldValue);
-            if (!isNaN(v) && v > 0) {
-                validate = true;
-                showError = false;
-                parent$("repeat1").value = fieldValue;
-                parent$("repeat2").value = radioValue;
-                parent$("repeat3").value = $('monthlyRepeat').value;
-                parent$("repeat4").value = $('monthlyDay').value;
-                parent$("repeat5").value = getSelectedDays("month");
-            }
+    // We check if the monthlyMonthsField really contains an integer
+    var showError = true;
+
+    var fieldValue = "" + $('monthlyMonthsField').value;
+    if (fieldValue.length > 0) {
+        var v = parseInt(fieldValue);
+        if (!isNaN(v) && v > 0) {
+            validate = true;
+            showError = false;
+            parent$("repeat1").value = fieldValue;
+            parent$("repeat2").value = radioValue;
+            parent$("repeat3").value = $('monthlyRepeat').value;
+            parent$("repeat4").value = $('monthlyDay').value;
+            parent$("repeat5").value = getSelectedDays("month");
         }
+    }
 
-        if (showError)
-            window.alert(monthFieldInvalid);
-    }
+    if (showError)
+        window.alert(monthFieldInvalid);
 
     return validate;
 }
monthly-recurrence.diff (10,397 bytes)   
wsourdeau

wsourdeau

2010-04-02 14:51

viewer   ~0000856

The attached patch implements the web-side functionality and the beginning of an implementation in the backend.

francis

francis

2010-04-19 21:18

administrator   ~0000964

Fixed in revision 0e9f9326c164b5f5513aeb461785100c6c18fd0e.

Issue History

Date Modified Username Field Change
2009-08-05 15:19 fsayd New Issue
2009-09-04 13:19 mstucky Note Added: 0000116
2009-10-09 17:31 ludovic Fixed in Version => 1.1.0
2009-10-09 17:51 ludovic Fixed in Version 1.1.0 =>
2009-10-09 17:51 ludovic Target Version => 1.1.0
2009-10-14 20:19 francis Status new => assigned
2009-10-14 20:19 francis Assigned To => francis
2010-02-01 18:36 francis Relationship added has duplicate 0000401
2010-02-13 19:08 ludovic Target Version 1.1.0 => 1.2.1
2010-02-19 16:57 wsourdeau Target Version 1.2.1 =>
2010-02-23 14:10 ludovic Target Version => 1.2.2
2010-03-25 19:30 kameleon Note Added: 0000802
2010-04-02 14:51 wsourdeau File Added: monthly-recurrence.diff
2010-04-02 14:51 wsourdeau Note Added: 0000856
2010-04-17 22:11 francis Relationship added parent of 0000577
2010-04-19 21:18 francis Note Added: 0000964
2010-04-19 21:18 francis Status assigned => resolved
2010-04-19 21:18 francis Fixed in Version => 1.2.2
2010-04-19 21:18 francis Resolution open => fixed