From 4bca7f746f17035f9055609775935fb23f544979 Mon Sep 17 00:00:00 2001 From: helge Date: Fri, 27 Aug 2004 01:48:23 +0000 Subject: [PATCH] first working version of addressbook git-svn-id: http://svn.opengroupware.org/SOGo/trunk@280 d1b88da0-ebda-0310-925b-ed51d893ca5b --- .../sql/testcontact-agenor-test-contact.psql | 2 +- SOGo/SoObjects/Contacts/ChangeLog | 4 + SOGo/SoObjects/Contacts/SOGoContactFolder.m | 2 +- SOGo/SoObjects/Contacts/SOGoContactObject.m | 11 + SOGo/SoObjects/Contacts/Version | 2 +- SOGo/UI/Contacts/ChangeLog | 2 + SOGo/UI/Contacts/UIxContactEditor.m | 217 +++++++++++++++++- SOGo/UI/Contacts/UIxContactEditor.wox | 213 ++++++++++++++++- SOGo/UI/Contacts/UIxContactView.wox | 10 + SOGo/UI/Contacts/UIxContactsListView.m | 29 ++- SOGo/UI/Contacts/Version | 2 +- SOGo/UI/Contacts/product.plist | 10 + SOGo/UI/Scheduler/ChangeLog | 3 + SOGo/UI/Scheduler/UIxAppointmentEditor.m | 20 +- SOGo/UI/Scheduler/UIxAppointmentEditor.wox | 10 +- SOGo/UI/Scheduler/Version | 2 +- 16 files changed, 513 insertions(+), 26 deletions(-) diff --git a/OGoContentStore/sql/testcontact-agenor-test-contact.psql b/OGoContentStore/sql/testcontact-agenor-test-contact.psql index 6b873db7..47274d14 100644 --- a/OGoContentStore/sql/testcontact-agenor-test-contact.psql +++ b/OGoContentStore/sql/testcontact-agenor-test-contact.psql @@ -15,7 +15,7 @@ VALUES ( 928383, 1, '{ - givenname="Donald"; cn="Donald Duck"; sn="Duck"; + givenName="Donald"; cn="Donald Duck"; sn="Duck"; l="Entenhausen"; mail="dd@entenhausen.com"; o="Geldspeicher AG"; diff --git a/SOGo/SoObjects/Contacts/ChangeLog b/SOGo/SoObjects/Contacts/ChangeLog index dd949d54..6ce174c0 100644 --- a/SOGo/SoObjects/Contacts/ChangeLog +++ b/SOGo/SoObjects/Contacts/ChangeLog @@ -1,5 +1,9 @@ 2004-08-27 Helge Hess + * v0.9.3 + + * SOGoContactObject.m: use 'cn' as davDisplayName + * SOGoContactObject.[hm]: can now decode the property list stored in the store (v0.9.2) diff --git a/SOGo/SoObjects/Contacts/SOGoContactFolder.m b/SOGo/SoObjects/Contacts/SOGoContactFolder.m index 849a3722..1628c039 100644 --- a/SOGo/SoObjects/Contacts/SOGoContactFolder.m +++ b/SOGo/SoObjects/Contacts/SOGoContactFolder.m @@ -117,7 +117,7 @@ static BOOL debugOn = YES; } records = [self fixupRecords:records]; if (debugOn) - [self logWithFormat:@"fetched %i records: %@", [records count], records]; + [self logWithFormat:@"fetched %i records.", [records count]]; return records; } diff --git a/SOGo/SoObjects/Contacts/SOGoContactObject.m b/SOGo/SoObjects/Contacts/SOGoContactObject.m index c446ce5b..0fd3b1f1 100644 --- a/SOGo/SoObjects/Contacts/SOGoContactObject.m +++ b/SOGo/SoObjects/Contacts/SOGoContactObject.m @@ -49,6 +49,17 @@ return [super valueForKey:_key]; } +/* DAV */ + +- (NSString *)davDisplayName { + NSString *n; + + if ((n = [self valueForKey:@"cn"])) + return n; + + return [self nameInContainer]; +} + /* GET */ - (id)GETAction:(WOContext *)_ctx { diff --git a/SOGo/SoObjects/Contacts/Version b/SOGo/SoObjects/Contacts/Version index 1bf86739..fc795f55 100644 --- a/SOGo/SoObjects/Contacts/Version +++ b/SOGo/SoObjects/Contacts/Version @@ -1,3 +1,3 @@ # $Id$ -SUBMINOR_VERSION:=2 +SUBMINOR_VERSION:=3 diff --git a/SOGo/UI/Contacts/ChangeLog b/SOGo/UI/Contacts/ChangeLog index 23ad4702..97f46b64 100644 --- a/SOGo/UI/Contacts/ChangeLog +++ b/SOGo/UI/Contacts/ChangeLog @@ -1,5 +1,7 @@ 2004-08-27 Helge Hess + * first working version of contacts UI (v0.9.4) + * removed GET from product.plist, the SoObject directly implements GET now and redirects to the view method (v0.9.3) diff --git a/SOGo/UI/Contacts/UIxContactEditor.m b/SOGo/UI/Contacts/UIxContactEditor.m index 9f7caf4a..d065a590 100644 --- a/SOGo/UI/Contacts/UIxContactEditor.m +++ b/SOGo/UI/Contacts/UIxContactEditor.m @@ -1,7 +1,7 @@ /* - Copyright (C) 2000-2004 SKYRIX Software AG + Copyright (C) 2004 SKYRIX Software AG - This file is part of OGo + This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the @@ -23,31 +23,230 @@ #include +@class NSMutableDictionary; + @interface UIxContactEditor : UIxComponent { - + NSString *contentString; + NSString *errorText; + NSMutableDictionary *snapshot; /* contains the values for editing */ } @end +#include +#include #include "common.h" @implementation UIxContactEditor +- (id)init { + if ((self = [super init])) { + self->snapshot = [[NSMutableDictionary alloc] initWithCapacity:16]; + } + return self; +} + +- (void)dealloc { + [self->snapshot release]; + [self->errorText release]; + [self->contentString release]; + [super dealloc]; +} + +/* accessors */ + +- (void)setContentString:(NSString *)_cstr { + ASSIGNCOPY(self->contentString, _cstr); +} +- (NSString *)contentString { + return self->contentString; +} + +- (NSString *)contentStringTemplate { + return @"{}"; /* empty property list */ +} + +- (NSMutableDictionary *)snapshot { + return self->snapshot; +} + +- (void)setErrorText:(NSString *)_txt { + ASSIGNCOPY(self->errorText, _txt); +} +- (NSString *)errorText { + return self->errorText; +} +- (BOOL)hasErrorText { + return [self->errorText length] > 0 ? YES : NO; +} + +/* load/store content format */ + +- (void)loadValuesFromContentString:(NSString *)_s { + NSDictionary *plist; + + if ((plist = [_s propertyList]) == nil) { + [self logWithFormat:@"ERROR: could not parse content string!"]; + return; + } + + [self->snapshot removeAllObjects]; + [self->snapshot addEntriesFromDictionary:plist]; +} + +- (void)_fixupSnapshot { + // TODO: perform sanity checking, eg build CN on demand + NSString *cn, *gn, *sn; + + cn = [self->snapshot objectForKey:@"cn"]; + gn = [self->snapshot objectForKey:@"givenName"]; + sn = [self->snapshot objectForKey:@"sn"]; + + if (![sn isNotNull] || [sn length] == 0) + sn = nil; + if (![cn isNotNull] || [cn length] == 0) + cn = nil; + + if (sn == nil) { + if (cn == nil) + sn = @"[noname]"; + else { + // TODO: need a better name parser here + NSRange r; + + r = [cn rangeOfString:@" "]; + sn = (r.length > 0) + ? [cn substringFromIndex:(r.location + r.length)] + : cn; + } + [self->snapshot setObject:sn forKey:@"sn"]; + } + + if (sn == nil && gn == nil) + cn = @"[noname]"; + else if (sn == nil) + cn = gn; + else if (gn == nil) + cn = sn; + else + cn = [[gn stringByAppendingString:@" "] stringByAppendingString:sn]; + [self->snapshot setObject:cn forKey:@"cn"]; +} + +- (void)saveValuesIntoRecord:(NSMutableDictionary *)_record { + [self _fixupSnapshot]; + [_record addEntriesFromDictionary:[self snapshot]]; +} + +/* helper */ + +- (NSString *)_completeURIForMethod:(NSString *)_method { + // TODO: this is a DUP of UIxAppointmentEditor + NSString *uri; + NSRange r; + + uri = [[[self context] request] uri]; + + /* first: identify query parameters */ + r = [uri rangeOfString:@"?" options:NSBackwardsSearch]; + if (r.length > 0) + uri = [uri substringToIndex:r.location]; + + /* next: append trailing slash */ + if (![uri hasSuffix:@"/"]) + uri = [uri stringByAppendingString:@"/"]; + + /* next: append method */ + uri = [uri stringByAppendingString:_method]; + + /* next: append query parameters */ + return [self completeHrefForMethod:uri]; +} + +/* actions */ + +- (BOOL)shouldTakeValuesFromRequest:(WORequest *)_rq inContext:(WOContext*)_c{ + return YES; +} + +- (id)defaultAction { + // TODO: very similiar to apt-editor (apt editor would need to use std names + NSString *c; + + /* load iCalendar file */ + + c = [[self clientObject] contentAsString]; + if ([c length] == 0) /* a new contact */ + c = [self contentStringTemplate]; + + [self setContentString:c]; + [self loadValuesFromContentString:c]; + + return self; +} + +- (BOOL)isWriteableClientObject { + return [[self clientObject] + respondsToSelector:@selector(saveContentString:)]; +} + - (id)saveAction { -#if 0 NSException *ex; - - ex = [[self clientObject] saveContentString:content]; + NSString *recstr; + id record; + + if (![self isWriteableClientObject]) { + /* return 400 == Bad Request */ + return [NSException exceptionWithHTTPStatus:400 + reason:@"method cannot be invoked on " + @"the specified object"]; + } + + record = [[[[self contentString] propertyList] mutableCopy] autorelease]; + if (record == nil) { + [self setErrorText:@"Invalid property list data ..."]; // localize + return self; + } + + [self saveValuesIntoRecord:record]; + + recstr = [record description]; // make plist + ex = [[self clientObject] saveContentString:recstr]; if (ex != nil) { [self setErrorText:[ex reason]]; return self; } return [self redirectToLocation:[self _completeURIForMethod:@".."]]; -#else +} + +- (id)testAction { + [self logWithFormat:@"test ..."]; return self; -#endif } -@end +- (id)newAction { + // TODO: this is almost a DUP of UIxAppointmentEditor + /* + This method creates a unique ID and redirects to the "edit" method on the + new ID. + It is actually a folder method and should be defined on the folder. + + Note: 'clientObject' is the SOGoAppointmentFolder! + Update: remember that there are group folders as well. + */ + NSString *uri, *objectId, *nextMethod; + + objectId = [NSClassFromString(@"SOGoContactFolder") globallyUniqueObjectId]; + if ([objectId length] == 0) { + return [NSException exceptionWithHTTPStatus:500 /* Internal Error */ + reason:@"could not create a unique ID"]; + } + + nextMethod = [NSString stringWithFormat:@"../%@/edit", objectId]; + uri = [self _completeURIForMethod:nextMethod]; + return [self redirectToLocation:uri]; +} + +@end /* UIxContactEditor */ diff --git a/SOGo/UI/Contacts/UIxContactEditor.wox b/SOGo/UI/Contacts/UIxContactEditor.wox index 7f53e297..0bba57eb 100644 --- a/SOGo/UI/Contacts/UIxContactEditor.wox +++ b/SOGo/UI/Contacts/UIxContactEditor.wox @@ -7,8 +7,217 @@ className="UIxPageFrame" title="name" > + + +
+ + + + + + + + +
+ + + + + +
+ + + +
+
+ +
+ +
+
+
+
+ + + + + + + + + + + + +
+ + + +
+ + : + + + + + +
+ + : + + + + + +
+
+ + + + + + + + + + + + + +
+ + + +
+ + : + + + + + +
+ + : + + + + + +
+
+ + + + + + + +
+ + + +
+ + : + + + +