]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1034 d1b88da0-ebda-0310...
authorwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 29 Mar 2007 19:53:25 +0000 (19:53 +0000)
committerwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 29 Mar 2007 19:53:25 +0000 (19:53 +0000)
85 files changed:
ChangeLog
SoObjects/Contacts/SOGoContactFolders.m
SoObjects/Contacts/product.plist
SoObjects/Mailer/SOGoMailFolder.m
SoObjects/SOGo/AgenorUserDefaults.h
SoObjects/SOGo/AgenorUserDefaults.m
SoObjects/SOGo/AgenorUserManager.h
SoObjects/SOGo/AgenorUserManager.m
SoObjects/SOGo/SOGoFolder.h
SoObjects/SOGo/SOGoObject.h
SoObjects/SOGo/SOGoUser.h
SoObjects/SOGo/SOGoUser.m
UI/Common/GNUmakefile
UI/Common/UIxAclEditor.h
UI/Common/UIxAclEditor.m
UI/Common/UIxFolderActions.h [new file with mode: 0644]
UI/Common/UIxFolderActions.m [new file with mode: 0644]
UI/Common/product.plist
UI/Contacts/English.lproj/Localizable.strings
UI/Contacts/French.lproj/Localizable.strings
UI/Contacts/GNUmakefile
UI/Contacts/UIxContactFoldersView.m
UI/Contacts/UIxContactsAclsSelection.m [deleted file]
UI/Contacts/UIxContactsAddressBooksSelection.m [deleted file]
UI/Contacts/UIxContactsCalendarsSelection.m [deleted file]
UI/Contacts/UIxContactsListView.m
UI/Contacts/UIxContactsListViewContainer.h
UI/Contacts/UIxContactsListViewContainer.m
UI/Contacts/UIxContactsUserFolders.h [moved from UI/Scheduler/UIxCalCalendarsListView.h with 64% similarity]
UI/Contacts/UIxContactsUserFolders.m [new file with mode: 0644]
UI/Contacts/product.plist
UI/MainUI/SOGoUserHomePage.m
UI/MainUI/product.plist
UI/SOGoUI/GNUmakefile
UI/SOGoUI/UIxComponent.m
UI/Scheduler/French.lproj/Localizable.strings
UI/Scheduler/GNUmakefile
UI/Scheduler/UIxCalBackForthNavView.m [deleted file]
UI/Scheduler/UIxCalCalendarsListView.m [deleted file]
UI/Scheduler/UIxCalDayTable.m
UI/Scheduler/UIxCalDayView.h
UI/Scheduler/UIxCalDayView.m
UI/Scheduler/UIxCalMainView.m
UI/Scheduler/UIxCalScheduleOverview.m [deleted file]
UI/Scheduler/UIxCalView.h
UI/Scheduler/UIxCalView.m
UI/Scheduler/UIxComponentEditor.m
UI/Scheduler/UIxContactSelector.h [moved from UI/Contacts/UIxContactSelector.h with 100% similarity]
UI/Scheduler/UIxContactSelector.m [moved from UI/Contacts/UIxContactSelector.m with 100% similarity]
UI/Scheduler/UIxTaskEditor.m
UI/Scheduler/product.plist
UI/Templates/ContactsUI/UIxContactsAclsSelection.wox [deleted file]
UI/Templates/ContactsUI/UIxContactsAddressBooksSelection.wox [deleted file]
UI/Templates/ContactsUI/UIxContactsCalendarsSelection.wox [deleted file]
UI/Templates/ContactsUI/UIxContactsFilterPanel.wox
UI/Templates/ContactsUI/UIxContactsListViewContainer.wox
UI/Templates/ContactsUI/UIxContactsMailerSelection.wox
UI/Templates/ContactsUI/UIxContactsUserFolders.wox [new file with mode: 0644]
UI/Templates/MailerUI/UIxMailFilterPanel.wox
UI/Templates/SchedulerUI/UIxCalBackForthNavView.wox [deleted file]
UI/Templates/SchedulerUI/UIxCalCalendarsListView.wox [deleted file]
UI/Templates/SchedulerUI/UIxCalDayTable.wox
UI/Templates/SchedulerUI/UIxCalFilterPanel.wox
UI/Templates/SchedulerUI/UIxCalMainView.wox
UI/Templates/SchedulerUI/UIxCalScheduleOverview.wox [deleted file]
UI/Templates/SchedulerUI/UIxContactSelector.wox [moved from UI/Templates/ContactsUI/UIxContactSelector.wox with 100% similarity]
UI/Templates/UIxAclEditor.wox
UI/WebServerResources/ContactsUI.js
UI/WebServerResources/MailerUI.css
UI/WebServerResources/MailerUI.js
UI/WebServerResources/SOGoUserHomePage.js [deleted file]
UI/WebServerResources/SchedulerUI.css
UI/WebServerResources/SchedulerUI.js
UI/WebServerResources/UIxAclEditor.css
UI/WebServerResources/UIxAclEditor.js
UI/WebServerResources/UIxContactsUserFolders.css [new file with mode: 0644]
UI/WebServerResources/UIxContactsUserFolders.js [new file with mode: 0644]
UI/WebServerResources/UIxMailEditor.js
UI/WebServerResources/add-calendar.png [new file with mode: 0644]
UI/WebServerResources/calendar-folder-16x16.png [new file with mode: 0644]
UI/WebServerResources/generic.css
UI/WebServerResources/generic.js
UI/WebServerResources/remove-calendar.png [new file with mode: 0644]
UI/WebServerResources/tb-mail-addressbook-flat-16x16.png [new file with mode: 0644]
UI/WebServerResources/week-view.png

index c1dad0c558dad13c7e5ad223fc53a96968de0a09..4091f7b80d11ee5ebb1b0619311ce2a7b3329833 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,103 @@
+2007-03-29  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * UI/Contacts/UIxContactsListViewContainer.m
+       ([UIxContactsListViewContainer -additionalFolders]): take the list
+       of subscribed folders from the new property list used for the user
+       settings. The value of its key is SubscribedFolders for the
+       dictionary entry named "Contacts".
+
+       * UI/Contacts/UIxContactsListView.m ([UIxContactsListView
+       -canAccessContentAction]): new method to override the one from
+       UIxFoldersActions by taking into account the fact that, this time,
+       the clientObject is an ldap folder. Removed many method that used
+       to be related to the handling of the user selector.
+
+       * UI/Scheduler/UIxCalDayView.m: commented out many unused methods
+       to make sure they can be removed.
+
+       * UI/Scheduler/UIxCalView.m ([UIxCalView -_setupCalendarFolders]):
+       populate the calendar entries based on the user settings plist.
+
+       * UI/Contacts/UIxContactFoldersView.m ([UIxContactFoldersView
+       -selectForMailerAction]): restored method.
+
+       * UI/Scheduler/UIxCalendarSelector.m: new template module derived
+       from a simplified version of the old UIxContactEditor (removed).
+
+       * UI/Contacts/UIxContactsUserFolders.m: new template module for
+       selecting users or user folders through an LDAP search of which
+       the results are displayed as a tree.
+
+       * UI/WebServerResources/UIxMailEditor.js: moved previous generic
+       method "onContactAdd" here since the Mailer is now the only module
+       to use it when composing emails.
+
+       * UI/WebServerResources/generic.js: added code for handling the
+       new scheme used for describing SOGo folders, common code to handle
+       folder addition or removal.
+
+       * UI/Common/UIxFolderActions.m ([UIxFolderActions
+       -activateFolderAction]): new method that change the "active"
+       settings in the folder-related fields in the user settings.
+       ([UIxFolderActions -deactivateFolderAction]): see above.
+
+       * UI/Contacts/UIxContactFoldersView.m ([UIxContactFoldersView
+       -checkRightsAction]): removed method.
+
+       * UI/Contacts/UIxContactFoldersView.m ([UIxContactFoldersView
+       -updateAdditionalAddressBooksAction]): removed method.
+
+       * UI/Scheduler/UIxCalMainView.m ([UIxCalMainView
+       -updateCalendarsAction]): removed method.
+
+2007-03-28  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * UI/Scheduler/UIxCalMainView.m ([UIxCalMainView
+       -checkRightsAction]): removed method.
+
+       * UI/Common/UIxFolderActions.m ([UIxFolderActions
+       -canAccessContentAction]): new method designed to replace
+       [UIxCalMainView checkRightsAction] in a more universal way.
+
+2007-03-27  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * SoObjects/Contacts/SOGoContactFolders.m ([SOGoContactFolders
+       -roleOfUser:uidinContext:context]): take all the subkeys into
+       account, not only the "personal" folder.
+
+       * UI/Scheduler/UIxComponentEditor.m ([UIxComponentEditor
+       -takeValuesFromRequest:_rqinContext:_ctx]): append a "uid" field
+       to the new components.
+
+       * SoObjects/SOGo/SOGoUser.m ([SOGoUser -userSettings]): new method
+       (see below).
+
+       * SoObjects/SOGo/AgenorUserManager.m ([AgenorUserManager
+       -getUserDefaultsForUID:uid]): rewrote method to use the "defaults"
+       field of the sogo_user_profile table, where the user-customizable
+       changes will be saved.
+       ([AgenorUserManager -getUserSettingsForUID:uid]): new method
+       similar to the one above, using the "settings" field where the
+       automatic settings will be saved.
+
+       * SoObjects/SOGo/AgenorUserDefaults.m: rewrote a big part of the
+       module to bind the userdefaults to a property list contained in a
+       specified field of the sogo_user_profile table.
+       ([AgenorUserDefaults
+       -initWithTableURL:tableURLuid:userIDfieldName:defaultsFieldName]):
+       added a "fieldName" parameter.
+
+       * UI/Common/UIxFolderActions.m: new module implementing web
+       actions common to all GCS-based folders.
+
+2007-03-26  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * UI/Scheduler/UIxCalDayTable.m ([UIxCalDayTable -labelForDay]):
+       put a carriage return after the day name.
+
+       * UI/MainUI/SOGoUserHomePage.m ([SOGoUserHomePage
+       -readFreeBusyAction]): restored method.
+
 2007-03-22  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
        * UI/MainUI/SOGoUserHomePage.m ([SOGoUserHomePage
index 4e57d72d51f3194d5e0e0850737190c6898c6910..fb81bb53a408f15f079c6250f197c3191c5f2aec 100644 (file)
   if ([traversalPath count] > 2)
     {
       objectName = [traversalPath objectAtIndex: 2];
-      if ([objectName isEqualToString: @"personal"])
-        {
-          roles = [[context activeUser]
-                    rolesForObject: [self lookupName: objectName
-                                          inContext: context
-                                          acquire: NO]
-                    inContext: context];
-          if ([roles containsObject: SOGoRole_Assistant]
-              || [roles containsObject: SOGoRole_Delegate])
-            role = SOGoRole_Assistant;
-        }
+      roles = [[context activeUser]
+               rolesForObject: [self lookupName: objectName
+                                     inContext: context
+                                     acquire: NO]
+               inContext: context];
+      if ([roles containsObject: SOGoRole_Assistant]
+         || [roles containsObject: SOGoRole_Delegate])
+       role = SOGoRole_Assistant;
     }
 
   return role;
index 4ff7a9372c19c616c83c11037768d77ed28c7cb0..6766efe025805f1585e741280bc5e955e940412b 100644 (file)
@@ -12,7 +12,7 @@
       superclass    = "SOGoObject";
       defaultRoles = {
         "Add Documents, Images, and Files" = ( "Owner", "Delegate" );
-        "View"          = ( "Owner", "Delegate", "Assistant" );
+        "View" = ( "Owner", "Delegate", "Assistant" );
         "WebDAV Access" = ( "Owner", "Delegate", "Assistant" );
         "Access Contents Information" = ( "Owner", "Assistant", "Delegate" );
         "ReadAcls" = ( "Owner", "Delegate", "Assistant" );
index cf537404ab475c03c2e22b2bd8df5118aaed11eb..00db1a0e0693760b1ac17caf0025e0c2c29fbd12 100644 (file)
@@ -295,7 +295,7 @@ static BOOL useAltNamespace = NO;
     return [self lookupImap4Message:_key inContext:_ctx];
   }
 
-  obj = [self lookupImap4Folder:_key  inContext:_ctx];
+  obj = [self lookupImap4Folder:_key inContext:_ctx];
   if (obj != nil)
     return obj;
   
@@ -320,7 +320,7 @@ static BOOL useAltNamespace = NO;
 }
 
 - (NSException *)delete {
-  /* Note: overrides SOGoObject -delete */
+  /* Note: overrides SOGoObject -delete */o
   return [[self imap4Connection] deleteMailboxAtURL:[self imap4URL]];
 }
 
index f984fc91f5aa0be2870d6ae1903ea786ad1f0928..7bdbca786d2c7d1785d8f4321d9ec12064d77789 100644 (file)
 @class NSString, NSURL, NSUserDefaults, NSArray, NSDictionary, NSData;
 @class NSCalendarDate, NSMutableDictionary;
 
-@interface AgenorUserDefaults : NSObject
+@interface AgenorUserDefaults :  NSObject
 {
   NSUserDefaults *parent;
   NSURL    *url;
   NSString *uid;
+  NSString *fieldName;
   
-  NSArray             *fieldNames;
-  NSDictionary        *attributes;
+  NSArray *fieldNames;
   NSMutableDictionary *values;
-  NSCalendarDate      *lastFetch;
+  NSCalendarDate *lastFetch;
 
-  struct {
-    int modified:1;
-    int isNew:1;
-    int reserved:30;
+  struct
+  {
+    int modified: 1;
+    int isNew: 1;
+    int reserved: 30;
   } defFlags;
 }
 
-- (id)initWithTableURL:(NSURL *)_url uid:(NSString *)_uid;
+- (id) initWithTableURL: (NSURL *) url
+                   uid: (NSString *) uid
+             fieldName: (NSString *) fieldName;
 
 /* value access */
 
-- (void)setObject:(id)_value forKey:(NSString *)_key;
-- (id)objectForKey:(NSString *)_key;
-- (void)removeObjectForKey:(NSString *)_key;
+- (void) setObject: (id) value
+           forKey: (NSString *) key;
+- (id) objectForKey: (NSString *) key;
+- (void) removeObjectForKey: (NSString *) key;
 
 /* typed accessors */
 
-- (NSArray *)arrayForKey:(NSString *)_key;
-- (NSDictionary *)dictionaryForKey:(NSString *)_key;
-- (NSData *)dataForKey:(NSString *)_key;
-- (NSArray *)stringArrayForKey:(NSString *)_key;
-- (NSString *)stringForKey:(NSString *)_key;
-- (BOOL)boolForKey:(NSString *)_key;
-- (float)floatForKey:(NSString *)_key;
-- (int)integerForKey:(NSString *)_key;
+- (NSArray *) arrayForKey: (NSString *)key;
+- (NSDictionary *) dictionaryForKey: (NSString *)key;
+- (NSData *) dataForKey: (NSString *)key;
+- (NSString *) stringForKey: (NSString *)key;
+- (BOOL) boolForKey: (NSString *) key;
+- (float) floatForKey: (NSString *) key;
+- (int) integerForKey: (NSString *) key;
 
-- (void)setBool:(BOOL)value   forKey:(NSString *)_key;
-- (void)setFloat:(float)value forKey:(NSString *)_key;
-- (void)setInteger:(int)value forKey:(NSString *)_key;
+- (void) setBool: (BOOL) value   forKey: (NSString *) key;
+- (void) setFloat: (float) value forKey: (NSString *) key;
+- (void) setInteger: (int) value forKey: (NSString *) key;
 
 /* saving changes */
 
-- (BOOL)synchronize;
+- (BOOL) synchronize;
 
 @end
 
-#endif /* __AgenorUserDefaults_H_ */
+#endif /* __AgenorUserDefaults_H__ */
index 9b97cc65ac6e8e4b8eef22ff727626fc932ea1ca..1069645b787085f0cdc4ea9f308a658006e2dc7f 100644 (file)
   02111-1307, USA.
 */
 
-#include "AgenorUserDefaults.h"
-#include <GDLContentStore/GCSChannelManager.h>
-#include <GDLContentStore/NSURL+GCS.h>
-#include <GDLAccess/EOAdaptorChannel.h>
-#include <GDLAccess/EOAdaptorContext.h>
-#include <GDLAccess/EOAttribute.h>
-#include "common.h"
+#import <Foundation/NSValue.h>
+#import <GDLContentStore/GCSChannelManager.h>
+#import <GDLContentStore/NSURL+GCS.h>
+#import <GDLAccess/EOAdaptorChannel.h>
+#import <GDLAccess/EOAdaptorContext.h>
+#import <GDLAccess/EOAttribute.h>
+
+#import "common.h"
+#import "AgenorUserDefaults.h"
 
 @implementation AgenorUserDefaults
 
 static NSString *uidColumnName = @"uid";
 
-- (id)initWithTableURL:(NSURL *)_url uid:(NSString *)_uid {
-  if ((self = [super init])) {
-    if (_url == nil || [_uid length] < 1) {
-      [self errorWithFormat:@"tried to create AgenorUserDefaults w/o args!"];
-      [self release];
-      return nil;
+- (id) initWithTableURL: (NSURL *) tableURL
+                   uid: (NSString *) userID
+             fieldName: (NSString *) defaultsFieldName
+{
+  if ((self = [super init]))
+    {
+      if (tableURL && [userID length] > 0
+         && [defaultsFieldName length] > 0)
+       {
+         parent = [[NSUserDefaults standardUserDefaults] retain];
+         fieldName = [defaultsFieldName copy];
+         url = [tableURL copy];
+         uid = [userID copy];
+       }
+      else
+       {
+         [self errorWithFormat: @"missing arguments"];
+         [self release];
+         self = nil;
+       }
     }
 
-    self->parent = [[NSUserDefaults standardUserDefaults] retain];
-    self->url = [_url copy];
-    self->uid = [_uid copy];
-  }
   return self;
 }
-- (id)init {
-  return [self initWithTableURL:nil uid:nil];
+
+- (id) init
+{
+  [self release];
+
+  return nil;
 }
 
-- (void)dealloc {
-  [self->attributes release];
-  [self->lastFetch  release];
-  [self->parent     release];
-  [self->url        release];
-  [self->uid        release];
+- (void) dealloc
+{
+  [values release];
+  [lastFetch release];
+  [parent release];
+  [url release];
+  [uid release];
+  [fieldName release];
   [super dealloc];
 }
 
 /* accessors */
 
-- (NSURL *)tableURL {
-  return self->url;
-}
-- (NSString *)uid {
-  return self->uid;
+- (NSURL *) tableURL
+{
+  return url;
 }
 
-- (NSUserDefaults *)parentDefaults {
-  return self->parent;
+- (NSString *) uid
+{
+  return uid;
 }
 
-/* operation */
+- (NSString *) fieldName
+{
+  return fieldName;
+}
 
-- (void)_loadAttributes:(NSArray *)_attrs {
-  NSMutableArray      *fields;
-  NSMutableDictionary *attrmap;
-  unsigned i, count;
-  
-  fields  = [[NSMutableArray      alloc] initWithCapacity:16];
-  attrmap = [[NSMutableDictionary alloc] initWithCapacity:16];
-  for (i = 0, count = [_attrs count]; i < count; i++) {
-    EOAttribute *attr;
-    NSString    *name;
-    
-    attr = [_attrs objectAtIndex:i];
-    name = [attr valueForKey:@"name"];
-    [attrmap setObject:attr forKey:name];
-    
-    if (![name isEqual:uidColumnName]) 
-      [fields  addObject:name];
-  }
-  
-  ASSIGNCOPY(self->fieldNames, fields);
-  ASSIGNCOPY(self->attributes, attrmap);
-  [attrmap release];
-  [fields  release];
+- (NSUserDefaults *) parentDefaults
+{
+  return parent;
 }
 
-- (BOOL)primaryFetchProfile {
+/* operation */
+
+- (BOOL) primaryFetchProfile
+{
   GCSChannelManager *cm;
-  EOAdaptorChannel  *channel;
-  NSDictionary      *row;
-  NSException       *ex;
-  NSString          *sql;
-  NSArray           *attrs;
+  EOAdaptorChannel *channel;
+  NSDictionary *row;
+  NSException *ex;
+  NSString *sql;
+  NSArray *attrs;
+  BOOL rc;
+
+  rc = NO;
   
   cm = [GCSChannelManager defaultChannelManager];
-  if ((channel = [cm acquireOpenChannelForURL:[self tableURL]]) == nil) {
+  channel = [cm acquireOpenChannelForURL: [self tableURL]];
+  if (channel)
+    {
+      /* generate SQL */
+      sql = [NSString stringWithFormat: (@"SELECT %@"
+                                        @"  FROM %@"
+                                        @" WHERE %@ = '%@'"),
+                     fieldName, [[self tableURL] gcsTableName],
+                     uidColumnName, [self uid]];
+  
+      /* run SQL */
+
+      ex = [channel evaluateExpressionX: sql];
+      if (ex)
+       {
+         [self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
+         values = [NSMutableDictionary new];
+       }
+      else
+       {
+         /* fetch schema */
+         attrs = [channel describeResults: NO /* don't beautify */];
+  
+         /* fetch values */
+         row = [channel fetchAttributes: attrs withZone: NULL];
+         defFlags.isNew = (row == nil);
+         [channel cancelFetch];
+  
+         /* remember values */
+         [values release];
+         values = [[row objectForKey: fieldName] propertyList];
+         if (values)
+           [values retain];
+         else
+           values = [NSMutableDictionary new];
+
+         ASSIGN(lastFetch, [NSCalendarDate date]);
+         defFlags.modified = NO;
+         rc = YES;
+       }
+
+      [cm releaseChannel:channel];
+    }
+  else
     [self errorWithFormat:@"failed to acquire channel for URL: %@", 
          [self tableURL]];
-    return NO;
-  }
-  
-  /* generate SQL */
-  
-  sql = [[self tableURL] gcsTableName];
-  sql = [@"SELECT * FROM " stringByAppendingString:sql];
-  sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'", 
-            uidColumnName, [self uid]];
-  
-  /* run SQL */
-  
-  if ((ex = [channel evaluateExpressionX:sql]) != nil) {
-    [self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
-    [cm releaseChannel:channel];
-    return NO;
-  }
 
-  /* fetch schema */
-  
-  attrs = [channel describeResults:NO /* don't beautify */];
-  [self _loadAttributes:attrs];
-  
-  /* fetch values */
-  
-  row = [channel fetchAttributes:attrs withZone:NULL];
-  self->defFlags.isNew = (row != nil) ? 0 : 1;
-  [channel cancelFetch];
-  
-  /* remember values */
-  
-  [self->values release]; self->values = nil;
-  self->values = (row != nil)
-    ? [row mutableCopy]
-    : [[NSMutableDictionary alloc] initWithCapacity:8];
-  [self->values removeObjectForKey:uidColumnName];
-  
-  ASSIGN(self->lastFetch, [NSCalendarDate date]);
-  self->defFlags.modified = 0;
-  
-  [cm releaseChannel:channel];
-  return YES;
-}
-
-- (NSString *)formatValue:(id)_value forAttribute:(EOAttribute *)_attribute {
-  NSString *s;
-  
-  if (![_value isNotNull])
-    return @"NULL";
-  
-  if ([[_attribute externalType] hasPrefix:@"int"])
-    return [_value stringValue];
-  
-  s = [_value stringValue];
-  s = [s stringByReplacingString:@"'" withString:@"''"];
-  s = [[@"'" stringByAppendingString:s] stringByAppendingString:@"'"];
-  return s;
+  return rc;
 }
 
-- (NSString *)generateSQLForInsert {
+- (NSString *) generateSQLForInsert
+{
   NSMutableString *sql;
-  unsigned i, count;
-  
-  if ([self->values count] == 0)
-    return nil;
-  
-  sql = [NSMutableString stringWithCapacity:2048];
-  
-  [sql appendString:@"INSERT INTO "];
-  [sql appendString:[[self tableURL] gcsTableName]];
-  [sql appendString:@" ( uid"];
-
-  for (i = 0, count = [self->fieldNames count]; i < count; i++) {
-    EOAttribute *attr;
-    
-    attr = [self->attributes objectForKey:[self->fieldNames objectAtIndex:i]];
-    [sql appendString:@", "];
-    [sql appendString:[attr columnName]];
-  }
-  
-  [sql appendString:@") VALUES ("];
-  
-  [sql appendString:@"'"];
-  [sql appendString:[self uid]]; // TODO: escaping necessary?
-  [sql appendString:@"'"];
-  
-  for (i = 0, count = [self->fieldNames count]; i < count; i++) {
-    EOAttribute *attr;
-    id value;
-    
-    attr  = [self->attributes objectForKey:[self->fieldNames objectAtIndex:i]];
-    value = [self->values objectForKey:[self->fieldNames objectAtIndex:i]];
-    
-    [sql appendString:@", "];
-    [sql appendString:[self formatValue:value forAttribute:attr]];
-  }
-  
-  [sql appendString:@")"];
+  NSString *serializedDefaults;
+
+#if LIB_FOUNDATION_LIBRARY
+  serializedDefaults = [values stringRepresentation];
+
+  sql = [NSString stringWithFormat: (@"INSERT INTO %@"
+                                    @"            (%@, %@)"
+                                    @"     VALUES ('%@', '%@')"),
+                 [[self tableURL] gcsTableName], uidColumnName, fieldName,
+                 [self uid],
+                 [serializedDefaults stringByReplacingString:@"'" withString:@"''"]];
+#else
+  NSData *serializedDefaultsData;
+  NSString *error;
+
+  serializedDefaultsData
+    = [NSPropertyListSerialization dataFromPropertyList: values
+                                  format: NSPropertyListOpenStepFormat
+                                  errorDescription: &error];
+
+  if (error)
+    sql = nil;
+  else
+    {
+      serializedDefaults = [[NSString alloc] initWithData: serializedDefaultsData
+                                            encoding: NSUTF8StringEncoding];
+
+      sql = [NSString stringWithFormat: (@"INSERT INTO %@"
+                                        @"            (%@, %@)"
+                                        @"     VALUES ('%@', '%@')"),
+                     [[self tableURL] gcsTableName], uidColumnName, fieldName,
+                     [self uid],
+                     [serializedDefaults stringByReplacingString:@"'" withString:@"''"]];
+      [serializedDefaults release];
+    }
+#endif
+
   return sql;
 }
 
-- (NSString *)generateSQLForUpdate {
+- (NSString *) generateSQLForUpdate
+{
   NSMutableString *sql;
-  unsigned i, count;
-  
-  if ([self->values count] == 0)
-    return nil;
-  
-  sql = [NSMutableString stringWithCapacity:2048];
-  
-  [sql appendString:@"UPDATE "];
-  [sql appendString:[[self tableURL] gcsTableName]];
-  [sql appendString:@" SET "];
-  
-  for (i = 0, count = [self->fieldNames count]; i < count; i++) {
-    EOAttribute *attr;
-    NSString    *name;
-    id value;
-    
-    name  = [self->fieldNames objectAtIndex:i];
-    value = [self->values objectForKey:name];
-    attr  = [self->attributes objectForKey:name];
-    
-    if (i != 0) [sql appendString:@", "];
-    [sql appendString:[attr columnName]];
-    [sql appendString:@" = "];
-    [sql appendString:[self formatValue:value forAttribute:attr]];
-  }
-  
-  [sql appendString:@" WHERE "];
-  [sql appendString:uidColumnName];
-  [sql appendString:@" = '"];
-  [sql appendString:[self uid]];
-  [sql appendString:@"'"];
+  NSString *serializedDefaults;
+
+#if LIB_FOUNDATION_LIBRARY
+  serializedDefaults = [values stringRepresentation];
+
+  sql = [NSString stringWithFormat: (@"UPDATE %@"
+                                    @"     SET %@ = '%@'"
+                                    @"   WHERE %@ = '%@'"),
+                 [[self tableURL] gcsTableName],
+                 fieldName,
+                 [serializedDefaults stringByReplacingString:@"'" withString:@"''"],
+                 uidColumnName, [self uid]];
+#else
+  NSData *serializedDefaultsData;
+  NSString *error;
+
+  serializedDefaultsData
+    = [NSPropertyListSerialization dataFromPropertyList: values
+                                  format: NSPropertyListOpenStepFormat
+                                  errorDescription: &error];
+  error = nil;
+  if (error)
+    {
+      sql = nil;
+      [error release];
+    }
+  else
+    {
+      serializedDefaults = [[NSString alloc] initWithData: serializedDefaultsData
+                                            encoding: NSUTF8StringEncoding];
+
+      sql = [NSString stringWithFormat: (@"UPDATE %@"
+                                        @"     SET %@ = '%@'"
+                                        @"   WHERE %@ = '%@'"),
+                     [[self tableURL] gcsTableName],
+                     fieldName,
+                     [serializedDefaults stringByReplacingString:@"'" withString:@"''"],
+                     uidColumnName, [self uid]];
+      [serializedDefaults release];
+    }
+#endif
+
   return sql;
 }
 
-- (BOOL)primaryStoreProfile {
+- (BOOL) primaryStoreProfile
+{
   GCSChannelManager *cm;
-  EOAdaptorChannel  *channel;
-  NSException       *ex;
-  NSString          *sql;
+  EOAdaptorChannel *channel;
+  NSException *ex;
+  NSString *sql;
+  BOOL rc;
+
+  rc = NO;
   
   cm = [GCSChannelManager defaultChannelManager];
-  if ((channel = [cm acquireOpenChannelForURL:[self tableURL]]) == nil) {
-    [self errorWithFormat:@"failed to acquire channel for URL: %@", 
-         [self tableURL]];
-    return NO;
-  }
-  
-  /* run SQL */
-  
-  sql = self->defFlags.isNew
-    ? [self generateSQLForInsert] 
-    : [self generateSQLForUpdate];
-  if ((ex = [channel evaluateExpressionX:sql]) != nil) {
-    [self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
-    [cm releaseChannel:channel];
-    return NO;
-  }
-  
-  /* commit */
-  
-  ex = nil;
-  if ([[channel adaptorContext] hasOpenTransaction])
-    ex = [channel evaluateExpressionX:@"COMMIT TRANSACTION"];
-  
-  [cm releaseChannel:channel];
-  
-  if (ex != nil) {
-    [self errorWithFormat:@"could not commit transaction for update: %@", ex];
-    return NO;
-  }
-  
-  self->defFlags.modified = 0;
-  self->defFlags.isNew    = 0;
-  return YES;
-}
-
+  sql = ((defFlags.isNew)
+        ? [self generateSQLForInsert] 
+        : [self generateSQLForUpdate]);
+  if (sql)
+    {
+      channel = [cm acquireOpenChannelForURL: [self tableURL]];
+      if (channel)
+       {
+         ex = [channel evaluateExpressionX:sql];
+         if (ex)
+           [self errorWithFormat: @"could not run SQL '%@': %@", sql, ex];
+         else
+           {
+             if ([[channel adaptorContext] hasOpenTransaction])
+               {
+                 ex = [channel evaluateExpressionX: @"COMMIT TRANSACTION"];
+                 if (ex)
+                   [self errorWithFormat:@"could not commit transaction for update: %@", ex];
+                 else
+                   rc = YES;
+               }
+             else
+               rc = YES;
+             
+             defFlags.modified = NO;
+             defFlags.isNew = NO;
+           }
+         
+         [cm releaseChannel: channel];
+       }
+      else
+       [self errorWithFormat: @"failed to acquire channel for URL: %@", 
+             [self tableURL]];
+    }
+  else
+    [self errorWithFormat: @"failed to generate SQL for storing defaults"];
 
-- (BOOL)fetchProfile {
-  if (self->values != nil)
-    return YES;
-  
-  return [self primaryFetchProfile];
+  return rc;
 }
 
-- (NSArray *)primaryDefaultNames {
-  if (![self fetchProfile])
-    return nil;
-  
-  return self->fieldNames;
+- (BOOL) fetchProfile
+{
+  return (values || [self primaryFetchProfile]);
 }
 
 /* value access */
 
-- (void)setObject:(id)_value forKey:(NSString *)_key {
-  if (![self fetchProfile])
-    return;
+- (void) setObject: (id) value
+           forKey: (NSString *) key
+{ 
+  id old;
   
-  if (![self->fieldNames containsObject:_key]) {
-    [self errorWithFormat:@"tried to write key: '%@'", _key];
+  if (![self fetchProfile])
     return;
-  }
-  
-  /* check whether the value is actually modified */
-  if (!self->defFlags.modified) {
-    id old;
 
-    old = [self->values objectForKey:_key];
-    if (old == _value || [old isEqual:_value]) /* value didn't change */
-      return;
-  
-    /* we need to this because our typed accessors convert to strings */
-    // TODO: especially problematic with bools
-    if ([_value isKindOfClass:[NSString class]]) {
-      if (![old isKindOfClass:[NSString class]])
-        if ([[old description] isEqualToString:_value])
-       return;
+  /* check whether the value is actually modified */
+  if (!defFlags.modified)
+    {
+      old = [values objectForKey: key];
+      if (old == value || [old isEqual: value]) /* value didn't change */
+       return;
+  
+      /* we need to this because our typed accessors convert to strings */
+      // TODO: especially problematic with bools
+      if ([value isKindOfClass: [NSString class]]) {
+       if (![old isKindOfClass: [NSString class]])
+         if ([[old description] isEqualToString: value])
+           return;
+      }
     }
-  }
-  
+
   /* set in hash and mark as modified */
-  [self->values setObject:(_value ? _value : [NSNull null])  forKey:_key];
-  self->defFlags.modified = 1;
+  [values setObject: value forKey: key];
+
+  defFlags.modified = YES;
 }
 
-- (id)objectForKey:(NSString *)_key {
+- (id) objectForKey: (NSString *) key
+{
   id value;
   
   if (![self fetchProfile])
-    return nil;
-  
-  if (![self->fieldNames containsObject:_key])
-    return [self->parent objectForKey:_key];
-  
-  value = [self->values objectForKey:_key];
-  return [value isNotNull] ? value : nil;
+    value = nil;
+  else
+    value = [values objectForKey: key];
+
+  return value;
 }
 
-- (void)removeObjectForKey:(NSString *)_key {
-  [self setObject:nil forKey:_key];
+- (void) removeObjectForKey: (NSString *) key
+{
+  [self setObject: nil forKey: key];
 }
 
 /* saving changes */
 
-- (BOOL)synchronize {
-  if (!self->defFlags.modified) /* was not modified */
-    return YES;
+- (BOOL) synchronize
+{
+//   if (!defFlags.modified) /* was not modified */
+//     return YES;
   
   /* ensure fetched data (more or less guaranteed by modified!=0) */
   if (![self fetchProfile])
     return NO;
   
   /* store */
-  if (![self primaryStoreProfile]) {
-    [self primaryFetchProfile];
-    return NO;
-  }
-  
+  if (![self primaryStoreProfile])
+    {
+      [self primaryFetchProfile];
+      return NO;
+    }
+
   /* refetch */
   return [self primaryFetchProfile];
 }
 
-- (void)flush {
-  [self->values     release]; self->values     = nil;
-  [self->fieldNames release]; self->fieldNames = nil;
-  [self->attributes release]; self->attributes = nil;
-  [self->lastFetch  release]; self->lastFetch  = nil;
-  self->defFlags.modified = 0;
-  self->defFlags.isNew    = 0;
+- (void) flush
+{
+  [values release];
+  [lastFetch release];
+  values = nil;
+  lastFetch = nil;
+  defFlags.modified = NO;
+  defFlags.isNew = NO;
 }
 
 /* typed accessors */
 
-- (NSArray *)arrayForKey:(NSString *)_key {
-  id obj = [self objectForKey:_key];
-  return [obj isKindOfClass:[NSArray class]] ? obj : nil;
+- (NSArray *) arrayForKey: (NSString *) key
+{
+  return [self objectForKey: key];
 }
 
-- (NSDictionary *)dictionaryForKey:(NSString *)_key {
-  id obj = [self objectForKey:_key];
-  return [obj isKindOfClass:[NSDictionary class]] ? obj : nil;
+- (NSDictionary *) dictionaryForKey: (NSString *) key
+{
+  return [self objectForKey: key];
 }
 
-- (NSData *)dataForKey:(NSString *)_key {
-  id obj = [self objectForKey:_key];
-  return [obj isKindOfClass:[NSData class]] ? obj : nil;
+- (NSData *) dataForKey: (NSString *) key
+{
+  return [self objectForKey: key];
 }
 
-- (NSArray *)stringArrayForKey:(NSString *)_key {
-  id obj = [self objectForKey:_key];
-  int n;
-  Class strClass = [NSString class];
-  
-  if (![obj isKindOfClass:[NSArray class]])
-    return nil;
-       
-  for (n = [obj count]-1; n >= 0; n--) {
-    if (![[obj objectAtIndex:n] isKindOfClass:strClass])
-      return nil;
-  }
-  return obj;
+- (NSString *) stringForKey: (NSString *) key
+{
+  return [self objectForKey: key];
 }
 
-- (NSString *)stringForKey:(NSString *)_key {
-  id obj = [self objectForKey:_key];
-  return [obj isKindOfClass:[NSString class]] ? obj : nil;
+- (BOOL) boolForKey: (NSString *) key
+{
+  return [[self objectForKey: key] boolValue];
 }
 
-- (BOOL)boolForKey:(NSString *)_key {
-  // TODO: need special support here for int-DB fields
-  id obj;
-  
-  if ((obj = [self objectForKey:_key]) == nil)
-    return NO;
-  if ([obj isKindOfClass:[NSString class]]) {
-    if ([obj compare:@"YES" options:NSCaseInsensitiveSearch] == NSOrderedSame)
-      return YES;
-  }
-  if ([obj respondsToSelector:@selector(intValue)])
-    return [obj intValue] ? YES : NO;
-  return NO;
+- (float) floatForKey: (NSString *) key
+{
+  return [[self objectForKey: key] floatValue];
 }
 
-- (float)floatForKey:(NSString *)_key {
-  id obj = [self stringForKey:_key];
-  return (obj != nil) ? [obj floatValue] : 0.0;
-}
-- (int)integerForKey:(NSString *)_key {
-  id obj = [self stringForKey:_key];
-  return (obj != nil) ? [obj intValue] : 0;
+- (int) integerForKey: (NSString *) key
+{
+  return [[self objectForKey: key] intValue];
 }
 
-- (void)setBool:(BOOL)value forKey:(NSString *)_key {
+- (void) setBool: (BOOL) value
+         forKey: (NSString *) key
+{
   // TODO: need special support here for int-DB fields
-  [self setObject:(value ? @"YES" : @"NO") forKey:_key];
-}
-- (void)setFloat:(float)value forKey:(NSString *)_key {
-  [self setObject:[NSString stringWithFormat:@"%f", value] forKey:_key];
-}
-- (void)setInteger:(int)value forKey:(NSString *)_key {
-  [self setObject:[NSString stringWithFormat:@"%d", value] forKey:_key];
+  [self setObject: [NSNumber numberWithBool: value]
+       forKey: key];
 }
 
-/* description */
+- (void) setFloat: (float) value
+          forKey: (NSString *) key
+{
+  [self setObject: [NSNumber numberWithFloat: value]
+       forKey: key];
+}
 
-- (NSString *)description {
-  NSMutableString *ms;
-  
-  ms = [NSMutableString stringWithCapacity:16];
-  [ms appendFormat:@"<0x%08X[%@]>", self, NSStringFromClass([self class])];
-  [ms appendFormat:@" uid=%@",        self->uid];
-  [ms appendFormat:@" url=%@",        [self->url absoluteString]];
-  [ms appendFormat:@" parent=0x%08X", self->parent];
-  [ms appendString:@">"];
-  return ms;
+- (void) setInteger: (int) value
+            forKey: (NSString *) key
+{
+  [self setObject: [NSNumber numberWithInt: value]
+       forKey: key];
 }
 
 @end /* AgenorUserDefaults */
index c23fd460aeab153b3cb6623a587fd508d5289a8d..2ad6090937c0904cd71d308af234957b6144b171 100644 (file)
@@ -75,7 +75,8 @@
 
 - (NSURL *)getFreeBusyURLForUID:(NSString *)_uid;
 
-- (NSUserDefaults *)getUserDefaultsForUID:(NSString *)_uid;
+- (NSUserDefaults *) getUserDefaultsForUID: (NSString *) uid;
+- (NSUserDefaults *) getUserSettingsForUID: (NSString *) uid;
 
 - (BOOL)isUserAllowedToChangeSOGoInternetAccess:(NSString *)_uid;
 
index b316a11a4381cf792f8e587bde07cfebb80328f3..619e66623a6277fabdd1b82269f5dc9bd9d66928 100644 (file)
@@ -1012,22 +1012,39 @@ static unsigned PoolScanInterval = 5 * 60 /* every five minutes */;
 
 /* defaults */
 
-- (NSUserDefaults *)getUserDefaultsForUID:(NSString *)_uid {
+- (NSUserDefaults *) _getUserDefaultsForUID: (NSString *) uid
+                                 fieldName: (NSString *) fieldName
+{
   id defaults;
   
-  if (AgenorProfileURL == nil) {
-    [self warnWithFormat:
-           @"no profile configured, cannot retrieve defaults for user: '%@'",
-           _uid];
-    return nil;
-  }
-  
-  /* Note: do not cache, otherwise updates can be quite tricky */
-  defaults = [[[AgenorUserDefaults alloc] 
-               initWithTableURL:AgenorProfileURL uid:_uid] autorelease];
+  if (AgenorProfileURL)
+    {
+      /* Note: do not cache, otherwise updates can be quite tricky */
+      defaults = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
+                                            uid: uid fieldName: fieldName];
+      [defaults autorelease];
+    }
+  else
+    {
+      [self warnWithFormat:
+             @"no profile configured, cannot retrieve defaults for user: '%@'",
+           uid];
+      return defaults = nil;
+    }
+
   return defaults;
 }
 
+- (NSUserDefaults *) getUserDefaultsForUID: (NSString *) uid
+{
+  return [self _getUserDefaultsForUID: uid fieldName: @"defaults"];
+}
+
+- (NSUserDefaults *) getUserSettingsForUID: (NSString *) uid
+{
+  return [self _getUserDefaultsForUID: uid fieldName: @"settings"];
+}
+
 /* internet access lock */
 
 - (BOOL)isUserAllowedToChangeSOGoInternetAccess:(NSString *)_uid {
@@ -1194,15 +1211,4 @@ static unsigned PoolScanInterval = 5 * 60 /* every five minutes */;
   return debugOn;
 }
 
-/* description */
-
-- (NSString *)description {
-  NSMutableString *ms;
-  
-  ms = [NSMutableString stringWithCapacity:16];
-  [ms appendFormat:@"<0x%08X[%@]", self, NSStringFromClass([self class])];
-  [ms appendString:@">"];
-  return ms;
-}
-
 @end /* AgenorUserManager */
index 53a75ce97fe593665f2b1c13acb43a66d9759efa..b3af1fc3789f718885f5c713a20e87af880dcfdb 100644 (file)
   GCSFolder *ocsFolder;
 }
 
-+ (NSString *)globallyUniqueObjectId;
++ (NSString *) globallyUniqueObjectId;
 
 /* accessors */
 
-- (void)setOCSPath:(NSString *)_Path;
-- (NSString *)ocsPath;
+- (void) setOCSPath: (NSString *)_Path;
+- (NSString *) ocsPath;
 
-- (GCSFolder *)ocsFolderForPath:(NSString *)_path;
-- (GCSFolder *)ocsFolder;
+- (GCSFolder *) ocsFolderForPath: (NSString *)_path;
+- (GCSFolder *) ocsFolder;
 
 /* lower level fetches */
 - (BOOL) nameExistsInFolder: (NSString *) objectName;
 
-- (NSArray *)fetchContentObjectNames;
-- (NSDictionary *)fetchContentStringsAndNamesOfAllObjects;
+- (NSArray *) fetchContentObjectNames;
+- (NSDictionary *) fetchContentStringsAndNamesOfAllObjects;
 
 /* folder type */
 
-- (NSString *)outlookFolderClass;
+- (NSString *) outlookFolderClass;
 
 - (BOOL) create;
 - (NSException *) delete;
index 892afff94fb13cb6f72ccb3efc6456564ff19913..e06864b246151665f51ff19e2d64e4d8369407ab 100644 (file)
 
 + (id) objectWithName: (NSString *)_name inContainer:(id)_container;
 
-- (id)initWithName:(NSString *)_name inContainer:(id)_container;
+- (id) initWithName: (NSString *) _name inContainer:(id)_container;
 
 /* accessors */
 
-- (NSString *)nameInContainer;
-- (id)container;
+- (NSString *) nameInContainer;
+- (id) container;
 
 - (NSTimeZone *) serverTimeZone;
 - (NSTimeZone *) userTimeZone;
 /* ownership */
 
 - (void) setOwner: (NSString *) newOwner;
-- (NSString *)ownerInContext:(id)_ctx;
+- (NSString *) ownerInContext: (id) _ctx;
 
 /* looking up shared objects */
 
-- (SOGoUserFolder *)lookupUserFolder;
-- (SOGoGroupsFolder *)lookupGroupsFolder;
+- (SOGoUserFolder *) lookupUserFolder;
+- (SOGoGroupsFolder *) lookupGroupsFolder;
 
-- (void)sleep;
+- (void) sleep;
 
 /* hierarchy */
 
-- (NSArray *)fetchSubfolders; /* uses toManyRelationshipKeys */
+- (NSArray *) fetchSubfolders; /* uses toManyRelationshipKeys */
 
 /* operations */
 
index 164af564a84ca6fdc07aa2701439b92cbc6a232f..62dc2ed9c80ab1ed40748347be4b6cf3372ac46a 100644 (file)
@@ -42,6 +42,7 @@
   NSString       *cn;
   NSString       *email;
   NSUserDefaults *userDefaults;
+  NSUserDefaults *userSettings;
 }
 
 /* properties */
@@ -60,7 +61,8 @@
 
 /* defaults */
 
-- (NSUserDefaults *)userDefaults;
+- (NSUserDefaults *) userDefaults;
+- (NSUserDefaults *) userSettings;
 
 /* folders */
 
index d3bb2eaac6552a4ef358b2c8c992b897d14b405d..6d863d530860ad5c92a2cac001c5fd3340b9741b 100644 (file)
 
 @implementation SOGoUser
 
+- (id) init
+{
+  if ((self = [super init]))
+    {
+      userDefaults = nil;
+      userSettings = nil;
+    }
+
+  return self;
+}
+
 - (void)dealloc {
   [self->userDefaults release];
+  [self->userSettings release];
   [self->cn    release];
   [self->email release];
   [super dealloc];
 
 /* defaults */
 
-- (NSUserDefaults *)userDefaults {
-  if (self->userDefaults == nil) {
-    self->userDefaults = 
-      [[[self userManager] getUserDefaultsForUID:[self login]] retain];
-  }
-  return self->userDefaults;
+- (NSUserDefaults *) userDefaults
+{
+  if (!userDefaults)
+    {
+      userDefaults = [[self userManager] getUserDefaultsForUID: [self login]];
+      [userDefaults retain];
+    }
+
+  return userDefaults;
+}
+
+- (NSUserDefaults *) userSettings
+{
+  if (!userSettings)
+    {
+      userSettings = [[self userManager] getUserSettingsForUID: [self login]];
+      [userSettings retain];
+    }
+
+  return userSettings;
 }
 
 /* folders */
index add62ea9abffe52d8b940f7146c46a6cbab68e14..d80d6bf042e843b0ace16650357bbbc5f8e9b45b 100644 (file)
@@ -14,9 +14,9 @@ CommonUI_OBJC_FILES +=                \
        UIxPrintPageFrame.m     \
        UIxSortButton.m         \
        UIxAppNavView.m         \
-       UIxJSClose.m            \
        \
        UIxAclEditor.m  \
+       UIxFolderActions.m      \
        UIxElemBuilder.m        \
        UIxTabView.m            \
        UIxTabItem.m            \
index e1dbaa50100391a93e0a0e0de19da4679882b7fb..d4b047af3b20003094664b09c9f66d44e41c89d2 100644 (file)
   NSMutableArray *users;
   NSMutableArray *assistants;
   NSMutableArray *delegates;
-  NSString *ownerCN;
+  NSString *currentUser;
+  NSString *ownerLogin;
 }
 
 - (NSArray *) aclsForFolder;
-- (NSString *) ownerCN;
 - (NSString *) assistantsValue;
 - (NSString *) delegatesValue;
 
+- (NSArray *) usersForFolder;
+- (void) setCurrentUser: (NSString *) newCurrentUser;
+- (NSString *) currentUser;
+
+- (NSString *) ownerLogin;
+- (NSString *) ownerName;
+
 @end
 
 #endif /* UIXACLEDITOR_H */
index b6917d56da8a011a4200568e0c20fee6c2a9396f..79d97b28dbc0b05998871053891d53dcb8d52e32 100644 (file)
@@ -44,7 +44,8 @@
       users = [NSMutableArray new];
       delegates = [NSMutableArray new];
       assistants = [NSMutableArray new];
-      ownerCN = nil;
+      ownerLogin = nil;
+      currentUser = nil;
     }
 
   return self;
@@ -55,8 +56,8 @@
   [users release];
   [delegates release];
   [assistants release];
-  if (ownerCN)
-    [ownerCN release];
+  [ownerLogin release];
+  [currentUser release];
   [super dealloc];
 }
 
   return acls;
 }
 
-- (NSString *) ownerCN
+- (NSString *) ownerLogin
 {
-  if (!ownerCN)
+  if (!ownerLogin)
     {
-      ownerCN = [[self clientObject] ownerInContext: context];
-      [ownerCN retain];
+      ownerLogin = [[self clientObject] ownerInContext: context];
+      [ownerLogin retain];
     }
 
-  return ownerCN;
+  return ownerLogin;
+}
+
+- (NSString *) _displayNameForUID: (NSString *) uid
+{
+  AgenorUserManager *um;
+  
+  um = [AgenorUserManager sharedUserManager];
+
+  return [NSString stringWithFormat: @"%@ <%@>",
+                  [um getCNForUID: uid],
+                  [um getEmailForUID: uid]];
+}
+
+- (NSString *) ownerName
+{
+  return [self _displayNameForUID: [self ownerLogin]];
 }
 
 - (void) _prepareUsers
   NSEnumerator *aclsEnum;
   AgenorUserManager *um;
   NSDictionary *currentAcl;
-  iCalPerson *currentUser;
   NSString *currentUID;
 
   aclsEnum = [[self aclsForFolder] objectEnumerator];
         publishInFreeBusy = YES;
       else
         {
-          currentUser = [um iCalPersonWithUid: currentUID];
-          if (![[currentUser cn] isEqualToString: [self ownerCN]])
+          if (![[um getCNForUID: currentUID]
+                isEqualToString: [self ownerLogin]])
             {
               if ([[currentAcl objectForKey: @"c_role"]
                     isEqualToString: SOGoRole_Delegate])
-                [delegates addObject: [currentUser cn]];
+                [delegates addObject: currentUID];
               else
-                [assistants addObject: [currentUser cn]];
-              [users addObject: currentUser];
+                [assistants addObject: currentUID];
+              [users addObject: currentUID];
             }
         }
       currentAcl = [aclsEnum nextObject];
   return users;
 }
 
+- (void) setCurrentUser: (NSString *) newCurrentUser
+{
+  ASSIGN (currentUser, newCurrentUser);
+}
+
+- (NSString *) currentUser
+{
+  return currentUser;
+}
+
+- (NSString *) currentUserDisplayName
+{
+  return [self _displayNameForUID: currentUser];
+}
+
 - (NSArray *) delegates
 {
   if (!prepared)
 
 - (NSString *) toolbar
 {
-  return (([[self ownerCN] isEqualToString: [[context activeUser] login]])
+  NSString *currentLogin;
+
+  currentLogin = [[context activeUser] login];
+
+  return (([[self ownerLogin] isEqualToString: currentLogin])
           ? @"SOGoAclOwner.toolbar" : @"SOGoAclAssistant.toolbar");
 }
 
diff --git a/UI/Common/UIxFolderActions.h b/UI/Common/UIxFolderActions.h
new file mode 100644 (file)
index 0000000..5a08a68
--- /dev/null
@@ -0,0 +1,54 @@
+/* UIxFolderActions.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 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 UIXFOLDERACTIONS_H
+#define UIXFOLDERACTIONS_H
+
+#import <NGObjWeb/WODirectAction.h>
+
+@class SOGoFolder;
+@class NSString;
+@class NSUserDefaults;
+@class NSMutableString;
+@class NSMutableDictionary;
+
+@interface UIxFolderActions : WODirectAction
+{
+  SOGoFolder *clientObject;
+  AgenorUserManager *um;
+  NSUserDefaults *ud;
+  NSString *owner;
+  NSString *login;
+  NSString *baseFolder;
+  NSMutableString *subscriptionPointer;
+  NSMutableDictionary *moduleSettings;
+}
+
+- (WOResponse *) subscribeAction;
+- (WOResponse *) unsubscribeAction;
+- (WOResponse *) canAccessContentAction;
+- (WOResponse *) activateFolderAction;
+- (WOResponse *) deactivateFolderAction;
+
+@end
+
+#endif /* UIXFOLDERACTIONS_H */
diff --git a/UI/Common/UIxFolderActions.m b/UI/Common/UIxFolderActions.m
new file mode 100644 (file)
index 0000000..473aaae
--- /dev/null
@@ -0,0 +1,203 @@
+/* UIxFolderActions.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 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 <Foundation/NSUserDefaults.h>
+#import <Foundation/NSValue.h>
+
+#import <NGObjWeb/WOContext.h>
+#import <NGObjWeb/WOContext+SoObjects.h>
+#import <NGObjWeb/WOResponse.h>
+#import <NGObjWeb/SoSecurityManager.h>
+
+#import <SOGo/AgenorUserManager.h>
+#import <SOGo/SOGoUser.h>
+#import <SOGo/SOGoObject.h>
+#import <SOGo/SOGoPermissions.h>
+
+#import "UIxFolderActions.h"
+
+@implementation UIxFolderActions
+
+#warning some of this code could probably be moved in one of the \
+         clientObject classes...
+
+- (void) _setupContext
+{
+  NSString *clientClass;
+
+  login = [[context activeUser] login];
+  clientObject = [self clientObject];
+  owner = [clientObject ownerInContext: nil];
+
+  clientClass = NSStringFromClass([clientObject class]);
+  if ([clientClass isEqualToString: @"SOGoContactGCSFolder"])
+    baseFolder = @"Contacts";
+  else if ([clientClass isEqualToString: @"SOGoAppointmentFolder"])
+    baseFolder = @"Calendar";
+  else
+    baseFolder = nil;
+
+  um = [AgenorUserManager sharedUserManager];
+  ud = [um getUserSettingsForUID: login];
+  moduleSettings = [ud objectForKey: baseFolder];
+  if (!moduleSettings)
+    {
+      moduleSettings = [NSMutableDictionary new];
+      [moduleSettings autorelease];
+    }
+  [ud setObject: moduleSettings forKey: baseFolder];
+
+  subscriptionPointer = [NSMutableString stringWithFormat: @"%@:%@",
+                                        owner, baseFolder];
+  if ([baseFolder isEqualToString: @"Contacts"])
+    [subscriptionPointer appendFormat: @"/%@",
+                        [clientObject nameInContainer]];
+}
+
+- (WOResponse *) _realActionWithFolderName: (NSDictionary *) folderDict
+{
+  WOResponse *response;
+  NSMutableDictionary *folderSubscription;
+
+  response = [context response];
+  if ([owner isEqualToString: login])
+    {
+      [response setStatus: 403];
+      [response appendContentString:
+                @"You cannot (un)subscribe to a folder that you own!"];
+    }
+  else
+    {
+      folderSubscription
+       = [moduleSettings objectForKey: @"SubscribedFolders"];
+      if (!folderSubscription)
+       {
+         folderSubscription = [NSMutableDictionary dictionary];
+         [moduleSettings setObject: folderSubscription
+                         forKey: @"SubscribedFolders"];
+       }
+      if (folderDict)
+       [folderSubscription setObject: folderDict
+                           forKey: subscriptionPointer];
+      else
+       [folderSubscription removeObjectForKey: subscriptionPointer];
+
+      [ud synchronize];
+      [response setStatus: 204];
+    }
+
+  return response;
+}
+
+- (WOResponse *) subscribeAction
+{
+  NSString *email;
+  NSMutableDictionary *folderDict;
+  NSString *folderName;
+
+  [self _setupContext];
+  email = [NSString stringWithFormat: @"%@ <%@>",
+                   [um getCNForUID: owner], [um getEmailForUID: owner]];
+  if ([baseFolder isEqualToString: @"Contacts"])
+    folderName = [NSString stringWithFormat: @"%@ (%@)",
+                          [clientObject nameInContainer], email];
+  else
+    folderName = email;
+
+  folderDict = [NSMutableDictionary new];
+  [folderDict setObject: folderName forKey: @"displayName"];
+  [folderDict setObject: [NSNumber numberWithBool: NO] forKey: @"active"];
+
+  return [self _realActionWithFolderName: folderDict];
+}
+
+- (WOResponse *) unsubscribeAction
+{
+  [self _setupContext];
+
+  return [self _realActionWithFolderName: nil];
+}
+
+- (WOResponse *) canAccessContentAction
+{
+  WOResponse *response;
+  SoSecurityManager *securityManager;
+  BOOL result;
+
+  securityManager = [SoSecurityManager sharedSecurityManager];
+  result = (![securityManager validatePermission: SoPerm_AccessContentsInformation
+                             onObject: [self clientObject]
+                             inContext: context]);
+
+  response = [context response];
+  [response setStatus: 200];
+  [response setHeader: @"text/plain; charset=\"ascii\""
+            forKey: @"content-type"];
+  [response appendContentString: (result) ? @"1" : @"0"];
+
+  return response;
+}
+
+- (WOResponse *) _realFolderActivation: (BOOL) makeActive
+{
+  WOResponse *response;
+  NSMutableDictionary *folderSubscription, *folderDict;
+  NSNumber *active;
+  
+  response = [context response];
+
+  [self _setupContext];
+  active = [NSNumber numberWithBool: makeActive];
+  if ([owner isEqualToString: login])
+    [moduleSettings setObject: active forKey: @"activateUserFolder"];
+  else
+    {
+      folderSubscription
+       = [moduleSettings objectForKey: @"SubscribedFolders"];
+      if (folderSubscription)
+       {
+          folderDict = [folderSubscription objectForKey: subscriptionPointer];
+          if (folderDict)
+            [folderDict setObject: active
+                        forKey: @"active"];
+       }
+    }
+
+  [ud synchronize];
+  [response setStatus: 204];
+
+  return response;
+}
+
+- (WOResponse *) activateFolderAction
+{
+  return [self _realFolderActivation: YES];
+}
+
+- (WOResponse *) deactivateFolderAction
+{
+  return [self _realFolderActivation: NO];
+}
+
+@end
index 8061b201d504c8b7e1f57cea4e45cea1505193cd..d0166ea5ae24b5721ae4fee6edbf0b06c8f1a51c 100644 (file)
@@ -1,47 +1,72 @@
 { /* -*-javascript-*- */
-  requires = ( MAIN, Mailer );
+   requires = ( MAIN, Mailer );
 
-  publicResources = (
-     calendar.css,
-     uix.css,
-     menu_logo_top.gif,
-     line_left.gif,
-     line_stretch.gif,
-     line_right.gif,
-     box_topleft.gif,
-     box_top.gif,
-     box_topright.gif,
-     box_left.gif,
-     box_right.gif,
-     box_botleft.gif,
-     box_bottom.gif,
-     box_botright.gif,
-     tab_selected.gif,
-     tab_.gif,
-     corner_right.gif,
-     closewindow.gif,
-     OGoLogo.gif,
-     upward_sorted.gif,
-     downward_sorted.gif,
-     non_sorted.gif
+   publicResources = (
+      calendar.css,
+      uix.css,
+      menu_logo_top.gif,
+      line_left.gif,
+      line_stretch.gif,
+      line_right.gif,
+      box_topleft.gif,
+      box_top.gif,
+      box_topright.gif,
+      box_left.gif,
+      box_right.gif,
+      box_botleft.gif,
+      box_bottom.gif,
+      box_botright.gif,
+      tab_selected.gif,
+      tab_.gif,
+      corner_right.gif,
+      closewindow.gif,
+      OGoLogo.gif,
+      upward_sorted.gif,
+      downward_sorted.gif,
+      non_sorted.gif
      );
 
-  factories = {
-  };
+   factories = {
+   };
 
-  categories = {
-     SOGoFolder = {
-        methods = {
-           acls = {
-              protectedBy = "ReadAcls";
-              pageName    = "UIxAclEditor";
-           };
-           saveAcls = {
-              protectedBy = "SaveAcls";
-              pageName    = "UIxAclEditor";
-              actionName = "saveAcls";
-           };
-        };
-     };
-  };
+   categories = {
+      SOGoFolder = {
+        methods = {
+           subscribe = {
+              protectedBy = "View";
+              actionClass = "UIxFolderActions";
+              actionName = "subscribe";
+           };
+           unsubscribe = {
+              protectedBy = "View";
+              actionClass = "UIxFolderActions";
+              actionName = "unsubscribe";
+           };
+           canAccessContent = {
+              protectedBy = "View";
+              actionClass = "UIxFolderActions";
+              actionName = "canAccessContent";
+           };
+            activateFolder = {
+              protectedBy = "View";
+              actionClass = "UIxFolderActions";
+              actionName = "activateFolder";
+            };
+            deactivateFolder = {
+              protectedBy = "View";
+              actionClass = "UIxFolderActions";
+              actionName = "deactivateFolder";
+            };
+           acls = {
+              protectedBy = "ReadAcls";
+              pageName    = "UIxAclEditor";
+           };
+           saveAcls = {
+              protectedBy = "SaveAcls";
+              pageName    = "UIxAclEditor";
+              actionName = "saveAcls";
+           };
+        };
+      };
+   };
 }
index 0067b60cd44f9630ecb126524af071271664a59a..c6256673b14cb6e52f97b7fce5209876de687abd 100644 (file)
@@ -86,9 +86,6 @@
 "Recipient" = "Recipient";
 "Carbon Copy" = "Carbon Copy";
 "Blind Carbon Copy" = "Blind Carbon Copy";
-"Add Attendee..." = "Add Attendee...";
-"Add Assistant" = "Add Assistant";
-"Add Delegate" = "Add Delegate";
 
 "New Addressbook..." = "New Addressbook...";
 "Subscribe to an Addressbook..." = "Subscribe to an Addressbook...";
@@ -97,3 +94,8 @@
 "Name of the Address Book" = "Name of the Address Book";
 "Are you sure you want to delete the selected address book?"
 = "Are you sure you want to delete the selected address book?";
+
+"You cannot subscribe to a folder that you own!"
+= "You cannot subscribe to a folder that you own!";
+"Unable to subscribe to that folder!"
+= "Unable to subscribe to that folder!";
index 45053a701bcc6734c1e93fe5047b7f12d9bec9a2..660de024232f0cfedb3bd818df481cd856f168c9 100644 (file)
 "Recipient" = "Destinataire";
 "Carbon Copy" = "Copie carbone";
 "Blind Carbon Copy" = "C. carbone cachée";
-"Add Attendee..." = "Ajouter participant...";
-"Add Calendar..." = "Ajouter agenda...";
-"Add Address Book..." = "Ajouter carnet...";
-"Add Assistant" = "Ajouter comme assistant";
-"Add Delegate" = "Ajouter comme délégué";
 
 "New Addressbook..." = "Nouveau carnet d'adresses...";
 "Subscribe to an Addressbook..." = "S'inscrire Ã  un carnet d'adresses...";
 "Name of the Address Book" = "Nom du carnet d'adresses";
 "Are you sure you want to delete the selected address book?"
 = "Voulez-vous vraiment supprimer le carnet d'adresses sélectionné ?";
+
+"You cannot subscribe to a folder that you own!"
+= "Vous ne pouvez pas vous inscrire Ã  un dossier qui vous appartient!";
+"Unable to subscribe to that folder!"
+= "Impossible de vous inscrire Ã  ce dossier!";
index 2c8b9a36f948fc28f9e2686cc93fe1c35035a92c..ed831d329d60e69649aa8d735a6d17644ef43b3c 100644 (file)
@@ -9,9 +9,7 @@ ContactsUI_PRINCIPAL_CLASS = ContactsUIProduct
 ContactsUI_LANGUAGES = English French
 
 ContactsUI_OBJC_FILES =                        \
-       UIxContactsAclsSelection.m \
-       UIxContactsAddressBooksSelection.m \
-       UIxContactsCalendarsSelection.m \
+       UIxContactsUserFolders.m \
        UIxContactsMailerSelection.m    \
        \
        ContactsUIProduct.m             \
@@ -20,7 +18,6 @@ ContactsUI_OBJC_FILES =                       \
        UIxContactEditor.m              \
        UIxContactsListView.m           \
        UIxContactsListViewContainer.m  \
-       UIxContactSelector.m    \
        UIxContactFoldersView.m         \
 
 ContactsUI_RESOURCE_FILES +=           \
index 88534001dc31fb3c042381c4225ba61386f229cd..45e98dd1f201672d131907ac1a9f81a97f61cb94 100644 (file)
 #import <NGObjWeb/WOResponse.h>
 #import <NGObjWeb/WOContext.h>
 
+#import <GDLContentStore/GCSFolder.h>
+#import <GDLContentStore/GCSFolderManager.h>
+
 #import <SoObjects/SOGo/SOGoUser.h>
 #import <SoObjects/SOGo/NSString+Utilities.h>
 #import <SoObjects/Contacts/SOGoContactFolders.h>
 #import <SoObjects/Contacts/SOGoContactFolder.h>
 #import <SoObjects/Contacts/SOGoContactGCSFolder.h>
+#import <SoObjects/Contacts/SOGoContactLDAPFolder.h>
 
 #import "common.h"
 
   return response;
 }
 
-- (id) selectForSchedulerAction
-{
-  return [self _selectActionForApplication: @"scheduler-contacts"];
-}
-
 - (id) selectForMailerAction
 {
   return [self _selectActionForApplication: @"mailer-contacts"];
 }
 
-- (id) selectForCalendarsAction
-{
-  return [self _selectActionForApplication: @"calendars-contacts"];
-}
-
-- (id) selectForAddressBooksAction
-{
-  return [self _selectActionForApplication: @"addressbooks-contacts"];
-}
-
-- (id) selectForAclsAction
-{
-  return [self _selectActionForApplication: @"acls-contacts"];
-}
-
 - (NSArray *) _searchResults: (NSString *) contact
+            ldapFoldersOnly: (BOOL) ldapFoldersOnly
 {
   NSMutableArray *results;
   SOGoContactFolders *topFolder;
   currentFolder = [sogoContactFolders nextObject];
   while (currentFolder)
     {
-      [results addObjectsFromArray: [currentFolder
-                                      lookupContactsWithFilter: contact
-                                      sortBy: @"cn"
-                                      ordering: NSOrderedAscending]];
+      if (!ldapFoldersOnly
+         || [currentFolder isKindOfClass: [SOGoContactLDAPFolder class]])
+       [results addObjectsFromArray: [currentFolder
+                                       lookupContactsWithFilter: contact
+                                       sortBy: @"cn"
+                                       ordering: NSOrderedAscending]];
       currentFolder = [sogoContactFolders nextObject];
     }
   [topFolder release];
 {
   NSString *contact;
   id <WOActionResults> result;
+  BOOL ldapFoldersOnly;
 
   contact = [self queryParameterForKey: @"search"];
-  if ([contact length])
-    result = [self _responseForResults: [self _searchResults: contact]];
+  ldapFoldersOnly = [[self queryParameterForKey: @"ldap-only"] boolValue];
+  if ([contact length] > 0)
+    result
+      = [self _responseForResults: [self _searchResults: contact
+                                        ldapFoldersOnly: ldapFoldersOnly]];
   else
     result = [NSException exceptionWithHTTPStatus: 400
                           reason: @"missing 'search' parameter"];
-
+  
   return result;
 }
 
-- (id <WOActionResults>) updateAdditionalAddressBooksAction
+- (NSArray *) _gcsFoldersFromFolder: (SOGoContactFolders *) contactFolders
+{
+  NSMutableArray *gcsFolders;
+  NSEnumerator *contactSubfolders;
+  SOGoContactGCSFolder *currentContactFolder;
+  NSString *folderName, *displayName;
+  NSMutableDictionary *currentDictionary;
+
+  gcsFolders = [NSMutableArray new];
+  [gcsFolders autorelease];
+
+  contactSubfolders = [[contactFolders contactFolders] objectEnumerator];
+  currentContactFolder = [contactSubfolders nextObject];
+  while (currentContactFolder)
+    {
+      if ([currentContactFolder
+           isKindOfClass: [SOGoContactGCSFolder class]])
+       {
+         folderName = [NSString stringWithFormat: @"/Contacts/%@",
+                                [currentContactFolder nameInContainer]];
+         currentDictionary = [NSMutableDictionary new];
+         [currentDictionary autorelease];
+         displayName = [[currentContactFolder ocsFolder] folderName];
+         [currentDictionary setObject: displayName forKey: @"displayName"];
+         [currentDictionary setObject: folderName forKey: @"name"];
+         [currentDictionary setObject: @"contact" forKey: @"type"];
+         [gcsFolders addObject: currentDictionary];
+       }
+      currentContactFolder = [contactSubfolders nextObject];
+    }
+
+  return gcsFolders;
+}
+
+- (NSArray *) _foldersForUID: (NSString *) uid
+                     ofType: (NSString *) folderType
+{
+  NSObject *topFolder, *userFolder;
+  SOGoContactFolders *contactFolders;
+  NSMutableArray *folders;
+  NSMutableDictionary *currentDictionary;
+
+  folders = [NSMutableArray new];
+  [folders autorelease];
+
+  topFolder = [[[self clientObject] container] container];
+  userFolder = [topFolder lookupName: uid inContext: context acquire: NO];
+
+  /* FIXME: should be moved in the SOGo* classes. Maybe by having a SOGoFolderManager. */
+#warning this might need adjustments whenever we permit multiple calendar folders per-user
+  if ([folderType length] == 0 || [folderType isEqualToString: @"calendar"])
+    {
+      currentDictionary = [NSMutableDictionary new];
+      [currentDictionary autorelease];
+      [currentDictionary setObject: [self labelForKey: @"Calendar"]
+                        forKey: @"displayName"];
+      [currentDictionary setObject: @"/Calendar" forKey: @"name"];
+      [currentDictionary setObject: @"calendar" forKey: @"type"];
+      [folders addObject: currentDictionary];
+    }
+  if ([folderType length] == 0 || [folderType isEqualToString: @"contact"])
+    {
+      contactFolders = [userFolder lookupName: @"Contacts"
+                                  inContext: context acquire: NO];
+      [folders
+       addObjectsFromArray: [self _gcsFoldersFromFolder: contactFolders]];
+    }
+
+  return folders;
+}
+
+- (NSString *) _foldersStringForFolders: (NSEnumerator *) folders
+{
+  NSMutableString *foldersString;
+  NSDictionary *currentFolder;
+
+  foldersString = [NSMutableString new];
+  [foldersString autorelease];
+
+  currentFolder = [folders nextObject];
+  while (currentFolder)
+    {
+      [foldersString appendFormat: @";%@:%@:%@",
+                    [currentFolder objectForKey: @"displayName"],
+                    [currentFolder objectForKey: @"name"],
+                    [currentFolder objectForKey: @"type"]];
+      currentFolder = [folders nextObject];
+    }
+
+  return foldersString;
+}
+
+- (WOResponse *) _foldersResponseForResults: (NSArray *) results
+                                  withType: (NSString *) folderType
 {
   WOResponse *response;
-  NSUserDefaults *ud;
+  NSString *uid, *foldersString;
+  NSMutableString *responseString;
+  NSDictionary *result;
+  NSEnumerator *resultsEnum;
+  NSArray *folders;
 
-  ud = [[context activeUser] userDefaults];
-  [ud setObject: [self queryParameterForKey: @"ids"]
-      forKey: @"additionaladdressbooks"];
-  [ud synchronize];
   response = [context response];
-  [response setStatus: 200];
-  [response setHeader: @"text/html; charset=\"utf-8\"" forKey: @"content-type"];
+
+  if ([results count])
+    {
+      [response setStatus: 200];
+      [response setHeader: @"text/plain; charset=iso-8859-1"
+                forKey: @"Content-Type"];
+
+      responseString = [NSMutableString new];
+      resultsEnum = [results objectEnumerator];
+      result = [resultsEnum nextObject];
+      while (result)
+       {
+         uid = [result objectForKey: @"c_uid"];
+         folders = [self _foldersForUID: uid ofType: folderType];
+         foldersString
+           = [self _foldersStringForFolders: [folders objectEnumerator]];
+         [responseString appendFormat: @"%@:%@%@\n",
+                         uid, [self _emailForResult: result], foldersString];
+         result = [resultsEnum nextObject];
+       }
+      [response appendContentString: responseString];
+      [responseString release];
+    }
+  else
+    [response setStatus: 404];
 
   return response;
 }
 
+- (id <WOActionResults>) foldersSearchAction
+{
+  NSString *contact, *folderType;
+  id <WOActionResults> result;
+  BOOL ldapOnly;
+
+  contact = [self queryParameterForKey: @"search"];
+  if ([contact length] > 0)
+    {
+      ldapOnly = [[self queryParameterForKey: @"ldap-only"] boolValue];
+      folderType = [self queryParameterForKey: @"type"];
+      result = [self _foldersResponseForResults:
+                      [self _searchResults: contact
+                            ldapFoldersOnly: ldapOnly]
+                    withType: folderType];
+    }
+  else
+    result = [NSException exceptionWithHTTPStatus: 400
+                          reason: @"missing 'search' parameter"];
+
+  return result;
+}
+
 - (SOGoContactGCSFolder *) contactFolderForUID: (NSString *) uid
 {
   SOGoFolder *upperContainer;
           ? contactFolder : nil);
 }
 
-- (id <WOActionResults>) checkRightsAction
-{
-  WOResponse *response;
-  NSUserDefaults *ud;
-  NSString *uids;
-  NSMutableString *rights;
-  NSArray *ids;
-  unsigned int count, max;
-  BOOL result;
-
-  ud = [[context activeUser] userDefaults];
-  uids = [ud objectForKey: @"additionaladdressbooks"];
-
-  response = [context response];
-  [response setStatus: 200];
-  [response setHeader: @"text/plain; charset=\"utf-8\""
-            forKey: @"content-type"];
-  rights = [NSMutableString string];
-  if ([uids length] > 0)
-    {
-      ids = [uids componentsSeparatedByString: @","];
-      max = [ids count];
-      for (count = 0; count < max; count++)
-        {
-          result = ([self contactFolderForUID: [ids objectAtIndex: count]] != nil);
-          if (count == 0)
-            [rights appendFormat: @"%d", result];
-          else
-            [rights appendFormat: @",%d", result];
-        }
-    }
-  [response appendContentString: rights];
-
-  return response;
-}
-
 @end
diff --git a/UI/Contacts/UIxContactsAclsSelection.m b/UI/Contacts/UIxContactsAclsSelection.m
deleted file mode 100644 (file)
index eed1fa3..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-  Copyright (C) 2004-2005 SKYRIX Software AG
-
-  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
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo 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 Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-
-#import <SOGoUI/UIxComponent.h>
-
-@interface UIxContactsAclsSelection : UIxComponent
-  
-@end
-
-@implementation UIxContactsAclsSelection
-
-@end /* UIxContactsAclsSelection */
diff --git a/UI/Contacts/UIxContactsAddressBooksSelection.m b/UI/Contacts/UIxContactsAddressBooksSelection.m
deleted file mode 100644 (file)
index 53232a1..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-  Copyright (C) 2004-2005 SKYRIX Software AG
-
-  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
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo 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 Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-
-#import <SOGoUI/UIxComponent.h>
-
-@interface UIxContactsAddressBooksSelection : UIxComponent
-  
-@end
-
-@implementation UIxContactsAddressBooksSelection
-
-@end /* UIxContactsAddressBooksSelection */
diff --git a/UI/Contacts/UIxContactsCalendarsSelection.m b/UI/Contacts/UIxContactsCalendarsSelection.m
deleted file mode 100644 (file)
index 7dc4d72..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-  Copyright (C) 2004-2005 SKYRIX Software AG
-
-  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
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo 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 Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-
-#import <SOGoUI/UIxComponent.h>
-
-@interface UIxContactsCalendarsSelection : UIxComponent
-  
-@end
-
-@implementation UIxContactsCalendarsSelection
-
-@end /* UIxContactsCalendarsSelection */
index a709758b7128cb4b0bc0aa1f6fd8278667d2521e..41f27e89da9e7a5ce1c40a357c24dbea126c53e8 100644 (file)
   return searchText;
 }
 
-- (NSString *) selectorComponentClass
-{
-  return selectorComponentClass;
-}
-
-- (id) mailerContactsAction
+- (id <WOActionResults>) mailerContactsAction
 {
   selectorComponentClass = @"UIxContactsMailerSelection";
 
   return self;
 }
 
-- (id) calendarsContactsAction
-{
-  selectorComponentClass = @"UIxContactsCalendarsSelection";
-
-  return self;
-}
-
-- (id) addressBooksContactsAction
-{
-  selectorComponentClass = @"UIxContactsAddressBooksSelection";
-
-  return self;
-}
-
-- (id) aclsContactsAction
-{
-  selectorComponentClass = @"UIxContactsAclsSelection";
-
-  return self;
-}
-
 - (id <WOActionResults>) deleteAction
 {
   id <WOActionResults> result;
   return YES;
 }
 
+- (WOResponse *) canAccessContentAction
+{
+  WOResponse *response;
+  NSString *clientClass;
+
+  clientClass = NSStringFromClass([[self clientObject] class]);
+
+  response = [context response];
+  [response setStatus: 200];
+  [response setHeader: @"text/plain; charset=\"ascii\""
+            forKey: @"content-type"];
+  [response
+    appendContentString:
+      ([clientClass isEqualToString: @"SOGoContactLDAPFolder"])
+    ? @"1" : @"0"];
+
+  return response;
+}
+
 @end /* UIxContactsListView */
index 7bed4f8975f8843100df2f0f589a549e57cbb3b9..5be9899fd0a95f28754d50f61264dbb6b4f9c184 100644 (file)
@@ -34,6 +34,7 @@
   NSString *foldersPrefix;
   NSString *selectorComponentClass;
   NSString *currentAdditionalFolder;
+  NSDictionary *additionalFolders;
   id currentFolder;
 }
 
 
 - (NSArray *) contactFolders;
 
-- (NSString *) contactFolderId;
 - (NSString *) currentContactFolderId;
 - (NSString *) currentContactFolderName;
 
-- (NSString *) additionalAddressBooks;
 - (NSArray *) additionalFolders;
 
 - (void) setCurrentAdditionalFolder: (NSString *) newCurrentAdditionalFolder;
 - (NSString *) currentAdditionalFolder;
+- (NSString *) currentAdditionalFolderName;
 
 @end
 
index b6e218f67815f6087bb8c4b6c3d6b7fa96e4c284..34fa3a32c691d29cf51ce6f82d84ec0dd259e133 100644 (file)
  */
 
 #import <Foundation/NSArray.h>
+#import <Foundation/NSDictionary.h>
 #import <Foundation/NSString.h>
 
 #import <NGObjWeb/SoObjects.h>
 #import <NGExtensions/NSObject+Values.h>
 
+#import <SoObjects/SOGo/AgenorUserManager.h>
 #import <SoObjects/SOGo/SOGoUser.h>
 #import <SoObjects/Contacts/SOGoContactFolder.h>
 
     {
       foldersPrefix = nil;
       selectorComponentClass = nil;
+      additionalFolders = nil;
     }
 
   return self;
 }
 
+- (void) dealloc
+{
+  [additionalFolders release];
+  [super dealloc];
+}
+
 - (void) setSelectorComponentClass: (NSString *) aComponentClass
 {
   selectorComponentClass = aComponentClass;
   return foldersPrefix;
 }
 
-- (NSString *) contactFolderId
-{
-  return [NSString stringWithFormat: @"%@/%@",
-                   [self foldersPrefix],
-                   [[self clientObject] nameInContainer]];
-}
-
 - (NSArray *) contactFolders
 {
   SOGoContactFolders *folderContainer;
   return [self labelForKey: [currentFolder displayName]];
 }
 
-- (BOOL) isFolderCurrent
-{
-  return [[self currentContactFolderId] isEqualToString: [self contactFolderId]];
-}
-
-- (NSString *) additionalAddressBooks
-{
-  NSUserDefaults *ud;
-
-  ud = [[context activeUser] userDefaults];
-
-  return [ud objectForKey: @"additionaladdressbooks"];
-}
-
 - (NSArray *) additionalFolders
 {
-  NSString *folders;
-  NSArray *folderNames;
+  AgenorUserManager *um;
+  NSUserDefaults *ud;
+  NSString *login;
 
-  folders = [self additionalAddressBooks];
-  if ([folders length] > 0)
-    folderNames = [folders componentsSeparatedByString: @","];
-  else
-    folderNames = nil;
+  if (!additionalFolders)
+    {
+      um = [AgenorUserManager sharedUserManager];
+      login = [[context activeUser] login];
+      ud = [um getUserSettingsForUID: login];
+      additionalFolders
+       = [[ud objectForKey: @"Contacts"] objectForKey: @"SubscribedFolders"];
+      [additionalFolders retain];
+    }
 
-  return folderNames;
+  return [additionalFolders allKeys];
 }
 
 - (void) setCurrentAdditionalFolder: (NSString *) newCurrentAdditionalFolder
   return currentAdditionalFolder;
 }
 
+- (NSString *) currentAdditionalFolderName
+{
+  return [[additionalFolders objectForKey: currentAdditionalFolder]
+          objectForKey: @"displayName"];
+}
+
 - (BOOL) hasContactSelectionButtons
 {
   return (selectorComponentClass != nil);
similarity index 64%
rename from UI/Scheduler/UIxCalCalendarsListView.h
rename to UI/Contacts/UIxContactsUserFolders.h
index e3ed293e687890c7b87da0a72db22d1b6fba8b17..4b9117cc8385cbad97b7766d8830b7ce740b775e 100644 (file)
@@ -1,6 +1,6 @@
-/* UIxCalCalendarsListView.h - this file is part of SOGo
+/* UIxContactsUserFolders.h - this file is part of SOGo
  *
- * Copyright (C) 2006 Inverse groupe conseil
+ * Copyright (C) 2007 Inverse groupe conseil
  *
  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
  *
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef UIXCALCALENDARSLISTVIEW_H
-#define UIXCALCALENDARSLISTVIEW_H
+#ifndef UIXCONTACTSUSERFOLDERS_H
+#define UIXCONTACTSUSERFOLDERS_H
 
 #import <SOGoUI/UIxComponent.h>
 
-@class NSMutableArray;
-@class NSMutableDictionary;
-@class iCalPerson;
-
-@interface UIxCalCalendarsListView : UIxComponent
-{
-  NSMutableArray *checkedContacts;
-  NSMutableArray *contacts;
-  NSMutableDictionary *colors;
-  iCalPerson *currentContactPerson;
-}
+@interface UIxContactsUserFolders : UIxComponent
 
 @end
 
-#endif /* UIXCALCALENDARSLISTVIEW_H */
+
+#endif /* UIXCONTACTSUSERFOLDERS_H */
diff --git a/UI/Contacts/UIxContactsUserFolders.m b/UI/Contacts/UIxContactsUserFolders.m
new file mode 100644 (file)
index 0000000..f941874
--- /dev/null
@@ -0,0 +1,27 @@
+/* UIxContactsUserFolders.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 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 "UIxContactsUserFolders.h"
+
+@implementation UIxContactsUserFolders
+
+@end
index 6e4d7ea822538bdc197f21af885dd750b41c8586..663ab8d97b70f79ea87aacf88bffd29655f390af 100644 (file)
@@ -1,5 +1,5 @@
 { /* -*-javascript-*- */
-  requires = ( MAIN, CommonUI, Contacts );
+  requires = ( MAIN, MainUI, CommonUI, Contacts );
 
   publicResources = ();
 
               pageName    = "UIxContactFoldersView";
               actionName  = "newAb";
            };
-           scheduler-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactFoldersView";
-              actionName  = "selectForScheduler";
-           };
            mailer-contacts = {
               protectedBy = "View";
               pageName    = "UIxContactFoldersView";
               actionName  = "selectForMailer";
            };
-           calendars-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactFoldersView";
-              actionName  = "selectForCalendars";
-           };
-           addressbooks-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactFoldersView";
-              actionName  = "selectForAddressBooks";
-           };
-           acls-contacts = {
+           contactSearch = {
               protectedBy = "View";
               pageName    = "UIxContactFoldersView";
-              actionName  = "selectForAcls";
+              actionName  = "contactSearch";
            };
-           contactSearch = {
+           foldersSearch = {
               protectedBy = "View";
               pageName    = "UIxContactFoldersView";
-              actionName  = "contactSearch";
+              actionName  = "foldersSearch";
            };
            updateAdditionalAddressBooks = {
               protectedBy = "View";
            saveAcls = {
               protectedBy = "SaveAcls";
               pageName    = "UIxAclEditor";
-              actionName = "saveAcls";
+              actionName  = "saveAcls";
            };
            checkRights = {
               protectedBy = "View";
               pageName    = "UIxContactFoldersView"; 
               actionName  = "checkRights";
            };
+          userFolders = {
+              protectedBy = "View";
+              pageName    = "UIxContactsUserFolders"; 
+          };
         };
      };
 
            mailer-contacts = {
               protectedBy = "View";
               pageName    = "UIxContactsListView";
-              actionName = "mailerContacts";
-           };
-           calendars-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactsListView";
-              actionName = "calendarsContacts";
-           };
-           acls-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactsListView";
-              actionName  = "aclsContacts";
-           };
-           addressbooks-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactsListView";
-              actionName = "addressBooksContacts";
+              actionName  = "mailerContacts";
            };
           delete = {
               protectedBy = "View";
               pageName    = "UIxContactsListView";
-              actionName = "delete";
+              actionName  = "delete";
           };
         };
      };
               pageName    = "UIxContactEditor";
               actionName  = "new";
            };
-           scheduler-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactsListView";
-              actionName = "schedulerContacts";
-           };
            mailer-contacts = {
               protectedBy = "View";
               pageName    = "UIxContactsListView";
               actionName = "mailerContacts";
            };
-           calendars-contacts = {
-              protectedBy = "View";
+          canAccessContent = {
+             protectedBy = "View";
               pageName    = "UIxContactsListView";
-              actionName = "calendarsContacts";
-           };
-           acls-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactsListView";
-              actionName  = "aclsContacts";
-           };
-           addressbooks-contacts = {
-              protectedBy = "View";
-              pageName    = "UIxContactsListView";
-              actionName = "addressBooksContacts";
-           };
+             actionName = "canAccessContent";
+          };
         };
      };
 
index 4cd16e76e34185fe1b0c84d85c5c545d823114fd..7731f9eaae9e2ca51d91b8d0873ef2af623dad53 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+#import <Foundation/NSArray.h>
+#import <Foundation/NSCalendarDate.h>
+#import <Foundation/NSValue.h>
 #import <NGObjWeb/WORequest.h>
+#import <NGObjWeb/WOResponse.h>
+#import <NGExtensions/NSCalendarDate+misc.h>
+
+#import <Appointments/SOGoFreeBusyObject.h>
+#import <SOGo/NSCalendarDate+SOGo.h>
 #import <SOGoUI/UIxComponent.h>
 
 @interface SOGoUserHomePage : UIxComponent
   return [self redirectToLocation: url];
 }
 
+- (void) _fillFreeBusyItems: (NSMutableArray *) items
+                withRecords: (NSEnumerator *) records
+              fromStartDate: (NSCalendarDate *) startDate
+                  toEndDate: (NSCalendarDate *) endDate
+{
+  NSDictionary *record;
+  int count, startInterval, endInterval, value;
+  NSNumber *status;
+  NSCalendarDate *currentDate;
+  
+  record = [records nextObject];
+  while (record)
+    {
+      status = [record objectForKey: @"status"];
+      value = [[record objectForKey: @"startdate"] intValue];
+      currentDate = [NSCalendarDate dateWithTimeIntervalSince1970: value];
+      if ([currentDate earlierDate: startDate] == currentDate)
+        startInterval = 0;
+      else
+        startInterval
+          = ([currentDate timeIntervalSinceDate: startDate] / 900);
+
+      value = [[record objectForKey: @"enddate"] intValue];
+      currentDate = [NSCalendarDate dateWithTimeIntervalSince1970: value];
+      if ([currentDate earlierDate: endDate] == endDate)
+        endInterval = [items count] - 1;
+      else
+        endInterval = ([currentDate timeIntervalSinceDate: startDate] / 900);
+
+      for (count = startInterval; count < endInterval; count++)
+        [items replaceObjectAtIndex: count withObject: status];
+
+      record = [records nextObject];
+    }
+}
+- (NSString *) _freeBusyAsTextFromStartDate: (NSCalendarDate *) startDate
+                                  toEndDate: (NSCalendarDate *) endDate
+                                forFreeBusy: (SOGoFreeBusyObject *) fb
+{
+  NSEnumerator *records;
+  NSMutableArray *freeBusyItems;
+  NSTimeInterval interval;
+  int count, intervals;
+
+  interval = [endDate timeIntervalSinceDate: startDate] + 60;
+  intervals = interval / 900; /* slices of 15 minutes */
+  freeBusyItems = [NSMutableArray arrayWithCapacity: intervals];
+  for (count = 1; count < intervals; count++)
+    [freeBusyItems addObject: @"0"];
+
+  records = [[fb fetchFreeBusyInfosFrom: startDate to: endDate] objectEnumerator];
+  [self _fillFreeBusyItems: freeBusyItems withRecords: records
+        fromStartDate: startDate toEndDate: endDate];
+
+  return [freeBusyItems componentsJoinedByString: @","];
+}
+
+- (NSString *) _freeBusyAsText
+{
+  SOGoFreeBusyObject *co;
+  NSCalendarDate *startDate, *endDate;
+  NSString *queryDay, *additionalDays;
+  NSTimeZone *uTZ;
+
+  co = [self clientObject];
+  uTZ = [co userTimeZone];
+
+  queryDay = [self queryParameterForKey: @"sday"];
+  if ([queryDay length])
+    startDate = [NSCalendarDate dateFromShortDateString: queryDay
+                                andShortTimeString: @"0000"
+                                inTimeZone: uTZ];
+  else
+    {
+      startDate = [NSCalendarDate calendarDate];
+      [startDate setTimeZone: uTZ];
+      startDate = [startDate hour: 0 minute: 0];
+    }
+
+  queryDay = [self queryParameterForKey: @"eday"];
+  if ([queryDay length])
+    endDate = [NSCalendarDate dateFromShortDateString: queryDay
+                              andShortTimeString: @"2359"
+                              inTimeZone: uTZ];
+  else
+    endDate = [startDate hour: 23 minute: 59];
+
+  additionalDays = [self queryParameterForKey: @"additional"];
+  if ([additionalDays length] > 0)
+    endDate = [endDate dateByAddingYears: 0 months: 0
+                       days: [additionalDays intValue]
+                       hours: 0 minutes: 0 seconds: 0];
+
+  return [self _freeBusyAsTextFromStartDate: startDate toEndDate: endDate
+               forFreeBusy: co];
+}
+
+- (id <WOActionResults>) readFreeBusyAction
+{
+  WOResponse *response;
+
+  response = [context response];
+  [response setStatus: 200];
+  [response setHeader: @"text/plain; charset=iso-8859-1"
+            forKey: @"Content-Type"];
+  [response appendContentString: [self _freeBusyAsText]];
+
+  return response;
+}
+
 @end
index 2ee0e399f4a5a5efee1b85b04f42442d0ba024c1..6895273fe5f959dbf19e0790a7a109a346264238 100644 (file)
@@ -17,7 +17,7 @@
     };
     SOGoUserFolder = {
       superclass  = "SOGoFolder";
-      protectedBy = "HomePage Access";
+      /* protectedBy = "HomePage Access"; */
       defaultRoles = {
         "Homepage Access" = ( "Owner", "Assistant", "Delegate", "FreeBusy" );
         "WebDAV Access" = ( "Owner", "Assistant", "Delegate", "FreeBusy" );
index d0c92e469d9c1addad80fe4f4a7edf94660071a1..13ea2c5ff7c5429ee6e77de76ea653e053fa8f6b 100644 (file)
@@ -14,6 +14,7 @@ FHS_HEADER_DIRS = SOGoUI
 
 libSOGoUI_HEADER_FILES +=      \
        \
+       UIxJSClose.h            \
        UIxComponent.h          \
        SOGoDateFormatter.h     \
        SOGoAptFormatter.h      \
@@ -22,6 +23,7 @@ libSOGoUI_HEADER_FILES +=     \
 
 libSOGoUI_OBJC_FILES +=                \
        \
+       UIxJSClose.m            \
        UIxComponent.m          \
        SOGoDateFormatter.m     \
        SOGoAptFormatter.m      \
index 52f05e55c7aa223668ae983217800cb455dfc629..0758c504bf10b64624d32864d0e6233d20e7e5ee 100644 (file)
@@ -32,7 +32,7 @@
 #import <SOGo/SOGoCustomGroupFolder.h>
 #import <SOGo/NSCalendarDate+SOGo.h>
 
-#import "../Common/UIxJSClose.h"
+#import "UIxJSClose.h"
 
 #import "UIxComponent.h"
 
index adb78b5d2436d14d613a2e6fef145136fe768d56..37002e785b84668853b08507a0f2b074295f7ab1 100644 (file)
@@ -362,10 +362,11 @@ validate_endbeforestart    = "La date de fin est avant la date de début !";
 "No free-busy information" = "Pas d'information";
 
 /* FreeBusy panel buttons */
-"Previous slot" = "Période précédente";
-"Next slot" = "Période suivante";
+"Suggest time slot:" = "Suggérer un créneau horaire :";
+"Previous slot" = "Précédent";
+"Next slot" = "Prochain";
 "Previous hour" = "Heure précédente";
-"Next hour" = "Heure suivante";
+"Next hour" = "Prochaine heure";
 
 "closeThisWindowMessage" = "Merci! Vous pouvez maintenant fermer cette fenêtre.";
 "Multicolumn Day View" = "Multicolonne";
index b90b510e02ebf4c315efcb638c4a7f3c6cc71685..d3594c4b5f28a8499a67386abb849fc452c119ac 100644 (file)
@@ -20,7 +20,6 @@ SchedulerUI_OBJC_FILES =              \
                                        \
        UIxComponent+Agenor.m           \
        UIxCalView.m                    \
-       UIxCalCalendarsListView.m       \
        UIxCalAptListView.m             \
        UIxCalTasksListView.m           \
        UIxCalDayView.m                 \
@@ -32,6 +31,7 @@ SchedulerUI_OBJC_FILES =              \
                                        \
        UIxAttendeesEditor.m            \
        UIxComponentEditor.m            \
+       UIxCalendarSelector.m           \
        UIxAppointmentView.m            \
        UIxAppointmentEditor.m          \
        UIxAppointmentProposal.m        \
@@ -40,12 +40,10 @@ SchedulerUI_OBJC_FILES =            \
        UIxTaskProposal.m       \
        UIxCalSelectTab.m               \
        UIxCalDateLabel.m               \
-       UIxCalBackForthNavView.m        \
        UIxDatePicker.m                 \
        UIxTimeDateControl.m            \
        UIxCalInlineAptView.m           \
        UIxCalInlineMonthAptView.m      \
-       UIxCalScheduleOverview.m        \
        UIxCalParticipationStatusView.m \
        UIxCalMonthOverview.m
 
diff --git a/UI/Scheduler/UIxCalBackForthNavView.m b/UI/Scheduler/UIxCalBackForthNavView.m
deleted file mode 100644 (file)
index d8e76b3..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-  Copyright (C) 2004 SKYRIX Software AG
-
-  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
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo 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 Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-// $Id$
-
-
-#include <NGObjWeb/NGObjWeb.h>
-
-/*
-    Associations:
-
-    methodName              -> maps to href
-    prevQueryParameters     -> queryDictionary
-    currentQueryParameters  -> queryDictionary
-    nextQueryParameters     -> queryDictionary
-    label                   -> user presentable name to display for "this"
- */
-
-@interface UIxCalBackForthNavView : WOComponent
-{
-}
-
-@end
-
-
-@implementation UIxCalBackForthNavView
-
-- (BOOL)synchronizesVariablesWithBindings {
-    return NO;
-}
-
-@end
diff --git a/UI/Scheduler/UIxCalCalendarsListView.m b/UI/Scheduler/UIxCalCalendarsListView.m
deleted file mode 100644 (file)
index b25de82..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* UIxCalCalendarsListView.m - this file is part of SOGo
- *
- * Copyright (C) 2006 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/NSDictionary.h>
-#import <Foundation/NSString.h>
-#import <Foundation/NSUserDefaults.h>
-
-#import <SOGo/AgenorUserManager.h>
-#import <SOGo/SOGoUser.h>
-
-#import "UIxCalCalendarsListView.h"
-
-static inline char
-darkenedColor (const char value)
-{
-  char newValue;
-
-  if (value >= '0' && value <= '9')
-    newValue = ((value - '0') / 2) + '0';
-  else if (value >= 'a' && value <= 'f')
-    newValue = ((value + 10 - 'a') / 2) + '0';
-  else if (value >= 'A' && value <= 'F')
-    newValue = ((value + 10 - 'A') / 2) + '0';
-  else
-    newValue = value;
-
-  return newValue;
-}
-
-@implementation UIxCalCalendarsListView
-
-- (id) init
-{
-  if ((self = [super init]))
-    {
-      contacts = nil;
-      checkedContacts = nil;
-      currentContactPerson = nil;
-      colors = nil;
-    }
-
-  return self;
-}
-
-- (void) dealloc
-{
-  if (currentContactPerson)
-    [currentContactPerson release];
-  if (contacts)
-    [contacts release];
-  if (checkedContacts)
-    [checkedContacts release];
-  if (colors)
-    [colors release];
-  [super dealloc];
-}
-
-- (NSString *) _colorForNumber: (unsigned int) number
-{
-  unsigned int index, currentValue;
-  unsigned char colorTable[] = { 1, 1, 1 };
-  NSString *color;
-
-  if (number == 0)
-    color = @"#ccf";
-  else if (number == NSNotFound)
-    color = @"#f00";
-  else
-    {
-      currentValue = number;
-      index = 0;
-      while (currentValue)
-        {
-          if (currentValue & 1)
-            colorTable[index]++;
-          if (index == 3)
-            index = 0;
-          currentValue >>= 1;
-          index++;
-        }
-      color = [NSString stringWithFormat: @"#%2x%2x%2x",
-                        (255 / colorTable[2]) - 1,
-                        (255 / colorTable[1]) - 1,
-                        (255 / colorTable[0]) - 1];
-    }
-
-  return color;
-}
-
-- (void) _addContactId: (NSString *) contactId
-                withUm: (AgenorUserManager *) um
-             andNumber: (unsigned int) count
-{
-  NSString *contactRealId;
-  iCalPerson *currentContact;
-
-  if ([contactId hasPrefix: @"-"])
-    contactRealId = [contactId substringFromIndex: 1];
-  else
-    contactRealId = contactId;
-
-  currentContact = [um iCalPersonWithUid: contactRealId];
-  [contacts addObject: currentContact];
-  if (contactId == contactRealId)
-    [checkedContacts addObject: currentContact];
-  [colors setObject: [self _colorForNumber: count]
-          forKey: contactRealId];
-}
-
-- (void) _setupContacts
-{
-  SOGoUser *user;
-  NSString *list, *currentId;
-  NSEnumerator *rawContacts;
-  AgenorUserManager *um;
-  unsigned int count;
-
-  contacts = [NSMutableArray new];
-  checkedContacts = [NSMutableArray new];
-  colors = [NSMutableDictionary new];
-
-  um = [AgenorUserManager sharedUserManager];
-  user = [context activeUser];
-  list = [[user userDefaults] stringForKey: @"calendaruids"];
-  if ([list length] == 0)
-    list = [self shortUserNameForDisplay];
-
-  rawContacts
-    = [[list componentsSeparatedByString: @","] objectEnumerator];
-  currentId = [rawContacts nextObject];
-  count = 0;
-  while (currentId)
-    {
-      [self _addContactId: currentId withUm: um andNumber: count];
-      currentId = [rawContacts nextObject];
-      count++;
-    }
-}
-
-- (NSArray *) contacts
-{
-  if (!contacts)
-    [self _setupContacts];
-
-  return contacts;
-}
-
-- (NSArray *) checkedContacts
-{
-  if (!checkedContacts)
-    [self _setupContacts];
-
-  return checkedContacts;
-}
-
-- (void) setCurrentContactPerson: (iCalPerson *) contact
-{
-  if (currentContactPerson)
-    [currentContactPerson release];
-  currentContactPerson = contact;
-  if (currentContactPerson)
-    [currentContactPerson retain];
-}
-
-- (NSString *) currentContactLogin
-{
-  return [currentContactPerson cn];
-}
-
-- (NSString *) currentContactSpanBG
-{
-  return [colors objectForKey: [currentContactPerson cn]];
-}
-
-- (NSString *) currentContactAptBorder
-{
-  NSString *spanBG;
-  char cColor[8];
-  unsigned int count;
-
-  spanBG = [colors objectForKey: [currentContactPerson cn]];
-  [spanBG getCString: cColor];
-  cColor[7] = 0;
-  for (count = 1; count < 7; count++)
-    cColor[count] = darkenedColor(cColor[count]);
-
-  return [NSString stringWithCString: cColor];
-}
-
-- (NSDictionary *) colors
-{
-  return colors;
-}
-
-@end
index 409bbdcfffcacc407add6713a9de9e458dcc01a3..0cb213e29e677edeb89f7d6a32b773ff0dba3213 100644 (file)
 
 - (NSString *) labelForDay
 {
-  return [NSString stringWithFormat: @"%@ %@",
+  return [NSString stringWithFormat: @"%@<br />%@",
                    [dateFormatter shortDayOfWeek: [currentTableDay dayOfWeek]],
                    [dateFormatter stringForObjectValue: currentTableDay]];
 }
index ae74b19e8251c79fc36f549425027f42c6a12ec7..ee4fbeda6a80499eaf5347c3f345897bbae590c1 100644 (file)
 #define        __UIxCalDayView_H_
 
 
-#include "UIxCalView.h"
+#import "UIxCalView.h"
 
 @interface UIxCalDayView : UIxCalView
-{
-  NSCalendarDate *currentDate;
-}
 
-- (void)setCurrentDate:(NSCalendarDate *)_date;
-- (NSCalendarDate *)currentDate;
-- (BOOL)isCurrentDateInApt;
-    
-- (NSDictionary *)currentDateQueryParameters;
+- (NSDictionary *) dayBeforePrevDayQueryParameters;
+- (NSDictionary *) prevDayQueryParameters;
+- (NSDictionary *) nextDayQueryParameters;
+- (NSDictionary *) dayAfterNextDayQueryParameters;
+- (NSDictionary *) currentDateQueryParameters;
 
-- (NSArray *)dateRange;
+- (NSCalendarDate *) startDate;
 
-/* appointments */
-- (NSArray *)aptsForCurrentDate;
-- (BOOL)hasAptsForCurrentDate;
+- (NSString *) dayBeforeYesterdayName;
+- (NSString *) yesterdayName;
+- (NSString *) currentDayName;
+- (NSString *) tomorrowName;
+- (NSString *) dayAfterTomorrowName;
 
 @end
 
index ddd0729ce33b37efbe1f0f94903053bda25f655e..fcca9b5e74135f71375624f2754b8a75373b5afc 100644 (file)
 
 #import "UIxCalDayView.h"
 
-@interface UIxCalDayView (PrivateAPI)
-- (BOOL)isCurrentDateInApt:(id)_apt;
-- (NSArray *)_getDatesFrom:(NSCalendarDate *)_from to:(NSCalendarDate *)_to;
-@end
+// @interface UIxCalDayView (PrivateAPI)
+// - (BOOL)isCurrentDateInApt:(id)_apt;
+// - (NSArray *)_getDatesFrom:(NSCalendarDate *)_from to:(NSCalendarDate *)_to;
+// @end
 
 @implementation UIxCalDayView
 
-- (void) dealloc
-{
-  [self->currentDate release];
-  [super dealloc];
-}
-
-- (void) setCurrentDate: (NSCalendarDate *) _date
-{
-  ASSIGN(self->currentDate, _date);
-}
-
-- (NSCalendarDate *) currentDate
-{
-  return self->currentDate;
-}
-
-- (BOOL) isCurrentDateInApt
-{
-  return [self isCurrentDateInApt: [self appointment]];
-}
-
-- (BOOL) isCurrentDateInApt: (id) _apt
-{
-  NSCalendarDate *dateStart, *dateEnd, *aptStart, *aptEnd;
-  NGCalendarDateRange *dateRange, *aptRange;
+// - (void) dealloc
+// {
+//   [self->currentDate release];
+//   [super dealloc];
+// }
+
+// - (void) setCurrentDate: (NSCalendarDate *) _date
+// {
+//   ASSIGN(self->currentDate, _date);
+// }
+
+// - (NSCalendarDate *) currentDate
+// {
+//   return self->currentDate;
+// }
+
+// - (BOOL) isCurrentDateInApt
+// {
+//   return [self isCurrentDateInApt: [self appointment]];
+// }
+
+// - (BOOL) isCurrentDateInApt: (id) _apt
+// {
+//   NSCalendarDate *dateStart, *dateEnd, *aptStart, *aptEnd;
+//   NGCalendarDateRange *dateRange, *aptRange;
     
-  dateStart = self->currentDate;
-  dateEnd   = [dateStart dateByAddingYears:0 months:0 days:0
-                         hours:1 minutes:0 seconds:0];
-  dateRange = [NGCalendarDateRange calendarDateRangeWithStartDate:dateStart
-                                   endDate:dateEnd];
-  aptStart = [self->appointment valueForKey:@"startDate"];
-  aptEnd   = [self->appointment valueForKey:@"endDate"];
-  aptRange = [NGCalendarDateRange calendarDateRangeWithStartDate:aptStart
-                                  endDate:aptEnd];
-
-  return [dateRange doesIntersectWithDateRange:aptRange];
-}
-
-- (NSArray *) dateRange
-{
-  /* default range is from dayStartHour to dayEndHour. Any values before
-     or after are also fine */
-
-  NSCalendarDate *min, *max;
-  NSArray        *aptDateRanges;
-
-  min = [[self startDate] hour:[self dayStartHour] minute:0];
-  max = [[self startDate] hour:[self dayEndHour]   minute:0];
-
-  aptDateRanges = [[self appointments] valueForKey: @"startDate"];
-  if([aptDateRanges count] != 0) {
-    NSCalendarDate *d;
-
-    aptDateRanges
-      = [aptDateRanges sortedArrayUsingSelector: @selector(compareAscending:)];
-    d   = [aptDateRanges objectAtIndex:0];
-    if ([d isDateOnSameDay:min])
-      min = (NSCalendarDate *)[d earlierDate:min];
-    d   = [aptDateRanges objectAtIndex:[aptDateRanges count] - 1];
-    if ([d isDateOnSameDay:max])
-      max = (NSCalendarDate *)[d laterDate:max];
-  }
+//   dateStart = self->currentDate;
+//   dateEnd   = [dateStart dateByAddingYears:0 months:0 days:0
+//                          hours:1 minutes:0 seconds:0];
+//   dateRange = [NGCalendarDateRange calendarDateRangeWithStartDate:dateStart
+//                                    endDate:dateEnd];
+//   aptStart = [self->appointment valueForKey:@"startDate"];
+//   aptEnd   = [self->appointment valueForKey:@"endDate"];
+//   aptRange = [NGCalendarDateRange calendarDateRangeWithStartDate:aptStart
+//                                   endDate:aptEnd];
+
+//   return [dateRange doesIntersectWithDateRange:aptRange];
+// }
+
+// - (NSArray *) dateRange
+// {
+//   /* default range is from dayStartHour to dayEndHour. Any values before
+//      or after are also fine */
+
+//   NSCalendarDate *min, *max;
+//   NSArray        *aptDateRanges;
+
+//   min = [[self startDate] hour:[self dayStartHour] minute:0];
+//   max = [[self startDate] hour:[self dayEndHour]   minute:0];
+
+//   aptDateRanges = [[self appointments] valueForKey: @"startDate"];
+//   if([aptDateRanges count] != 0) {
+//     NSCalendarDate *d;
+
+//     aptDateRanges
+//       = [aptDateRanges sortedArrayUsingSelector: @selector(compareAscending:)];
+//     d   = [aptDateRanges objectAtIndex:0];
+//     if ([d isDateOnSameDay:min])
+//       min = (NSCalendarDate *)[d earlierDate:min];
+//     d   = [aptDateRanges objectAtIndex:[aptDateRanges count] - 1];
+//     if ([d isDateOnSameDay:max])
+//       max = (NSCalendarDate *)[d laterDate:max];
+//   }
   
-  return [self _getDatesFrom:min to:max];
-}
-
-- (NSArray *) _getDatesFrom: (NSCalendarDate *) _from
-                         to: (NSCalendarDate *) _to
-{
-  NSMutableArray *dates;
-  unsigned       i, count, offset;
-
-  offset = [_from hourOfDay];
-  count  = ([_to hourOfDay] + 1) - offset;
-  dates  = [[NSMutableArray alloc] initWithCapacity:count];
-  for(i = 0; i < count; i++) {
-    NSCalendarDate *date;
+//   return [self _getDatesFrom:min to:max];
+// }
+
+// - (NSArray *) _getDatesFrom: (NSCalendarDate *) _from
+//                          to: (NSCalendarDate *) _to
+// {
+//   NSMutableArray *dates;
+//   unsigned       i, count, offset;
+
+//   offset = [_from hourOfDay];
+//   count  = ([_to hourOfDay] + 1) - offset;
+//   dates  = [[NSMutableArray alloc] initWithCapacity:count];
+//   for(i = 0; i < count; i++) {
+//     NSCalendarDate *date;
         
-    date = [_from hour:offset + i minute:0];
-    [dates addObject:date];
-  }
-  return [dates autorelease];
-}
+//     date = [_from hour:offset + i minute:0];
+//     [dates addObject:date];
+//   }
+//   return [dates autorelease];
+// }
 
 /* URLs */
 
   NSString *hmString;
   NSCalendarDate *date;
     
-  date = [self currentDate];
+  date = [self selectedDate];
   hmString = [NSString stringWithFormat:@"%.2d%.2d",
                        [date hourOfDay], [date minuteOfHour]];
   qp = [[self queryParameters] mutableCopy];
   [self setSelectedDateQueryParameter:date inDictionary:qp];
-  [qp setObject:hmString forKey:@"hm"];
+  [qp setObject: hmString forKey:@"hm"];
   return [qp autorelease];
 }
 
   return [[self selectedDate] beginOfDay];
 }
 
-- (NSCalendarDate *) endDate
-{
-  return [[self selectedDate] endOfDay];
-}
-
 /* appointments */
 
-- (NSArray *) appointments
-{
-  return [self fetchCoreAppointmentsInfos];
-}
-
-- (NSArray *)aptsForCurrentDate {
-  NSArray        *apts;
-  NSMutableArray *filtered;
-  unsigned       i, count;
-  NSCalendarDate *start, *end;
-
-  start = self->currentDate;
-  end   = [start dateByAddingYears:0
-                            months:0
-                              days:0
-                             hours:0
-                           minutes:59
-                           seconds:59];
+// - (NSArray *)allDayApts {
+//   NSCalendarDate *start;
+//   NSArray        *apts;
+//   NSMutableArray *filtered;
+//   unsigned       i, count;
   
-  apts     = [self appointments];
-  filtered = [[NSMutableArray alloc] initWithCapacity:1];
-  count    = [apts count];
-  for (i = 0; i < count; i++) {
-    id apt;
-    NSCalendarDate *aptStartDate;
+//   if (self->allDayApts)
+//     return self->allDayApts;
+
+//   start    = [self startDate];
+//   apts     = [self appointments];
+//   filtered = [[NSMutableArray alloc] initWithCapacity:1];
+//   count    = [apts count];
+//   for (i = 0; i < count; i++) {
+//     id       apt;
+//     NSNumber *bv;
     
-    apt = [apts objectAtIndex:i];
-    aptStartDate = [apt valueForKey:@"startDate"];
-    if([aptStartDate isGreaterThanOrEqualTo:start] &&
-       [aptStartDate isLessThan:end])
-    {
-      [filtered addObject:apt];
-    }
-  }
+//     apt = [apts objectAtIndex:i];
+//     bv  = [apt valueForKey:@"isallday"];
+//     if ([bv boolValue]) {
+//       [filtered addObject:apt];
+//     }
+//     else {
+//       NSCalendarDate *aptStartDate;
+
+//       aptStartDate = [apt valueForKey:@"startDate"];
+//       if([aptStartDate isLessThan:start]) {
+//         [filtered addObject:apt];
+//       }
+//     }
+//   }
   
-  return [filtered autorelease];
-}
-
-- (NSArray *)allDayApts {
-  NSCalendarDate *start;
-  NSArray        *apts;
-  NSMutableArray *filtered;
-  unsigned       i, count;
-  
-  if (self->allDayApts)
-    return self->allDayApts;
-
-  start    = [self startDate];
-  apts     = [self appointments];
-  filtered = [[NSMutableArray alloc] initWithCapacity:1];
-  count    = [apts count];
-  for (i = 0; i < count; i++) {
-    id       apt;
-    NSNumber *bv;
-    
-    apt = [apts objectAtIndex:i];
-    bv  = [apt valueForKey:@"isallday"];
-    if ([bv boolValue]) {
-      [filtered addObject:apt];
-    }
-    else {
-      NSCalendarDate *aptStartDate;
-
-      aptStartDate = [apt valueForKey:@"startDate"];
-      if([aptStartDate isLessThan:start]) {
-        [filtered addObject:apt];
-      }
-    }
-  }
-  
-  ASSIGN(self->allDayApts, filtered);
-  [filtered release];
-  return self->allDayApts;
-}
-
-- (BOOL) hasAptsForCurrentDate
-{
-  return [[self aptsForCurrentDate] count] != 0;
-}
+//   ASSIGN(self->allDayApts, filtered);
+//   [filtered release];
+//   return self->allDayApts;
+// }
+
+// - (BOOL) hasAptsForCurrentDate
+// {
+//   return [[self aptsForCurrentDate] count] != 0;
+// }
 
 - (NSString *) _dayNameWithOffsetFromToday: (int) offset
 {
index fc2bcad5ff58cb579e992911c75764d2e375956f..80b66f66d643de14a889d0490b4521183bc4fce4 100644 (file)
@@ -114,78 +114,4 @@ static NSMutableArray *yearMenuItems = nil;
   return self;
 }
 
-- (id <WOActionResults>) updateCalendarsAction
-{
-  WOResponse *response;
-  NSUserDefaults *ud;
-
-  ud = [[context activeUser] userDefaults];
-  [ud setObject: [self queryParameterForKey: @"ids"]
-                       forKey: @"calendaruids"];
-  [ud synchronize];
-  response = [context response];
-  [response setStatus: 200];
-  [response setHeader: @"text/html; charset=\"utf-8\"" forKey: @"content-type"];
-
-  return response;
-}
-
-- (NSString *) _rightsForUIDs: (NSString *) uids
-{
-  NSEnumerator *ids;
-  NSString *uid;
-  NSMutableString *rights;
-  SOGoAppointmentFolder *refFolder, *currentFolder;
-  SoSecurityManager *securityManager;
-  BOOL result;
-
-  securityManager = [SoSecurityManager sharedSecurityManager];
-  refFolder = [self clientObject];
-
-  rights = [NSMutableString string];
-  if ([uids length] > 0)
-    {
-      ids = [[uids componentsSeparatedByString: @","] objectEnumerator];
-      uid = [ids nextObject];
-      while (uid)
-        {
-          currentFolder
-            = [refFolder
-                lookupCalendarFolderForUID: (([uid hasPrefix: @"-"])
-                                             ? [uid substringFromIndex: 1]
-                                             : uid)];
-          result = (![securityManager validatePermission: SoPerm_AccessContentsInformation
-                                      onObject: currentFolder
-                                      inContext: context]);
-          if ([rights length] == 0)
-            [rights appendFormat: @"%d", result];
-          else
-            [rights appendFormat: @",%d", result];
-          uid = [ids nextObject];
-        }
-    }
-
-  return rights;
-}
-
-- (id <WOActionResults>) checkRightsAction
-{
-  WOResponse *response;
-  NSUserDefaults *ud;
-  NSString *uids, *rights;
-
-  ud = [[context activeUser] userDefaults];
-  uids = [ud stringForKey: @"calendaruids"];
-
-  response = [context response];
-  [response setStatus: 200];
-  [response setHeader: @"text/plain; charset=\"utf-8\""
-            forKey: @"content-type"];
-
-  rights = [self _rightsForUIDs: uids];
-  [response appendContentString: rights];
-
-  return response;
-}
-
 @end
diff --git a/UI/Scheduler/UIxCalScheduleOverview.m b/UI/Scheduler/UIxCalScheduleOverview.m
deleted file mode 100644 (file)
index 5fe7a0f..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- Copyright (C) 2004 SKYRIX Software AG
- 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
- Free Software Foundation; either version 2, or (at your option) any
- later version.
- OGo 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 Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING.  If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
- */
-
-#include <SOGoUI/UIxComponent.h>
-
-@class NSMutableArray;
-
-@interface UIxCalScheduleOverview : UIxComponent
-{
-  NSMutableArray *userApts;
-  NSMutableArray *foreignApts;
-  id             item;
-  NSMutableArray *partNames;
-  NSMutableArray *partStates;
-  NSString       *userParticipationStatus;
-  unsigned       participantIndex;
-  unsigned       userIndex;
-}
-
-- (NSCalendarDate *)startDate;
-- (NSCalendarDate *)endDate;
-
-- (NSArray *)userAppointments;
-- (NSArray *)foreignAppointments;
-
-- (BOOL)hasUserAppointments;
-- (BOOL)hasForeignAppointments;
-- (BOOL)hasAnyAppointments;
-
-- (void)fetchInfos;
-
-- (NSString *)appointmentBaseURL;
-
-- (unsigned)participantsCount;
-- (unsigned)maxRenderedParticipantsCount;
-- (unsigned)renderedParticipantsCount;
-- (unsigned)truncatedParticipantsCount;
-- (BOOL)didTruncateParticipants;
-
-- (NSString *)getUserPartStateFromApt:(id)_apt;
-
-- (BOOL)shouldIgnoreRejectedAppointments;
-- (BOOL)shouldIgnoreAcceptedAppointments;
-- (BOOL)shouldShowRejectedAndAcceptedAppointments;
-  
-@end
-
-#include <NGObjWeb/SoComponent.h>
-#include "UIxComponent+Agenor.h"
-#include "SoObjects/Appointments/SOGoAppointmentFolder.h"
-#include "common.h"
-
-@implementation UIxCalScheduleOverview
-
-- (void)dealloc {
-  [self->userApts                release];
-  [self->foreignApts             release];
-  [self->item                    release];
-  [self->partNames               release];
-  [self->partStates              release];
-  [self->userParticipationStatus release];
-  [super dealloc];
-}
-
-
-/* accessors */
-
-- (void)setItem:(id)_item {
-  NSString *ps, *email;
-  NSArray  *partmails;
-  unsigned idx;
-  
-  ASSIGN(self->item, _item);
-
-  [self->partNames  release];
-  [self->partStates release];
-  ps               = [self->item valueForKey:@"participants"];
-  self->partNames  = [[ps componentsSeparatedByString:@"\n"] mutableCopy];
-  ps               = [self->item valueForKey:@"partstates"];
-  self->partStates = [[ps componentsSeparatedByString:@"\n"] mutableCopy];
-  ps               = [self->item valueForKey:@"partmails"];
-  partmails        = [ps componentsSeparatedByString:@"\n"];
-
-  /* reorder partNames/partStates */
-  
-  /* ensure organizer is first entry */
-  email = [self->item valueForKey:@"orgmail"];
-  if ([email isNotNull]) {
-    idx = [partmails indexOfObject:email];
-    if (idx != NSNotFound && idx != 0) {
-      id obj;
-
-      obj = [self->partNames objectAtIndex:idx];
-      [self->partNames insertObject:obj atIndex:0]; /* frontmost */
-      [self->partNames removeObjectAtIndex:idx + 1];
-      obj = [self->partStates objectAtIndex:idx];
-      [self->partStates insertObject:obj atIndex:0]; /* frontmost */
-      [self->partStates removeObjectAtIndex:idx + 1];
-    }
-  }
-  /* user is either second, first or none at all */
-  [self->userParticipationStatus release];
-  email     = [self emailForUser];
-  idx       = [partmails indexOfObject:email];
-  if (idx != NSNotFound && idx != 0 && idx != 1) {
-    id obj;
-
-    self->userIndex = 1;
-    obj = [self->partNames objectAtIndex:idx];
-    [self->partNames insertObject:obj atIndex:self->userIndex]; /* second */
-    [self->partNames removeObjectAtIndex:idx + 1];
-    obj = [self->partStates objectAtIndex:idx];
-    [self->partStates insertObject:obj atIndex:self->userIndex]; /* second */
-    [self->partStates removeObjectAtIndex:idx + 1];
-  }
-  else {
-    self->userIndex = idx;
-  }
-  if (self->userIndex != NSNotFound)
-    self->userParticipationStatus =
-      [[self->partStates objectAtIndex:self->userIndex] retain];
-  else
-    self->userParticipationStatus = nil;
-}
-- (id)item {
-  return self->item;
-}
-
-- (void)setParticipantIndex:(unsigned)_participantIndex {
-  self->participantIndex = _participantIndex;
-}
-- (unsigned)participantIndex {
-  return self->participantIndex;
-}
-
-- (unsigned)userIndex {
-  return self->userIndex;
-}
-
-- (BOOL)isFirstParticipant {
-  return self->participantIndex == 0 ? YES : NO;
-}
-
-- (BOOL)hasUserAppointments {
-  // NOTE: this has been disabled for Agenor 0.8 on client's request
-#if 1
-  return NO;
-#else
-  return [[self userAppointments] count] > 0;
-#endif
-}
-- (BOOL)hasForeignAppointments {
-  return [[self foreignAppointments] count] > 0;
-}
-- (BOOL)hasAnyAppointments {
-  return ([self hasUserAppointments] ||
-          [self hasForeignAppointments]) ? YES : NO;
-}
-
-- (unsigned)participantsCount {
-  return [self->partNames count];
-}
-
-- (NSString *)participant {
-  return [self->partNames objectAtIndex:self->participantIndex];
-}
-
-- (NSString *)participationStatus {
-  return [self->partStates objectAtIndex:self->participantIndex];
-}
-
-- (unsigned)maxRenderedParticipantsCount {
-  return 3;
-}
-
-- (unsigned)renderedParticipantsCount {
-  if ([self didTruncateParticipants])
-    return [self maxRenderedParticipantsCount];
-  return [self participantsCount];
-}
-
-- (unsigned)truncatedParticipantsCount {
-  return [self participantsCount] - [self renderedParticipantsCount];
-}
-
-- (BOOL)didTruncateParticipants {
-  return [self participantsCount] >
-         ([self maxRenderedParticipantsCount] + 1) ? YES : NO;
-}
-
-- (unsigned)rowspan {
-  unsigned count;
-  
-  count = [self renderedParticipantsCount];
-  if ([self didTruncateParticipants])
-    count += 1;
-  return count;
-}
-
-- (NSString *)userParticipationStatus {
-  return self->userParticipationStatus;
-}
-
-- (BOOL)shouldIgnoreRejectedAppointments {
-  return ![self shouldShowRejectedAndAcceptedAppointments];
-}
-
-- (BOOL)shouldIgnoreAcceptedAppointments {
-  return ![self shouldShowRejectedAndAcceptedAppointments];
-}
-
-- (BOOL)shouldShowRejectedAndAcceptedAppointments {
-  NSString *value;
-  
-  value = [[[self context] request] formValueForKey:@"dr"];
-  if (!value) return NO;
-  return [value boolValue];
-}
-
-- (NSString *)toggleShowHideAptsQueryParameter {
-  BOOL shouldShow;
-  
-  shouldShow = [self shouldShowRejectedAndAcceptedAppointments];
-  return shouldShow ? @"0" : @"1";
-}
-
-- (NSString *)toggleShowHideAptsText {
-  if ([self shouldShowRejectedAndAcceptedAppointments])
-    return @"Hide already accepted and rejected appointments";
-  return @"Show already accepted and rejected appointments";
-}
-
-
-- (NSString *)getUserPartStateFromApt:(id)_apt {
-  NSString *email;
-  NSArray  *ps, *pms;
-  unsigned idx;
-
-  email = [self emailForUser];
-  pms   = [[_apt valueForKey:@"partmails"]
-                 componentsSeparatedByString:@"\n"];
-  idx   = [pms indexOfObject:email];
-  if (idx == NSNotFound) return nil;
-  ps    = [[_apt valueForKey:@"partstates"]
-                 componentsSeparatedByString:@"\n"];
-  return [ps objectAtIndex:idx];
-}
-
-
-/* fetching */
-
-- (NSCalendarDate *)startDate {
-  return [[NSCalendarDate date] beginOfDay];
-}
-
-/* ZNeK: is a month ok? */
-- (NSCalendarDate *)endDate {
-  NSCalendarDate *date;
-  
-  date = [NSCalendarDate date];
-  date = [date dateByAddingYears:0 months:1 days:0
-                           hours:0 minutes:0 seconds:0];
-  date = [date endOfDay];
-  return date;
-}
-
-- (NSArray *)userAppointments {
-  if (!self->userApts) {
-    [self fetchInfos];
-  }
-  return self->userApts;
-}
-
-- (NSArray *)foreignAppointments {
-  if (!self->foreignApts) {
-    [self fetchInfos];
-  }
-  return self->foreignApts;
-}
-
-- (void) fetchInfos {
-  static NSArray *orders = nil;
-  id       aptFolder;
-  NSArray  *apts;
-  NSString *userEmail;
-  unsigned i, count;
-
-  if (!orders) {
-    EOSortOrdering *so;
-    so     = [EOSortOrdering sortOrderingWithKey:@"startDate"
-                             selector:EOCompareAscending];
-    orders = [[NSArray alloc] initWithObjects:so, nil];
-  }
-
-  aptFolder = [self clientObject];
-  apts      = [aptFolder fetchCoreInfosFrom: [self startDate]
-                         to: [self endDate]
-                         component: @"vevent"];
-  userEmail = [self emailForUser];
-  count     = [apts count];
-
-  self->userApts    = [[NSMutableArray alloc] initWithCapacity:count];
-  self->foreignApts = [[NSMutableArray alloc] initWithCapacity:count];
-
-  for (i = 0; i < count; i++) {
-    id       apt;
-    NSString *orgEmail;
-
-    apt      = [apts objectAtIndex:i];
-    orgEmail = [(NSDictionary *)apt objectForKey:@"orgmail"];
-    if (orgEmail && [orgEmail isEqualToString:userEmail]) {
-      [self->userApts addObject:apt];
-    }
-    else {
-      BOOL shouldAdd = YES;
-
-      if ([self shouldIgnoreAcceptedAppointments] ||
-          [self shouldIgnoreRejectedAppointments])
-      {
-        NSString *userPartStat;
-
-        userPartStat = [self getUserPartStateFromApt:apt];
-        if (userPartStat) {
-          if ([self shouldIgnoreAcceptedAppointments] &&
-              [userPartStat isEqualToString:@"1"])
-            shouldAdd = NO;
-          else if ([self shouldIgnoreRejectedAppointments] &&
-                   [userPartStat isEqualToString:@"2"])
-            shouldAdd = NO;
-        }
-      }
-      if (shouldAdd)
-        [self->foreignApts addObject:apt];
-    }
-  }
-  [self->userApts    sortUsingKeyOrderArray:orders];
-  [self->foreignApts sortUsingKeyOrderArray:orders];
-}
-
-
-/* URLs */
-
-- (NSString *)appointmentBaseURL {
-  id pkey;
-  
-  if (![(pkey = [self->item valueForKey:@"uid"]) isNotNull])
-    return nil;
-  
-  return [[self clientObject] baseURLForAptWithUID:[pkey stringValue]
-                              inContext:[self context]];
-}
-- (NSString *)appointmentViewURL {
-  return [[self appointmentBaseURL] stringByAppendingPathComponent:@"view"];
-}
-- (NSString *)acceptAppointmentURL {
-  return [[self appointmentBaseURL] stringByAppendingPathComponent:@"accept"];
-}
-- (NSString *)declineAppointmentURL {
-  return [[self appointmentBaseURL] stringByAppendingPathComponent:@"decline"];
-}
-
-
-/* access protection */
-
-- (BOOL)canAccess {
-  NSString *owner;
-  
-  owner = [[self clientObject] ownerInContext:[self context]];
-  if (!owner)
-    return NO;
-  return [[[[self context] activeUser] login] isEqualToString:owner];
-}
-
-@end
index 9446c0ade67aafd84e8bee3344c24adcc1e176cc..4b2eeb10c3aecbc6443acea7b63138b335c910aa 100644 (file)
@@ -18,6 +18,7 @@
 @interface UIxCalView : UIxComponent
 {
   NSArray          *appointments;
+  NSMutableArray *calendarFolders;
   NSMutableDictionary *componentsData;
   NSArray          *tasks;
   NSArray          *allDayApts;
index 74b683280949d9153a5c5db412cb1745015e788f..11047344f9fe191bbbdc26faefb81aa0bf09b2e9 100644 (file)
@@ -56,12 +56,15 @@ static BOOL shouldDisplayWeekend = NO;
         = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: tz];
       [self configureFormatters];
       componentsData = [NSMutableDictionary new];
+      calendarFolders = nil;
     }
+
   return self;
 }
 
 - (void) dealloc
 {
+  [calendarFolders release];
   [componentsData release];
   [appointments               release];
   [allDayApts                 release];
@@ -446,37 +449,120 @@ static BOOL shouldDisplayWeekend = NO;
   return [[self startDate] tomorrow];
 }
 
-- (NSArray *) activeCalendarFolders
+#warning We only support ONE calendar per user at this time
+- (BOOL) _appendSubscribedFolders: (NSDictionary *) subscribedFolders
 {
-  NSUserDefaults *ud;
-  NSEnumerator *calendarUIDs;
-  SOGoAppointmentFolder *currentFolder;
-  NSMutableArray *folders;
-  NSString *currentUID;
-  SoSecurityManager *securityManager;
-
-  securityManager = [SoSecurityManager sharedSecurityManager];
-
-  folders = [NSMutableArray array];
-  ud = [[context activeUser] userDefaults];
-  calendarUIDs = [[[ud stringForKey: @"calendaruids"]
-                    componentsSeparatedByString: @","] objectEnumerator];
-  currentUID = [calendarUIDs nextObject];
-  while (currentUID)
+  NSEnumerator *keys;
+  NSString *currentKey;
+  NSMutableDictionary *currentCalendar;
+  BOOL firstShouldBeActive;
+  unsigned int count;
+
+  firstShouldBeActive = YES;
+
+  keys = [[subscribedFolders allKeys] objectEnumerator];
+  currentKey = [keys nextObject];
+  count = 1;
+  while (currentKey)
     {
-      if (![currentUID hasPrefix: @"-"])
-        {
-          currentFolder = [[self clientObject] lookupCalendarFolderForUID: currentUID];
-          if (currentFolder
-              && ![securityManager validatePermission: SoPerm_AccessContentsInformation
-                                   onObject: currentFolder
-                                   inContext: context])
-            [folders addObject: currentFolder];
-        }
-      currentUID = [calendarUIDs nextObject];
+      currentCalendar = [NSMutableDictionary new];
+      [currentCalendar autorelease];
+      [currentCalendar
+       setDictionary: [subscribedFolders objectForKey: currentKey]];
+      [currentCalendar setObject: currentKey forKey: @"folder"];
+      [calendarFolders addObject: currentCalendar];
+      if ([[currentCalendar objectForKey: @"active"] boolValue])
+       firstShouldBeActive = NO;
+      count++;
+      currentKey = [keys nextObject];
+    }
+
+  return firstShouldBeActive;
+}
+
+- (void) _setupCalendarFolders
+{
+  NSMutableDictionary *userCalendar, *calendarDict;
+  SOGoUser *activeUser;
+  BOOL firstActive;
+
+  calendarFolders = [NSMutableArray new];
+  activeUser = [context activeUser];
+
+  userCalendar = [NSMutableDictionary new];
+  [userCalendar autorelease];
+  [userCalendar setObject: @"/" forKey: @"folder"];
+  [userCalendar setObject: [self labelForKey: @"Calendar"]
+                  forKey: @"displayName"];
+  [calendarFolders addObject: userCalendar];
+
+  calendarDict = [[activeUser userSettings] objectForKey: @"Calendar"];
+  firstActive = [[calendarDict objectForKey: @"activateUserFolder"] boolValue];
+  firstActive = ([self _appendSubscribedFolders:
+                        [calendarDict objectForKey: @"SubscribedFolders"]]
+                || firstActive);
+  [userCalendar setObject: [NSNumber numberWithBool: firstActive]
+               forKey: @"active"];
+}
+
+- (SOGoAppointmentFolder *) _aptFolder: (NSString *) folder
+                     withClientObject: (SOGoAppointmentFolder *) clientObject
+{
+  SOGoAppointmentFolder *aptFolder;
+  NSArray *folderParts;
+
+  if ([folder isEqualToString: @"/"])
+    aptFolder = clientObject;
+  else
+    {
+      folderParts = [folder componentsSeparatedByString: @":"];
+      aptFolder
+       = [clientObject lookupCalendarFolderForUID:
+                         [folderParts objectAtIndex: 0]];
+    }
+
+  return aptFolder;
+}
+
+- (NSArray *) calendarFolders
+{
+  if (!calendarFolders)
+    [self _setupCalendarFolders];
+
+  return calendarFolders;
+}
+
+- (NSArray *) _activeCalendarFolders
+{
+  NSMutableArray *activeFolders;
+  NSEnumerator *folders;
+  NSDictionary *currentFolderDict;
+  SOGoAppointmentFolder *currentFolder, *clientObject;
+
+  activeFolders = [NSMutableArray new];
+  [activeFolders autorelease];
+
+  if (!calendarFolders)
+    [self _setupCalendarFolders];
+
+  clientObject = [self clientObject];
+
+  folders = [calendarFolders objectEnumerator];
+  currentFolderDict = [folders nextObject];
+  while (currentFolderDict)
+    {
+      if ([[currentFolderDict objectForKey: @"active"] boolValue])
+       {
+         currentFolder
+           = [self _aptFolder: [currentFolderDict objectForKey: @"folder"]
+                   withClientObject: clientObject];
+         [activeFolders addObject: currentFolder];
+       }
+
+      currentFolderDict = [folders nextObject];
     }
 
-  return folders;
+  return activeFolders;
 }
 
 - (NSArray *) _fetchCoreInfosForComponent: (NSString *) component
@@ -490,7 +576,7 @@ static BOOL shouldDisplayWeekend = NO;
   if (!infos)
     {
       infos = [NSMutableArray array];
-      folders = [[self activeCalendarFolders] objectEnumerator];
+      folders = [[self _activeCalendarFolders] objectEnumerator];
       currentFolder = [folders nextObject];
       while (currentFolder)
         {
index 03479b99124850c4f362e8e6da514bfecf6ca683..1b8c8d7d63c4355be0c6edaf9818c871cbd5a8f2 100644 (file)
                      inContext: (WOContext *) _ctx
 {
   NSCalendarDate *now;
+  SOGoCalendarComponent *clientObject;
 
   [super takeValuesFromRequest: _rq inContext: _ctx];
 
   [component setUrl: url];
   [self _handleAttendeesEdition];
   [self _handleOrganizer];
-  if ([[self clientObject] isNew])
+  clientObject = [self clientObject];
+  if ([clientObject isNew])
     {
+      [component setUid: [clientObject nameInContainer]];
       [component setCreated: now];
       [component setTimeStampAsDate: now];
       [component setPriority: @"0"];
index d4330911ac77ea6fc7e5ecdc7c52f944e74f51dd..4a34ac6bd36a20d7263f54b6587ab33b5991e70d 100644 (file)
       else
        {
          [todo setCompleted: nil];
-         [todo setPercentComplete: 0];
+         [todo setPercentComplete: @"0"];
          [todo setStatus: @"IN-PROCESS"];
        }
 
index 8b9b78fbd6dedad0ada1749eaa77693ab97884aa..c96c9bfc4f82530521ffb41d0b086ebf9ee491ba 100644 (file)
@@ -1,5 +1,5 @@
 {
-  requires = ( MAIN, CommonUI, Appointments, Contacts, ContactsUI );
+  requires = ( MAIN, MainUI, CommonUI, Appointments, Contacts, ContactsUI );
 
   publicResources = (
     previous_week.gif,
           pageName    = "UIxCalMainView";
           actionName  = "updateCalendars";
         };
-        checkRights = {
-          protectedBy = "View";
-          pageName    = "UIxCalMainView";
-          actionName  = "checkRights";
-        };
         editAttendees = {
           protectedBy = "View";
           pageName    = "UIxAttendeesEditor";
diff --git a/UI/Templates/ContactsUI/UIxContactsAclsSelection.wox b/UI/Templates/ContactsUI/UIxContactsAclsSelection.wox
deleted file mode 100644 (file)
index 7a106ac..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version='1.0' standalone='yes'?>
-  <div
-    xmlns="http://www.w3.org/1999/xhtml"
-    xmlns:var="http://www.skyrix.com/od/binding"
-    xmlns:const="http://www.skyrix.com/od/constant"
-    xmlns:uix="OGo:uix"
-    xmlns:label="OGo:label"
-    xmlns:rsrc="OGo:url"
-    class="calendar"
-    >
-    <input type="submit"
-      class="button"
-      label:value="Add Assistant"
-      name="validate"
-      onclick="return onConfirmContactSelection('assistant');" /><br />
-    <input type="submit"
-      class="button"
-      label:value="Add Delegate"
-      name="validate"
-      onclick="return onConfirmContactSelection('delegate');" />
-  </div>
diff --git a/UI/Templates/ContactsUI/UIxContactsAddressBooksSelection.wox b/UI/Templates/ContactsUI/UIxContactsAddressBooksSelection.wox
deleted file mode 100644 (file)
index daf472d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version='1.0' standalone='yes'?>
-  <div
-    xmlns="http://www.w3.org/1999/xhtml"
-    xmlns:var="http://www.skyrix.com/od/binding"
-    xmlns:const="http://www.skyrix.com/od/constant"
-    xmlns:uix="OGo:uix"
-    xmlns:label="OGo:label"
-    xmlns:rsrc="OGo:url"
-    class="calendar"
-    >
-    <input type="submit"
-      class="button"
-      label:value="Add Address Book..."
-      name="validate"
-      onclick="return onConfirmAddressBookSelection();" />
-  </div>
diff --git a/UI/Templates/ContactsUI/UIxContactsCalendarsSelection.wox b/UI/Templates/ContactsUI/UIxContactsCalendarsSelection.wox
deleted file mode 100644 (file)
index 06888b3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version='1.0' standalone='yes'?>
-  <div
-    xmlns="http://www.w3.org/1999/xhtml"
-    xmlns:var="http://www.skyrix.com/od/binding"
-    xmlns:const="http://www.skyrix.com/od/constant"
-    xmlns:uix="OGo:uix"
-    xmlns:label="OGo:label"
-    xmlns:rsrc="OGo:url"
-    class="calendar"
-    >
-    <input type="submit"
-      class="button"
-      label:value="Add Calendar..."
-      name="validate"
-      onclick="return onConfirmContactSelection(null);" />
-  </div>
index 54614dc0170a2434bec09811c16fd0acfccc1ca9..916ce36c408992c3529cdf5d5e82a4a76f0e6901 100644 (file)
@@ -16,7 +16,9 @@
     <div id="filterPanel">
       <span class="searchBox" style="float: right">
         <input id="searchCriteria" name="criteria" type="hidden" var:value="searchCriteria" />
-        <input id="searchValue" class="textField" autocomplete="off" name="search" type="text" var:value="searchText" onmousedown="onSearchMouseDown(event, this);" onclick="popupSearchMenu(event, 'searchMenu');" onblur="onSearchBlur(this);" onfocus="onSearchFocus(this);" onkeydown="onSearchKeyDown(this);" />
+        <input id="searchValue" class="textField" autocomplete="off" name="search"
+         menuid="searchMenu"
+         type="text" var:value="searchText" />
       </span>
     </div>
   </container>
index ca5c54bf872344864c2bd20762cfcf71f4aed7bf..45d90f3b5d388f73bcbe4a3986c43335679deafa 100644 (file)
                /></span></a
            ></div><!-- var:if -->
 
-       <ul id="contactFolders"
-         var:additional-addressbooks="additionalAddressBooks">
+       <ul id="contactFolders">
          <var:foreach list="contactFolders" item="currentFolder"
-           ><var:if condition="isFolderCurrent"
-             ><li var:id="currentContactFolderId" class="_selected"
-               ><var:string value="currentContactFolderName" /></li
-               ></var:if
-             ><var:if condition="isFolderCurrent" const:negate="YES"
-             ><li var:id="currentContactFolderId"
-               ><var:string value="currentContactFolderName" /></li
-               ></var:if>
-         </var:foreach
+           ><li var:id="currentContactFolderId"
+              ><var:string value="currentContactFolderName" /></li
+             ></var:foreach
            ><var:foreach list="additionalFolders"
            item="currentAdditionalFolder"
-           ><li var:id="currentAdditionalFolder"
-             var:external-addressbook="currentAdditionalFolder"
-             ><var:string value="currentAdditionalFolder" /></li
+           ><li var:id="currentAdditionalFolder" class="denied"
+             ><var:string value="currentAdditionalFolderName" /></li
              ></var:foreach>
        </ul>
 
   <var:if condition="hideFrame">
     <var:component-content />
   </var:if>
-
-  <script type="text/javascript">
-    currentContactFolder = '<var:string value="contactFolderId" />';
-  </script>
 </var:component>
index a6e1c1b36d875e7e2a8f22ba37d3fc0ab6cfe2da..7b391ccbae8764c3d9b97d8b5f5ed3d04c980f59 100644 (file)
@@ -1,26 +1,24 @@
 <?xml version='1.0' standalone='yes'?>
-  <span
-    xmlns="http://www.w3.org/1999/xhtml"
-    xmlns:var="http://www.skyrix.com/od/binding"
-    xmlns:const="http://www.skyrix.com/od/constant"
-    xmlns:uix="OGo:uix"
-    xmlns:label="OGo:label"
-    xmlns:rsrc="OGo:url"
-    >
-    <span id="selectionLabel"><var:string label:value="Add as..." /></span><br />
-    <input type="submit"
+<!DOCTYPE span>
+<span
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:var="http://www.skyrix.com/od/binding"
+  xmlns:const="http://www.skyrix.com/od/constant"
+  xmlns:uix="OGo:uix"
+  xmlns:label="OGo:label"
+  xmlns:rsrc="OGo:url"
+  id="contactSelectionButtons">
+  <span id="selectionLabel"><var:string label:value="Add as..."/></span><br/>
+  <input type="submit"
+    class="button"
+    label:value="Recipient"
+    name="to"/><br/>
+  <input type="submit"
       class="button"
-      label:value="Recipient"
-      name="to"
-      onclick="return onConfirmContactSelection('to');" /><br />
-    <input type="submit"
-      class="button"
-      label:value="Carbon Copy"
-      name="cc"
-      onclick="return onConfirmContactSelection('cc');" /><br />
-    <input type="submit"
-      class="button"
-      label:value="Blind Carbon Copy"
-      name="bcc"
-      onclick="return onConfirmContactSelection('bcc');" />
-  </span>
+    label:value="Carbon Copy"
+    name="cc"/><br/>
+  <input type="submit"
+    class="button"
+    label:value="Blind Carbon Copy"
+    name="bcc"/>
+</span>
diff --git a/UI/Templates/ContactsUI/UIxContactsUserFolders.wox b/UI/Templates/ContactsUI/UIxContactsUserFolders.wox
new file mode 100644 (file)
index 0000000..b6b95e6
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version='1.0' standalone='yes'?>
+<!DOCTYPE var:component>
+<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:uix="OGo:uix"
+  xmlns:label="OGo:label"
+  className="UIxPageFrame"
+  title="name"
+  const:toolbar="none"
+  const:popup="YES">
+  <script type="text/javascript" rsrc:src="dtree.js"><!-- space --></script>
+  <var:component className="UIxContactsFilterPanel" qualifier="qualifier" />
+  <div id="folders">
+  </div>
+  <div id="buttons">
+    <input type="submit" id="addButton" class="button" label:value="Add..."/>
+  </div>
+</var:component>
index c3647767211e961fe5d27d4b488d1942a45b04b5..349b5c0bf1202465a1687f284085f92ea0e39ae7 100644 (file)
           <input id="searchValue"
             class="textField"
             autocomplete="off" name="search" type="text" var:value="searchText"
-            onmousedown="onSearchMouseDown(event, this);"
-            onclick="popupSearchMenu(event, 'searchMenu');"
-            onchange="onSearchChange();"
-            onblur="onSearchBlur(this);"
-            onfocus="onSearchFocus(this);"
-            onkeydown="onSearchKeyDown(this);" />
+           menuid="searchMenu" />
         </span>
 
         <var:string label:value="View:" />
diff --git a/UI/Templates/SchedulerUI/UIxCalBackForthNavView.wox b/UI/Templates/SchedulerUI/UIxCalBackForthNavView.wox
deleted file mode 100644 (file)
index d8bc655..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version='1.0' standalone='yes'?>
-
-<table 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"
-       border="0"
- >
-    <tr>
-        <td align="right" valign="middle">
-            <a var:href="^methodName" var:queryDictionary="^prevQueryParameters"><img rsrc:src="previous_week.gif" alt="previous" border="0"/></a>
-        </td>
-        <td align="right" valign="middle" class="button_auto_env">
-            <a var:href="^methodName" var:queryDictionary="^currentQueryParameters" class="button_auto"><var:string value="^label" /></a>
-        </td>
-        <td align="right" valign="middle">
-            <a var:href="^methodName" var:queryDictionary="^nextQueryParameters"><img rsrc:src="next_week.gif" alt="next" border="0"/></a>
-        </td>
-    </tr>
-</table>
diff --git a/UI/Templates/SchedulerUI/UIxCalCalendarsListView.wox b/UI/Templates/SchedulerUI/UIxCalCalendarsListView.wox
deleted file mode 100644 (file)
index 24d547b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" standalone="yes"?>
-  <container
-    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">
-    <style type="text/css">
-      <var:foreach list="contacts" item="currentContactPerson">
-      .ownerIs<var:string value="currentContactLogin" />
-      {
-        background-color: <var:string value="currentContactSpanBG" /> !important;
-      }
-      </var:foreach>
-    </style>
-    <var:component className="UIxContactSelector"
-      const:selectorId="calendarsList"
-      const:hasCheckBoxes="YES"
-      colors="colors"
-      contacts="contacts"
-      checkedBoxes="checkedContacts"
-      />
-  </container>
index 42022b7d5483c5dd9c0b10a4e86966ebfa64ba45..15662a4c3f417beee272ee94e4d2de6cdf60eb80 100644 (file)
@@ -43,7 +43,8 @@
         <var:foreach list="daysToDisplay" item="currentTableDay"
           ><div var:class="dayClasses"
             var:day="currentTableDay.shortDateString"
-            ><div class="header"><var:string value="labelForDay" /></div>
+            ><div class="header"><var:string value="labelForDay"
+               const:escapeHTML="NO"/></div>
             <div class="appointments">
             <var:foreach list="hoursToDisplay" item="currentTableHour"
               ><div var:class="clickableHourCellClass"
index b1bd4da03b67c642dca695036173ffc80344f7ba..44c03cadeb46d2d18298993eb860ae8ddb271018 100644 (file)
         <input id="searchValue"
           class="textField"
           autocomplete="off" name="search" type="text" var:value="searchText"
-          onmousedown="onSearchMouseDown(event, this);"
-          onclick="popupSearchMenu(event, 'searchMenu');"
-          onchange="onSearchChange();"
-          onblur="onSearchBlur(this);"
-          onfocus="onSearchFocus(this);"
-          onkeydown="onSearchKeyDown(this);" />
+         menuid="searchMenu" />
       </span>
 
       <var:string label:value="View:" />
index ec44153e8dad187f561562c354d64122cf574ea5..a0c4675b826aacbf04ee9e3eb4e300baab646468 100644 (file)
           ><var:component className="UIxCalDateSelector"
             selectedDate="thisMonth"
             /></div>
-        <div id="calendarSelectorView"
-          class="tab"
-          ><var:component className="UIxCalCalendarsListView"
-            /></div>
+        <div id="calendarSelectorView" class="tab"
+          ><var:component className="UIxCalendarSelector"
+           var:calendarFolders="calendarFolders" /></div>
       </div>
 
       <div id="tasksListView"
diff --git a/UI/Templates/SchedulerUI/UIxCalScheduleOverview.wox b/UI/Templates/SchedulerUI/UIxCalScheduleOverview.wox
deleted file mode 100644 (file)
index d06013d..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-<?xml version='1.0' standalone='yes'?>
-
-<span 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"
->
-  <table border="0"
-         width="100%"
-         cellpadding="2"
-         cellspacing="0"
-         class="schedoverview"
-  >
-    <tr>
-      <th colspan="5" class="schedoverview titlefont titleheader">
-        <var:string label:value="Schedule"/>
-        <var:string value="startDate" label:dateformat="dayLabelFormat" /> -
-        <var:string value="endDate" label:dateformat="dayLabelFormat" />
-      </th>
-      <!-- TODO: maybe enable this at a later stage
-      <th colspan="2"
-          class="titleheader button_auto_env defaultfont buttonheader">
-        <a var:href="ownMethodName"
-             var:queryDictionary="context.request.formValues"
-             var:_dr="toggleShowHideAptsQueryParameter"
-             class="button_auto"
-          ><var:string label:value="$toggleShowHideAptsText"
-           /></a>
-      </th>
-      -->
-    </tr>
-    <var:if condition="hasAnyAppointments" const:negate="YES">
-      <tr>
-        <td colspan="5">
-          <var:string label:value="No appointments found"
-                      const:style="schedoverview"
-          />
-        </td>
-      </tr>
-    </var:if>
-    <var:if condition="hasAnyAppointments">
-      <var:if condition="hasUserAppointments">
-        <tr>
-          <!-- meetings proposed by user -->
-          <th colspan="5" class="schedoverview_title">
-            <var:string label:value="Meetings proposed by you" />
-          </th>
-        </tr>
-        <tr>
-          <th class="schedoverview"
-          ><var:string label:value="Start date" /></th>
-          <th class="schedoverview"
-          ><var:string label:value="Title" /></th>
-          <th class="schedoverview"
-              colspan="2"
-          ><var:string label:value="participants"/></th>
-        </tr>
-        <var:foreach list="userAppointments"
-                     item="item"
-        >
-          <var:foreach count="renderedParticipantsCount"
-                       index="participantIndex"
-          >
-            <tr>
-              <var:if condition="isFirstParticipant">  
-                <td class="schedoverview"
-                    var:rowspan="rowspan"
-                >
-                  <var:string value="item.startDate"
-                              label:dateformat="sched_startDateFormat"
-                  />
-                </td>
-                <td class="schedoverview"
-                    var:rowspan="rowspan"
-                >
-                  <a var:href="appointmentViewURL"
-                     class="schedoverview"
-                  ><var:string value="item.title"
-                               const:escapeHTML="YES"
-                   /></a>
-                </td>
-              </var:if>
-              <td class="schedoverview">
-                <var:string value="participant" />
-              </td>
-              <td class="schedoverview">
-                <var:component className="UIxCalParticipationStatusView"
-                               partStat="participationStatus"
-                />
-              </td>
-            </tr>
-          </var:foreach>
-          <var:if condition="didTruncateParticipants">
-            <tr>
-              <td colspan="2" class="schedoverview">
-                <a var:href="appointmentViewURL"
-                   class="schedoverview"
-                ><var:string value="truncatedParticipantsCount" />
-                <var:string label:value="more participants" />...
-                </a>
-              </td>
-            </tr>
-          </var:if>
-        </var:foreach>
-      </var:if>
-      <var:if condition="hasForeignAppointments">
-        <var:if condition="hasUserAppointments">
-          <tr>
-            <td><var:entity const:name="nbsp" /></td>
-          </tr>
-        </var:if>
-        <!-- ZNeK: removed for Agenor 0.8 on client's request
-        <tr>
-          <th colspan="5" class="schedoverview_title">
-            <var:string label:value="Meetings proposed to you" />
-          </th>
-        </tr>
-        -->
-        <tr>
-          <th class="schedoverview"
-          ><var:string label:value="Start date" /></th>
-          <th class="schedoverview"
-          ><var:string label:value="Title" /></th>
-          <th class="schedoverview"
-              colspan="2"
-          ><var:string label:value="participants" /></th>
-          <th class="schedoverview"
-          ><var:string label:value="action" /></th>
-        </tr>
-        <var:foreach list="foreignAppointments"
-                     item="item"
-        >
-          <var:foreach count="renderedParticipantsCount"
-                       index="participantIndex"
-          >
-            <tr>
-              <var:if condition="isFirstParticipant">  
-                <td class="schedoverview"
-                    var:rowspan="rowspan"
-                >
-                  <var:string value="item.startDate"
-                              label:dateformat="sched_startDateFormat"
-                  />
-                </td>
-                <td class="schedoverview"
-                    var:rowspan="rowspan"
-                >
-                  <a var:href="appointmentViewURL"
-                     class="schedoverview"
-                  ><var:string value="item.title"
-                               const:escapeHTML="YES"
-                   /></a>
-                </td>
-              </var:if>
-              <td class="schedoverview">
-                <var:string value="participant" />
-              </td>
-              <td class="schedoverview">
-                <var:component className="UIxCalParticipationStatusView"
-                               partStat="participationStatus"
-                />
-              </td>
-              <td class="schedoverview">
-                <var:if-key const:key="participantIndex"
-                            value="userIndex"
-                >
-                  <!-- TODO: exchange with inline updates -->
-                  <var:if-key const:key="userParticipationStatus"
-                              const:value="1"
-                              const:negate="YES"
-                  >  
-                    <a var:href="acceptAppointmentURL"
-                       class="button_auto"
-                    ><var:string label:value="accept" /></a>
-                  </var:if-key>
-                  <!-- TODO: exchange with inline updates -->
-                  <var:if-key const:key="userParticipationStatus"
-                              const:value="2"
-                              const:negate="YES"
-                  >  
-                    <a var:href="declineAppointmentURL"
-                       class="button_auto"
-                    ><var:string label:value="decline" /></a>
-                  </var:if-key>
-                </var:if-key>
-              </td>
-            </tr>
-          </var:foreach>
-          <var:if condition="didTruncateParticipants">
-            <tr>
-              <td colspan="3" class="schedoverview">
-                <a var:href="appointmentViewURL"
-                   class="schedoverview"
-                ><var:string value="truncatedParticipantsCount" />
-                <var:string label:value="more participants" />...
-                </a>
-              </td>
-            </tr>
-          </var:if>
-        </var:foreach>
-      </var:if>
-    </var:if>
-  </table>
-</span>
\ No newline at end of file
index f32d48415a320aa30fb6a2e929f9d9cc64c7aabe..d0d6d55f6055f4e0454f7497520f55529f57738a 100644 (file)
@@ -1,37 +1,64 @@
 <?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:uix="OGo:uix"
-    xmlns:label="OGo:label"
-    className="UIxPageFrame"
-    title="title"
-    var:toolbar="toolbar"
-    const:popup="YES">
+<!DOCTYPE var:component>
+<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:uix="OGo:uix"
+  xmlns:label="OGo:label"
+  xmlns:rsrc="OGo:url"
+  className="UIxPageFrame"
+  title="title"
+  var:toolbar="toolbar"
+  const:popup="YES">
 
-    <form id="aclForm" const:href="saveAcls">
-      <div class="acls">
-        <input type="hidden" name="action" value="saveAcls" />
-        <input type="hidden" name="delegates" var:value="delegatesValue"
-          id="delegates" />
-        <input type="hidden" name="assistants" var:value="assistantsValue"
-          id="assistants" />
-        <label><var:string label:value="Owner:" />
-          <span class="value"><strong><var:string value="ownerCN" /></strong></span></label><br />
-        <var:component className="UIxContactSelector"
-          const:selectorId="userRoles"
-          const:checkBoxOnChange="return updateAclStatus(this);"
-          contacts="usersForFolder" />
-        <select id="userRoleDropDown" name="currentUserRole">
-          <option value="assistant"><var:string label:value="Assistant" /></option>
-          <option value="delegate"><var:string label:value="Delegate" /></option>
-        </select><br />
-        <var:if condition="clientIsCalendar"
-          ><label id="freeBusyLabel"><input type="checkbox"
-              var:checked="publishInFreeBusy"
-              class="checkBox" name="freebusy" id="freebusy"
-              /><var:string label:value="Localizable/Publish the Free/Busy information"
-              /></label></var:if>
+  <form id="aclForm" const:href="saveAcls">
+    <div class="acls">
+      <input type="hidden" name="action" value="saveAcls"/>
+      <input type="hidden" name="delegates" var:value="delegatesValue"
+       id="delegates"/>
+      <input type="hidden" name="assistants" var:value="assistantsValue"
+       id="assistants"/>
+      <label><var:string label:value="Owner:"/><br/>
+       <span class="value"><strong><var:string value="ownerName"/></strong></span></label><br/>
+
+      <!-- var:component className="UIxContactSelector"
+      const:checkBoxOnChange="return updateAclStatus(this);"
+      contacts="usersForFolder" -->
+
+      <div class="userSelector" id="userRoles">
+       <span id="userSelectorButtons">
+         <a href="#"
+           class="button"><img rsrc:src="add-contact.gif"
+             label:title="Add..."
+             /></a>
+         <a href="#"
+           class="button"><img rsrc:src="remove-contact.gif"
+             label:title="Remove"
+             /></a>
+       </span>
+       <input type="hidden"
+         var:id="selectorIdList"
+         var:name="selectorId"
+         var:value="initialContactsAsString"/>
+       <ul id="userList" multiselect="yes">
+         <var:foreach list="usersForFolder" item="currentUser"
+           ><li var:id="currentUser">
+             <img rsrc:src="abcard.gif"/>
+             <var:string value="currentUserDisplayName"/></li>
+         </var:foreach>
+       </ul>
       </div>
-    </form>
-  </var:component>
+      
+      <select id="userRoleDropDown" name="currentUserRole">
+       <option value="assistant"><var:string label:value="Assistant"/></option>
+       <option value="delegate"><var:string label:value="Delegate"/></option>
+      </select><br/>
+      <var:if condition="clientIsCalendar"
+       ><label id="freeBusyLabel"><input type="checkbox"
+           var:checked="publishInFreeBusy"
+           class="checkBox" name="freebusy" id="freebusy"
+           /><var:string label:value="Localizable/Publish the Free/Busy information"
+           /></label></var:if>
+    </div>
+  </form>
+</var:component>
index 5ac0bfba64fe5083a8ebf21d886a2a26c6dec0d0..caee6cdb7cec219ed5aa13c79205436d0a38fb45 100644 (file)
@@ -1,70 +1,13 @@
-/*
-  Copyright (C) 2005 SKYRIX Software AG
-
-  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
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo 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 Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-/* JavaScript for SOGo Mailer */
-
-/*
-  DOM ids available in mail list view:
-    row_$msgid
-    div_$msgid
-    readdiv_$msgid
-    unreaddiv_$msgid
-
-  Window Properties:
-    width, height
-    bool: resizable, scrollbars, toolbar, location, directories, status,
-          menubar, copyhistory
-*/
+/* JavaScript for SOGoContacts */
 
 var cachedContacts = new Array();
-var currentContactFolder = '';
-var currentFolderIsExternal = false;
-var contactSelectorAction = 'addressbooks-contacts';
+var currentContactFolder = '/personal';
 
 function openContactWindow(sender, url) {
   var msgWin = window.open(url, null, "width=450,height=600,resizable=0");
   msgWin.focus();
 }
 
-function clickedUid(sender, contactuid) {
-  resetSelection(window);
-  openContactWindow(sender, contactuid,
-                    CurrentContactFolderURL()
-                    + "/" + contactuid + "/edit");
-  return true;
-}
-
-function doubleClickedUid(sender, contactuid) {
-  alert("DOUBLE Clicked " + contactuid);
-
-  return false;
-}
-
-function toggleMailSelect(sender) {
-  var row;
-  row = $(sender.name);
-  row.className = sender.checked ? "tableview_selected" : "tableview";
-}
-
-/* mail editor */
-
 function validateEditorInput(sender) {
   var errortext = "";
   var field;
@@ -84,25 +27,7 @@ function validateEditorInput(sender) {
   return true;
 }
 
-function onContactsFolderTreeItemClick(element) {
-  var topNode = $('d');
-  var contactsFolder = element.parentNode.getAttribute("dataname");
-
-  if (topNode.selectedEntry)
-    topNode.selectedEntry.deselect();
-  element.select();
-  topNode.selectedEntry = element;
-
-  openContactsFolder(contactsFolder);
-}
-
-function CurrentContactFolderURL() {
-  return ((currentFolderIsExternal)
-          ? UserFolderURL + "../" + currentContactFolder + "/Contacts/personal"
-          : ApplicationBaseURL + currentContactFolder);
-}
-
-function openContactsFolder(contactsFolder, params, external) {
+function openContactsFolder(contactsFolder, params) {
   if (contactsFolder != currentContactFolder || params) {
      if (contactsFolder == currentContactFolder) {
         var contactsList = $("contactsList");
@@ -115,11 +40,8 @@ function openContactsFolder(contactsFolder, params, external) {
       selection = null;
 
     currentContactFolder = contactsFolder;
-    if (external)
-      currentFolderIsExternal = true;
-    else
-      currentFolderIsExternal = false;
-    var url = CurrentContactFolderURL() + "/view?noframe=1&sort=cn&desc=0";
+    var url = URLForFolderID(currentContactFolder) +
+       "/view?noframe=1&sort=cn&desc=0";
     if (params)
       url += '&' + params;
 
@@ -135,7 +57,7 @@ function openContactsFolder(contactsFolder, params, external) {
 
 function openContactsFolderAtIndex(element) {
   var idx = element.getAttribute("idx");
-  var url = CurrentContactFolderURL() + "/view?noframe=1&idx=" + idx;
+  var url = URLForFolderID(currentContactFolder) + "/view?noframe=1&idx=" + idx;
 
   if (document.contactsListAjaxRequest) {
     document.contactsListAjaxRequest.aborted = true;
@@ -243,8 +165,8 @@ function loadContact(idx) {
     div.innerHTML = cachedContacts[currentContactFolder + "/" + idx];
   }
   else {
-    var url = (CurrentContactFolderURL() + "/"
-               + idx + "/view?noframe=1");
+    var url = (URLForFolderID(currentContactFolder)
+              + "/" + idx + "/view?noframe=1");
     document.contactAjaxRequest
       = triggerAjaxRequest(url, contactLoadCallback, idx);
   }
@@ -304,7 +226,7 @@ function onContactRowDblClick(event, node) {
   var contactId = node.getAttribute('id');
 
   openContactWindow(null,
-                    CurrentContactFolderURL()
+                    URLForFolderID(currentContactFolder)
                     + "/" + contactId + "/edit");
 
   return false;
@@ -315,7 +237,7 @@ function onMenuEditContact(event, node) {
   var contactId = node.getAttribute('id');
 
   openContactWindow(null,
-                    CurrentContactFolderURL()
+                    URLForFolderID(currentContactFolder)
                     + "/" + contactId + "/edit");
 
   return false;
@@ -325,7 +247,7 @@ function onMenuWriteToContact(event, node) {
   var node = getParentMenu(node).menuTarget.parentNode;
   var contactId = node.getAttribute('id');
 
-  openMailComposeWindow(CurrentContactFolderURL()
+  openMailComposeWindow(ApplicationBaseURL + currentContactFolder
                         + "/" + contactId + "/write");
 
   return false;
@@ -343,7 +265,7 @@ function onToolbarEditSelectedContacts(event) {
 
   for (var i = 0; i < rows.length; i++) {
     openContactWindow(null,
-                      CurrentContactFolderURL()
+                     URLForFolderID(currentContactFolder)
                       + "/" + rows[i] + "/edit");
   }
 
@@ -355,7 +277,7 @@ function onToolbarWriteToSelectedContacts(event) {
   var rows = contactsList.getSelectedRowsId();
 
   for (var i = 0; i < rows.length; i++)
-    openMailComposeWindow(CurrentContactFolderURL()
+    openMailComposeWindow(ApplicationBaseURL + currentContactFolder
                           + "/" + rows[i] + "/write");
 
   return false;
@@ -374,7 +296,7 @@ function uixDeleteSelectedContacts(sender) {
     
     /* send AJAX request (synchronously) */
     
-    url = (CurrentContactFolderURL() + "/"
+    url = (URLForFolderID(currentContactFolder) + "/"
            + rows[i] + "/delete");
     http = createHTTPClient();
     http.open("POST", url, false /* not async */);
@@ -394,7 +316,7 @@ function uixDeleteSelectedContacts(sender) {
   }
 
   if (failCount > 0)
-    alert("Could not delete " + failCount + " messages!");
+    alert("Could not delete the selected contacts!");
   
   return false;
 }
@@ -419,7 +341,7 @@ function onHeaderClick(event) {
     document.contactsListAjaxRequest.aborted = true;
     document.contactsListAjaxRequest.abort();
   }
-  url = CurrentContactFolderURL() + "/" + this.link;
+  url = URLForFolderID(currentContactFolder) + "/" + this.link;
   if (!this.link.match(/noframe=/))
     url += "&noframe=1";
   document.contactsListAjaxRequest
@@ -434,145 +356,63 @@ function registerDraggableMessageNodes() {
 
 function newContact(sender) {
   openContactWindow(sender,
-                    CurrentContactFolderURL() + "/new");
+                    URLForFolderID(currentContactFolder) + "/new");
 
   return false; /* stop following the link */
 }
 
 function onFolderSelectionChange() {
-  var folderList = $("contactFolders");
-  var nodes = folderList.getSelectedNodes();
-  $("contactView").innerHTML = '';
-
-  if (nodes[0].hasClassName("denied")) {
-    var div = $("contactsListContent");
-    div.innerHTML = "";
-  }
-  else {
-    var newFolder;
-    var externalFolder = nodes[0].getAttribute("external-addressbook");
-    if (externalFolder)
-      newFolder = externalFolder;
-    else
-      newFolder = nodes[0].getAttribute("id");
-
-    openContactsFolder(newFolder, null, externalFolder);
-  }
+   var folderList = $("contactFolders");
+   var nodes = folderList.getSelectedNodes();
+   $("contactView").innerHTML = '';
+  
+   if (nodes[0].hasClassName("denied")) {
+      var div = $("contactsListContent");
+      div.innerHTML = "";
+   }
+   else
+      openContactsFolder(nodes[0].getAttribute("id"), null);
 }
 
 function onSearchFormSubmit() {
   var searchValue = $("searchValue");
 
-  openContactsFolder(currentContactFolder, "search=" + searchValue.value);
+  openContactsFolder(URLForFolderID(currentContactFolder),
+                    "search=" + searchValue.value);
 
   return false;
 }
 
-function onConfirmContactSelection(tag) {
-  var folderLi = $(currentContactFolder);
-  var currentContactFolderName = folderLi.innerHTML;
-  var selectorList = null;
-  var initialValues = null;
+function onConfirmContactSelection(event) {
+   var tag = this.getAttribute("name");
+   var folderLi = $(currentContactFolder);
+   var currentContactFolderName = folderLi.innerHTML;
+   var selectorList = null;
+   var initialValues = null;
 
-  if (selector)
-    {
+   if (selector) {
       var selectorId = selector.getAttribute("id");
       selectorList = opener.window.document.getElementById('uixselector-'
                                                            + selectorId
                                                            + '-uidList');
       initialValues = selectorList.value;
-    }
-
-  var contactsList = $("contactsList");
-  var rows = contactsList.getSelectedRows();
-  for (i = 0; i < rows.length; i++) {
-    var cid = rows[i].getAttribute("contactid");
-    var cname = '' + rows[i].getAttribute("contactname");
-    var email = '' + rows[i].cells[1].innerHTML;
-    opener.window.addContact(tag, currentContactFolderName + '/' + cname,
-                             cid, cname, email);
-  }
-
-  if (selector && selector.changeNotification
-      && selectorList.value != initialValues)
-    selector.changeNotification("addition");
-
-  return false;
-}
-
-function onConfirmAddressBookSelection() {
-  var folderLi = $(currentContactFolder);
-  var currentContactFolderName = folderLi.innerHTML;
-
-  var selector = window.opener.document.getElementById("contactFolders");
-  var initialValues = selector.getAttribute("additional-addressbooks");
-  if (!initialValues)
-    initialValues = "";
-  var newValues = initialValues;
-
-  var contactsList = $("contactsList");
-  var rows = contactsList.getSelectedRows();
-  for (i = 0; i < rows.length; i++) {
-    var cid = rows[i].getAttribute("contactid");
-    var cname = '' + rows[i].getAttribute("contactname");
-    var email = '' + rows[i].cells[1].innerHTML;
-    var re = new RegExp("(^|,)" + cid + "($|,)");
-    if (!re.test(newValues)) {
-      if (newValues.length)
-        newValues += "," + cid;
-      else
-        newValues = cid;
-    }
-  }
-
-  if (newValues != initialValues)
-    window.opener.setTimeout("setAdditionalAddressBooks(\""
-                             + newValues + "\");", 100);
+   }
 
-  return false;
-}
+   var contactsList = $("contactsList");
+   var rows = contactsList.getSelectedRows();
+   for (i = 0; i < rows.length; i++) {
+      var cid = rows[i].getAttribute("contactid");
+      var cname = '' + rows[i].getAttribute("contactname");
+      var email = '' + rows[i].cells[1].innerHTML;
+      opener.window.addContact(tag, currentContactFolderName + '/' + cname,
+                              cid, cname, email);
+   }
 
-function setAdditionalAddressBooks(additionalAddressBooks) {
-  var urlstr = (ApplicationBaseURL + "/updateAdditionalAddressBooks?ids="
-                + additionalAddressBooks);
-  if (document.addressBooksAjaxRequest) {
-    document.addressBooksAjaxRequest.aborted = true;
-    document.addressBooksAjaxRequest.abort();
-  }
-  document.addressBooksAjaxRequest
-    = triggerAjaxRequest(urlstr,
-                         addressBooksCallback, additionalAddressBooks);
-}
+   if (selector && selector.changeNotification
+       && selectorList.value != initialValues)
+      selector.changeNotification("addition");
 
-function addressBooksCallback(http) {
-  if (http.readyState == 4) {
-    if (http.status == 200) {
-      var ul = $("contactFolders");
-
-      var children = ul.childNodesWithTag("li");
-      for (var i = 0; i < children.length; i++)
-        if (children[i].getAttribute("external-addressbook"))
-          ul.removeChild(children[i]);
-
-      ul.setAttribute("additional-addressbooks", http.callbackData);
-      if (http.callbackData.length > 0) {
-        var list = http.callbackData.split(",");
-        var newCode = "";
-        for (var i = 0; i < list.length; i++) {
-          var username = list[i];
-          newCode += ( "<li external-addressbook=\"" + username + "\""
-                       + " onmousedown=\"return false;\""
-                       + " onclick=\"return onRowClick(event);\""
-                       + " oncontextmenu=\"return onContactFolderContextMenu(event);\">" );
-          newCode += ( username + "</li>" );
-        }
-        ul.innerHTML += newCode;
-      }
-    }
-    document.addressBooksAjaxRequest = null;
-  }
-  else
-    log ("ajax fuckage 3");
+   event.preventDefault();
 }
 
 function onContactMailTo(node) {
@@ -580,7 +420,7 @@ function onContactMailTo(node) {
 }
 
 function refreshContacts(contactId) {
-  openContactsFolder(currentContactFolder, "reload=true", currentFolderIsExternal);
+  openContactsFolder(currentContactFolder, "reload=true");
   cachedContacts[currentContactFolder + "/" + contactId] = null;
   loadContact(contactId);
 
@@ -601,63 +441,62 @@ function onAddressBookNew(event) {
   event.preventDefault();
 }
 
+function appendAddressBook(name, folder) {
+   var li = document.createElement("li");
+   li.setAttribute("id", folder);
+   li.appendChild(document.createTextNode(name));
+   li.addEventListener("mousedown", listRowMouseDownHandler, false);
+   li.addEventListener("click", onRowClick, false);
+   li.addEventListener("contextmenu", onContactFoldersContextMenu, false);
+   $("contactFolders").appendChild(li);
+}
+
 function newAbCallback(http) {
   if (http.readyState == 4
       && http.status == 201) {
-     var ul = $("contactFolders");
      var name = http.callbackData;
-     var li = document.createElement("li");
-     li.setAttribute("id", "/" + name);
-     li.appendChild(document.createTextNode(name));
-     li.addEventListener("mousedown", listRowMouseDownHandler, false);
-     li.addEventListener("click", onRowClick, false);
-     li.addEventListener("contextmenu", onContactFoldersContextMenu, false);
-     ul.appendChild(li);
+     appendAddressBook(name, "/" + name);
   }
   else
     log ("ajax fuckage 4:" + http.status);
 }
 
+function newUserFolderCallback(folderData) {
+   var folder = $(folderData["folder"]);
+   if (!folder)
+      appendAddressBook(folderData["folderName"], folderData["folder"]);
+}
+
 function onAddressBookAdd(event) {
-  var selector = $("contactFolders");
-  var selectorURL = '?popup=YES&selectorId=contactFolders';
-
-  urlstr = ApplicationBaseURL;
-  if (urlstr[urlstr.length-1] != '/')
-    urlstr += '/';
-  urlstr += ("../../" + UserLogin + "/Contacts/"
-             + contactSelectorAction + selectorURL);
-//   log (urlstr);
-  var w = window.open(urlstr, "Addressbook",
-                      "width=640,height=400,resizable=1,scrollbars=0");
-  w.selector = selector;
-  w.opener = window;
-  w.focus();
+   openUserFolderSelector(newUserFolderCallback, "contact");
 
-  event.preventDefault();
+   event.preventDefault();
+}
+
+function onFolderUnsubscribeCB(folderId) {
+   var node = $(folderId);
+   node.parentNode.removeChild(node);
+   var personal = $("/personal");
+   personal.select();
+   onFolderSelectionChange();
 }
 
 function onAddressBookRemove(event) {
   var selector = $("contactFolders");
   var nodes = selector.getSelectedNodes();
-  if (nodes.length > 0) {
-    var cid = nodes[0].getAttribute("external-addressbook");
-    if (cid) {
-      var initialValues = selector.getAttribute("additional-addressbooks");
-      var re = new RegExp("(^|,)" + cid + "($|,)");
-      var newValues = initialValues.replace(re, "");
-      if (initialValues != newValues)
-        setAdditionalAddressBooks(newValues);
-    }
-    else {
-       nodes[0].deselect();
-       var folderId = nodes[0].getAttribute("id").substr(1);
-       deletePersonalAddressBook(folderId);
-    }
-
-    var personal = $("/personal");
-    personal.select();
-    onFolderSelectionChange();
+  if (nodes.length > 0) { 
+     nodes[0].deselect();
+     var folderId = nodes[0].getAttribute("id");
+     var folderIdElements = folderId.split(":");
+     if (folderIdElements.length > 1)
+       unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
+     else {
+       var abId = folderIdElements[0].substr(1);
+       deletePersonalAddressBook(abId);
+       var personal = $("/personal");
+       personal.select();
+       onFolderSelectionChange();
+     }
   }
 
   event.preventDefault();
@@ -719,19 +558,26 @@ function configureDragHandles() {
 }
 
 function lookupDeniedFolders() {
-  var rights;
-  var http = createHTTPClient();
-  if (http) {
-    http.url = ApplicationBaseURL + "/checkRights";
-    http.open("GET", http.url, false /* not async */);
-    http.send("");
-    if (http.status == 200
-        && http.responseText.length > 0) {
-      rights = http.responseText.split(",");
-    }
+  var list = $("contactFolders").childNodesWithTag("li");
+  for (var i = 0; i < list.length; i++) {
+     var folderID = list[i].getAttribute("id");
+     var url = URLForFolderID(folderID) + "/canAccessContent";
+     triggerAjaxRequest(url, deniedFoldersLookupCallback, folderID);
   }
+}
 
-  return rights;
+function deniedFoldersLookupCallback(http) {
+   if (http.readyState == 4) { 
+      var denied = true;
+
+      if (http.status == 200)
+         denied = (http.responseText == "0");
+      var entry = $(http.callbackData);
+      if (denied)
+        entry.addClassName("denied");
+      else
+        entry.removeClassName("denied");
+   }
 }
 
 function configureAbToolbar() {
@@ -754,31 +600,21 @@ function configureContactFolders() {
       lis[i].addEventListener("contextmenu", onContactFoldersContextMenu, false);
     }
 
-    var denieds = lookupDeniedFolders();
-    if (denieds) {
-      var start = (lis.length - denieds.length);
-      for (var i = start; i < lis.length; i++) {
-        if (denieds[i-start] == "1")
-          lis[i].removeClassName("denied");
-        else
-          lis[i].addClassName("denied");
-      }
-    }
+    lookupDeniedFolders();
     contactFolders.style.visibility = "visible;";
+
+    var personalFolder = $("/personal");
+    personalFolder.select();
   }
 }
 
 function onAccessRightsMenuEntryMouseUp(event) {
   var folders = $("contactFolders");
   var selected = folders.getSelectedNodes()[0];
-  var external = selected.getAttribute("external-addressbook");
   var title = this.innerHTML;
-  if (external)
-    url = UserFolderURL + "../" + external + "/Contacts/personal/acls";
-  else
-    url = ApplicationBaseURL + selected.getAttribute("id") + "/acls";
+  var url = URLForFolderID(selected.getAttribute("id"))
 
-  openAclWindow(url, title);
+  openAclWindow(url + "/acls", title);
 }
 
 function initializeMenus() {
@@ -789,11 +625,34 @@ function initializeMenus() {
   menuEntry.addEventListener("mouseup", onAccessRightsMenuEntryMouseUp, false);
 }
 
+function configureSearchField() {
+   var searchValue = $("searchValue");
+
+   searchValue.addEventListener("mousedown", onSearchMouseDown, false);
+   searchValue.addEventListener("click", popupSearchMenu, false);
+   searchValue.addEventListener("blur", onSearchBlur, false);
+   searchValue.addEventListener("focus", onSearchFocus, false);
+   searchValue.addEventListener("keydown", onSearchKeyDown, false);
+}
+
+function configureSelectionButtons() {
+   var container = $("contactSelectionButtons");
+   if (container) {
+      var buttons = container.childNodesWithTag("input");
+      for (var i = 0; i < buttons.length; i++)
+        buttons[i].addEventListener("click", onConfirmContactSelection,
+                                    false);
+   }
+}
+
 var initContacts = {
   handleEvent: function (event) {
     if (!document.body.hasClassName("popup")) {
       configureAbToolbar();
+      configureSearchField();
     }
+    else
+      configureSelectionButtons();
     configureContactFolders();
 //     initDnd();
   }
index f10b370af39fb0871aad5e3460840b698afc3175..4a27af53bfd3379333ca267c94fa8dbb8396301d 100644 (file)
@@ -452,26 +452,6 @@ table.linked_attachment_meta
   font-style: italic;
 }
 
-/* folder tree (js) )*/
-DIV.dTreeNode A SPAN.nodeName
-{
-  margin: 0px .2em;
-  padding-left: .2em;
-  padding-right: .2em;
-}
-
-DIV.dTreeNode A._selected SPAN.nodeName
-{
-  background: #4b6983;
-  color: #fff;
-}
-
-DIV.dTreeNode SPAN._dragOver
-{ 
-  background: #4b6983;
-  color: #fff;
-}
-
 /* drag-n-drop */
 IMG.dragMessage
 {
index 9be2fc50fdf1d1ca0906284cb2e6e84600f55b86..47d933dbcd0c52859b8a9abdbaa9c7a3131ee926 100644 (file)
@@ -1,37 +1,4 @@
-/*
-  Copyright (C) 2005 SKYRIX Software AG
-
-  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
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo 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 Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-/* JavaScript for SOGo Mailer */
-
-/*
-  DOM ids available in mail list view:
-    row_$msgid
-    div_$msgid
-    readdiv_$msgid
-    unreaddiv_$msgid
-
-  Window Properties:
-    width, height
-    bool: resizable, scrollbars, toolbar, location, directories, status,
-          menubar, copyhistory
-*/
+/* JavaScript for SOGoMail */
 
 var currentMessages = new Array();
 var maxCachedMessages = 20;
@@ -1013,32 +980,42 @@ function openInbox(node) {
   }
 }
 
-var initMailer = {
-  handleEvent: function (event) {
-    if (!document.body.hasClassName("popup")) {
-      var inboxFound = false;
-      configureMessageListEvents();
-      initDnd();
-      var tree = $("d");
-      var nodes = document.getElementsByClassName("node", tree);
-      for (i = 0; i < nodes.length; i++) {
-        nodes[i].addEventListener("click", onMailboxTreeItemClick, false);
-        nodes[i].addEventListener("contextmenu", onFolderMenuClick, false);
-        if (!inboxFound
-            && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
-          openInbox(nodes[i]);
-          inboxFound = true;
-        }
-      }
-    }
-
-    /*
-, 'onMailboxTreeItemClick(this);'
-<!--      if (typeof(node.datatype) != "undefined") str += ' oncontextmenu="onFolderMenuClick(event, this);"';
+function configureSearchField() {
+   var searchValue = $("searchValue");
 
-    */
+   searchValue.addEventListener("mousedown", onSearchMouseDown, false);
+   searchValue.addEventListener("click", popupSearchMenu, false);
+   searchValue.addEventListener("blur", onSearchBlur, false);
+   searchValue.addEventListener("focus", onSearchFocus, false);
+   searchValue.addEventListener("keydown", onSearchKeyDown, false);
+}
 
-  }
+var initMailer = {
+   handleEvent: function (event) {
+      if (!document.body.hasClassName("popup")) {
+        configureSearchField();
+        var inboxFound = false;
+        configureMessageListEvents();
+        initDnd();
+        var tree = $("d");
+        var nodes = document.getElementsByClassName("node", tree);
+        for (i = 0; i < nodes.length; i++) {
+           nodes[i].addEventListener("click", onMailboxTreeItemClick, false);
+           nodes[i].addEventListener("contextmenu", onFolderMenuClick, false);
+           if (!inboxFound
+               && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
+              openInbox(nodes[i]);
+              inboxFound = true;
+           }
+        }
+      }
+      
+      /*
+      , 'onMailboxTreeItemClick(this);'
+      <!--      if (typeof(node.datatype) != "undefined") str += ' oncontextmenu="onFolderMenuClick(event, this);"';
+      
+      */
+   }
 }
 
 function initializeMenus() {
diff --git a/UI/WebServerResources/SOGoUserHomePage.js b/UI/WebServerResources/SOGoUserHomePage.js
deleted file mode 100644 (file)
index b98b9a1..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- Copyright (C) 2005 SKYRIX Software AG
- 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
- Free Software Foundation; either version 2, or (at your option) any
- later version.
- OGo 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 Lesser General Public
- License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING.  If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
- */
-/* JavaScript for SOGo Homepage */
-
-function toggleInternetAccessState(sender) {
-//    var form = document.getElementById("syncDefaultsForm");
-//    document.syncDefaultsForm.action="saveInternetAccessState:method";
-//    form.submit();
-    this.postInternetAccessState(sender, sender.value);
-    return true;
-}
-
-function postInternetAccessState(sender, state) {
-    var url;
-    var http = createHTTPClient();
-    
-    url = "edit?allowinternet=" + state;
-    
-    if (http) {
-        http.open("POST", url, false);
-        http.send("");
-        if (http.status != 200) {
-            alert("Failed to change state: " + http.statusText);
-            window.location.reload();
-        }
-    }
-    else {
-        alert("Unable to retrieve HTTPClient object!");
-        window.location.href = url;
-    }
-}
index fbf9371358bc04085ba566afdfd49e27c3d5373f..adc757af6066be9a8bd58efa38c7f087f8493e8f 100644 (file)
@@ -1,3 +1,4 @@
+
 DIV#leftPanel
 { 
   position: absolute;
@@ -36,20 +37,24 @@ DIV#tasksListView H2
 DIV#tasksListView LABEL
 { margin: .25em; }
 
+DIV#calendarSelectorView
+{ top: 0px; }
+
 DIV#calendarsList
 { height: 100%;
   padding: 0px;
   margin: 0px; }
 
-SPAN.colorBox
-{ display: block;
-  float: right;
+DIV.colorBox
+{ display: inline;
   border: 1px solid #333;
-  margin: .12em;
+  font-weight: normal; 
+  margin: 0px;
+  font-size: 80%;
   width: 1em;
   height: .75em; }
 
-UL#tasksList, UL#uixselector-calendarsList-display
+UL#tasksList, UL#calendarList
 { cursor: default;
   margin: .25px;
   padding: 0px;
@@ -64,12 +69,16 @@ UL#tasksList, UL#uixselector-calendarsList-display
   list-style-type: none;
   list-style-image: none; }
 
-UL#uixselector-calendarsList-display
-{ height: 10.5em;
+UL#calendarList
+{ clear: both;
+  height: 10.5em;
   margin: 0px; }
 
-UL#uixselector-calendarsList-display LI.denied
-{ background: #fefefe;
+UL#calendarList LI
+{ white-space: nowrap; }
+
+UL#calendarList LI.denied
+{ background-color: #fefefe;
   font-style: italic;
   color: #f33; }
 
@@ -793,7 +802,7 @@ DIV.appointments > DIV.appointment
 { cursor: default;
   position: absolute;
   left: 0px;
-  right: 0px;
+  right: 1px;
   padding: 1px; }
 
 DIV[class~="appointment"]._selected > DIV.appointmentInside
@@ -856,10 +865,11 @@ DIV.monthView DIV.appointment
   cursor: default;
   white-space: nowrap;
   margin: 2px;
+  margin-right: 3px;
   padding: 1px;
   height: 1.5em; }
 
-DIV.monthView DIV.appointment DIV.text
+DIV.appointment DIV.text
 { font-size: 80%; }
 
 DIV.daysView DIV[class~="appointment"].starts0
index 77d5d205f0a9ac9f57c045487532493780707122..856077e52d5080cb7993505b6e3c27871c86c603 100644 (file)
@@ -1,3 +1,5 @@
+/* JavaScript for SOGoCalendar */
+
 var sortOrder = '';
 var sortKey = '';
 var listFilter = 'view_today';
@@ -846,158 +848,87 @@ function updateTaskStatus(node) {
   return false;
 }
 
-function updateCalendarStatus() {
+function updateCalendarStatus(event) {
   var list = new Array();
 
-  var clist = $("calendarsList");
-  var nodes = clist.childNodesWithTag("ul")[0].childNodesWithTag("li");
+  var nodes = $("calendarList").childNodesWithTag("li");
   for (var i = 0; i < nodes.length; i++) {
     var input = nodes[i].childNodesWithTag("input")[0];
-    if (input.checked)
-      list.push(nodes[i].getAttribute("uid"));
+    if (input.checked) {
+       var folderId = nodes[i].getAttribute("id");
+       var elems = folderId.split(":");
+       if (elems.length > 1)
+         list.push(elems[0]);
+       else
+         list.push(UserLogin);
+    }
   }
 
   if (!list.length) {
-    list.push(nodes[0].getAttribute("uid"));
-    nodes[0].childNodesWithTag("input")[0].checked = true;
+     list.push(UserLogin);
+     nodes[0].childNodesWithTag("input")[0].checked = true;
   }
 //   ApplicationBaseURL = (UserFolderURL + "Groups/_custom_"
-//                      + list.join(",") + "/Calendar/");
-
-  updateCalendarsList();
-  refreshAppointments();
-  refreshTasks();
-  changeCalendarDisplay();
+//                     + list.join(",") + "/Calendar/");
+
+  if (event) {
+     var folderID = this.parentNode.getAttribute("id");
+     var urlstr = URLForFolderID(folderID);
+     if (this.checked)
+       urlstr += "/activateFolder";
+     else
+       urlstr += "/deactivateFolder";
+     triggerAjaxRequest(urlstr, calendarStatusCallback, folderID);
+  }
+  else {
+     updateCalendarsList();
+     refreshAppointments();
+     refreshTasks();
+     changeCalendarDisplay();
+  }
 
   return false;
 }
 
-function calendarUidsList() {
-  var list = "";
-
-  var nodes = $("uixselector-calendarsList-display").childNodesWithTag("li");
-  for (var i = 0; i < nodes.length; i++) {
-    var currentNode = nodes[i];
-    var input = currentNode.childNodesWithTag("input")[0];
-    if (!input.checked)
-      list += "-";
-    list += currentNode.getAttribute("uid") + ",";
-  }
-
-  return list.substr(0, list.length - 1);
-}
-
-// function updateCalendarContacts(contacts)
-// {
-//   var list = contacts.split(",");
-
-//   var clist = $("calendarsList");
-//   var nodes = clist.childNodes[5].childNodes;
-//   for (var i = 0; i < nodes.length; i++) {
-//     var currentNode = nodes[i];
-//     if (currentNode instanceof HTMLLIElement) {
-//       var input = currentNode.childNodes[3];
-//       if (!input.checked)
-//         list += "-";
-//       list += currentNode.getAttribute("uid") + ",";
-//     }
-//   }
-// }
-
-function inhibitMyCalendarEntry() {
-  var clist = $("calendarsList");
-  var nodes = clist.childNodes[5].childNodes;
-  var done = false;
-
-  var i = 0;
-  while (!done && i < nodes.length) {
-    var currentNode = nodes[i];
-    if (currentNode instanceof HTMLLIElement) {
-      var input = currentNode.childNodes[3];
-      if (currentNode.getAttribute("uid") == UserLogin) {
-        done = true;
-//         currentNode.style.color = "#999;";
-        currentNode.style.fontWeight = "bold;";
-//         currentNode.setAttribute("onclick", "");
+function calendarStatusCallback(http) {
+   if (http.readyState == 4) {
+      if (http.status == 204) {
+         refreshAppointments();
+         refreshTasks();
+         changeCalendarDisplay();
       }
-    }
-    i++;
-  }
+      else {
+         var folder = $(http.callbackData);
+         var input = folder.childNodesWithTag("input")[0];
+         input.checked = (!input.checked);
+      }
+   }
 }
 
-function userCalendarEntry(user, color) {
-  var li = document.createElement("li");
-  li.setAttribute("uid", user);
-  li.addEventListener("mousedown", listRowMouseDownHandler, false);
-  li.addEventListener("click", onRowClick, false);
-  var colorBox = document.createElement("span");
-  colorBox.addClassName("colorBox");
-  if (color) {
-    log("color:  " + color);
-    colorBox.style.backgroundColor = color + ";";
-  }
-  li.appendChild(colorBox);
-  var checkBox = document.createElement("input");
-  checkBox.addClassName("checkBox");
-  checkBox.type = "checkbox";
-  checkBox.addEventListener("change", updateCalendarStatus, false);
-  li.appendChild(checkBox);
-  var text = document.createTextNode(" " + user);
-  li.appendChild(text);
-
-  return li;
-}
-
-function ensureSelfIfPresent() {
-  var ul = $("uixselector-calendarsList-display");
-  var list = ul.childNodesWithTag("li");
-  var selfEntry = userCalendarEntry(UserLogin, indexColor(0));
-  selfEntry.style.fontWeight = "bold;";
-  if (list.length < 1) {
-    ul.appendChild(selfEntry);
-  } else if (list[0].getAttribute("uid") != UserLogin) {
-    ul.insertBefore(selfEntry, list[0]);
-  }
+function calendarEntryCallback(http) {
+   var disabled = true;
+
+   if (http.readyState == 4) {
+      if (http.status == 200)
+        disabled = (http.responseText == "0");
+      var entry = $(http.callbackData);
+      var input = entry.childNodesWithTag("input")[0];
+      input.disabled = disabled;
+      if (disabled) {
+        input.checked = false;
+        entry.addClassName("denied");
+      }
+      else
+        entry.removeClassName("denied");
+   }
 }
 
 function updateCalendarsList(method) {
-  ensureSelfIfPresent();
-  var url = (ApplicationBaseURL + "updateCalendars?ids="
-             + calendarUidsList());
-  if (document.calendarsListAjaxRequest) {
-    document.calendarsListAjaxRequest.aborted = true;
-    document.calendarsListAjaxRequest.abort();
-  }
-  var http = createHTTPClient();
-  if (http) {
-    http.url = url;
-    http.open("GET", url, false);
-    http.send("");
-
-    if (method == "removal")
-      updateCalendarStatus();
-
-    http = createHTTPClient();
-    http.url = ApplicationBaseURL + "checkRights";
-    http.open("GET", http.url, false /* not async */);
-    http.send("");
-    if (http.status == 200
-        && http.responseText.length > 0) {
-      rights = http.responseText.split(",");
-      var list = $("uixselector-calendarsList-display").childNodesWithTag("li");
-      for (var i = 0; i < list.length; i++) {
-        var input = list[i].childNodesWithTag("input")[0];
-        if (rights[i] == "1") {
-          list[i].removeClassName("denied");
-          input.disabled = false;
-        }
-        else {
-          input.checked = false;
-          input.disabled = true;
-          list[i].addClassName("denied");
-        }
-      }
-    }
+  var list = $("calendarList").childNodesWithTag("li");
+  for (var i = 0; i < list.length; i++) {
+     var folderID = list[i].getAttribute("id");
+     var url = URLForFolderID(folderID) + "/canAccessContent";
+     triggerAjaxRequest(url, calendarEntryCallback, folderID);
   }
 }
 
@@ -1014,16 +945,11 @@ function addContact(tag, fullContactName, contactId, contactName, contactEmail)
             uids.value += ',' + contactId;
           else
             uids.value = contactId;
-          var names = $("uixselector-calendarsList-display");
+          var names = $("calendarList");
           var listElems = names.childNodesWithTag("li");
           var colorDef = indexColor(listElems.length);
           names.appendChild(userCalendarEntry(contactId, colorDef));
 
-          var styles = document.getElementsByTagName("style");
-          styles[0].innerHTML += ('.ownerIs' + contactId + ' {'
-                                  + ' background-color: '
-                                  + colorDef
-                                  + ' !important; }');
         }
     }
 
@@ -1066,7 +992,7 @@ function initializeMenus() {
                         "appointmentsListMenu", "calendarsMenu", "searchMenu");
   initMenusNamed(menus);
 
-  $("calendarsList").attachMenu("calendarsMenu");
+  $("calendarSelector").attachMenu("calendarsMenu");
 
   var accessRightsMenuEntry = $("accessRightsMenuEntry");
   accessRightsMenuEntry.addEventListener("mouseup",
@@ -1075,16 +1001,12 @@ function initializeMenus() {
 }
 
 function onAccessRightsMenuEntryMouseUp(event) {
-  var folders = $("uixselector-calendarsList-display");
+  var folders = $("calendarList");
   var selected = folders.getSelectedNodes()[0];
-  var uid = selected.getAttribute("uid");
-  log("application base url: " + ApplicationBaseURL);
-  if (uid == UserLogin)
-    url = ApplicationBaseURL + "acls";
-  else
-    url = UserFolderURL + "../" + uid + "/Calendar/acls";
+  var folderID = selected.getAttribute("id");
+  var urlstr = URLForFolderID(folderID) + "/acls";
 
-  openAclWindow(url, uid);
+  openAclWindow(urlstr);
 }
 
 function configureDragHandles() {
@@ -1103,31 +1025,107 @@ function configureDragHandles() {
   }
 }
 
-function initCalendarContactsSelector() {
-  var selector = $("calendarsList");
-  inhibitMyCalendarEntry();
+function initCalendarSelector() {
+  var selector = $("calendarSelector");
   updateCalendarStatus();
   selector.changeNotification = updateCalendarsList;
 
-  var list = $("uixselector-calendarsList-display").childNodesWithTag("li");
+  var list = $("calendarList").childNodesWithTag("li");
   for (var i = 0; i < list.length; i++) {
     var input = list[i].childNodesWithTag("input")[0];
     input.addEventListener("change", updateCalendarStatus, false);
+    list[i].addEventListener("mousedown", listRowMouseDownHandler, false);
+    list[i].addEventListener("click", onRowClick, false);
+//     list[i].addEventListener("contextmenu", onContactFoldersContextMenu, false);
+  }
+
+  var links = $("calendarSelectorButtons").childNodesWithTag("a");
+  links[0].addEventListener("click", onCalendarAdd, false);
+  links[1].addEventListener("click", onCalendarRemove, false);
+}
+
+function onCalendarAdd(event) {
+   openUserFolderSelector(onFolderSubscribeCB, "calendar");
+
+   event.preventDefault();
+}
+
+function appendCalendar(folderName, folder) {
+   var calendarList = $("calendarList");
+   var lis = calendarList.childNodesWithTag("li");
+   var color = indexColor(lis.length);
+   log ("color: " + color);
+   var li = document.createElement("li");
+   li.setAttribute("id", folder);
+   li.addEventListener("mousedown", listRowMouseDownHandler, false);
+   li.addEventListener("click", onRowClick, false);
+   var checkBox = document.createElement("input");
+   checkBox.addClassName("checkBox");
+   checkBox.type = "checkbox";
+   checkBox.addEventListener("change", updateCalendarStatus, false);
+   li.appendChild(checkBox);
+   var colorBox = document.createElement("div");
+   colorBox.appendChild(document.createTextNode("OO"));
+   colorBox.addClassName("colorBox");
+   if (color) {
+      colorBox.style.color = color + ";";
+      colorBox.style.backgroundColor = color + ";";
+   }
+   li.appendChild(colorBox);
+   li.appendChild(document.createTextNode(folderName));
+
+   calendarList.appendChild(li);
+
+   var contactId = folder.split(":")[0];
+   var styles = document.getElementsByTagName("style");
+   styles[0].innerHTML += ('.ownerIs' + contactId + ' {'
+                          + ' color: '
+                          + color + ';'
+                          + ' background-color: '
+                          + color
+                          + ' !important; }');
+}
+
+function onFolderSubscribeCB(folderData) {
+   var folder = $(folderData["folder"]);
+   if (!folder)
+      appendCalendar(folderData["folderName"], folderData["folder"]);
+}
+
+function onFolderUnsubscribeCB(folderId) {
+   var node = $(folderId);
+   node.parentNode.removeChild(node);
+}
+
+function onCalendarRemove(event) {
+  var nodes = $("calendarList").getSelectedNodes();
+  if (nodes.length > 0) { 
+     nodes[0].deselect();
+     var folderId = nodes[0].getAttribute("id");
+     var folderIdElements = folderId.split(":");
+     if (folderIdElements.length > 1) {
+       unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId);
+     }
   }
+
+  event.preventDefault();
 }
 
-function initCalendars() {
-  if (!document.body.hasClassName("popup"))
-    initCalendarContactsSelector();
+function configureSearchField() {
+   var searchValue = $("searchValue");
+
+   searchValue.addEventListener("mousedown", onSearchMouseDown, false);
+   searchValue.addEventListener("click", popupSearchMenu, false);
+   searchValue.addEventListener("blur", onSearchBlur, false);
+   searchValue.addEventListener("focus", onSearchFocus, false);
+   searchValue.addEventListener("keydown", onSearchKeyDown, false);
 }
 
-function onSchedulerBodyKeyUp(event) {
-   if (event.which == 46) {
-      window.alert("coucou");
-      deleteEvent();
-      event.cancelBubble = true;
+function initCalendars() {
+   if (!document.body.hasClassName("popup")) {
+      initCalendarSelector();
+      configureSearchField();
    }
 }
 
 window.addEventListener("load", initCalendars, false);
-// document.body.addEventListener("keyup", onSchedulerBodyKeyUp, false);
index bca5e667f818fab7f4643693b2d51a7586cc2c1c..3439d4afe6090c1b11dc39c66fafb3d8b27a2b0e 100644 (file)
@@ -4,15 +4,9 @@ DIV.acls
 { padding: 1em; }
 
 DIV.acls LABEL
-{ position: relative;
-  white-space: normal;
+{ white-space: nowrap;
   width: 100%; }
 
-DIV.acls LABEL > SPAN.value
-{ position: absolute;
-  top: 0px;
-  left: 11em; }
-
 DIV.acls UL
 { height: 100%;
   width: 100%; }
@@ -21,7 +15,7 @@ DIV#userRoles
 { height: 7em;
   padding-bottom: 2em; }
 
-UL#uixselector-userRoles-display
+UL#userList
 { cursor: default;
   margin: .25px;
   padding: 0px;
@@ -36,7 +30,7 @@ UL#uixselector-userRoles-display
   list-style-type: none;
   list-style-image: none; }
 
-UL#uixselector-userRoles-display > LI._selected
+UL#userList > LI._selected
 { 
   background: #4b6983 !important;
   color: #fff !important;
index b10635c6465b678da7ce46a9893d16039ad7e3e6..f8cd0b950957db41870d9bde71a1a68594ae45a2 100644 (file)
@@ -2,47 +2,24 @@
 
 var contactSelectorAction = 'acls-contacts';
 
-function addContact(tag, fullContactName, contactId, contactName,
-                    contactEmail) {
-   if (tag == "assistant")
-      addUser(contactName, contactId, false);
-   else if (tag == "delegate")
-      addUser(contactName, contactId, true);
-}
-
-function addUser(userName, userId, delegate) {
-   var uidList = $("uixselector-userRoles-uidList");
-   var uids;
-
-   if (uidList.value.length > 0) {
-      uids = uidList.value.split(",");
-   } else {
-      uids = new Array();
-   }
-
-   if (uids.indexOf(userId) < 0) {
-      uids.push(userId);
-      var ul = $("uixselector-userRoles-display");
-      ul.appendChild(nodeForUser(userName, userId));
-      uidList.value = uids.join(",");
-      var roleList;
-      if (delegate)
-        roleList = $("delegates");
-      else
-        roleList = $("assistants");
+function addUser(userName, userID) {
+   if (!$(userID)) {
+      var ul = $("userList");
+      ul.appendChild(nodeForUser(userName, userID));
+      var roleList = $("assistants");
       if (roleList.value.length > 0) {
-        uids = roleList.value.split(",");
-        uids.push(userId);
-        roleList.value = uids.join(",");
+        var uids = roleList.value.split(",");
+        uids.push(userID);
+        roleList.value = uids.join(",");
       }
       else
-        roleList.value = userId;
+        roleList.value = userID;
    }
 }
 
 function nodeForUser(userName, userId) {
    var node = document.createElement("li");
-   node.setAttribute("uid", userId);
+   node.setAttribute("id", userId);
    node.setAttribute("class", "");
    node.addEventListener("mousedown", listRowMouseDownHandler, true);
    node.addEventListener("click", onRowClick, true);
@@ -69,7 +46,7 @@ function updateSelectedRole(list) {
     select.style.visibility = "visible;";
     var selected = selection[0];
     var assistantsValue = $("assistants");
-    var uid = selected.getAttribute("uid");
+    var uid = selected.getAttribute("id");
     var regexp = new RegExp("(^|,)" + uid + "(,|$)","i");
     if (regexp.test(assistantsValue.value))
       select.selectedIndex = 0;
@@ -85,32 +62,6 @@ function onAclSelectionChange() {
   updateSelectedRole(this);
 }
 
-function onUsersChange(type) {
-  var select = $("userRoleDropDown");
-  if (type == "removal") {
-    var list;
-    if (select.selectedIndex == 0)
-      list = $("assistants");
-    else
-      list = $("delegates");
-
-    var uids = $("uixselector-userRoles-uidList");
-    var listArray = list.value.split(",");
-    var newListArray = new Array();
-    for (var i = 0; i < listArray.length; i++) {
-      var regexp = new RegExp("(^|,)" + listArray[i] + "($|,)");
-      if (regexp.test(uids.value))
-        newListArray.push(listArray[i]);
-    }
-    if (newListArray.length > 0)
-      list.value = newListArray.join(",");
-    else
-      list.value = "";
-  }
-
-  updateSelectedRole($("uixselector-userRoles-display"));
-}
-
 function onUserRoleDropDownChange() {
   var oldList;
   var newList;
@@ -123,7 +74,7 @@ function onUserRoleDropDownChange() {
     newList = $("delegates");
   }
 
-  var uid = $("uixselector-userRoles-display").getSelectedRows()[0].getAttribute("uid");
+  var uid = $("userList").getSelectedRows()[0].getAttribute("id");
   var newListArray;
   if (newList.value.length > 0) {
     newListArray = newList.value.split(",");
@@ -143,14 +94,55 @@ function onUserRoleDropDownChange() {
   log("delegates: " + $("delegates").value);
 }
 
-function onAclLoadHandler() {
-  $("userRoles").changeNotification = onUsersChange;
+function onUserAdd(event) {
+   openUserFolderSelector(null, "user");
+
+   event.preventDefault();
+}
+
+function onUserRemove(event) {
+   var userlist = $("userList");
+   var node = userlist.getSelectedRows()[0];
+   var uid = node.getAttribute("id");
+   var regexp = new RegExp("(^|,)" + uid + "($|,)");
+   var uids = $("assistants");
+   if (!regexp.test(uids.value))
+      uids = $("delegates");
+   if (regexp.test(uids.value)) {
+      var list = uids.value.split(",");
+      var newList = new Array();
+      for (var i = 0; i < list.length; i++) {
+        if (list[i] != uid)
+           newList.push(list[i]);
+      }
+      uids.value = newList.join(",");
+      node.parentNode.removeChild(node);
+   }
+   updateSelectedRole(userlist);
+   event.preventDefault();
+}
 
-  var ul = $("uixselector-userRoles-display");
+function subscribeToFolder(refreshCallback, refreshCallbackData) {
+   addUser(refreshCallbackData["folderName"],
+          refreshCallbackData["folder"]);
+}
+
+function onAclLoadHandler() {
+  var ul = $("userList");
   ul.addEventListener("selectionchange",
                       onAclSelectionChange, false);
+  var lis = ul.childNodesWithTag("li");
+  for (var i = 0; i < lis.length; i++) {
+     lis[i].addEventListener("mousedown", listRowMouseDownHandler, false);
+     lis[i].addEventListener("click", onRowClick, false);
+  }
+
   var select = $("userRoleDropDown");
   select.addEventListener("change", onUserRoleDropDownChange, false);
+
+  var buttons = $("userSelectorButtons").childNodesWithTag("a");
+  buttons[0].addEventListener("click", onUserAdd, false);
+  buttons[1].addEventListener("click", onUserRemove, false);
 }
 
 window.addEventListener("load", onAclLoadHandler, false);
diff --git a/UI/WebServerResources/UIxContactsUserFolders.css b/UI/WebServerResources/UIxContactsUserFolders.css
new file mode 100644 (file)
index 0000000..b502613
--- /dev/null
@@ -0,0 +1,41 @@
+DIV#filterPanel
+{ position: absolute;
+  text-align: center;
+  width: auto;
+  top: 1em;
+  left: 1em;
+  right: 1em; }
+
+SPAN.searchBox
+{ float: none !important; }
+
+INPUT#searchValue
+{ margin: 0px; }
+
+DIV#folders
+{ position: absolute;
+  left: 1em;
+  right: 1em;
+  top: 3em;
+  bottom: 3em;
+  background-color: #fff;
+  padding: .5em;
+  padding-top: 0px;
+  overflow: auto;
+  border-bottom: 1px solid #fff;
+  border-right: 1px solid #fff;
+  border-top: 2px solid #222;
+  border-left: 2px solid #222;
+  -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
+  -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent; }
+
+DIV#folders DIV
+{ width: auto; }
+
+DIV#buttons
+{ position: absolute;
+  text-align: center;
+  height: 1.5em;
+  left: 1em;
+  right: 1em;
+  bottom: 1em;  }
diff --git a/UI/WebServerResources/UIxContactsUserFolders.js b/UI/WebServerResources/UIxContactsUserFolders.js
new file mode 100644 (file)
index 0000000..06906f5
--- /dev/null
@@ -0,0 +1,138 @@
+function onSearchFormSubmit() {
+  var searchValue = $("searchValue");
+
+  var url = (ApplicationBaseURL
+            + "/foldersSearch?ldap-only=YES&search=" + searchValue.value
+            + "&type=" + window.userFolderType);
+  if (document.userFoldersRequest) {
+     document.userFoldersRequest.aborted = true;
+     document.userFoldersRequest.abort();
+  }
+  document.userFoldersRequest
+     = triggerAjaxRequest(url, userFoldersCallback);
+
+  return false;
+}
+
+function addLineToTree(tree, parent, line) {
+   var offset = 0;
+
+   var nodes = line.split(";");
+   if (window.userFolderType == "user"
+       || nodes.length > 1) {
+      var parentNode = nodes[0];
+      var userInfos = parentNode.split(":");
+      var email = userInfos[1].replace("<", "&lt;");
+      tree.add(parent, 0, email, 0, '#', userInfos[0], 'person',
+              '', '',
+              ResourcesURL + '/abcard.gif',
+              ResourcesURL + '/abcard.gif');
+      for (var i = 1; i < nodes.length; i++) {
+        var folderInfos = nodes[i].split(":");
+        var icon = ResourcesURL + '/';
+        if (folderInfos[2] == 'contact')
+           icon += 'tb-mail-addressbook-flat-16x16.png';
+        else
+           icon += 'calendar-folder-16x16.png';
+        var folderId = userInfos[0] + ":" + folderInfos[1];
+        tree.add(parent + i, parent, folderInfos[0], 0, '#', folderId,
+                 folderInfos[2] + '-folder', '', '', icon, icon);
+      }
+      offset = nodes.length - 1;
+   }
+   else
+      window.alert("nope:" + window.userFolderType);
+
+   return offset;
+}
+
+function buildTree(response) { 
+   d = new dTree("d");
+   d.config.folderLlinks = true;
+   d.config.hideRoot = true;
+   d.icon.root = ResourcesURL + '/tbtv_account_17x17.gif';
+   d.icon.folder = ResourcesURL + '/tbtv_leaf_corner_17x17.gif';
+   d.icon.folderOpen = ResourcesURL + '/tbtv_leaf_corner_17x17.gif';
+   d.icon.node = ResourcesURL + '/tbtv_leaf_corner_17x17.gif';
+   d.icon.line = ResourcesURL + '/tbtv_line_17x17.gif';
+   d.icon.join = ResourcesURL + '/tbtv_junction_17x17.gif';
+   d.icon.joinBottom = ResourcesURL + '/tbtv_corner_17x17.gif';
+   d.icon.plus = ResourcesURL + '/tbtv_plus_17x17.gif';
+   d.icon.plusBottom = ResourcesURL + '/tbtv_corner_plus_17x17.gif';
+   d.icon.minus = ResourcesURL + '/tbtv_minus_17x17.gif';
+   d.icon.minusBottom = ResourcesURL + '/tbtv_corner_minus_17x17.gif';
+   d.icon.nlPlus = ResourcesURL + '/tbtv_corner_plus_17x17.gif';
+   d.icon.nlMinus = ResourcesURL + '/tbtv_corner_minus_17x17.gif';
+   d.icon.empty = ResourcesURL + '/empty.gif';
+   d.add(0, -1, '');
+
+   var lines = response.split("\n");
+   var offset = 0;
+   for (var i = 0; i < lines.length; i++) {
+      if (lines[i].length > 0)
+        offset += addLineToTree(d, i + 1 + offset, lines[i]);
+   }
+
+   return d;
+}
+
+function onFolderTreeItemClick(event) {
+   event.preventDefault();
+
+   var topNode = $("d");
+   if (topNode.selectedEntry)
+      topNode.selectedEntry.deselect();
+   this.select();
+   topNode.selectedEntry = this;
+}
+
+function userFoldersCallback(http) {
+   if (http.readyState == 4) {
+      document.userFoldersRequest = null;
+      if (http.status == 200) {
+        var div = $("folders");
+        var response = http.responseText;
+        div.innerHTML = buildTree(http.responseText);
+        var nodes = document.getElementsByClassName("node", $("d"));
+        for (i = 0; i < nodes.length; i++)
+           nodes[i].addEventListener("click",
+                                     onFolderTreeItemClick, false);
+      }
+   }
+}
+
+function onConfirmFolderSelection(event) {
+   var topNode = $("d");
+   if (topNode.selectedEntry) {
+      var node = topNode.selectedEntry.parentNode;
+      var folder = node.getAttribute("dataname");
+      var folderName;
+      if (window.userFolderType == "user") {
+        var spans = document.getElementsByClassName("nodeName",
+                                                    topNode.selectedEntry);
+        var email = spans[0].innerHTML;
+        email = email.replace("&lt;", "<");
+        email = email.replace("&gt;", ">");
+        folderName = email;
+      }
+      else {
+        var spans1 = document.getElementsByClassName("nodeName",
+                                                  node);
+        var spans2 = document.getElementsByClassName("nodeName",
+                                                     node.parentNode.previousSibling);
+        var email = spans2[0].innerHTML;
+        email = email.replace("&lt;", "<");
+        email = email.replace("&gt;", ">");
+        folderName = spans1[0].innerHTML + ' (' + email + ')';
+      }
+      var data = { folderName: folderName, folder: folder };
+      window.opener.subscribeToFolder(window.userFolderCallback, data);
+   }
+}
+
+function initUserFoldersWindow() {
+   configureSearchField();
+   $("addButton").addEventListener("click", onConfirmFolderSelection, false);
+}
+
+window.addEventListener("load", initUserFoldersWindow, false);
index cde06ab8fe732d18782875b3798a1f4edb7f755f..839d8991f903db8ea5c2928f7a26564b67291acb 100644 (file)
@@ -1,5 +1,24 @@
 var contactSelectorAction = 'mailer-contacts';
 
+function onContactAdd() {
+  var selector = null;
+  var selectorURL = '?popup=YES&selectorId=mailer-contacts';
+  urlstr = ApplicationBaseURL;
+  if (urlstr[urlstr.length-1] != '/')
+    urlstr += '/';
+  urlstr += ("../../" + UserLogin + "/Contacts/"
+             + contactSelectorAction + selectorURL);
+//   log (urlstr);
+  var w = window.open(urlstr, "Addressbook",
+                      "width=640,height=400,resizable=1,scrollbars=0");
+  w.selector = selector;
+  w.opener = this;
+  w.focus();
+
+  return false;
+ }
+
 function addContact(tag, fullContactName, contactId, contactName, contactEmail) {
   if (!mailIsRecipient(contactEmail)) {
     var neededOptionValue = 0;
diff --git a/UI/WebServerResources/add-calendar.png b/UI/WebServerResources/add-calendar.png
new file mode 100644 (file)
index 0000000..3ef04b7
Binary files /dev/null and b/UI/WebServerResources/add-calendar.png differ
diff --git a/UI/WebServerResources/calendar-folder-16x16.png b/UI/WebServerResources/calendar-folder-16x16.png
new file mode 100644 (file)
index 0000000..977173e
Binary files /dev/null and b/UI/WebServerResources/calendar-folder-16x16.png differ
index b25c6d4a505d5d104a03a763c2d0f87788fafcb2..4169c19c1ecf0497aa0af620d45c53c4e8ad4a29 100644 (file)
@@ -720,6 +720,26 @@ A[class~="_disabled"].button:active
 { color: #999;
   background: inherit; }
 
+/* folder tree (js) )*/
+DIV.dTreeNode A SPAN.nodeName
+{
+  margin: 0px .2em;
+  padding-left: .2em;
+  padding-right: .2em;
+}
+
+DIV.dTreeNode A._selected SPAN.nodeName
+{
+  background: #4b6983;
+  color: #fff;
+}
+
+DIV.dTreeNode SPAN._dragOver
+{ 
+  background: #4b6983;
+  color: #fff;
+}
+
 /* tabs */
 DIV.tabsContainer
 { 
index 5b6a8fa10c59b446e0a9ac46a83f7093d6416b89..cd7923d24d466bcc4b074ced944cdc4c70ac2fb5 100644 (file)
@@ -110,6 +110,24 @@ function ml_stripActionInURL(url) {
   return url;
 }
 
+function URLForFolderID(folderID) {
+   var folderInfos = folderID.split(":");
+   var url;
+   if (folderInfos.length > 1) {
+      url = UserFolderURL + "../" + folderInfos[0];
+      if (folderInfos[1][0] != '/')
+        url += '/';
+      url += folderInfos[1];
+   }
+   else
+      url = ApplicationBaseURL + folderInfos[0];
+   
+   if (url[url.length-1] == '/')
+      url = url.substr(0, url.length-1);
+
+   return url;
+}
+
 function extractEmailAddress(mailTo) {
   var email = "";
 
@@ -148,6 +166,19 @@ function sanitizeMailTo(dirtyMailTo) {
   return mailto;
 }
 
+function openUserFolderSelector(callback, type) {
+   var urlstr = ApplicationBaseURL;
+   if (urlstr[urlstr.length-1] != '/')
+      urlstr += '/';
+   urlstr += ("../../" + UserLogin + "/Contacts/userFolders");
+   var w = window.open(urlstr, "User Selector",
+                      "width=322,height=250,resizable=1,scrollbars=0");
+   w.opener = window;
+   w.userFolderCallback = callback;
+   w.userFolderType = type;
+   w.focus();
+}
+
 function openMailComposeWindow(url) {
   var w = window.open(url, null,
                       "width=680,height=520,resizable=1,scrollbars=1,toolbar=0,"
@@ -633,8 +664,10 @@ function checkDropDown(event) {
 }
 
 /* search field */
-function popupSearchMenu(event, menuId) {
+function popupSearchMenu(event) {
   var node = event.target;
+
+  var menuId = this.getAttribute("menuid");
   relX = event.pageX - node.cascadeLeftOffset();
   relY = event.pageY - node.cascadeTopOffset();
 
@@ -679,50 +712,50 @@ function onSearchChange() {
   log ("onSearchChange()...");
 }
 
-function onSearchMouseDown(event, searchValue) {
-  superNode = searchValue.parentNode.parentNode.parentNode;
-  relX = (event.pageX - superNode.offsetLeft - searchValue.offsetLeft);
-  relY = (event.pageY - superNode.offsetTop - searchValue.offsetTop);
+function onSearchMouseDown(event) {
+   var superNode = this.parentNode.parentNode.parentNode;
+   relX = (event.pageX - superNode.offsetLeft - this.offsetLeft);
+   relY = (event.pageY - superNode.offsetTop - this.offsetTop);
 
-  if (relY < 24) {
-    event.cancelBubble = true;
-    event.returnValue = false;
-  }
+   if (relY < 24) {
+      event.cancelBubble = true;
+      event.returnValue = false;
+   }
 }
 
-function onSearchFocus(searchValue) {
-  ghostPhrase = searchValue.getAttribute("ghost-phrase");
-  if (searchValue.value == ghostPhrase) {
-    searchValue.value = "";
-    searchValue.setAttribute("modified", "");
+function onSearchFocus() {
+  ghostPhrase = this.getAttribute("ghost-phrase");
+  if (this.value == ghostPhrase) {
+    this.value = "";
+    this.setAttribute("modified", "");
   } else {
-    searchValue.select();
+    this.select();
   }
 
-  searchValue.style.color = "#000";
+  this.style.color = "#000";
 }
 
-function onSearchBlur(searchValue) {
-  var ghostPhrase = searchValue.getAttribute("ghost-phrase");
-//   log ("search blur: '" + searchValue.value + "'");
-  if (!searchValue.value) {
-    searchValue.setAttribute("modified", "");
-    searchValue.style.color = "#aaa";
-    searchValue.value = ghostPhrase;
-  } else if (searchValue.value == ghostPhrase) {
-    searchValue.setAttribute("modified", "");
-    searchValue.style.color = "#aaa";
+function onSearchBlur(event) {
+  var ghostPhrase = this.getAttribute("ghost-phrase");
+//   log ("search blur: '" + this.value + "'");
+  if (!this.value) {
+    this.setAttribute("modified", "");
+    this.style.color = "#aaa";
+    this.value = ghostPhrase;
+  } else if (this.value == ghostPhrase) {
+    this.setAttribute("modified", "");
+    this.style.color = "#aaa";
   } else {
-    searchValue.setAttribute("modified", "yes");
-    searchValue.style.color = "#000";
+    this.setAttribute("modified", "yes");
+    this.style.color = "#000";
   }
 }
 
-function onSearchKeyDown(searchValue) {
-  if (searchValue.timer)
-    clearTimeout(searchValue.timer);
+function onSearchKeyDown(event) {
+  if (this.timer)
+    clearTimeout(this.timer);
 
-  searchValue.timer = setTimeout("onSearchFormSubmit()", 1000);
+  this.timer = setTimeout("onSearchFormSubmit()", 1000);
 }
 
 function initCriteria() {
@@ -772,54 +805,75 @@ function popupToolbarMenu(event, menuId) {
 
 /* contact selector */
 
-function onContactAdd(node) {
-  var selector = null;
-  var selectorURL = '?popup=YES';
-  if (node) {
-    selector = node.parentNode.parentNode;
-    selectorURL += ("&selectorId=" + selector.getAttribute("id"));
-  }
-
-  urlstr = ApplicationBaseURL;
-  if (urlstr[urlstr.length-1] != '/')
-    urlstr += '/';
-  urlstr += ("../../" + UserLogin + "/Contacts/"
-             + contactSelectorAction + selectorURL);
-//   log (urlstr);
-  var w = window.open(urlstr, "Addressbook",
-                      "width=640,height=400,resizable=1,scrollbars=0");
-  w.selector = selector;
-  w.opener = this;
-  w.focus();
-
-  return false;
+function folderSubscriptionCallback(http) {
+   if (http.readyState == 4) {
+      if (http.status == 204) {
+        if (http.callbackData)
+           http.callbackData["method"](http.callbackData["data"]);
+      }
+      else
+        window.alert(labels["Unable to subscribe to that folder!"].decodeEntities());
+      document.subscriptionAjaxRequest = null;
+   }
+   else
+      log ("ajax fuckage");
+}
+
+function subscribeToFolder(refreshCallback, refreshCallbackData) {
+   var folderData = refreshCallbackData["folder"].split(":");
+   var username = folderData[0];
+   var folderPath = folderData[1];
+   if (username != UserLogin) {
+      var url = (UserFolderURL + "../" + username
+                + "/" + folderPath + "/subscribe");
+      if (document.subscriptionAjaxRequest) {
+        document.subscriptionAjaxRequest.aborted = true;
+        document.subscriptionAjaxRequest.abort();
+      }
+      var rfCbData = { method: refreshCallback, data: refreshCallbackData };
+      document.subscriptionAjaxRequest = triggerAjaxRequest(url,
+                                                           folderSubscriptionCallback,
+                                                           rfCbData);
+   }
+   else
+      window.alert(labels["You cannot subscribe to a folder that you own!"].decodeEntities());
 }
 
-function onContactRemove(node) {
-  var selector = node.parentNode.parentNode;
-  var selectorId = selector.getAttribute("id");
-  var hasChanged = false;
-
-  var names = $('uixselector-' + selectorId + '-display');
-  var nodes = names.getSelectedNodes();
-  hasChanged = (nodes.length > 0);
-  for (var i = 0; i < nodes.length; i++) {
-    var currentNode = nodes[i];
-    currentNode.parentNode.removeChild(currentNode);
-  }
-
-  var uids = $('uixselector-' + selectorId + '-uidList');
-  nodes = node.parentNode.childNodes;
-  var ids = new Array();
-  for (var i = 0; i < nodes.length; i++)
-    if (nodes[i] instanceof HTMLLIElement)
-      ids.push(nodes[i].getAttribute("uid"));
-  uids.value = ids.join(",");
-
-  if (selector.changeNotification && hasChanged)
-    selector.changeNotification("removal");
+function folderUnsubscriptionCallback(http) {
+   if (http.readyState == 4) {
+      if (http.status == 204) {
+        if (http.callbackData)
+           http.callbackData["method"](http.callbackData["data"]);
+      }
+      else
+        window.alert(labels["Unable to unsubscribe from that folder!"].decodeEntities());
+      document.unsubscriptionAjaxRequest = null;
+   }
+}
 
-  return false;
+function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
+   if (document.body.hasClassName("popup")) {
+      window.opener.unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData);
+   }
+   else {
+      var folderData = folder.split(":");
+      var username = folderData[0];
+      var folderPath = folderData[1];
+      if (username != UserLogin) {
+        var url = (UserFolderURL + "../" + username
+                   + "/" + folderPath + "/unsubscribe");
+        if (document.unsubscriptionAjaxRequest) {
+           document.unsubscriptionAjaxRequest.aborted = true;
+           document.unsubscriptionAjaxRequest.abort();
+        }
+        var rfCbData = { method: refreshCallback, data: refreshCallbackData };
+        document.unsubscriptionAjaxRequest = triggerAjaxRequest(url,
+                                                                folderUnsubscriptionCallback,
+                                                                rfCbData);
+      }
+      else
+        window.alert(labels["You cannot unsubscribe from a folder that you own!"].decodeEntities());
+   }
 }
 
 function listRowMouseDownHandler(event) {
@@ -881,13 +935,13 @@ function openExternalLink(anchor) {
   return false;
 }
 
-function openAclWindow(url, objectTitle) {
+function openAclWindow(url) {
   var w = window.open(url, "aclWindow",
                       "width=300,height=300,resizable=1,scrollbars=1,toolbar=0,"
                       + "location=0,directories=0,status=0,menubar=0"
                       + ",copyhistory=0");
+  w.opener = window;
   w.focus();
-  w.title = "Poil: " + objectTitle;
 
   return w;
 }
diff --git a/UI/WebServerResources/remove-calendar.png b/UI/WebServerResources/remove-calendar.png
new file mode 100644 (file)
index 0000000..c60dceb
Binary files /dev/null and b/UI/WebServerResources/remove-calendar.png differ
diff --git a/UI/WebServerResources/tb-mail-addressbook-flat-16x16.png b/UI/WebServerResources/tb-mail-addressbook-flat-16x16.png
new file mode 100644 (file)
index 0000000..6691dbb
Binary files /dev/null and b/UI/WebServerResources/tb-mail-addressbook-flat-16x16.png differ
index eb4703caa2318ae4bfef7a781d26da20c63a9d75..6fddf1f94d016766a2740ad8df3d34adacb8f7a5 100644 (file)
Binary files a/UI/WebServerResources/week-view.png and b/UI/WebServerResources/week-view.png differ