(feat) we now handle optional and non-required attendee states
parent
2901560df9
commit
249671543e
3
NEWS
3
NEWS
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
- [web] create card from sender or recipient address (#3002, #4610)
|
- [web] create card from sender or recipient address (#3002, #4610)
|
||||||
- [core] baseDN now accept dynamic domain values (#3685)
|
- [core] baseDN now accept dynamic domain values (#3685 - sponsored by iRedMail)
|
||||||
|
- [core] we now handle optional and non-required attendee states
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
- [web] fixed all-day event dates with different timezone
|
- [web] fixed all-day event dates with different timezone
|
||||||
|
|
|
@ -62,3 +62,8 @@ vtodo_class2 = "(Confidential task)";
|
||||||
/* Resources */
|
/* Resources */
|
||||||
"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "Cannot access resource: \"%{Cn} %{SystemEmail}\"";
|
"Cannot access resource: \"%{Cn} %{SystemEmail}\"" = "Cannot access resource: \"%{Cn} %{SystemEmail}\"";
|
||||||
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}.";
|
"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}." = "Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}.";
|
||||||
|
|
||||||
|
/* Participation role */
|
||||||
|
"Your participation is required to this event" = "Your participation is required to this event";
|
||||||
|
"Your participation is optional to this event" = "Your participation is optional to this event";
|
||||||
|
"Your participation is not required to this event" = "Your participation is not required to this event";
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2007-2016 Inverse inc.
|
Copyright (C) 2007-2019 Inverse inc.
|
||||||
|
|
||||||
This file is part of SOGo
|
This file is part of SOGo
|
||||||
|
|
||||||
|
@ -187,9 +187,17 @@
|
||||||
{
|
{
|
||||||
SOGoAppointmentObject *attendeeObject;
|
SOGoAppointmentObject *attendeeObject;
|
||||||
iCalCalendar *iCalendarToSave;
|
iCalCalendar *iCalendarToSave;
|
||||||
|
iCalPerson *attendee;
|
||||||
|
SOGoUser *user;
|
||||||
|
|
||||||
iCalendarToSave = nil;
|
iCalendarToSave = nil;
|
||||||
|
user = [SOGoUser userWithLogin: theUID];
|
||||||
attendeeObject = [self _lookupEvent: [newEvent uid] forUID: theUID];
|
attendeeObject = [self _lookupEvent: [newEvent uid] forUID: theUID];
|
||||||
|
attendee = [newEvent userAsAttendee: user];
|
||||||
|
|
||||||
|
// If the atttende's role is NON-PARTICIPANT, we write nothing to its calendar
|
||||||
|
if ([[attendee role] caseInsensitiveCompare: @"NON-PARTICIPANT"] == NSOrderedSame)
|
||||||
|
return;
|
||||||
|
|
||||||
if ([newEvent recurrenceId])
|
if ([newEvent recurrenceId])
|
||||||
{
|
{
|
||||||
|
@ -197,12 +205,11 @@
|
||||||
if ([attendeeObject isNew])
|
if ([attendeeObject isNew])
|
||||||
{
|
{
|
||||||
iCalEvent *ownerEvent;
|
iCalEvent *ownerEvent;
|
||||||
SOGoUser *user;
|
|
||||||
// We check if the attendee that was added to a single occurence is
|
// We check if the attendee that was added to a single occurence is
|
||||||
// present in the master component. If not, we create a calendar with
|
// present in the master component. If not, we create a calendar with
|
||||||
// a single event for the occurence.
|
// a single event for the occurence.
|
||||||
ownerEvent = [[[newEvent parent] events] objectAtIndex: 0];
|
ownerEvent = [[[newEvent parent] events] objectAtIndex: 0];
|
||||||
user = [SOGoUser userWithLogin: theUID];
|
|
||||||
|
|
||||||
if (![ownerEvent userAsAttendee: user])
|
if (![ownerEvent userAsAttendee: user])
|
||||||
{
|
{
|
||||||
|
@ -339,7 +346,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self errorWithFormat: @"Unable to find event with UID %@ in %@'s calendar - skipping delete operation", nameInContainer, theUID];
|
[self errorWithFormat: @"Unable to find event with UID %@ in %@'s calendar - skipping delete operation. This can be normal for NON-PARTICIPANT attendees.", nameInContainer, theUID];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,6 +1178,10 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
|
||||||
NSException *error;
|
NSException *error;
|
||||||
BOOL addDelegate, removeDelegate;
|
BOOL addDelegate, removeDelegate;
|
||||||
|
|
||||||
|
// If the atttende's role is NON-PARTICIPANT, we write nothing to its calendar
|
||||||
|
if ([[attendee role] caseInsensitiveCompare: @"NON-PARTICIPANT"] == NSOrderedSame)
|
||||||
|
return;
|
||||||
|
|
||||||
error = nil;
|
error = nil;
|
||||||
|
|
||||||
eventObject = [self _lookupEvent: eventUID forUID: uid];
|
eventObject = [self _lookupEvent: eventUID forUID: uid];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2010-2012 Inverse
|
Copyright (C) 2010-2019 Inverse
|
||||||
|
|
||||||
This file is part of SOGo
|
This file is part of SOGo
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2006-2018 Inverse inc.
|
Copyright (C) 2006-2019 Inverse inc.
|
||||||
|
|
||||||
This file is part of SOGo.
|
This file is part of SOGo.
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
@class NSMutableDictionary;
|
@class NSMutableDictionary;
|
||||||
@class NSString;
|
@class NSString;
|
||||||
@class NSTimeZone;
|
@class NSTimeZone;
|
||||||
|
@class iCalPerson;
|
||||||
@class iCalRepeatableEntityObject;
|
@class iCalRepeatableEntityObject;
|
||||||
@class SOGoDateFormatter;
|
@class SOGoDateFormatter;
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
NSCalendarDate *oldEndDate;
|
NSCalendarDate *oldEndDate;
|
||||||
NSCalendarDate *newEndDate;
|
NSCalendarDate *newEndDate;
|
||||||
NSString *organizerName;
|
NSString *organizerName;
|
||||||
|
iCalPerson *currentAttendee;
|
||||||
NSMutableDictionary *values;
|
NSMutableDictionary *values;
|
||||||
SOGoDateFormatter *dateFormatter;
|
SOGoDateFormatter *dateFormatter;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +63,9 @@
|
||||||
- (void) setOrganizerName: (NSString *) theString;
|
- (void) setOrganizerName: (NSString *) theString;
|
||||||
- (NSString *) organizerName;
|
- (NSString *) organizerName;
|
||||||
|
|
||||||
|
- (void) setCurrentAttendee: (iCalPerson *) theAttendee;
|
||||||
|
- (iCalPerson *) currentAttendee;
|
||||||
|
|
||||||
- (NSCalendarDate *) oldStartDate;
|
- (NSCalendarDate *) oldStartDate;
|
||||||
- (NSCalendarDate *) newStartDate;
|
- (NSCalendarDate *) newStartDate;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2006-2013 Inverse inc.
|
Copyright (C) 2006-2019 Inverse inc.
|
||||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||||
|
|
||||||
This file is part of SOGo.
|
This file is part of SOGo.
|
||||||
|
@ -48,6 +48,8 @@
|
||||||
apt = nil;
|
apt = nil;
|
||||||
values = nil;
|
values = nil;
|
||||||
dateFormatter = RETAIN([[context activeUser] dateFormatterInContext: context]);
|
dateFormatter = RETAIN([[context activeUser] dateFormatterInContext: context]);
|
||||||
|
organizerName = nil;
|
||||||
|
currentAttendee = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -59,6 +61,7 @@
|
||||||
[apt release];
|
[apt release];
|
||||||
[previousApt release];
|
[previousApt release];
|
||||||
[organizerName release];
|
[organizerName release];
|
||||||
|
[currentAttendee release];
|
||||||
[viewTZ release];
|
[viewTZ release];
|
||||||
[oldStartDate release];
|
[oldStartDate release];
|
||||||
[newStartDate release];
|
[newStartDate release];
|
||||||
|
@ -164,6 +167,16 @@
|
||||||
return organizerName;
|
return organizerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setCurrentAttendee: (iCalPerson *) theAttendee
|
||||||
|
{
|
||||||
|
ASSIGN(currentAttendee, theAttendee);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (iCalPerson *) currentAttendee
|
||||||
|
{
|
||||||
|
return currentAttendee;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *) sentByText
|
- (NSString *) sentByText
|
||||||
{
|
{
|
||||||
NSDictionary *sentByValues;
|
NSDictionary *sentByValues;
|
||||||
|
@ -293,4 +306,21 @@
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) getParticipationRole
|
||||||
|
{
|
||||||
|
if ([[currentAttendee role] caseInsensitiveCompare: @"OPT-PARTICIPANT"] == NSOrderedSame)
|
||||||
|
{
|
||||||
|
return [self labelForKey: @"Your participation is optional to this event"
|
||||||
|
inContext: context];
|
||||||
|
}
|
||||||
|
else if ([[currentAttendee role] caseInsensitiveCompare: @"NON-PARTICIPANT"] == NSOrderedSame)
|
||||||
|
{
|
||||||
|
return [self labelForKey: @"Your participation is not required to this event"
|
||||||
|
inContext: context];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [self labelForKey: @"Your participation is required to this event"
|
||||||
|
inContext: context];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* SOGoCalendarComponent.m - this file is part of SOGo
|
/* SOGoCalendarComponent.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006-2016 Inverse inc.
|
* Copyright (C) 2006-2019 Inverse inc.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -846,6 +846,7 @@
|
||||||
p = [app pageWithName: pageName inContext: context];
|
p = [app pageWithName: pageName inContext: context];
|
||||||
[p setApt: (iCalEvent *) object];
|
[p setApt: (iCalEvent *) object];
|
||||||
[p setPreviousApt: (iCalEvent *) previousObject];
|
[p setPreviousApt: (iCalEvent *) previousObject];
|
||||||
|
[p setCurrentAttendee: attendee];
|
||||||
|
|
||||||
if ([[object organizer] cn] && [[[object organizer] cn] length])
|
if ([[object organizer] cn] && [[[object organizer] cn] length])
|
||||||
{
|
{
|
||||||
|
@ -893,7 +894,8 @@
|
||||||
/* attach text part to multipart body */
|
/* attach text part to multipart body */
|
||||||
[body addBodyPart: bodyPart];
|
[body addBodyPart: bodyPart];
|
||||||
|
|
||||||
/* attach calendar part to multipart body */
|
/* attach calendar part to multipart body only if the participation role is not NON-PARTICIPANT */
|
||||||
|
if ([[attendee role] caseInsensitiveCompare: @"NON-PARTICIPANT"] != NSOrderedSame)
|
||||||
[body addBodyPart: eventBodyPart];
|
[body addBodyPart: eventBodyPart];
|
||||||
|
|
||||||
/* attach multipart body to message */
|
/* attach multipart body to message */
|
||||||
|
|
|
@ -20,7 +20,12 @@ th, td { font-family: Lucida Grande, Bitstream VeraSans, Tahoma, sans-serif; fon
|
||||||
value="getSubject" const:escapeHTML="NO"/> <small style="font-size: 12px; color: #999;"><var:string
|
value="getSubject" const:escapeHTML="NO"/> <small style="font-size: 12px; color: #999;"><var:string
|
||||||
value="organizerName" const:escapeHTML="NO"/><var:string value="sentByText" const:escapeHTML="NO"/></small></h1></td>
|
value="organizerName" const:escapeHTML="NO"/><var:string value="sentByText" const:escapeHTML="NO"/></small></h1></td>
|
||||||
</tr>
|
</tr>
|
||||||
<var:if condition="location.length"
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<td><h1 style="font-size: 14px; font-weight: normal;
|
||||||
|
padding-bottom: 9px; border-bottom: 1px solid #ccc;"><var:string
|
||||||
|
value="getParticipationRole" const:escapeHTML="NO"/></h1></td>
|
||||||
|
</tr> <var:if condition="location.length"
|
||||||
><tr>
|
><tr>
|
||||||
<th align="right" style="font-weight: bold;"><var:string label:value="location_label" const:escapeHTML="NO"/></th>
|
<th align="right" style="font-weight: bold;"><var:string label:value="location_label" const:escapeHTML="NO"/></th>
|
||||||
<td><var:string value="location" const:escapeHTML="NO"/></td>
|
<td><var:string value="location" const:escapeHTML="NO"/></td>
|
||||||
|
|
|
@ -20,6 +20,12 @@ th, td { font-family: Lucida Grande, Bitstream VeraSans, Tahoma, sans-serif; fon
|
||||||
value="getSubject" const:escapeHTML="NO"/> <small style="font-size: 12px; color: #999;"><var:string
|
value="getSubject" const:escapeHTML="NO"/> <small style="font-size: 12px; color: #999;"><var:string
|
||||||
value="organizerName" const:escapeHTML="NO"/><var:string value="sentByText" const:escapeHTML="NO"/></small></h1></td>
|
value="organizerName" const:escapeHTML="NO"/><var:string value="sentByText" const:escapeHTML="NO"/></small></h1></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<td><h1 style="font-size: 14px; font-weight: normal;
|
||||||
|
padding-bottom: 9px; border-bottom: 1px solid #ccc;"><var:string
|
||||||
|
value="getParticipationRole" const:escapeHTML="NO"/></h1></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
<td><var:string value="bodyStartText" const:escapeHTML="NO"/></td>
|
<td><var:string value="bodyStartText" const:escapeHTML="NO"/></td>
|
||||||
|
|
Loading…
Reference in New Issue