]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1385 d1b88da0-ebda-0310...
authorwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 7 Mar 2008 22:36:00 +0000 (22:36 +0000)
committerwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 7 Mar 2008 22:36:00 +0000 (22:36 +0000)
43 files changed:
ChangeLog
NEWS
OGoContentStore/OCSContactFieldExtractor.m
OGoContentStore/contact-oracle.ocs
OGoContentStore/contact.ocs
SOPE/NGCards/ChangeLog
SOPE/NGCards/GNUmakefile
SOPE/NGCards/NGVCard.h
SOPE/NGCards/NGVList.h [new file with mode: 0644]
SOPE/NGCards/NGVList.m [new file with mode: 0644]
SOPE/NGCards/versitCardsSaxDriver/bundle-info.plist
Scripts/sql-update-20080303.sh [new file with mode: 0644]
SoObjects/Appointments/SOGoAppointmentFolder.m
SoObjects/Appointments/SOGoFreeBusyObject.m
SoObjects/Appointments/product.plist
SoObjects/Contacts/GNUmakefile
SoObjects/Contacts/SOGoContactGCSEntry.h
SoObjects/Contacts/SOGoContactGCSFolder.m
SoObjects/Contacts/SOGoContactGCSList.h [new file with mode: 0644]
SoObjects/Contacts/SOGoContactGCSList.m [new file with mode: 0644]
SoObjects/Contacts/product.plist
SoObjects/Mailer/SOGoMailBaseObject.h
SoObjects/Mailer/SOGoMailBaseObject.m
SoObjects/Mailer/SOGoMailBodyPart.m
SoObjects/SOGo/SOGoContentObject.m
SoObjects/SOGo/SOGoFolder.h
SoObjects/SOGo/SOGoFolder.m
SoObjects/SOGo/SOGoObject.m
UI/Contacts/GNUmakefile
UI/Contacts/UIxContactEditor.m
UI/Contacts/UIxListEditor.h [new file with mode: 0644]
UI/Contacts/UIxListEditor.m [new file with mode: 0644]
UI/Contacts/UIxListView.h [new file with mode: 0644]
UI/Contacts/UIxListView.m [new file with mode: 0644]
UI/Contacts/product.plist
UI/Scheduler/UIxAppointmentEditor.m
UI/Templates/ContactsUI/UIxContactEditor.wox
UI/Templates/ContactsUI/UIxListEditor.wox [new file with mode: 0644]
UI/Templates/ContactsUI/UIxListView.wox [new file with mode: 0644]
UI/Templates/SchedulerUI/UIxComponentEditor.wox
UI/WebServerResources/ContactsUI.js
UI/WebServerResources/UIxContactEditor.js
UI/WebServerResources/UIxMailEditor.js

index 7742fdb827a56f15197a344a191e96b79aa99f0d..3aedecfb7ea96e93fb5e3a505c162d8e07ad795d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2008-03-07  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * OGoContentStore/OCSContactFieldExtractor.m
+       ([OCSContactFieldExtractor -extractQuickFieldsFromVList:vList]):
+       new method to handle extraction of quick information from the
+       VLIST components. I.e.: the display name of the card.
+
+       * SoObjects/SOGo/SOGoFolder.m ([SOGoFolder
+       -isValidContentName:name]): moved method from
+       SOGoAppointmentFolder's isValidAppointmentName.
+
+       * SoObjects/Contacts/SOGoContactGCSFolder.m ([SOGoContactGCSFolder -objectClassForContent:content])
+       ([SOGoContactGCSFolder -deduceObjectForName:inContext:])
+       ([SOGoContactGCSFolder -requestNamedIsHandledLater:name])
+       ([SOGoContactGCSFolder -lookupName:inContext:acquire:]): those
+       methods were modified to match the ones in SOGoAppointmentFolder,
+       in order to manage both vcard and vlist components.
+
+       * SoObjects/Contacts/SOGoContactGCSList.[hm]: new class module
+       that implements the list counterpart to VCARD: VLIST.
+
+       * UI/Contacts/UIxContactEditor.m ([UIxContactEditor -saveURL]):
+       new accessor that returns the url + "saveAsContact".
+       ([UIxContactEditor
+       -shouldTakeValuesFromRequest:requestinContext:context]): changed
+       method to match the one from the event and todo editor module.
+       ([UIxContactEditor -editActionName]): changed to "editAsContact".
+       ([UIxContactEditor -newAction]): changed method to match the one
+       from the event and todo editor module.
+
+       * UI/Contacts/UIxListView.m: new view module for the VLIST format
+       components.
+
+       * UI/Contacts/UIxListEditor.m: new edition module for the VLIST
+       format components.
+
+       * SoObjects/Contacts/SOGoContactGCSList.m: new controller module
+       for the VLIST format.
+
+2008-03-04  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * SoObjects/SOGo/SOGoObject.m ([SOGoObject -isFolderish]): new
+       parent method, meant to be overriden.
+       ([SOGoObject -davIsCollection]): moved method from SOGoFolder up
+       to this parent class.
+
 2008-02-25  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
        * SoObjects/SOGo/SOGoGCSFolder.m ([SOGoGCSFolder
diff --git a/NEWS b/NEWS
index 415ca7fbfb9543e34f4061063054fb70772329b3..03ec83cb28dde69afcc1f267089af7753d87cc82 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@
 - retrieving the freebusy DAV object was causing SOGo to crash
 - converted to use the gnustep-make 2 build framework
 - added custom DAV methods for managing user permissions from the SOGo Integrator
+- pressing enter in the contact edition dialog will perform the creation/update operation
 
 0.9.0-20080208 (1.0 rc5)
 ------------------------
index b52b567e88f1f5469f033b7eab285fcc8788a538..24fb4246cfea9415ba254fb6f667b1d54aa37104 100644 (file)
@@ -25,6 +25,7 @@
 
 #import <GDLContentStore/GCSFieldExtractor.h>
 #import <NGCards/NGVCard.h>
+#import <NGCards/NGVList.h>
 
 @interface OCSContactFieldExtractor : GCSFieldExtractor
 @end
     [fields setObject: [adr value: 3] forKey: @"c_l"];
   value = [[vCard uniqueChildWithTag: @"X-AIM"] value: 0];
   [fields setObject: value forKey: @"c_screenname"];
+  [fields setObject: @"vcard" forKey: @"c_component"];
+
+  return fields;
+}
+
+- (NSMutableDictionary *) extractQuickFieldsFromVList: (NGVList *) vList
+{
+  NSMutableDictionary *fields;
+  NSString *value;
+
+  fields = [NSMutableDictionary dictionaryWithCapacity: 1];
+
+  value = [vList fn];
+  if (value)
+    [fields setObject: value forKey: @"c_cn"];
+  [fields setObject: @"vlist" forKey: @"c_component"];
 
   return fields;
 }
 {
   NSMutableDictionary *fields;
   NGVCard *vCard;
+  NGVList *vList;
+  NSString *upperContent;
 
   fields = nil;
-  if ([content length] > 0
-      && [[content uppercaseString] hasPrefix: @"BEGIN:VCARD"])
+  if ([content length] > 0)
     {
-      vCard = [NGVCard parseSingleFromSource: content];
-      if (vCard)
-       fields = [self extractQuickFieldsFromVCard: vCard];
+      upperContent = [content uppercaseString];
+      if ([upperContent hasPrefix: @"BEGIN:VCARD"])
+       {
+         vCard = [NGVCard parseSingleFromSource: content];
+         if (vCard)
+           fields = [self extractQuickFieldsFromVCard: vCard];
+         else
+           [self errorWithFormat: @"Could not parse VCARD content."];
+       }
+      else if ([upperContent hasPrefix: @"BEGIN:VLIST"])
+       {
+         vList = [NGVList parseSingleFromSource: content];
+         if (vList)
+           fields = [self extractQuickFieldsFromVList: vList];
+         else
+           [self errorWithFormat: @"Could not parse VLIST content."];
+       }
       else
-       [self errorWithFormat: @"Could not parse content as a vCard."];
+       [self errorWithFormat: @"Content is unknown."];
     }
   else
-    [self errorWithFormat: @"Content is not a vCard"];
+    [self errorWithFormat: @"Content is empty."];
 
   return fields;
 }
index 1174d649a75e51549aefb75b3c67af1fa8706bf5..f3539c289e10fc5718719ac7cd03cdc658da59c9 100644 (file)
       sqlType    = "VARCHAR2(256)";
       allowsNull = YES;
     },
+    {
+      columnName = c_component;
+      sqlType    = "VARCHAR2(10)";
+      allowsNull = NO;
+    },
   );
 }
index d51c6e704f87eee68a937bfb687a0733f39a4b7c..dd46531794c3874c55c22fb487e137d86697f5ca 100644 (file)
       sqlType    = "VARCHAR(256)";
       allowsNull = YES;
     },
+    {
+      columnName = c_component;
+      sqlType    = "VARCHAR(10)";
+      allowsNull = NO;
+    },
   );
 }
index 6ecd16f965fcb10fe1b7d7e56eda39a44767f23c..a3644f072ba794d295194c09226306e4820cd456 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-03  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * NGVCardReference.[hm]: new class module that implements the base
+       data type contained in a VLIST element.
+
+       * NGVList.[hm]: new class module that implements Thunderbird-style
+       personal mailing lists. Base mime-type is "text/x-vlist".
+
 2008-02-08  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
        * iCalRecurrenceRule.m ([iCalRecurrenceRule -wkst]): if no wkst
index 7c3244341d31c382b50c5db305630475d2bbd7b9..252fbbdcbe2b2a3e449ad725f42d4c59b8ceeb77 100644 (file)
@@ -53,6 +53,8 @@ libNGCards_HEADER_FILES =             \
        NSCalendarDate+ICal.h           \
        \
        NGVCard.h                       \
+       NGVList.h                       \
+       NGVCardReference.h              \
 #      NGVCardAddress.h                \
 #      NGVCardStrArrayValue.h          \
 #      NGVCardName.h                   \
@@ -101,11 +103,12 @@ libNGCards_OBJC_FILES =                   \
        iCalYearlyRecurrenceCalculator.m\
        \
        NGVCard.m                       \
+       NGVList.m                       \
+       NGVCardReference.m              \
        NGCardsSaxHandler.m             \
 #      IcalElements.m
 #      IcalResponse.m
 
-
 # framework support
 
 NGCards_PCH_FILE     = $(libNGCards_PCH_FILE)
index 7b9f69ee2f3003c5786f19cdd383b7812c1110cb..a687e2a01a5fd2400e038cffb53bd06e6524cffb 100644 (file)
 @class NSDictionary;
 @class NSString;
 
+/* this should be merged in a common definition headers with iCalAccessClass */
+typedef enum
+{
+  NGCardsAccessPublic = 0,
+  NGCardsAccessPrivate = 1,
+  NGCardsAccessConfidential = 2,
+} NGCardsAccessClass;
+
 @interface NGVCard : CardGroup
 
 + (id) cardWithUid: (NSString *) _uid;
diff --git a/SOPE/NGCards/NGVList.h b/SOPE/NGCards/NGVList.h
new file mode 100644 (file)
index 0000000..85d9caf
--- /dev/null
@@ -0,0 +1,69 @@
+/* NGVList.h - this file is part of NGCards
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef NGVLIST_H
+#define NGVLIST_H
+
+#import "CardGroup.h"
+
+#import "NGVCard.h"
+
+@class NSArray;
+@class NSDictionary;
+@class NSString;
+
+@class NGVCardReference;
+
+@interface NGVList : CardGroup
+
++ (id) listWithUid: (NSString *) newUid;
+- (id) initWithUid: (NSString *) newUid;
+
+/* accessors */
+
+- (void) setProdID: (NSString *) newProdID;
+- (NSString *) prodID;
+- (void) setVersion: (NSString *) newVersion;
+- (NSString *) version;
+
+- (void) setUid: (NSString *) newUid;
+- (NSString *) uid;
+
+- (void) setAccessClass: (NSString *) newAccessClass;
+- (NSString *) accessClass;
+- (NGCardsAccessClass) symbolicAccessClass;
+- (BOOL) isPublic;
+
+- (void) setFn: (NSString *) newFn;
+- (NSString *) fn;
+- (void) setNickname: (NSString *) newNickname;
+- (NSString *) nickname;
+- (void) setDescription: (NSString *) newDescription;
+- (NSString *) description;
+
+- (void) addCardReference: (NGVCardReference *) newCardRef;
+- (void) deleteCardReference: (NGVCardReference *) cardRef;
+- (NSArray *) cardReferences;
+
+@end
+
+#endif /* NGVLIST_H */
diff --git a/SOPE/NGCards/NGVList.m b/SOPE/NGCards/NGVList.m
new file mode 100644 (file)
index 0000000..7d359df
--- /dev/null
@@ -0,0 +1,200 @@
+/* NGVList.m - this file is part of NGCards
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSEnumerator.h>
+#import <Foundation/NSString.h>
+
+#import "NGVCardReference.h"
+
+#import "NGVList.h"
+
+@implementation NGVList
+
++ (id) listWithUid: (NSString *) _uid
+{
+  NGVList *newList;
+
+  newList = [[self alloc] initWithUid: _uid];
+  [newList autorelease];
+
+  return newList;
+}
+
+- (id) initWithUid: (NSString *) _uid
+{
+  if ((self = [self init]))
+    {
+      [self setTag: @"vlist"];
+      [self setUid: _uid];
+      [self setVersion: @"1.0"];
+    }
+
+  return self;
+}
+
+/* class mapping */
+- (Class) classForTag: (NSString *) classTag
+{
+  Class tagClass;
+
+  tagClass = Nil;
+  if ([classTag isEqualToString: @"PRODID"]
+      || [classTag isEqualToString: @"VERSION"]
+      || [classTag isEqualToString: @"UID"]
+      || [classTag isEqualToString: @"CLASS"]
+      || [classTag isEqualToString: @"FN"]
+      || [classTag isEqualToString: @"NICKNAME"]
+      || [classTag isEqualToString: @"DESCRIPTION"])
+    tagClass = [CardElement class];
+  else if ([classTag isEqualToString: @"CARD"])
+    tagClass = [NGVCardReference class];
+  else
+    tagClass = [super classForTag: classTag];
+
+  return tagClass;
+}
+
+- (void) setProdID: (NSString *) newProdID
+{
+  [[self uniqueChildWithTag: @"prodid"] setValue: 0 to: newProdID];
+}
+
+- (NSString *) prodID
+{
+  return [[self uniqueChildWithTag: @"prodid"] value: 0];
+}
+
+- (void) setVersion: (NSString *) newVersion
+{
+  [[self uniqueChildWithTag: @"version"] setValue: 0
+                                        to: newVersion];
+}
+
+- (NSString *) version
+{
+  return [[self uniqueChildWithTag: @"version"] value: 0];
+}
+
+- (void) setUid: (NSString *) newUid
+{
+  [[self uniqueChildWithTag: @"uid"] setValue: 0
+                                    to: newUid];
+}
+
+- (NSString *) uid
+{
+  return [[self uniqueChildWithTag: @"uid"] value: 0];
+}
+
+- (void) setAccessClass: (NSString *) newAccessClass
+{
+  [[self uniqueChildWithTag: @"class"] setValue: 0
+                                      to: newAccessClass];
+}
+
+- (NSString *) accessClass
+{
+  return [[self uniqueChildWithTag: @"class"] value: 0];
+}
+
+- (NGCardsAccessClass) symbolicAccessClass
+{
+  NGCardsAccessClass symbolicAccessClass;
+  NSString *accessClass;
+
+  accessClass = [[self accessClass] uppercaseString];
+  if ([accessClass isEqualToString: @"PRIVATE"])
+    symbolicAccessClass = NGCardsAccessPrivate;
+  else if ([accessClass isEqualToString: @"CONFIDENTIAL"])
+    symbolicAccessClass = NGCardsAccessConfidential;
+  else
+    symbolicAccessClass = NGCardsAccessPublic;
+
+  return symbolicAccessClass;
+}
+
+- (BOOL) isPublic
+{
+  return ([self symbolicAccessClass] == NGCardsAccessPublic);
+}
+
+- (void) setFn: (NSString *) newFn
+{
+  [[self uniqueChildWithTag: @"fn"] setValue: 0 to: newFn];
+}
+
+- (NSString *) fn
+{
+  return [[self uniqueChildWithTag: @"fn"] value: 0];
+}
+
+- (void) setNickname: (NSString *) newNickname
+{
+  [[self uniqueChildWithTag: @"nickname"] setValue: 0
+                                         to: newNickname];
+}
+
+- (NSString *) nickname
+{
+  return [[self uniqueChildWithTag: @"nickname"] value: 0];
+}
+
+- (void) setDescription: (NSString *) newDescription
+{
+  [[self uniqueChildWithTag: @"description"] setValue: 0
+                                            to: newDescription];
+}
+
+- (NSString *) description
+{
+  return [[self uniqueChildWithTag: @"description"] value: 0];
+}
+
+- (void) addCardReference: (NGVCardReference *) newCardRef
+{
+  [self addChild: newCardRef];
+}
+
+- (void) deleteCardReference: (NGVCardReference *) cardRef
+{
+  NSEnumerator *cardReferences;
+  NGVCardReference *currentRef;
+  NSMutableArray *deletedRefs;
+
+  deletedRefs = [NSMutableArray array];
+  cardReferences
+    = [[self childrenWithTag: @"card"] objectEnumerator];
+  while ((currentRef = [cardReferences nextObject]))
+    if ([[currentRef reference]
+         isEqualToString: [cardRef reference]])
+      [deletedRefs addObject: currentRef];
+
+  [children removeObjectsInArray: deletedRefs];
+}
+
+- (NSArray *) cardReferences
+{
+  return [self childrenWithTag: @"card"];
+}
+
+@end
index 41acb50872ac5d8af61bb811b2685f9564e63247..69ad8c4204db7faa94b1abcc7df626bc82b7b4fb 100644 (file)
@@ -9,6 +9,7 @@
       {
         name        = "VSCardSaxDriver";
         sourceTypes = ( "text/x-vcard", "text/vcard",
+                       "text/x-vlist",
                         "text/x-calendar", "text/calendar" );
       }
     );
diff --git a/Scripts/sql-update-20080303.sh b/Scripts/sql-update-20080303.sh
new file mode 100644 (file)
index 0000000..e71a28b
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+# this script only work with PostgreSQL
+
+defaultusername=$USER
+defaulthostname=localhost
+defaultdatabase=$USER
+indextable=sogo_folder_info
+
+read -p "Username ($defaultusername): " username
+read -p "Hostname ($defaulthostname): " hostname
+read -p "Database ($defaultdatabase): " database
+
+if [ -z "$username" ]
+then
+  username=$defaultusername
+fi
+if [ -z "$hostname" ]
+then
+  hostname=$defaulthostname
+fi
+if [ -z "$database" ]
+then
+  database=$defaultdatabase
+fi
+
+echo ""
+echo "You will now be requested your password twice..."
+echo "After that, a list of SQL operations will scroll."
+echo ""
+
+sqlscript=""
+
+function addField() {
+    oldIFS="$IFS"
+    IFS=" "
+    part="`echo -e \"ALTER TABLE $table ADD COLUMN c_component VARCHAR(10) NOT NULL DEFAULT 'vcard';\\n\"`";
+    sqlscript="$sqlscript$part"
+    IFS="$oldIFS"
+}
+
+tables=`psql -t -U $username -h $hostname $database -c "select split_part(c_quick_location, '/', 5) from $indextable where c_folder_type = 'Contact';"`
+
+for table in $tables;
+do
+  addField
+done
+
+echo "$sqlscript" | psql -q -e -U $username -h $hostname $database > /dev/null
+
+echo "Please ignore the errors above. They just mean that the migration was already done for the elements in question.";
index 745e312c42ffc9b33b2b6b3f7919e3167014b2a6..6491a35372ff5bd67ad96df4fe689211d5e9fe3e 100644 (file)
@@ -150,11 +150,6 @@ static NSNumber   *sharedYes = nil;
 
 /* name lookup */
 
-- (BOOL) isValidAppointmentName: (NSString *)_key
-{
-  return ([_key length] != 0);
-}
-
 - (void) appendObject: (NSDictionary *) object
           withBaseURL: (NSString *) baseURL
      toREPORTResponse: (WOResponse *) r
@@ -391,7 +386,7 @@ static NSNumber   *sharedYes = nil;
       obj = [super lookupName:_key inContext:_ctx acquire:NO];
       if (!obj)
         {
-         if ([self isValidAppointmentName:_key])
+         if ([self isValidContentName:_key])
             {
               url = [[[_ctx request] uri] urlWithoutParameters];
               if ([url hasSuffix: @"AsTask"])
index b6ecfda2f1b42e12645f95e81d41cf5837bc4d28..d8c3ea43332964cdd33366fe28bf84279b332822 100644 (file)
   return r;
 }
 
+- (BOOL) isFolderish
+{
+  return NO;
+}
+
 - (NSString *) davContentType
 {
   return @"text/calendar";
index 3250fef2c26e1ad8fdc605239e5c22348d4a5c4d..ce2616d7165486e968c11b557406a303df5775f4 100644 (file)
@@ -8,7 +8,7 @@
   };
   
   classes = {
-    SOGoAppointmentFolder = {
+    SOGoAppointmentFolders = {
       superclass = "SOGoParentFolder";
     };
     SOGoAppointmentFolder = {
index dd0ae6daa5002770ad1f40bf0b12cebd0bd80fda..b452a417691dfb3b24dc94331766b36178ff130a 100644 (file)
@@ -12,6 +12,7 @@ Contacts_OBJC_FILES =                 \
        SOGoFolder+CardDAV.m            \
        SOGoContactFolders.m            \
        SOGoContactGCSEntry.m           \
+       SOGoContactGCSList.m            \
        SOGoContactGCSFolder.m          \
        SOGoContactLDIFEntry.m          \
        SOGoContactLDAPFolder.m         \
index 4ebfeac3346b5a1d654e5e25f81a4629ef8dd923..fe9b62e06ad816d73ba50d69dee21aa0292555a3 100644 (file)
@@ -29,7 +29,8 @@
 
 @class NGVCard;
 
-@interface SOGoContactGCSEntry : SOGoContentObject <SOGoContactObject>
+@interface SOGoContactGCSEntry
+  : SOGoContentObject <SOGoContactObject>
 {
   NGVCard *card;
 }
index eff8313e93e6d5aec9d828c6b99345580e0d7b7d..0c285bae37ca8a008d90df87957f853c4817cc60 100644 (file)
 #import <NGObjWeb/WOResponse.h>
 #import <NGExtensions/NSObject+Logs.h>
 #import <NGExtensions/NSString+misc.h>
+#import <NGCards/CardGroup.h>
 #import <EOControl/EOQualifier.h>
 #import <EOControl/EOSortOrdering.h>
 #import <GDLContentStore/GCSFolder.h>
 
-#import <SoObjects/SOGo/NSDictionary+Utilities.h>
+#import <SOGo/SOGoCache.h>
+#import <SOGo/NSArray+Utilities.h>
+#import <SOGo/NSDictionary+Utilities.h>
+#import <SOGo/NSString+Utilities.h>
+
 #import "SOGoContactGCSEntry.h"
+#import "SOGoContactGCSList.h"
+
 #import "SOGoContactGCSFolder.h"
 
 #define folderListingFields [NSArray arrayWithObjects: @"c_name", @"c_cn", \
   return contact;
 }
 
-- (id) lookupName: (NSString *) _key
-        inContext: (WOContext *) _ctx
-          acquire: (BOOL) _flag
+- (Class) objectClassForContent: (NSString *) content
 {
-  id obj;
-  BOOL isPut;
+  CardGroup *cardEntry;
+  NSString *firstTag;
+  Class objectClass;
 
-  isPut = NO;
-  obj = [super lookupName:_key inContext:_ctx acquire:NO];
-  
-  if (!obj)
+  objectClass = Nil;
+
+  cardEntry = [CardGroup parseSingleFromSource: content];
+  if (cardEntry)
+    {
+      firstTag = [[cardEntry tag] uppercaseString];
+      if ([firstTag isEqualToString: @"VCARD"])
+       objectClass = [SOGoContactGCSEntry class];
+      else if ([firstTag isEqualToString: @"VLIST"])
+       objectClass = [SOGoContactGCSList class];
+    }
+
+  return objectClass;
+}
+
+- (Class) objectClassForResourceNamed: (NSString *) name
+{
+  EOQualifier *qualifier;
+  NSArray *records;
+  NSString *component;
+  Class objectClass;
+
+  qualifier = [EOQualifier qualifierWithQualifierFormat:@"c_name = %@", name];
+  records = [[self ocsFolder] fetchFields: [NSArray arrayWithObject: @"c_component"]
+                              matchingQualifier: qualifier];
+
+  if ([records count])
     {
-      if ([[[_ctx request] method] isEqualToString: @"PUT"])
-       {
-         if ([_key isEqualToString: @"PUT"])
-           isPut = YES;
-         else
-           obj = [SOGoContactGCSEntry objectWithName: _key
-                                      inContainer: self];
-       }
+      component = [[records objectAtIndex: 0] valueForKey: @"c_component"];
+      if ([component isEqualToString: @"vcard"])
+        objectClass = [SOGoContactGCSEntry class];
+      else if ([component isEqualToString: @"vlist"])
+        objectClass = [SOGoContactGCSList class];
       else
-        obj = [self lookupContactWithId: _key];
+        objectClass = Nil;
     }
+  else
+    objectClass = Nil;
+  
+  return objectClass;
+}
+
+- (id) deduceObjectForName: (NSString *)_key
+                 inContext: (id)_ctx
+{
+  WORequest *request;
+  NSString *method;
+  Class objectClass;
+  id obj;
+
+  request = [_ctx request];
+  method = [request method];
+  if ([method isEqualToString: @"PUT"])
+    objectClass = [self objectClassForContent: [request contentAsString]];
+  else
+    objectClass = [self objectClassForResourceNamed: _key];
+
+  if (objectClass)
+    obj = [objectClass objectWithName: _key inContainer: self];
+  else
+    obj = nil;
+
+  return obj;
+}
+
+- (BOOL) requestNamedIsHandledLater: (NSString *) name
+{
+  return [name isEqualToString: @"OPTIONS"];
+}
+
+- (id) lookupName: (NSString *)_key
+        inContext: (id)_ctx
+          acquire: (BOOL)_flag
+{
+  id obj;
+  NSString *url;
+  BOOL handledLater;
+
+  /* first check attributes directly bound to the application */
+  handledLater = [self requestNamedIsHandledLater: _key];
+  if (handledLater)
+    obj = nil;
+  else
+    {
+      obj = [super lookupName:_key inContext:_ctx acquire:NO];
+      if (!obj)
+        {
+         if ([self isValidContentName: _key])
+            {
+              url = [[[_ctx request] uri] urlWithoutParameters];
+              if ([url hasSuffix: @"AsContact"])
+                obj = [SOGoContactGCSEntry objectWithName: _key
+                                          inContainer: self];
+              else if ([url hasSuffix: @"AsList"])
+                obj = [SOGoContactGCSList objectWithName: _key
+                                         inContainer: self];
+              else
+                obj = [self deduceObjectForName: _key
+                            inContext: _ctx];
+            }
+        }
+      if (!obj)
+        obj = [NSException exceptionWithHTTPStatus:404 /* Not Found */];
+    }
+
+  if (obj)
+    [[SOGoCache sharedCache] registerObject: obj
+                            withName: _key
+                            inContainer: container];
+
+  return obj;
+}
+
+// - (id) lookupName: (NSString *) _key
+//         inContext: (WOContext *) _ctx
+//           acquire: (BOOL) _flag
+// {
+//   id obj;
+//   BOOL isPut;
+
+//   isPut = NO;
+//   obj = [super lookupName:_key inContext:_ctx acquire:NO];
+  
+//   if (!obj)
+//     {
+//       if ([[[_ctx request] method] isEqualToString: @"PUT"])
+//     {
+//       if ([_key isEqualToString: @"PUT"])
+//         isPut = YES;
+//       else
+
+//         obj = [SOGoContactGCSEntry objectWithName: _key
+//                                    inContainer: self];
+//     }
+//       else
+//         obj = [self lookupContactWithId: _key];
+//     }
 //   if (!(obj || isPut))
 //     obj = [NSException exceptionWithHTTPStatus:404 /* Not Found */];
 
 //       return [self contactWithName:_key inContext:_ctx];
 //   }
 
-  /* return 404 to stop acquisition */
-  return obj;
-}
+//   /* return 404 to stop acquisition */
+//   return obj;
+// }
 
 /* fetching */
 - (EOQualifier *) _qualifierForFilter: (NSString *) filter
   cardDavCollection
     = [NSArray arrayWithObjects: @"addressbook",
               @"urn:ietf:params:xml:ns:carddav", nil];
-
   resourceType = [NSMutableArray arrayWithArray: [super davResourceType]];
   [resourceType addObject: cardDavCollection];
 
diff --git a/SoObjects/Contacts/SOGoContactGCSList.h b/SoObjects/Contacts/SOGoContactGCSList.h
new file mode 100644 (file)
index 0000000..5e3cc16
--- /dev/null
@@ -0,0 +1,37 @@
+/* SOGoContactGCSList.h - this file is part of SOGo
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SOGOCONTACTGCSLIST_H
+#define SOGOCONTACTGCSLIST_H
+
+#import <SOGo/SOGoContentObject.h>
+
+@class NGVList;
+
+@interface SOGoContactGCSList : SOGoContentObject
+{
+  NGVList *list;
+}
+
+@end
+
+#endif /* SOGOCONTACTGCSLIST_H */
diff --git a/SoObjects/Contacts/SOGoContactGCSList.m b/SoObjects/Contacts/SOGoContactGCSList.m
new file mode 100644 (file)
index 0000000..2534fc6
--- /dev/null
@@ -0,0 +1,92 @@
+/* SOGoContactGCSList.m - this file is part of SOGo
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSString.h>
+
+#import <NGCards/NGVList.h>
+
+#import "SOGoContactGCSList.h"
+
+@implementation SOGoContactGCSList
+
+- (id) init
+{
+  if ((self = [super init]))
+    {
+      list = nil;
+    }
+
+  return self;
+}
+
+- (void) dealloc
+{
+  [list release];
+  [super dealloc];
+}
+
+/* content */
+
+- (NGVList *) vList
+{
+  NSString *content;
+
+  if (!list)
+    {
+      content = [record objectForKey: @"c_content"];
+      if ([[content uppercaseString] hasPrefix: @"BEGIN:VLIST"])
+        list = [NGVList parseSingleFromSource: content];
+      else
+        list = [NGVList listWithUid: [self nameInContainer]];
+      [list retain];
+    }
+
+  return list;
+}
+
+/* DAV */
+
+- (NSString *) davContentType
+{
+  return @"text/x-vlist";
+}
+
+/* specialized actions */
+
+- (void) save
+{
+  NGVList *vlist;
+
+  vlist = [self vList];
+
+  [self saveContentString: [vlist versitString]];
+}
+
+/* message type */
+
+- (NSString *) outlookMessageClass
+{
+  return @"IPM.Contact";
+}
+
+@end
index f303590298fa174a0141fa446e1e0db4f51d5be8..dd5dcd4104f198aa2fafa6ecf90a172b49b3e813 100644 (file)
@@ -17,6 +17,9 @@
     SOGoContactGCSEntry = {
       superclass = "SOGoContentObject";
     };
+    SOGoContactGCSList = {
+      superclass = "SOGoContentObject";
+    };
     SOGoContactLDAPFolder = {
       superclass = "SOGoGCSFolder";
       protectedBy = "Access Contents Information";
index 8d59674297b76b02a68695b6dc356ae75e8dc09c..a7028b3065aa4c9decc515b6b767dfeaf88c2d5a 100644 (file)
@@ -48,6 +48,8 @@
   NGImap4Connection *imap4;
 }
 
+- (BOOL) isFolderish;
+
 - (id) initWithImap4URL: (NSURL *) _url
            inContainer: (id) _container;
 
index cfeda797fbb9c6291fdcae4acf5b3f81f7f9c519..7c5ec4e78d548974ed397cae6e317e358ff46a10 100644 (file)
@@ -60,6 +60,11 @@ static BOOL debugOn = YES;
   [super dealloc];
 }
 
+- (BOOL) isFolderish
+{
+  return YES;
+}
+
 /* hierarchy */
 
 - (SOGoMailAccount *) mailAccountFolder
index 3afd10e076aee681bcf32e4a363b2069578a2ee6..38671f819df9d6f5a789fc6f2cf9ca86c8847e8d 100644 (file)
@@ -449,6 +449,11 @@ static BOOL debugOn = NO;
   return klazz;
 }
 
+- (BOOL) isFolderish
+{
+  return NO;
+}
+
 /* etag support */
 
 - (id)davEntityTag {
index ac27122be5b4f574ab2b8d6f5b69697a5e0d74df..a4bfbc3775742e6a7d85ac40cc8b3c21e6d09690 100644 (file)
                       reason:@"this object cannot be copied via WebDAV"];
 }
 
-- (BOOL)davIsCollection {
-  return [self isFolderish];
-}
-
 /* acls */
 
 - (NSArray *) aclUsers
index 69951d955da046aae999c5a65d0059fa3aaf80d1..03f1c934f8b8a5e816ef703d8bc2061ba389e4d7 100644 (file)
@@ -36,6 +36,8 @@
 - (NSString *) folderType;
 - (NSArray *) fetchContentObjectNames;
 
+- (BOOL) isValidContentName: (NSString *) name;
+
 /* sorting */
 - (NSComparisonResult) compare: (id) otherFolder;
 
index 3f404fdf9cf14653e821722d00146de063009bf9..b01bfe5a52319edaca378ad5905d6d003f5f86e4 100644 (file)
   return [NSArray array];
 }
 
+- (BOOL) isValidContentName: (NSString *) name
+{
+  return ([name length] > 0);
+}
+
 - (BOOL) isFolderish
 {
   return YES;
 
 /* WebDAV */
 
-- (BOOL) davIsCollection
-{
-  return [self isFolderish];
-}
-
 - (NSString *) davContentType
 {
   return @"httpd/unix-directory";
index 7fbace9f9c16db3f6fea3eac36f20819e4bb439e..84d69356b8ff0e6b41a224620eb855fd37302380 100644 (file)
@@ -634,6 +634,18 @@ static BOOL sendACLAdvisories = NO;
   return [NSNumber numberWithBool:YES]; /* delete worked out ... */
 }
 
+- (BOOL) isFolderish
+{
+  [self subclassResponsibility: _cmd];
+
+  return NO;
+}
+
+- (BOOL) davIsCollection
+{
+  return [self isFolderish];
+}
+
 - (NSString *) davContentType
 {
   return @"text/plain";
index b9d4b0eb762e7a4022c461b9e436926dcb0164fb..a561d82f5e4447e49ef05797730fd159069a7ac2 100644 (file)
@@ -17,6 +17,8 @@ ContactsUI_OBJC_FILES =                       \
        UIxContactsFilterPanel.m        \
        UIxContactView.m                \
        UIxContactEditor.m              \
+       UIxListView.m           \
+       UIxListEditor.m         \
        UIxContactsListView.m           \
        UIxContactsListViewContainer.m  \
        UIxContactFoldersView.m         \
index 754b6ea7887d22fe1fb3502c8141e306017a9809..af0317af6869a561e7092f43766dec91736a30c2 100644 (file)
 #import <NGObjWeb/NSException+HTTP.h>
 #import <NGObjWeb/SoObject.h>
 #import <NGObjWeb/WORequest.h>
+#import <NGObjWeb/WOResponse.h>
 #import <NGExtensions/NSNull+misc.h>
 
 #import <NGCards/NGVCard.h>
 #import <NGCards/NSArray+NGCards.h>
 
 #import <Contacts/SOGoContactObject.h>
-#import <Contacts/SOGoContactFolder.h>
+#import <Contacts/SOGoContactGCSEntry.h>
+#import <Contacts/SOGoContactGCSFolder.h>
 
 #import "UIxContactEditor.h"
 
 
 /* accessors */
 
+- (NSString *) saveURL
+{
+  return [NSString stringWithFormat: @"%@/saveAsContact",
+                  [[self clientObject] baseURL]];
+}
+
 - (NSArray *) htmlMailFormatList
 {
   static NSArray *htmlMailFormatItems = nil;
 
 /* actions */
 
-- (BOOL) shouldTakeValuesFromRequest: (WORequest *) _rq
-                           inContext: (WOContext*) _c
+- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
+                           inContext: (WOContext*) context
 {
-  return YES;
+  NSString *actionName;
+
+  actionName = [[request requestHandlerPath] lastPathComponent];
+
+  return ([[self clientObject] isKindOfClass: [SOGoContactGCSEntry class]]
+         && [actionName hasPrefix: @"save"]);
 }
 
 - (void) _setSnapshotValue: (NSString *) key
 - (NSString *) editActionName
 {
   /* this is overridden in the mail based contacts UI to redirect to tb.edit */
-  return @"edit";
+  return @"editAsContact";
 }
 
 - (CardElement *) _elementWithTag: (NSString *) tag
 
 - (id <WOActionResults>) saveAction
 {
-  id <SOGoContactObject> contact;
+  SOGoContactGCSEntry *contact;
   id result;
   NSString *jsRefreshMethod;
 
   return [self redirectToLocation: url];
 }
 
+#warning Could this be part of a common parent with UIxAppointment/UIxTaskEditor/UIxListEditor ?
 - (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;
-  SOGoObject <SOGoContactFolder> *co;
+  NSString *objectId, *method, *uri;
+  id <WOActionResults> result;
+  SOGoContactGCSFolder *co;
 
   co = [self clientObject];
-  if ([co respondsToSelector: @selector (globallyUniqueObjectId)])
-    objectId = [co globallyUniqueObjectId];
+  objectId = [co globallyUniqueObjectId];
+  if ([objectId length] > 0)
+    {
+      method = [NSString stringWithFormat:@"%@/%@.vcf/editAsContact",
+                         [co soURL], objectId];
+      uri = [self completeHrefForMethod: method];
+      result = [self redirectToLocation: uri];
+    }
   else
-    objectId = nil;
-
-  if ([objectId length] == 0)
-    return [NSException exceptionWithHTTPStatus: 500 /* Internal Error */
-                        reason: @"could not create a unique ID"];
+    result = [NSException exceptionWithHTTPStatus: 500 /* Internal Error */
+                          reason: @"could not create a unique ID"];
 
-  nextMethod = [NSString stringWithFormat: @"../%@.vcf/%@", 
-                        objectId, [self editActionName]];
-  uri = [self _completeURIForMethod: nextMethod];
-
-  return [self redirectToLocation: uri];
+  return result;
 }
 
 @end /* UIxContactEditor */
diff --git a/UI/Contacts/UIxListEditor.h b/UI/Contacts/UIxListEditor.h
new file mode 100644 (file)
index 0000000..f895eae
--- /dev/null
@@ -0,0 +1,32 @@
+/* UIxListEditor.h - this file is part of SOGo
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef UIXLISTEDITOR_H
+#define UIXLISTEDITOR_H
+
+#import <SOGoUI/UIxComponent.h>
+
+@interface UIxListEditor : UIxComponent
+
+@end
+
+#endif /* UIXLISTEDITOR_H */
diff --git a/UI/Contacts/UIxListEditor.m b/UI/Contacts/UIxListEditor.m
new file mode 100644 (file)
index 0000000..ba9e57a
--- /dev/null
@@ -0,0 +1,61 @@
+/* UIxListEditor.m - this file is part of SOGo
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <NGObjWeb/NSException+HTTP.h>
+#import <NGObjWeb/WOResponse.h>
+
+#import <Contacts/SOGoContactGCSFolder.h>
+
+#import "UIxListEditor.h"
+
+@implementation UIxListEditor
+
+- (NSString *) saveURL
+{
+  return [NSString stringWithFormat: @"%@/saveAsList",
+                   [[self clientObject] baseURL]];
+}
+
+#warning Could this be part of a common parent with UIxAppointment/UIxTaskEditor/UIxListEditor ?
+- (id) newAction
+{
+  NSString *objectId, *method, *uri;
+  id <WOActionResults> result;
+  SOGoContactGCSFolder *co;
+
+  co = [self clientObject];
+  objectId = [co globallyUniqueObjectId];
+  if ([objectId length] > 0)
+    {
+      method = [NSString stringWithFormat:@"%@/%@.vls/editAsList",
+                         [co soURL], objectId];
+      uri = [self completeHrefForMethod: method];
+      result = [self redirectToLocation: uri];
+    }
+  else
+    result = [NSException exceptionWithHTTPStatus: 500 /* Internal Error */
+                          reason: @"could not create a unique ID"];
+
+  return result;
+}
+
+@end
diff --git a/UI/Contacts/UIxListView.h b/UI/Contacts/UIxListView.h
new file mode 100644 (file)
index 0000000..40783eb
--- /dev/null
@@ -0,0 +1,32 @@
+/* UIxListView.h - this file is part of SOGo
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef UIXLISTVIEW_H
+#define UIXLISTVIEW_H
+
+#import <SOGoUI/UIxComponent.h>
+
+@interface UIxListView : UIxComponent
+
+@end
+
+#endif /* UIXLISTVIEW_H */
diff --git a/UI/Contacts/UIxListView.m b/UI/Contacts/UIxListView.m
new file mode 100644 (file)
index 0000000..de69286
--- /dev/null
@@ -0,0 +1,27 @@
+/* UIxListView.m - this file is part of SOGo
+ *
+ * Copyright (C) 2008 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import "UIxListView.h"
+
+@implementation UIxListView
+
+@end
index 4a0285aeeae911e8f559af0b201ed39c0552f384..5b19b2f6ef129d9553add9bcbb6df54c09594903 100644 (file)
               protectedBy = "View";
               pageName    = "UIxContactsListView";
            };
-           new = {
+           newcontact = {
               protectedBy = "Add Documents, Images, and Files";
               pageName    = "UIxContactEditor";
               actionName  = "new";
            };
+           newlist = {
+              protectedBy = "Add Documents, Images, and Files";
+              pageName    = "UIxListEditor";
+              actionName  = "new";
+           };
            mailer-contacts = {
               protectedBy = "View";
               pageName    = "UIxContactsListView";
               protectedBy = "Access Contents Information";
               pageName    = "UIxContactEditor";
            };
+           editAsContact = {
+              protectedBy = "Access Contents Information";
+              pageName    = "UIxContactEditor";
+           };
            save = {
               protectedBy = "Change Images And Files";
               pageName    = "UIxContactEditor";
               actionName  = "save";
            };
+           saveAsContact = {
+              protectedBy = "Change Images And Files";
+              pageName    = "UIxContactEditor";
+              actionName  = "save";
+           };
            write = {
               protectedBy = "View";
               pageName    = "UIxContactEditor";
         };
      };
 
+     SOGoContactGCSList = {
+        methods = {
+           view = {
+              protectedBy = "Access Contents Information";
+              pageName    = "UIxListView";
+           };
+           delete = {
+              protectedBy = "Delete Objects";
+              pageName    = "UIxListView";
+              actionName  = "delete";
+           };
+           edit = {
+              protectedBy = "Access Contents Information";
+              pageName    = "UIxListEditor";
+           };
+           editAsList = {
+              protectedBy = "Access Contents Information";
+              pageName    = "UIxListEditor";
+           };
+           save = {
+              protectedBy = "Change Images And Files";
+              pageName    = "UIxListEditor";
+              actionName  = "save";
+           };
+           saveAsList = {
+              protectedBy = "Change Images And Files";
+              pageName    = "UIxListEditor";
+              actionName  = "save";
+           };
+        };
+     };
+
      SOGoContactLDIFEntry = {
         methods = {
            view = {
      };
   };
 }
-
index a1c33099d83649d6d544c5e29c9b82e96f80f833..745d432a968d71d5ae00e52bcb2796f9668f9825 100644 (file)
@@ -80,7 +80,7 @@
 - (NSString *) saveURL
 {
   return [NSString stringWithFormat: @"%@/saveAsAppointment",
-                   [[self clientObject] baseURL]];
+                  [[self clientObject] baseURL]];
 }
 
 /* icalendar values */
index 96894d145b1ddf470c7457324bd6f84850118cd4..2f49e537ac85237e6c3016ea7066ea5a70636c95 100644 (file)
@@ -9,7 +9,7 @@
     title="name"
     const:popup="YES"
     >
-    <form var:href="clientObject.baseURL" name="editform"
+    <form var:href="saveURL" name="editform"
       onsubmit="return validateContactEditor()">
 
       <div class="tabsContainer" id="editorTabs">
       </div>
       <div id="buttons">
         <input
-          type="submit"
+         id="cancelButton"
+          type="button"
           class="button"
           label:value="Cancel"
-          name="cancel"
-          onclick="window.close(); return false;" />
+          name="cancel"/>
         <var:if condition="canCreateOrModify"
        ><input
            type="submit"
            class="button"
            label:value="Save"
-           name="save:method" /></var:if>
+           name="submit" /></var:if>
       </div>
     </form>
   </var:component>
diff --git a/UI/Templates/ContactsUI/UIxListEditor.wox b/UI/Templates/ContactsUI/UIxListEditor.wox
new file mode 100644 (file)
index 0000000..02bb021
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' standalone='yes'?>
+  <var:component
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:var="http://www.skyrix.com/od/binding"
+    xmlns:const="http://www.skyrix.com/od/constant"
+    xmlns:rsrc="OGo:url"
+    xmlns:label="OGo:label"
+    xmlns:uix="OGo:uix"
+    className="UIxPageFrame"
+    title="name"
+    const:popup="YES"
+    >Unimplemented</var:component>
diff --git a/UI/Templates/ContactsUI/UIxListView.wox b/UI/Templates/ContactsUI/UIxListView.wox
new file mode 100644 (file)
index 0000000..02bb021
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' standalone='yes'?>
+  <var:component
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:var="http://www.skyrix.com/od/binding"
+    xmlns:const="http://www.skyrix.com/od/constant"
+    xmlns:rsrc="OGo:url"
+    xmlns:label="OGo:label"
+    xmlns:uix="OGo:uix"
+    className="UIxPageFrame"
+    title="name"
+    const:popup="YES"
+    >Unimplemented</var:component>
index f9f1a7bad6725d2357744bb425025a19376df9b1..965690323be5443d810172be34c9358fe14f33a2 100644 (file)
      <input type="hidden" name="range2"
        id="range2"
        var:value="range2"/>
-
-
     </div>
   </form>
 </var:component>
index e6196b0b54aec8c69f8dc5c8d92798fee02eb8ce..d9d7a876a6d4e0a21f2335c6c73ff82eaf746555 100644 (file)
@@ -455,7 +455,7 @@ function onHeaderClick(event) {
 }
 
 function newContact(sender) {
-  openContactWindow(URLForFolderID(currentContactFolder) + "/new");
+  openContactWindow(URLForFolderID(currentContactFolder) + "/newcontact");
 
   return false; /* stop following the link */
 }
index 76910d0322c770bc235bbe10eb0e9c054cbb8e55..97d38c7047de1b4bb9eba77fb2b96c1999a33ca4 100644 (file)
@@ -127,11 +127,18 @@ function onFnNewValue(event) {
   return true;
 }
 
+function onEditorCancelClick(event) {
+   preventDefault(event);
+   window.close();
+}
+
 function initEditorForm() {
   displayNameChanged = ($("fn").value.length > 0);
   $("fn").onkeydown = onFnKeyDown;
   $("sn").onkeyup = onFnNewValue;
   $("givenName").onkeyup = onFnNewValue;
+
+  $("cancelButton").observe("click", onEditorCancelClick);
 }
 
 FastInit.addOnLoad(initEditorForm);
index e961740bfe12955b3f2412d2ca4ab18e5032df14..1aa2e1a5459bedec6bc302c8d69bc7cccf0a6e50 100644 (file)
@@ -288,10 +288,8 @@ function initMailEditor() {
   var list = $("attachments");
   $(list).attachMenu("attachmentsMenu");
   var elements = list.childNodesWithTag("li");
-  for (var i = 0; i < elements.length; i++) {
-    Event.observe(elements[i], "click",
-                 onRowClick.bindAsEventListener(elements[i]));
-  }
+  for (var i = 0; i < elements.length; i++)
+    elements[i].observe("click", onRowClick);
 
   var listContent = $("attachments").childNodesWithTag("li");
   if (listContent.length > 0)