+2005-07-08 Marcus Mueller <znek@mulle-kybernetik.com>
+
+ * SOGoAppointmentFolder.m: added 'partmails' and 'partstates' to
+ infos returned by -fetchOverviewInfosFrom:to: (v0.9.36)
+
2005-07-06 Marcus Mueller <znek@mulle-kybernetik.com>
* v0.9.35
infos = [[NSArray alloc] initWithObjects:
@"title",
@"location", @"orgmail", @"status", @"ispublic",
- @"isallday", @"priority", nil];
+ @"isallday", @"priority",
+ @"partmails", @"partstates",
+ nil];
}
return [self fetchFields:infos
from:_startDate
# Version file
-SUBMINOR_VERSION:=35
+SUBMINOR_VERSION:=36
# v0.9.32 requires libGDLContentStore v4.5.26
# v0.9.28 requires libNGiCal v4.5.47
2005-07-08 Marcus Mueller <znek@mulle-kybernetik.com>
+ * v0.9.127
+
+ * UIxCalView.[hm]: added -shouldDisplayRejectedAppointments API. Added
+ toggling of hide/show rejected appointments via form values. Added
+ new -filterAppointments: method to support filtering of appointments
+ (currently used for rejected appointments). Fixed -fetchCoreInfos
+ to use proper accessor method. Fixed aptFlags logic to allow access
+ to appointments that don't belong to user but which user is invited
+ to. Cleaned up +initialize a bit.
+
+ * UIxCalWeekListview.m: added comment and slightly changed
+ -fetchCoreInfos to do the proper thing
+
+ * English.lproj/Localizable.strings: added labels 'show_rejected_apts'
+ and 'hide_rejected_apts'
+
* v0.9.126
* UIxComponent+Agenor.[hm]: new method -isAccessRestricted, uses the
"proposal" = "proposal";
"Save" = "Save";
"Cancel" = "Cancel";
-
+"show_rejected_apts" = "Show rejected appointments";
+"hide_rejected_apts" = "Hide rejected appointments";
/* Schedule */
- (unsigned)dayStartHour;
- (unsigned)dayEndHour;
- (BOOL)shouldDisplayWeekend;
-
+- (BOOL)shouldDisplayRejectedAppointments;
+
- (NSCalendarDate *)referenceDateForFormatter;
- (NSCalendarDate *)thisMonth;
#include <NGObjWeb/SoUser.h>
#include <SOGoUI/SOGoAptFormatter.h>
#include <NGExtensions/NGCalendarDateRange.h>
+#include <NGiCal/NGiCal.h>
#include "UIxComponent+Agenor.h"
@interface UIxCalView (PrivateAPI)
static BOOL shouldDisplayWeekend = NO;
+ (void)initialize {
- NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
- shouldDisplayWeekend = [ud boolForKey:@"SOGoShouldDisplayWeekend"];
+ static BOOL didInit = NO;
+ NSUserDefaults *ud;
+
+ if (didInit) return;
+
+ ud = [NSUserDefaults standardUserDefaults];
+ shouldDisplayWeekend = [ud boolForKey:@"SOGoShouldDisplayWeekend"];
}
- (id)init {
[self->privateAptTooltipFormatter setPrivateTitle:title];
}
+- (NSArray *)filterAppointments:(NSArray *)_apts {
+ NSMutableArray *filtered;
+ unsigned i, count;
+ NSString *email;
+
+ count = [_apts count];
+ if (!count) return _apts;
+ if ([self shouldDisplayRejectedAppointments]) return _apts;
+
+ filtered = [[[NSMutableArray alloc] initWithCapacity:count] autorelease];
+ email = [self emailForUser];
+
+ for (i = 0; i < count; i++) {
+ NSDictionary *info;
+ NSArray *partmails;
+ unsigned p, pCount;
+ BOOL shouldAdd;
+
+ shouldAdd = NO;
+ info = [_apts objectAtIndex:i];
+ partmails = [[info objectForKey:@"partmails"]
+ componentsSeparatedByString:@"\n"];
+ pCount = [partmails count];
+ for (p = 0; p < pCount; p++) {
+ NSString *pEmail;
+
+ pEmail = [partmails objectAtIndex:p];
+ if ([pEmail isEqualToString:email]) {
+ NSArray *partstates;
+ NSString *state;
+
+ partstates = [[info objectForKey:@"partstates"]
+ componentsSeparatedByString:@"\n"];
+ state = [partstates objectAtIndex:p];
+ if ([state intValue] != iCalPersonPartStatDeclined)
+ shouldAdd = YES;
+ break;
+ }
+ }
+ if (shouldAdd)
+ [filtered addObject:info];
+ }
+ return filtered;
+}
+
/* accessors */
- (void)setAppointments:(NSArray *)_apts {
+ _apts = [self filterAppointments:_apts];
ASSIGN(self->appointments, _apts);
}
- (NSArray *)appointments {
self->aptFlags.canAccessApt = YES;
}
else {
- self->aptFlags.isMyApt = NO;
- self->aptFlags.canAccessApt = [[_apt valueForKey:@"ispublic"] boolValue];
+ NSString *partmails;
+
+ self->aptFlags.isMyApt = NO;
+
+ partmails = [_apt valueForKey:@"partmails"];
+ if ([partmails rangeOfString:myEmail].length)
+ self->aptFlags.canAccessApt = YES;
+ else
+ self->aptFlags.canAccessApt = [[_apt valueForKey:@"ispublic"] boolValue];
}
}
- (id)appointment {
folder = [self clientObject];
sd = [self startDate];
ed = [self endDate];
- self->appointments = [[folder fetchOverviewInfosFrom:sd to:ed] retain];
+ [self setAppointments:[folder fetchOverviewInfosFrom:sd to:ed]];
}
return self->appointments;
}
+/* query parameters */
+
+- (BOOL)shouldDisplayRejectedAppointments {
+ NSString *bv;
+
+ bv = [[[self context] request] formValueForKey:@"dr"];
+ if (!bv) return NO;
+ return [bv boolValue];
+}
+
+- (NSDictionary *)toggleShowRejectedAptsQueryParameters {
+ NSMutableDictionary *qp;
+ BOOL shouldDisplay;
+
+ shouldDisplay = ![self shouldDisplayRejectedAppointments];
+ qp = [[[self queryParameters] mutableCopy] autorelease];
+ [qp setObject:shouldDisplay ? @"1" : @"0" forKey:@"dr"];
+ return qp;
+}
+
+- (NSString *)toggleShowRejectedAptsLabel {
+ if (![self shouldDisplayRejectedAppointments])
+ return @"show_rejected_apts";
+ return @"hide_rejected_apts";
+}
/* date selection & conversion */
/* fetching */
+/* NOTE: this fetches coreInfos instead of overviewInfos
+ * as is done in the superclass!
+ */
- (NSArray *)fetchCoreInfos {
if (!self->appointments) {
id folder;
folder = [self clientObject];
sd = [self startDate];
ed = [self endDate];
- self->appointments = [[folder fetchCoreInfosFrom:sd to:ed] retain];
+ [self setAppointments:[folder fetchCoreInfosFrom:sd to:ed]];
}
return self->appointments;
}
# Version file
-SUBMINOR_VERSION:=126
+SUBMINOR_VERSION:=127
# v0.9.123 requires Appointments v0.9.35
# v0.9.123 requires SOGoUI v0.9.24
2005-07-08 Marcus Mueller <znek@mulle-kybernetik.com>
+ * UIxCalDayOverview.wox, UIxCalWeekOverview.wox,
+ UIxCalWeekColumnsview.wox, UIxCalDayChartview.wox,
+ UIxCalDayListview.wox, UIxCalWeekChartview.wox,
+ UIxCalMonthOverview.wox, UIxCalWeekListview.wox:
+ added 'hide/show rejected apts' toggle to all views
+
+ * UIxPageFrame.wox: added 'headers' to the debug output
+
* UIxAppointmentEditor.wox: removed conditionals from UI as they were
wrongly placed in the template, component does now deal with it
</tr>
</table>
</td>
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border="0" cellpadding="0" cellspacing="1">
<tr>
</tr>
</table>
</td>
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border="0" cellpadding="0" cellspacing="1">
<tr>
</tr>
</table>
</td>
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border="0" cellpadding="0" cellspacing="1">
<tr>
>
<table border="0" cellpadding="4" width="100%" cellspacing="2">
<tr>
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border="0" cellpadding="0" cellspacing="1">
<tr>
</tr>
</table>
</td>
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border='0' cellpadding='0' cellspacing='1'>
<tr>
</tr>
</table>
</td>
-
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border='0' cellpadding='0' cellspacing='1'>
<tr>
</tr>
</table>
</td>
-
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border='0' cellpadding='0' cellspacing='1'>
<tr>
</tr>
</table>
</td>
-
+ <td align="left" bgcolor="#e8e8e0" class="button_auto_env">
+ <a var:href="ownMethodName"
+ class="button_auto"
+ var:queryDictionary="toggleShowRejectedAptsQueryParameters"
+ label:string="$toggleShowRejectedAptsLabel"
+ />
+ </td>
<td align="right" bgcolor="#e8e8e0">
<table border='0' cellpadding='0' cellspacing='1'>
<tr>
>NO</var:if>
</td>
</tr>
+ <tr>
+ <td valign="top">Headers:</td>
+ <td valign="top">
+ <span style="white-space: pre;">
+ <var:string value="context.request.headers"
+ const:escapeHTML="YES"
+ />
+ </span>
+ </td>
+ </tr>
</table>
</td>
</tr>