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.sogomaint-2.0.2
parent
2f39baacc1
commit
7a4b84b9b6
|
@ -1,3 +1,10 @@
|
|||
2009-08-24 Cyril Robert <crobert@inverse.ca>
|
||||
|
||||
* 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 <crobert@inverse.ca>
|
||||
|
||||
* UI/Contacts/UIxListView.m: Implementation, allows VLISTs to be displayed.
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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"; }
|
||||
),
|
||||
(
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
||||
#import <SoObjects/SOGo/NSDictionary+Utilities.h>
|
||||
#import <SoObjects/SOGo/NSString+Utilities.h>
|
||||
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
|
@ -103,6 +109,66 @@
|
|||
return contactInfos;
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) contactSearchAction
|
||||
{
|
||||
id <WOActionResults> result;
|
||||
id <SOGoContactFolder> 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
|
||||
|
|
|
@ -24,8 +24,14 @@
|
|||
#define UIXLISTEDITOR_H
|
||||
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
#import <SoObjects/Contacts/SOGoContactGCSList.h>
|
||||
|
||||
@interface UIxListEditor : UIxComponent
|
||||
{
|
||||
NGVList *list;
|
||||
SOGoContactGCSList *co;
|
||||
id reference;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -20,33 +20,204 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
#import <Foundation/NSPropertyList.h>
|
||||
|
||||
#import <Contacts/SOGoContactGCSFolder.h>
|
||||
#import <NGCards/NGVCardReference.h>
|
||||
#import <NGCards/NGVList.h>
|
||||
|
||||
#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 <WOActionResults>) 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 <WOActionResults> 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 <WOActionResults>) 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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -78,6 +78,11 @@
|
|||
protectedBy = "View";
|
||||
pageName = "UIxContactsListView";
|
||||
};
|
||||
contactSearch = {
|
||||
protectedBy = "<public>";
|
||||
pageName = "UIxContactsListView";
|
||||
actionName = "contactSearch";
|
||||
};
|
||||
newcontact = {
|
||||
protectedBy = "<public>";
|
||||
pageName = "UIxContactEditor";
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#import <Foundation/NSUserDefaults.h>
|
||||
|
||||
#import <NGCards/NGVCard.h>
|
||||
#import <NGCards/NGVList.h>
|
||||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WORequest.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
|
@ -32,6 +33,8 @@
|
|||
#import <NGExtensions/NSString+misc.h>
|
||||
|
||||
#import <Contacts/SOGoContactObject.h>
|
||||
#import <Contacts/SOGoContactGCSList.h>
|
||||
#import <Contacts/SOGoContactGCSEntry.h>
|
||||
#import <Contacts/SOGoContactFolders.h>
|
||||
|
||||
#import <SoObjects/Mailer/SOGoMailObject.h>
|
||||
|
@ -154,18 +157,18 @@
|
|||
|
||||
- (id <WOActionResults>) composeAction
|
||||
{
|
||||
id <SOGoContactObject> 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;
|
||||
|
|
|
@ -9,4 +9,67 @@
|
|||
className="UIxPageFrame"
|
||||
title="name"
|
||||
const:popup="YES"
|
||||
>Unimplemented</var:component>
|
||||
const:jsFiles="UIxMailEditor.js"
|
||||
>
|
||||
<div class="popupMenu" id="contactsMenu">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<form var:href="saveURL" name="editform"
|
||||
onsubmit="return validateListEditor();">
|
||||
<div id="listEditor">
|
||||
<h3><var:string label:value="List details" /></h3>
|
||||
<table><tr><td><var:string label:value="List name:"/></td>
|
||||
<td><input type="text" const:id="name" const:name="name"
|
||||
var:value="name" class="textField" /></td></tr>
|
||||
<tr><td><var:string label:value="List nickname:"/></td>
|
||||
<td><input type="text" const:id="nickname" const:name="nickname"
|
||||
var:value="nickname" class="textField" /></td></tr>
|
||||
<tr><td><var:string label:value="List description:"/></td>
|
||||
<td><input type="text" const:id="description" const:name="description"
|
||||
var:value="description" class="textField" /></td></tr>
|
||||
</table>
|
||||
<h3><var:string label:value="Members" /></h3>
|
||||
<div id="referenceListWrapper">
|
||||
<table id="referenceList" cellspacing="0">
|
||||
<thead>
|
||||
<tr class="tableview">
|
||||
<td const:class="tbtv_headercell" const:id="nameTableHeader">
|
||||
<var:string label:value="Contacts" />
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<var:foreach list="references" item="reference">
|
||||
<tr const:class="referenceListRow">
|
||||
<td const:class="referenceListCell" var:card="reference.id">
|
||||
<var:string var:value="reference.name"/>
|
||||
</td></tr>
|
||||
</var:foreach>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="referencesValue" id="referencesValue"
|
||||
var:value="referencesValue" />
|
||||
<div id="windowButtons">
|
||||
<label><input type="button" class="button"
|
||||
id="referenceAdd" label:value="Add"/></label>
|
||||
<label><input type="button" class="button"
|
||||
id="referenceDelete" label:value="Delete"/></label>
|
||||
</div>
|
||||
<div id="buttons">
|
||||
<input
|
||||
id="cancelButton"
|
||||
type="button"
|
||||
class="button"
|
||||
label:value="Cancel"
|
||||
name="cancel"/>
|
||||
<var:if condition="canCreateOrModify"
|
||||
><input
|
||||
type="submit"
|
||||
class="button"
|
||||
label:value="Save"
|
||||
name="submit" /></var:if>
|
||||
</div>
|
||||
</form>
|
||||
</var:component>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -64,4 +64,4 @@ DIV#windowButtons
|
|||
height: 3.5em;
|
||||
line-height: 2em;
|
||||
vertical-align: middle;
|
||||
text-align: right; }
|
||||
text-align: right; }
|
||||
|
|
Loading…
Reference in New Issue