From 7a4b84b9b6fff1b2d4e937f27de7881c6f7ed2e3 Mon Sep 17 00:00:00 2001 From: C Robert Date: Mon, 24 Aug 2009 20:26:52 +0000 Subject: [PATCH] Finished vList implementation Monotone-Parent: 2570bc0c998646aa6c0501c971a29d77357cb7a1 Monotone-Revision: b798ab587b14c946102732e79770636904870654 Monotone-Author: crobert@inverse.ca Monotone-Date: 2009-08-24T20:26:52 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 7 + .../Localizable.strings | 9 + UI/Contacts/Czech.lproj/Localizable.strings | 9 + UI/Contacts/Dutch.lproj/Localizable.strings | 9 + UI/Contacts/English.lproj/Localizable.strings | 9 + UI/Contacts/French.lproj/Localizable.strings | 9 + UI/Contacts/German.lproj/Localizable.strings | 9 + .../Hungarian.lproj/Localizable.strings | 9 + UI/Contacts/Italian.lproj/Localizable.strings | 9 + UI/Contacts/Russian.lproj/Localizable.strings | 9 + UI/Contacts/Spanish.lproj/Localizable.strings | 9 + .../Toolbars/SOGoContactFolder.toolbar | 2 +- UI/Contacts/UIxContactsListView.m | 66 ++++++ UI/Contacts/UIxListEditor.h | 6 + UI/Contacts/UIxListEditor.m | 200 +++++++++++++++++- UI/Contacts/Welsh.lproj/Localizable.strings | 9 + UI/Contacts/product.plist | 5 + UI/MailerUI/UIxMailMainFrame.m | 105 +++++---- UI/Templates/ContactsUI/UIxListEditor.wox | 65 +++++- UI/WebServerResources/ContactsUI.js | 11 +- UI/WebServerResources/UIxMailEditor.js | 51 ++++- UI/WebServerResources/UIxPreferences.css | 2 +- 22 files changed, 571 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad5ec27ee..0174cf8f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-08-24 Cyril Robert + + * UI/MailerUI/UIxMailMainFrame.m: Refactoring + added vLists support. + * UI/Contacts/UIxListEditor.m: Implementation. + * UI/Contacts/UIxContactsListView.m (contactSearchAction): added to support + search in a single folder. + 2009-08-21 Cyril Robert * UI/Contacts/UIxListView.m: Implementation, allows VLISTs to be displayed. diff --git a/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings b/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings index 92c46f652..2b8097500 100644 --- a/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/Contacts/BrazilianPortuguese.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "Você não pode gravar neste catálogo."; "Invalid Contact" = "O contato selecionado não existe."; "Unknown Destination Folder" = "O catálogo de destino selecionado não existe."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/Czech.lproj/Localizable.strings b/UI/Contacts/Czech.lproj/Localizable.strings index 34e4e1de4..c4d276c2f 100644 --- a/UI/Contacts/Czech.lproj/Localizable.strings +++ b/UI/Contacts/Czech.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "Nemůžete zapisovat do tohoto adresáře."; "Invalid Contact" = "Označený kontakt již neexistuje."; "Unknown Destination Folder" = "Zvolený cílový adresář již neexistuje."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/Dutch.lproj/Localizable.strings b/UI/Contacts/Dutch.lproj/Localizable.strings index 1516269d6..f7524a16c 100644 --- a/UI/Contacts/Dutch.lproj/Localizable.strings +++ b/UI/Contacts/Dutch.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "You cannot write to this address book."; "Invalid Contact" = "The selected contact no longer exists."; "Unknown Destination Folder" = "The chosen destination address book no longer exists."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/English.lproj/Localizable.strings b/UI/Contacts/English.lproj/Localizable.strings index 2550a6771..5220f9b5e 100644 --- a/UI/Contacts/English.lproj/Localizable.strings +++ b/UI/Contacts/English.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "You cannot write to this address book."; "Invalid Contact" = "The selected contact no longer exists."; "Unknown Destination Folder" = "The chosen destination address book no longer exists."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/French.lproj/Localizable.strings b/UI/Contacts/French.lproj/Localizable.strings index 90e1c01e0..916522242 100644 --- a/UI/Contacts/French.lproj/Localizable.strings +++ b/UI/Contacts/French.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "Vous ne pouvez pas ajouter de fiches à ce carnet."; "Invalid Contact" = "La fiche sélectionnée n'existe plus."; "Unknown Destination Folder" = "Le carnet d'adresses choisi n'existe plus."; + +/* Lists */ +"List details" = "Détails"; +"List name:" = "Liste:"; +"List nickname:" = "Surnom:"; +"List description:" = "Description:"; +"Members" = "Membres"; +"Contacts" = "Contacts"; +"Add" = "Ajouter"; diff --git a/UI/Contacts/German.lproj/Localizable.strings b/UI/Contacts/German.lproj/Localizable.strings index 8755d4bef..7b4b4431f 100644 --- a/UI/Contacts/German.lproj/Localizable.strings +++ b/UI/Contacts/German.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "Sie können nicht auf dieses Adressbuch schreiben."; "Invalid Contact" = "Der gewählte Kontakt existiert nicht mehr."; "Unknown Destination Folder" = "Das gewählte Ziel-Adressbuch existiert nicht mehr."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/Hungarian.lproj/Localizable.strings b/UI/Contacts/Hungarian.lproj/Localizable.strings index a4c9f0a1b..4386ea88e 100644 --- a/UI/Contacts/Hungarian.lproj/Localizable.strings +++ b/UI/Contacts/Hungarian.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "Ön nem írhat ebbe a címjegyzékbe."; "Invalid Contact" = "A kijelölt kapcsolat már nem létezik."; "Unknown Destination Folder" = "A kijelölt címjegyzék már nem elérhető."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/Italian.lproj/Localizable.strings b/UI/Contacts/Italian.lproj/Localizable.strings index 873183cd5..40213f802 100644 --- a/UI/Contacts/Italian.lproj/Localizable.strings +++ b/UI/Contacts/Italian.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "You cannot write to this address book."; "Invalid Contact" = "The selected contact no longer exists."; "Unknown Destination Folder" = "The chosen destination address book no longer exists."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/Russian.lproj/Localizable.strings b/UI/Contacts/Russian.lproj/Localizable.strings index e863a72c4..d68b6350e 100644 --- a/UI/Contacts/Russian.lproj/Localizable.strings +++ b/UI/Contacts/Russian.lproj/Localizable.strings @@ -153,3 +153,12 @@ "Forbidden" = "You cannot write to this address book."; "Invalid Contact" = "The selected contact no longer exists."; "Unknown Destination Folder" = "The chosen destination address book no longer exists."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/Spanish.lproj/Localizable.strings b/UI/Contacts/Spanish.lproj/Localizable.strings index 857a211b0..b97a7b61b 100644 --- a/UI/Contacts/Spanish.lproj/Localizable.strings +++ b/UI/Contacts/Spanish.lproj/Localizable.strings @@ -168,3 +168,12 @@ "Forbidden" = "You cannot write to this address book."; "Invalid Contact" = "The selected contact no longer exists."; "Unknown Destination Folder" = "The chosen destination address book no longer exists."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/Toolbars/SOGoContactFolder.toolbar b/UI/Contacts/Toolbars/SOGoContactFolder.toolbar index 3143697a3..e05a4d7bb 100644 --- a/UI/Contacts/Toolbars/SOGoContactFolder.toolbar +++ b/UI/Contacts/Toolbars/SOGoContactFolder.toolbar @@ -7,9 +7,9 @@ onclick = "newContact(this); return false;"; tooltip = "Create a new address book card"; }, { link = "new_list"; - enabled = "NO"; label="New List"; image="new-list.png"; + onclick = "newList(this); return false;"; tooltip = "Create a new list"; } ), ( diff --git a/UI/Contacts/UIxContactsListView.m b/UI/Contacts/UIxContactsListView.m index d04de0c09..f0b3f289c 100644 --- a/UI/Contacts/UIxContactsListView.m +++ b/UI/Contacts/UIxContactsListView.m @@ -19,6 +19,12 @@ 02111-1307, USA. */ +#import +#import +#import +#import + +#import #import #import #import @@ -103,6 +109,66 @@ return contactInfos; } +- (id ) contactSearchAction +{ + id result; + id folder; + NSString *searchText, *mail; + NSDictionary *contact, *data; + NSArray *contacts, *descriptors, *sortedContacts; + NSMutableDictionary *uniqueContacts; + unsigned int i; + NSSortDescriptor *commonNameDescriptor; + + searchText = [self queryParameterForKey: @"search"]; + if ([searchText length] > 0) + { + NS_DURING + folder = [self clientObject]; + NS_HANDLER + if ([[localException name] isEqualToString: @"SOGoDBException"]) + folder = nil; + else + [localException raise]; + NS_ENDHANDLER + + uniqueContacts = [NSMutableDictionary dictionary]; + contacts = [folder lookupContactsWithFilter: searchText + sortBy: @"c_cn" + ordering: NSOrderedAscending]; + for (i = 0; i < [contacts count]; i++) + { + contact = [contacts objectAtIndex: i]; + mail = [contact objectForKey: @"c_mail"]; + if ([mail isNotNull] && [uniqueContacts objectForKey: mail] == nil) + [uniqueContacts setObject: contact forKey: mail]; + } + + if ([uniqueContacts count] > 0) + { + // Sort the contacts by display name + commonNameDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"c_cn" + ascending:YES] autorelease]; + descriptors = [NSArray arrayWithObjects: commonNameDescriptor, nil]; + sortedContacts = [[uniqueContacts allValues] sortedArrayUsingDescriptors: descriptors]; + } + else + sortedContacts = [NSArray array]; + + data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText", + sortedContacts, @"contacts", nil]; + result = [self responseWithStatus: 200]; + + [(WOResponse*)result appendContentString: [data jsonRepresentation]]; + } + else + result = [NSException exceptionWithHTTPStatus: 400 + reason: @"missing 'search' parameter"]; + + return result; +} + + /* actions */ - (BOOL) shouldTakeValuesFromRequest: (WORequest *) _rq diff --git a/UI/Contacts/UIxListEditor.h b/UI/Contacts/UIxListEditor.h index c48b42d68..72f3ce5af 100644 --- a/UI/Contacts/UIxListEditor.h +++ b/UI/Contacts/UIxListEditor.h @@ -24,8 +24,14 @@ #define UIXLISTEDITOR_H #import +#import @interface UIxListEditor : UIxComponent +{ + NGVList *list; + SOGoContactGCSList *co; + id reference; +} @end diff --git a/UI/Contacts/UIxListEditor.m b/UI/Contacts/UIxListEditor.m index f5ee19859..aa18e5123 100644 --- a/UI/Contacts/UIxListEditor.m +++ b/UI/Contacts/UIxListEditor.m @@ -20,33 +20,204 @@ * Boston, MA 02111-1307, USA. */ +#import +#import +#import + #import #import +#import #import +#import +#import #import "UIxListEditor.h" @implementation UIxListEditor + +- (NSString *) name +{ + return [list fn]; +} +- (void) setName: (NSString *) newName +{ + [list setFn: newName]; +} + +- (NSString *) nickname +{ + return [list nickname]; +} +- (void) setNickname: (NSString *) newName +{ + [list setNickname: newName]; +} + +- (NSString *) description +{ + return [list description]; +} +- (void) setDescription: (NSString *) newDescription +{ + [list setDescription: newDescription]; +} + +- (NSArray *) references +{ + NSMutableArray *rc; + NSMutableDictionary *row; + id ref; + int i, count; + + rc = [NSMutableArray array]; + count = [[list cardReferences] count]; + + for (i = 0; i < count; i++) + { + ref = [[list cardReferences] objectAtIndex: i]; + row = [NSMutableDictionary dictionary]; + [row setObject: [NSString stringWithFormat: @"%@ <%@>", [ref fn], [ref email]] + forKey: @"name"]; + [row setObject: [ref reference] forKey: @"id"]; + [rc addObject: row]; + } + + return rc; +} + +- (void) setReferencesValue: (NSString *) value +{ + NSData *data; + NSDictionary *references; + NSArray *values, *initialReferences; + NSString *error, *currentReference; + NSPropertyListFormat format; + int i, count; + NGVCardReference *cardReference; + + data = [value dataUsingEncoding: NSUTF8StringEncoding]; + references = [NSPropertyListSerialization propertyListFromData: data + mutabilityOption: NSPropertyListImmutable + format: &format + errorDescription: &error]; + if(!references) + { + NSLog(error); + [error release]; + } + else + { + // Remove from list + initialReferences = [list cardReferences]; + count = [initialReferences count]; + + for (i = 0; i < count; i++) + { + cardReference = [initialReferences objectAtIndex: i]; + if (![[references allKeys] containsObject: [cardReference reference]]) + [list deleteCardReference: cardReference]; + } + + // Add new objects + initialReferences = [list cardReferences]; + count = [[references allKeys] count]; + + for (i = 0; i < count; i++) + { + currentReference = [[references allKeys] objectAtIndex: i]; + if (![self cardReferences: initialReferences + contain: currentReference]) + { + NSLog (@"Adding a new cardRef"); + values = [references objectForKey: currentReference]; + cardReference = [NGVCardReference elementWithTag: @"card"]; + [cardReference setFn: [values objectAtIndex: 0]]; + [cardReference setEmail: [values objectAtIndex: 1]]; + [cardReference setReference: currentReference]; + [list addCardReference: cardReference]; + } + } + } +} +- (BOOL) cardReferences: (NSArray *) references + contain: (NSString *) ref +{ + int i, count; + BOOL rc = NO; + + count = [references count]; + for (i = 0; i < count; i++) + { + if ([ref isEqualToString: [[references objectAtIndex: i] reference]]) + { + rc = YES; + break; + } + } + + return rc; +} + - (NSString *) saveURL { return [NSString stringWithFormat: @"%@/saveAsList", [[self clientObject] baseURL]]; } +- (BOOL) canCreateOrModify +{ + return ([co isKindOfClass: [SOGoContentObject class]] + && [super canCreateOrModify]); +} + +- (id ) defaultAction +{ + co = [self clientObject]; + list = [co vList]; + if (list) + NSLog (@"Found list"); + else + return [NSException exceptionWithHTTPStatus:404 /* Not Found */ + reason: @"could not open list"]; + + return self; +} + +- (void) takeValuesFromRequest: (WORequest *) _rq + inContext: (WOContext *) _ctx +{ + co = [self clientObject]; + list = [co vList]; + + [super takeValuesFromRequest: _rq inContext: _ctx]; +} + +- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request + inContext: (WOContext*) context +{ + NSString *actionName; + + actionName = [[request requestHandlerPath] lastPathComponent]; + + return ([[self clientObject] isKindOfClass: [SOGoContactGCSList class]] + && [actionName hasPrefix: @"save"]); +} + + + #warning Could this be part of a common parent with UIxAppointment/UIxTaskEditor/UIxListEditor ? - (id) newAction { NSString *objectId, *method, *uri; id result; - SOGoContactGCSFolder *co; co = [self clientObject]; objectId = [co globallyUniqueObjectId]; if ([objectId length] > 0) { - method = [NSString stringWithFormat:@"%@/%@.vls/editAsList", + method = [NSString stringWithFormat:@"%@/%@.vlf/editAsList", [co soURL], objectId]; uri = [self completeHrefForMethod: method]; result = [self redirectToLocation: uri]; @@ -58,4 +229,29 @@ return result; } +- (id ) saveAction +{ + id result; + NSString *jsRefreshMethod; + + if (co) + { + [co save]; + if ([[[[self context] request] formValueForKey: @"nojs"] intValue]) + result = [self redirectToLocation: [self applicationPath]]; + else + { + jsRefreshMethod + = [NSString stringWithFormat: @"refreshContacts(\"%@\")", + [co nameInContainer]]; + result = [self jsCloseWithRefreshMethod: jsRefreshMethod]; + } + } + else + result = [NSException exceptionWithHTTPStatus: 400 /* Bad Request */ + reason: @"method cannot be invoked on " + @"the specified object"]; + return result; +} + @end diff --git a/UI/Contacts/Welsh.lproj/Localizable.strings b/UI/Contacts/Welsh.lproj/Localizable.strings index 576f561e3..0f4cdd56b 100644 --- a/UI/Contacts/Welsh.lproj/Localizable.strings +++ b/UI/Contacts/Welsh.lproj/Localizable.strings @@ -152,3 +152,12 @@ "Forbidden" = "Ni fedrwch ysgrifennu i'r llyfr cyfeiriadau hwn."; "Invalid Contact" = "Nid yw'r cyswllt dewisol yn bodoli mwyach."; "Unknown Destination Folder" = "Nid yw'r llyfr cyfeiriadau dewisol yn bodoli mwyach."; + +/* Lists */ +"List details" = "List details"; +"List name:" = "List name:"; +"List nickname:" = "List nickname:"; +"List description:" = "List description:"; +"Members" = "Members"; +"Contacts" = "Contacts"; +"Add" = "Add"; diff --git a/UI/Contacts/product.plist b/UI/Contacts/product.plist index 24f3fbf27..9c8b0c75d 100644 --- a/UI/Contacts/product.plist +++ b/UI/Contacts/product.plist @@ -78,6 +78,11 @@ protectedBy = "View"; pageName = "UIxContactsListView"; }; + contactSearch = { + protectedBy = ""; + pageName = "UIxContactsListView"; + actionName = "contactSearch"; + }; newcontact = { protectedBy = ""; pageName = "UIxContactEditor"; diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m index edfba7bb8..881281b17 100644 --- a/UI/MailerUI/UIxMailMainFrame.m +++ b/UI/MailerUI/UIxMailMainFrame.m @@ -25,6 +25,7 @@ #import #import +#import #import #import #import @@ -32,6 +33,8 @@ #import #import +#import +#import #import #import @@ -154,18 +157,18 @@ - (id ) composeAction { - id contact; - NSArray *accounts, *contactsId, *n; - NSString *firstAccount, *newLocation, *parameters, *folderId, *uid, *email; - NSMutableString *fn; + id contact; + NSArray *accounts, *contactsId, *cards; + NSString *firstAccount, *newLocation, *parameters, *folderId, *uid; NSEnumerator *uids; NSMutableArray *addresses; NGVCard *card; + NGVList *list; SOGoMailAccounts *co; SOGoContactFolders *folders; SOGoParentFolder *folder; WORequest *request; - unsigned int max; + int i, count; parameters = nil; co = [self clientObject]; @@ -198,43 +201,21 @@ contact = [folder lookupName: uid inContext: [self context] acquire: NO]; - if (![(NSObject*)contact isKindOfClass: [NSException class]]) + if ([contact isKindOfClass: [SOGoContactGCSList class]]) + { + list = [contact vList]; + cards = [list cardReferences]; + count = [cards count]; + for (i = 0; i < count; i++) + [addresses addObject: + [self formattedMailtoString: [cards objectAtIndex: i]]]; + } + else if ([contact isKindOfClass: [SOGoContactGCSEntry class]]) { // We fetch the preferred email address of the contact or // the first defined email address card = [contact vCard]; - email = [card preferredEMail]; - if (email == nil) - email = (NSString*)[card firstChildWithTag: @"EMAIL"]; - if (email) - { - email = [NSString stringWithFormat: @"<%@>", email]; - - // We append the contact's name - fn = [NSMutableString stringWithString: [card fn]]; - if ([fn length] == 0) - { - n = [card n]; - if (n) - { - max = [n count]; - if (max > 0) - { - if (max > 1) - fn = [NSMutableString stringWithFormat: @"%@ %@", [n objectAtIndex: 1], [n objectAtIndex: 0]]; - else - fn = [NSMutableString stringWithString: [n objectAtIndex: 0]]; - } - } - } - if (fn) - { - [fn appendFormat: @" %@", email]; - [addresses addObject: fn]; - } - else - [addresses addObject: email]; - } + [addresses addObject: [self formattedMailtoString: card]]; } uid = [uids nextObject]; } @@ -259,6 +240,54 @@ return [self redirectToLocation: newLocation]; } +- (NSString *) formattedMailtoString: (NGVCard *) card +{ + NSString *email; + NSMutableString *fn, *rc = nil; + NSArray *n; + unsigned int max; + + if ([card respondsToSelector: @selector (preferredEMail)]) + email = [card preferredEMail]; + else + email = [card email]; + + if (email == nil) + email = (NSString*)[card firstChildWithTag: @"EMAIL"]; + + if (email) + { + email = [NSString stringWithFormat: @"<%@>", email]; + + // We append the contact's name + fn = [NSMutableString stringWithString: [card fn]]; + if ([fn length] == 0) + { + n = [card n]; + if (n) + { + max = [n count]; + if (max > 0) + { + if (max > 1) + fn = [NSMutableString stringWithFormat: @"%@ %@", [n objectAtIndex: 1], [n objectAtIndex: 0]]; + else + fn = [NSMutableString stringWithString: [n objectAtIndex: 0]]; + } + } + } + if (fn) + { + [fn appendFormat: @" %@", email]; + rc = fn; + } + else + rc = email; + } + + return rc; +} + - (WOResponse *) getFoldersStateAction { NSString *expandedFolders; diff --git a/UI/Templates/ContactsUI/UIxListEditor.wox b/UI/Templates/ContactsUI/UIxListEditor.wox index 02bb02116..e4842236e 100644 --- a/UI/Templates/ContactsUI/UIxListEditor.wox +++ b/UI/Templates/ContactsUI/UIxListEditor.wox @@ -9,4 +9,67 @@ className="UIxPageFrame" title="name" const:popup="YES" - >Unimplemented + const:jsFiles="UIxMailEditor.js" + > +
+
    +
    +
    +
    +

    + + + + + + +
    +

    +
    + + + + + + + + + + + + +
    + +
    + +
    +
    +
    + +
    + + +
    +
    + + +
    +
    + diff --git a/UI/WebServerResources/ContactsUI.js b/UI/WebServerResources/ContactsUI.js index a91ee8df1..c9dcd2288 100644 --- a/UI/WebServerResources/ContactsUI.js +++ b/UI/WebServerResources/ContactsUI.js @@ -501,6 +501,11 @@ function newContact(sender) { return false; /* stop following the link */ } +function newList(sender) { + openContactWindow(URLForFolderID(Contact.currentAddressBook) + "/newlist"); + return false; +} + function onFolderSelectionChange(event) { var folderList = $("contactFolders"); var nodes = folderList.getSelectedNodes(); @@ -1039,8 +1044,10 @@ function onDocumentKeydown(event) { function fixSearchFieldPosition () { var panel = $("filterPanel"); - panel.style.position = "relative"; - panel.style.top = "3px"; + if (panel) { + panel.style.position = "relative"; + panel.style.top = "3px"; + } } function initContacts(event) { diff --git a/UI/WebServerResources/UIxMailEditor.js b/UI/WebServerResources/UIxMailEditor.js index 1136451ae..961dd7cbf 100644 --- a/UI/WebServerResources/UIxMailEditor.js +++ b/UI/WebServerResources/UIxMailEditor.js @@ -360,9 +360,33 @@ function onContactBlur(event) { MailEditor.currentField = null; } +function findPos(obj) { + var curleft = curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } while (obj = obj.offsetParent); + } + return [curleft,curtop]; +} + function performSearch() { // Perform address completion - if (MailEditor.currentField) { + var reference = $("referenceList"); + if (reference) { + var field = reference.down ("TD.editing INPUT"); + if (field && field.value.trim().length > 2) { + /*var pos = findPos (field); + $('contactsMenu').absolutize (); + $('contactsMenu').style.top = pos[1];*/ + var urlstr = window.location.href + "/../../contactSearch?search=" + + encodeURIComponent (field.value.trim()); + document.contactLookupAjaxRequest = + triggerAjaxRequest(urlstr, performSearchCallback, field); + } + } + else if (MailEditor.currentField) { if (document.contactLookupAjaxRequest) { // Abort any pending request document.contactLookupAjaxRequest.aborted = true; @@ -402,6 +426,8 @@ function performSearchCallback(http) { var contact = data.contacts[i]; var completeEmail = contact["c_cn"] + " <" + contact["c_mail"] + ">"; var node = new Element('li', { 'address': completeEmail }); + node.writeAttribute("mail", contact["c_mail"]); + node.writeAttribute("name", contact["c_cn"]); var matchPosition = completeEmail.toLowerCase().indexOf(data.searchText.toLowerCase()); var matchBefore = completeEmail.substring(0, matchPosition); var matchText = completeEmail.substring(matchPosition, matchPosition + data.searchText.length); @@ -417,8 +443,8 @@ function performSearchCallback(http) { } // Show popup menu - var offsetScroll = Element.cumulativeScrollOffset(MailEditor.currentField); - var offset = Element.cumulativeOffset(MailEditor.currentField); + var offsetScroll = Element.cumulativeScrollOffset(input); + var offset = Element.cumulativeOffset(input); var top = offset[1] - offsetScroll[1] + node.offsetHeight + 3; var height = 'auto'; var heightDiff = window.height() - offset[1]; @@ -445,6 +471,12 @@ function performSearchCallback(http) { // Single result var contact = data.contacts[0]; input.uid = contact["c_name"]; + if ($("referenceList")) { + var line = $(input).ancestors().first(); + line.writeAttribute ("card", contact["c_name"]); + line.writeAttribute ("name", contact["c_cn"]); + line.writeAttribute ("mail", contact["c_mail"]); + } var completeEmail = contact["c_cn"] + " <" + contact["c_mail"] + ">"; if (contact["c_cn"].substring(0, input.value.length).toUpperCase() == input.value.toUpperCase()) @@ -469,6 +501,16 @@ function performSearchCallback(http) { } function onAddressResultClick(event) { + var reference = $("referenceList"); + if (reference) { + var field = reference.down ("TD.editing INPUT"); + var td = reference.down ("TD.editing"); + td.writeAttribute ("card", this.uid); + td.writeAttribute ("mail", this.readAttribute("mail")); + td.writeAttribute ("name", this.readAttribute("name")); + field.value = $(this).readAttribute("address"); + endAllEditables (); + } if (MailEditor.currentField) { MailEditor.currentField.uid = this.uid; MailEditor.currentField.value = $(this).readAttribute("address"); @@ -492,6 +534,7 @@ function initTabIndex(addressList, subjectField, msgArea) { function initMailEditor() { var list = $("attachments"); + if (!list) return; $(list).attachMenu("attachmentsMenu"); var elements = $(list).childNodesWithTag("li"); for (var i = 0; i < elements.length; i++) @@ -669,6 +712,8 @@ function onSelectPriority(event) { } function onWindowResize(event) { + if (!document.pageform) + return; var textarea = document.pageform.text; var rowheight = (Element.getHeight(textarea) / textarea.rows); var headerarea = $("headerArea"); diff --git a/UI/WebServerResources/UIxPreferences.css b/UI/WebServerResources/UIxPreferences.css index d7e43a18e..43171760d 100644 --- a/UI/WebServerResources/UIxPreferences.css +++ b/UI/WebServerResources/UIxPreferences.css @@ -64,4 +64,4 @@ DIV#windowButtons height: 3.5em; line-height: 2em; vertical-align: middle; - text-align: right; } \ No newline at end of file + text-align: right; }