mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-10-13 07:47:12 +00:00
Merge branch 'feature-5726-gab-autocomplete'
This commit is contained in:
commit
fb542e6e26
6 files changed
+164
-20
No files matched your search
@@ -271,6 +271,9 @@ static NSArray *folderListingFields = nil;
|
|||||||
if ([data length])
|
if ([data length])
|
||||||
[contactRecord setObject: data forKey: @"id"];
|
[contactRecord setObject: data forKey: @"id"];
|
||||||
|
|
||||||
|
// Container name
|
||||||
|
[contactRecord setObject: [self displayName] forKey: @"containerName"];
|
||||||
|
|
||||||
// c_cn
|
// c_cn
|
||||||
data = [contactRecord objectForKey: @"c_cn"];
|
data = [contactRecord objectForKey: @"c_cn"];
|
||||||
if (![data length])
|
if (![data length])
|
||||||
|
|||||||
@@ -242,6 +242,10 @@
|
|||||||
//source id
|
//source id
|
||||||
[newRecord setObject: [source sourceID] forKey: @"sourceID"];
|
[newRecord setObject: [source sourceID] forKey: @"sourceID"];
|
||||||
|
|
||||||
|
//source display name
|
||||||
|
[newRecord setObject: [self displayName]
|
||||||
|
forKey: @"containerName"];
|
||||||
|
|
||||||
// c_name => id
|
// c_name => id
|
||||||
[newRecord setObject: [oldRecord objectForKey: @"c_name"]
|
[newRecord setObject: [oldRecord objectForKey: @"c_name"]
|
||||||
forKey: @"c_name"];
|
forKey: @"c_name"];
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
#import <SoObjects/Contacts/SOGoContactGCSEntry.h>
|
#import <SoObjects/Contacts/SOGoContactGCSEntry.h>
|
||||||
#import <SoObjects/Contacts/SOGoContactGCSFolder.h>
|
#import <SoObjects/Contacts/SOGoContactGCSFolder.h>
|
||||||
|
#import <SoObjects/Contacts/SOGoContactSourceFolder.h>
|
||||||
|
|
||||||
#import "UIxContactsListActions.h"
|
#import "UIxContactsListActions.h"
|
||||||
|
|
||||||
@@ -140,17 +141,18 @@
|
|||||||
{
|
{
|
||||||
id <SOGoContactFolder> folder;
|
id <SOGoContactFolder> folder;
|
||||||
NSString *ascending, *valueText;
|
NSString *ascending, *valueText;
|
||||||
NSArray *results, *searchFields, *fields;
|
NSArray *searchFields, *fields, *folders, *tmpGlobalAddressBookResults;
|
||||||
NSMutableArray *filteredContacts, *headers;
|
NSMutableArray *filteredContacts, *headers, *results, *globalAddressBookResults;
|
||||||
NSDictionary *data, *contact;
|
NSDictionary *data, *contact;
|
||||||
BOOL excludeLists;
|
BOOL excludeLists;
|
||||||
NSComparisonResult ordering;
|
NSComparisonResult ordering;
|
||||||
NSUInteger max, count;
|
NSUInteger max, count;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
NSSortDescriptor *descriptor;
|
||||||
|
NSMutableDictionary *tmpDict;
|
||||||
|
|
||||||
if (!contactInfos)
|
if (!contactInfos)
|
||||||
{
|
{
|
||||||
folder = [self clientObject];
|
|
||||||
data = [self requestData];
|
data = [self requestData];
|
||||||
|
|
||||||
ascending = [data objectForKey: @"asc"];
|
ascending = [data objectForKey: @"asc"];
|
||||||
@@ -167,11 +169,78 @@
|
|||||||
excludeLists = [[data objectForKey: @"excludeLists"] boolValue];
|
excludeLists = [[data objectForKey: @"excludeLists"] boolValue];
|
||||||
|
|
||||||
[contactInfos release];
|
[contactInfos release];
|
||||||
results = [folder lookupContactsWithFilter: valueText
|
|
||||||
onCriteria: searchFields
|
folders = [[[self clientObject] container] subFolders];
|
||||||
|
|
||||||
|
globalAddressBookResults = nil;
|
||||||
|
for (folder in folders) {
|
||||||
|
// Global AB
|
||||||
|
if ([folder isKindOfClass: [SOGoContactSourceFolder class]] && (![folder isEqual: [self clientObject]])) {
|
||||||
|
tmpGlobalAddressBookResults = [folder lookupContactsWithFilter: valueText
|
||||||
|
onCriteria: nil
|
||||||
sortBy: [self sortKey]
|
sortBy: [self sortKey]
|
||||||
ordering: ordering
|
ordering: ordering
|
||||||
inDomain: [[context activeUser] domain]];
|
inDomain: [[context activeUser] domain]];
|
||||||
|
if (globalAddressBookResults) {
|
||||||
|
globalAddressBookResults = [globalAddressBookResults arrayByAddingObjectsFromArray: tmpGlobalAddressBookResults];
|
||||||
|
} else {
|
||||||
|
globalAddressBookResults = [NSMutableArray arrayWithArray: tmpGlobalAddressBookResults];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process for global address book instead of array
|
||||||
|
if (globalAddressBookResults) {
|
||||||
|
for (i = 0 ; i < [globalAddressBookResults count] ; i++) {
|
||||||
|
tmpDict = [NSMutableDictionary dictionaryWithDictionary: [globalAddressBookResults objectAtIndex: i]];
|
||||||
|
// Flatten emails
|
||||||
|
if ([tmpDict objectForKey: @"c_mail"] && [[tmpDict objectForKey: @"c_mail"] isKindOfClass:[NSArray class]] && [[tmpDict objectForKey: @"c_mail"] count] > 0) {
|
||||||
|
[tmpDict setObject:[[tmpDict objectForKey: @"c_mail"] componentsJoinedByString: @","] forKey:@"c_mail"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((![tmpDict objectForKey:@"c_cn"] || [tmpDict objectForKey:@"c_cn"] == [NSNull null]) && [tmpDict objectForKey:@"c_name"]) {
|
||||||
|
// Replace c_cn if not filled
|
||||||
|
[tmpDict setObject:[tmpDict objectForKey:@"c_name"] forKey:@"c_cn"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((![tmpDict objectForKey:@"c_uid"] || [tmpDict objectForKey:@"c_uid"] == [NSNull null]) && [tmpDict objectForKey:@"c_id"]) {
|
||||||
|
// Replace c_uid if not filled
|
||||||
|
[tmpDict setObject:[tmpDict objectForKey:@"c_uid"] forKey:@"c_id"];
|
||||||
|
}
|
||||||
|
|
||||||
|
[globalAddressBookResults replaceObjectAtIndex:i withObject: tmpDict];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current AB
|
||||||
|
folder = [self clientObject];
|
||||||
|
results = [NSMutableArray arrayWithArray: [folder lookupContactsWithFilter: valueText
|
||||||
|
onCriteria: searchFields
|
||||||
|
sortBy: [self sortKey]
|
||||||
|
ordering: ordering
|
||||||
|
inDomain: [[context activeUser] domain]]];
|
||||||
|
|
||||||
|
// Add sourceid for current AB
|
||||||
|
for (i = 0 ; i < [results count] ; i++) {
|
||||||
|
tmpDict = [NSMutableDictionary dictionaryWithDictionary: [results objectAtIndex: i]];
|
||||||
|
// Add sourceid
|
||||||
|
[tmpDict setObject:[folder nameInContainer] forKey:@"sourceid"];
|
||||||
|
[results replaceObjectAtIndex:i withObject: tmpDict];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalAddressBookResults && results) { // Both results, merge arrays
|
||||||
|
// Results in personal folder will appear first
|
||||||
|
results = [results arrayByAddingObjectsFromArray: globalAddressBookResults];
|
||||||
|
} else if (globalAddressBookResults) { // No results in personal AB
|
||||||
|
results = globalAddressBookResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the results
|
||||||
|
descriptor = [[NSSortDescriptor alloc] initWithKey: [self sortKey]
|
||||||
|
ascending: ordering];
|
||||||
|
results = [results sortedArrayUsingDescriptors: [NSArray arrayWithObjects: descriptor, nil]];
|
||||||
|
[descriptor release];
|
||||||
|
|
||||||
if (excludeLists)
|
if (excludeLists)
|
||||||
{
|
{
|
||||||
filteredContacts = [NSMutableArray array];
|
filteredContacts = [NSMutableArray array];
|
||||||
@@ -198,6 +267,7 @@
|
|||||||
count = 0;
|
count = 0;
|
||||||
fields = [[contactInfos objectAtIndex: 0] allKeys];
|
fields = [[contactInfos objectAtIndex: 0] allKeys];
|
||||||
[headers addObject: fields];
|
[headers addObject: fields];
|
||||||
|
|
||||||
while (count < max)
|
while (count < max)
|
||||||
{
|
{
|
||||||
[headers addObject: [[contactInfos objectAtIndex: count] objectsForKeys: fields
|
[headers addObject: [[contactInfos objectAtIndex: count] objectsForKeys: fields
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
#import <SOGo/NSDictionary+Utilities.h>
|
#import <SOGo/NSDictionary+Utilities.h>
|
||||||
#import <SOGo/NSString+Utilities.h>
|
#import <SOGo/NSString+Utilities.h>
|
||||||
|
|
||||||
|
#import <SoObjects/Contacts/SOGoContactSourceFolder.h>
|
||||||
|
|
||||||
#import <Contacts/SOGoContactGCSEntry.h>
|
#import <Contacts/SOGoContactGCSEntry.h>
|
||||||
#import <Contacts/SOGoContactGCSFolder.h>
|
#import <Contacts/SOGoContactGCSFolder.h>
|
||||||
|
|
||||||
@@ -173,12 +175,14 @@
|
|||||||
{
|
{
|
||||||
NSAutoreleasePool *pool;
|
NSAutoreleasePool *pool;
|
||||||
NSDictionary *values;
|
NSDictionary *values;
|
||||||
NSArray *initialReferences, *refs, *emails;
|
NSArray *initialReferences, *refs, *emails, *folders;
|
||||||
NSDictionary *currentReference;
|
NSDictionary *currentReference;
|
||||||
NSString *uid, *workMail, *fn, *newUID;
|
NSString *uid, *workMail, *fn, *newUID;
|
||||||
int i, count;
|
int i, count;
|
||||||
NGVCardReference *cardReference;
|
NGVCardReference *cardReference;
|
||||||
SOGoContactGCSFolder *folder;
|
SOGoContactGCSFolder *folder;
|
||||||
|
NSMutableArray *publicSourceIDs;
|
||||||
|
id f;
|
||||||
|
|
||||||
folder = [co container];
|
folder = [co container];
|
||||||
|
|
||||||
@@ -200,12 +204,25 @@
|
|||||||
count = [references count];
|
count = [references count];
|
||||||
pool = [[NSAutoreleasePool alloc] init];
|
pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
// List container name of global AB
|
||||||
|
folders = [[[co lookupUserFolder] privateContacts: @"Contacts" inContext: nil] subFolders];
|
||||||
|
publicSourceIDs = [[NSMutableArray alloc] init];
|
||||||
|
for (f in folders) {
|
||||||
|
if ([f isKindOfClass:[SOGoContactSourceFolder class]]) {
|
||||||
|
[publicSourceIDs addObject: [f nameInContainer]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if ([[references objectAtIndex: i] isKindOfClass: [NSDictionary class]])
|
if ([[references objectAtIndex: i] isKindOfClass: [NSDictionary class]])
|
||||||
{
|
{
|
||||||
currentReference = [references objectAtIndex: i];
|
currentReference = [references objectAtIndex: i];
|
||||||
|
|
||||||
uid = [currentReference objectForKey: @"id"];
|
uid = [currentReference objectForKey: @"id"];
|
||||||
|
|
||||||
|
|
||||||
if (![self cardReferences: [list cardReferences]
|
if (![self cardReferences: [list cardReferences]
|
||||||
contain: uid])
|
contain: uid])
|
||||||
{
|
{
|
||||||
@@ -222,8 +239,18 @@
|
|||||||
|
|
||||||
[list addCardReference: cardReference];
|
[list addCardReference: cardReference];
|
||||||
}
|
}
|
||||||
else
|
else if ([currentReference objectForKey:@"sourceid"] && [publicSourceIDs containsObject:[currentReference objectForKey:@"sourceid"]]) {
|
||||||
{
|
// Create reference for shared AB (public)
|
||||||
|
uid = [currentReference objectForKey: @"id"];
|
||||||
|
emails = [[currentReference objectForKey: @"c_mail"] componentsSeparatedByString: @","];
|
||||||
|
cardReference = [NGVCardReference elementWithTag: @"card"];
|
||||||
|
[cardReference setFn: [currentReference objectForKey: @"c_cn"]];
|
||||||
|
if ([emails count])
|
||||||
|
[cardReference setEmail: [emails objectAtIndex: 0]];
|
||||||
|
[cardReference setReference: uid];
|
||||||
|
|
||||||
|
[list addCardReference: cardReference];
|
||||||
|
} else {
|
||||||
// Invalid UID or no UID
|
// Invalid UID or no UID
|
||||||
NGVCard *newCard;
|
NGVCard *newCard;
|
||||||
CardElement *newWorkMail;
|
CardElement *newWorkMail;
|
||||||
@@ -264,6 +291,8 @@
|
|||||||
pool = [[NSAutoreleasePool alloc] init];
|
pool = [[NSAutoreleasePool alloc] init];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[publicSourceIDs release];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) cardReferences: (NSArray *) references
|
- (BOOL) cardReferences: (NSArray *) references
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#import <SOGo/NSArray+Utilities.h>
|
#import <SOGo/NSArray+Utilities.h>
|
||||||
#import <SOGo/NSDictionary+Utilities.h>
|
#import <SOGo/NSDictionary+Utilities.h>
|
||||||
|
|
||||||
|
#import <SoObjects/Contacts/SOGoContactSourceFolder.h>
|
||||||
|
|
||||||
#import "UIxListView.h"
|
#import "UIxListView.h"
|
||||||
|
|
||||||
@implementation UIxListView
|
@implementation UIxListView
|
||||||
@@ -36,6 +38,7 @@
|
|||||||
NGVCardReference *card, *cardCopy;
|
NGVCardReference *card, *cardCopy;
|
||||||
int i, count;
|
int i, count;
|
||||||
id test;
|
id test;
|
||||||
|
NSArray *folders;
|
||||||
|
|
||||||
invalid = [NSMutableArray array];
|
invalid = [NSMutableArray array];
|
||||||
|
|
||||||
@@ -46,7 +49,22 @@
|
|||||||
test = [[co container] lookupName: [card reference]
|
test = [[co container] lookupName: [card reference]
|
||||||
inContext: context
|
inContext: context
|
||||||
acquire: NO];
|
acquire: NO];
|
||||||
if ([test isKindOfClass: [NSException class]])
|
if ([test isKindOfClass: [NSException class]]) {
|
||||||
|
folders = [[[co lookupUserFolder] privateContacts: @"Contacts" inContext: nil] subFolders];
|
||||||
|
id <SOGoContactFolder> folder;
|
||||||
|
for (folder in folders) {
|
||||||
|
// Global AB
|
||||||
|
if ([folder isKindOfClass: [SOGoContactSourceFolder class]]) {
|
||||||
|
test = [folder lookupName: [card reference]
|
||||||
|
inContext: context
|
||||||
|
acquire: NO];
|
||||||
|
if (test && ![test isKindOfClass: [NSException class]]) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (test && [test isKindOfClass: [NSException class]])
|
||||||
{
|
{
|
||||||
//NSLog (@"%@ not found", [card reference]);
|
//NSLog (@"%@ not found", [card reference]);
|
||||||
cardCopy = [card copy];
|
cardCopy = [card copy];
|
||||||
|
|||||||
@@ -468,17 +468,37 @@
|
|||||||
<label class="pseudo-input-label">
|
<label class="pseudo-input-label">
|
||||||
<var:string label:value="Members"/>
|
<var:string label:value="Members"/>
|
||||||
</label>
|
</label>
|
||||||
<md-contact-chips
|
<md-chips ng-model="editor.card.refs"
|
||||||
class="sg-chips-autocomplete"
|
md-separator-keys="editor.recipientSeparatorKeys"
|
||||||
ng-model="editor.card.refs"
|
md-add-on-blur="true"
|
||||||
ng-change="contactForm.$setDirty()"
|
md-autocomplete-snap="width">
|
||||||
md-contacts="editor.userFilter($query, editor.card.refs)"
|
<md-autocomplete
|
||||||
md-contact-name="$$fullname"
|
class="md-flex"
|
||||||
md-contact-image="$$image"
|
ng-model="editor.card.refs"
|
||||||
md-contact-email="$$email"
|
sg-enter="contactForm.$setDirty()"
|
||||||
md-require-match="true"
|
md-menu-class="md-2-line"
|
||||||
filter-selected="false"
|
md-search-text="editor.searchText"
|
||||||
label:placeholder="Add Member"><!-- members --></md-contact-chips>
|
md-items="card in editor.userFilter(editor.searchText, editor.card.refs)"
|
||||||
|
md-item-text="card.empty"
|
||||||
|
md-autoselect="true"
|
||||||
|
var:md-min-length="2"
|
||||||
|
md-delay="150"
|
||||||
|
md-no-cache="true">
|
||||||
|
<md-item-template>
|
||||||
|
<div class="sg-tile-content">
|
||||||
|
<div class="sg-tile-content">
|
||||||
|
<div class="sg-md-subhead md-block" md-highlight-text="editor.searchText" md-highlight-flags="gi">{{ card.$shortFormat(editor.searchText) }}</div>
|
||||||
|
<div class="sg-md-body" md-colors="::{color: 'default-background-500'}">{{ card.containername }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</md-item-template>
|
||||||
|
</md-autocomplete>
|
||||||
|
<md-chip-template>
|
||||||
|
<div class="sg-tile-content">
|
||||||
|
{{$chip.c_cn}}
|
||||||
|
</div>
|
||||||
|
</md-chip-template>
|
||||||
|
</md-chips>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in new issue
Block a user