Prevent Invitations and whitelist GUI
parent
1cc93c700a
commit
8ded5a8aaf
|
@ -412,6 +412,73 @@
|
|||
withType: @"calendar:invitation-update"];
|
||||
}
|
||||
|
||||
// This methods scans the list of attendees.
|
||||
- (NSException *) _handleAttendeeAvalability: (NSArray *) theAttendees
|
||||
forEvent: (iCalEvent *) theEvent
|
||||
{
|
||||
iCalPerson *currentAttendee;
|
||||
NSMutableArray *attendees, *unavailableAttendees;
|
||||
NSEnumerator *enumerator;
|
||||
NSString *currentUID, *buffer;
|
||||
NSMutableString *reason;
|
||||
NSDictionary *values;
|
||||
NSMutableDictionary *value;
|
||||
SOGoUser *user, *currentUser, *ownerUser;
|
||||
NSException *e;
|
||||
int count = 0, i = 0;
|
||||
|
||||
// Build a list of the attendees uids without the ressources
|
||||
attendees = [NSMutableArray arrayWithCapacity: [theAttendees count]];
|
||||
unavailableAttendees = [[NSMutableArray alloc] init];
|
||||
enumerator = [theAttendees objectEnumerator];
|
||||
while ((currentAttendee = [enumerator nextObject]))
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
{
|
||||
user = [SOGoUser userWithLogin: currentUID];
|
||||
if (![user isResource])
|
||||
{
|
||||
// Check if the user can be invited to an event.
|
||||
if ([[user userSettings] objectForKey:@"PreventInvitations"])
|
||||
{
|
||||
values = [NSDictionary dictionaryWithObject:[user cn] forKey:@"Cn"];
|
||||
[unavailableAttendees addObject:values];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
count = [unavailableAttendees count];
|
||||
if (count > 0)
|
||||
{
|
||||
if (count > 1)
|
||||
{
|
||||
reason = [NSMutableString stringWithString:[self labelForKey: @"These persons cannot be invited :"]];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
value = [unavailableAttendees objectAtIndex:i];
|
||||
[reason appendString:[value keysWithFormat: @"\n %{Cn}"]];
|
||||
if (!(i == (count - 1)))
|
||||
{
|
||||
[reason appendString:@" &"];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = [unavailableAttendees objectAtIndex:0];
|
||||
reason = [self labelForKey: @"This person cannot be invited:"];
|
||||
[reason appendString:[value keysWithFormat: @"\n %{Cn}"]];
|
||||
}
|
||||
[unavailableAttendees release];
|
||||
return [NSException exceptionWithHTTPStatus:403 reason: reason];
|
||||
}
|
||||
else {
|
||||
[unavailableAttendees release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This methods scans the list of attendees. If they are
|
||||
// considered as resource, it checks for conflicting
|
||||
|
@ -435,172 +502,172 @@
|
|||
NSEnumerator *enumerator;
|
||||
NSString *currentUID;
|
||||
SOGoUser *user, *currentUser, *ownerUser;
|
||||
|
||||
|
||||
// Build a list of the attendees uids
|
||||
attendees = [NSMutableArray arrayWithCapacity: [theAttendees count]];
|
||||
enumerator = [theAttendees objectEnumerator];
|
||||
while ((currentAttendee = [enumerator nextObject]))
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
{
|
||||
[attendees addObject: currentUID];
|
||||
}
|
||||
[attendees addObject: currentUID];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If the active user is not the owner of the calendar, check possible conflict when
|
||||
// the owner is a resource
|
||||
currentUser = [context activeUser];
|
||||
if (!activeUserIsOwner && ![currentUser isSuperUser])
|
||||
{
|
||||
[attendees addObject: owner];
|
||||
}
|
||||
|
||||
{
|
||||
[attendees addObject: owner];
|
||||
}
|
||||
|
||||
enumerator = [attendees objectEnumerator];
|
||||
while ((currentUID = [enumerator nextObject]))
|
||||
{
|
||||
{
|
||||
user = [SOGoUser userWithLogin: currentUID];
|
||||
|
||||
if ([user isResource])
|
||||
{
|
||||
SOGoAppointmentFolder *folder;
|
||||
NSCalendarDate *start, *end;
|
||||
NGCalendarDateRange *range;
|
||||
NSMutableArray *fbInfo;
|
||||
NSArray *allOccurences;
|
||||
|
||||
BOOL must_delete;
|
||||
int i, j;
|
||||
|
||||
// We get the start/end date for our conflict range. If the event to be added is recurring, we
|
||||
// check for at least a year to start with.
|
||||
start = [[theEvent startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: 1];
|
||||
end = [[theEvent endDate] dateByAddingYears: ([theEvent isRecurrent] ? 1 : 0) months: 0 days: 0 hours: 0 minutes: 0 seconds: -1];
|
||||
|
||||
folder = [user personalCalendarFolderInContext: context];
|
||||
|
||||
// Deny access to the resource if the ACLs don't allow the user
|
||||
if (![folder aclSQLListingFilter])
|
||||
{
|
||||
NSDictionary *values;
|
||||
NSString *reason;
|
||||
|
||||
values = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[user cn], @"Cn",
|
||||
[user systemEmail], @"SystemEmail"];
|
||||
reason = [values keysWithFormat: [self labelForKey: @"Cannot access resource: \"%{Cn} %{SystemEmail}\""]];
|
||||
return [NSException exceptionWithHTTPStatus:403 reason: reason];
|
||||
}
|
||||
|
||||
fbInfo = [NSMutableArray arrayWithArray: [folder fetchFreeBusyInfosFrom: start
|
||||
to: end]];
|
||||
|
||||
// We first remove any occurences in the freebusy that corresponds to the
|
||||
// current event. We do this to avoid raising a conflict if we move a 1 hour
|
||||
// meeting from 12:00-13:00 to 12:15-13:15. We would overlap on ourself otherwise.
|
||||
//
|
||||
// We must also check here for repetitive events that don't overlap our event.
|
||||
// We remove all events that don't overlap. The events here are already
|
||||
// decomposed.
|
||||
//
|
||||
if ([theEvent isRecurrent])
|
||||
allOccurences = [theEvent recurrenceRangesWithinCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: start
|
||||
endDate: end]
|
||||
firstInstanceCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: [theEvent startDate]
|
||||
endDate: [theEvent endDate]]];
|
||||
else
|
||||
allOccurences = nil;
|
||||
|
||||
for (i = [fbInfo count]-1; i >= 0; i--)
|
||||
{
|
||||
range = [NGCalendarDateRange calendarDateRangeWithStartDate: [[fbInfo objectAtIndex: i] objectForKey: @"startDate"]
|
||||
endDate: [[fbInfo objectAtIndex: i] objectForKey: @"endDate"]];
|
||||
|
||||
if ([[[fbInfo objectAtIndex: i] objectForKey: @"c_uid"] compare: [theEvent uid]] == NSOrderedSame)
|
||||
{
|
||||
SOGoAppointmentFolder *folder;
|
||||
NSCalendarDate *start, *end;
|
||||
NGCalendarDateRange *range;
|
||||
NSMutableArray *fbInfo;
|
||||
NSArray *allOccurences;
|
||||
|
||||
BOOL must_delete;
|
||||
int i, j;
|
||||
|
||||
// We get the start/end date for our conflict range. If the event to be added is recurring, we
|
||||
// check for at least a year to start with.
|
||||
start = [[theEvent startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: 1];
|
||||
end = [[theEvent endDate] dateByAddingYears: ([theEvent isRecurrent] ? 1 : 0) months: 0 days: 0 hours: 0 minutes: 0 seconds: -1];
|
||||
|
||||
folder = [user personalCalendarFolderInContext: context];
|
||||
|
||||
// Deny access to the resource if the ACLs don't allow the user
|
||||
if (![folder aclSQLListingFilter])
|
||||
{
|
||||
NSDictionary *values;
|
||||
NSString *reason;
|
||||
|
||||
values = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[user cn], @"Cn",
|
||||
[user systemEmail], @"SystemEmail"];
|
||||
reason = [values keysWithFormat: [self labelForKey: @"Cannot access resource: \"%{Cn} %{SystemEmail}\""]];
|
||||
return [NSException exceptionWithHTTPStatus:403 reason: reason];
|
||||
}
|
||||
|
||||
fbInfo = [NSMutableArray arrayWithArray: [folder fetchFreeBusyInfosFrom: start
|
||||
to: end]];
|
||||
|
||||
// We first remove any occurences in the freebusy that corresponds to the
|
||||
// current event. We do this to avoid raising a conflict if we move a 1 hour
|
||||
// meeting from 12:00-13:00 to 12:15-13:15. We would overlap on ourself otherwise.
|
||||
//
|
||||
// We must also check here for repetitive events that don't overlap our event.
|
||||
// We remove all events that don't overlap. The events here are already
|
||||
// decomposed.
|
||||
//
|
||||
if ([theEvent isRecurrent])
|
||||
allOccurences = [theEvent recurrenceRangesWithinCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: start
|
||||
endDate: end]
|
||||
firstInstanceCalendarDateRange: [NGCalendarDateRange calendarDateRangeWithStartDate: [theEvent startDate]
|
||||
endDate: [theEvent endDate]]];
|
||||
else
|
||||
allOccurences = nil;
|
||||
|
||||
for (i = [fbInfo count]-1; i >= 0; i--)
|
||||
{
|
||||
range = [NGCalendarDateRange calendarDateRangeWithStartDate: [[fbInfo objectAtIndex: i] objectForKey: @"startDate"]
|
||||
endDate: [[fbInfo objectAtIndex: i] objectForKey: @"endDate"]];
|
||||
|
||||
if ([[[fbInfo objectAtIndex: i] objectForKey: @"c_uid"] compare: [theEvent uid]] == NSOrderedSame)
|
||||
{
|
||||
[fbInfo removeObjectAtIndex: i];
|
||||
continue;
|
||||
}
|
||||
|
||||
// No need to check if the event isn't recurrent here as it's handled correctly
|
||||
// when we compute the "end" date.
|
||||
if ([allOccurences count])
|
||||
|
||||
// No need to check if the event isn't recurrent here as it's handled correctly
|
||||
// when we compute the "end" date.
|
||||
if ([allOccurences count])
|
||||
{
|
||||
must_delete = YES;
|
||||
|
||||
|
||||
for (j = 0; j < [allOccurences count]; j++)
|
||||
{
|
||||
if ([range doesIntersectWithDateRange: [allOccurences objectAtIndex: j]])
|
||||
{
|
||||
must_delete = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
if ([range doesIntersectWithDateRange: [allOccurences objectAtIndex: j]])
|
||||
{
|
||||
must_delete = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (must_delete)
|
||||
[fbInfo removeObjectAtIndex: i];
|
||||
[fbInfo removeObjectAtIndex: i];
|
||||
}
|
||||
}
|
||||
|
||||
// Find the attendee associated to the current UID
|
||||
for (i = 0; i < [theAttendees count]; i++)
|
||||
{
|
||||
currentAttendee = [theAttendees objectAtIndex: i];
|
||||
if ([[currentAttendee uid] isEqualToString: currentUID])
|
||||
break;
|
||||
else
|
||||
currentAttendee = nil;
|
||||
}
|
||||
|
||||
if ([fbInfo count])
|
||||
{
|
||||
// If we always force the auto-accept if numberOfSimultaneousBookings == 0 (ie., no limit
|
||||
// is imposed) or if numberOfSimultaneousBookings is greater than the number of
|
||||
// overlapping events
|
||||
if ([user numberOfSimultaneousBookings] == 0 ||
|
||||
[user numberOfSimultaneousBookings] > [fbInfo count])
|
||||
{
|
||||
if (currentAttendee)
|
||||
{
|
||||
[[currentAttendee attributes] removeObjectForKey: @"RSVP"];
|
||||
[currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
NSDictionary *values;
|
||||
NSString *reason;
|
||||
iCalEvent *event;
|
||||
|
||||
calendar = [iCalCalendar parseSingleFromSource: [[fbInfo objectAtIndex: 0] objectForKey: @"c_content"]];
|
||||
event = [[calendar events] lastObject];
|
||||
|
||||
values = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSString stringWithFormat: @"%d", [user numberOfSimultaneousBookings]], @"NumberOfSimultaneousBookings",
|
||||
[user cn], @"Cn",
|
||||
[user systemEmail], @"SystemEmail",
|
||||
([event summary] ? [event summary] : @""), @"EventTitle",
|
||||
[[fbInfo objectAtIndex: 0] objectForKey: @"startDate"], @"StartDate",
|
||||
nil];
|
||||
|
||||
reason = [values keysWithFormat: [self labelForKey: @"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}."]];
|
||||
|
||||
return [NSException exceptionWithHTTPStatus: 403
|
||||
reason: reason];
|
||||
}
|
||||
}
|
||||
else if (currentAttendee)
|
||||
{
|
||||
// No conflict, we auto-accept. We do this for resources automatically if no
|
||||
// double-booking is observed. If it's not the desired behavior, just don't
|
||||
// set the resource as one!
|
||||
[[currentAttendee attributes] removeObjectForKey: @"RSVP"];
|
||||
[currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the attendee associated to the current UID
|
||||
for (i = 0; i < [theAttendees count]; i++)
|
||||
{
|
||||
currentAttendee = [theAttendees objectAtIndex: i];
|
||||
if ([[currentAttendee uid] isEqualToString: currentUID])
|
||||
break;
|
||||
else
|
||||
currentAttendee = nil;
|
||||
}
|
||||
|
||||
if ([fbInfo count])
|
||||
{
|
||||
// If we always force the auto-accept if numberOfSimultaneousBookings == 0 (ie., no limit
|
||||
// is imposed) or if numberOfSimultaneousBookings is greater than the number of
|
||||
// overlapping events
|
||||
if ([user numberOfSimultaneousBookings] == 0 ||
|
||||
[user numberOfSimultaneousBookings] > [fbInfo count])
|
||||
{
|
||||
if (currentAttendee)
|
||||
{
|
||||
[[currentAttendee attributes] removeObjectForKey: @"RSVP"];
|
||||
[currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
NSDictionary *values;
|
||||
NSString *reason;
|
||||
iCalEvent *event;
|
||||
|
||||
calendar = [iCalCalendar parseSingleFromSource: [[fbInfo objectAtIndex: 0] objectForKey: @"c_content"]];
|
||||
event = [[calendar events] lastObject];
|
||||
|
||||
values = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSString stringWithFormat: @"%d", [user numberOfSimultaneousBookings]], @"NumberOfSimultaneousBookings",
|
||||
[user cn], @"Cn",
|
||||
[user systemEmail], @"SystemEmail",
|
||||
([event summary] ? [event summary] : @""), @"EventTitle",
|
||||
[[fbInfo objectAtIndex: 0] objectForKey: @"startDate"], @"StartDate",
|
||||
nil];
|
||||
|
||||
reason = [values keysWithFormat: [self labelForKey: @"Maximum number of simultaneous bookings (%{NumberOfSimultaneousBookings}) reached for resource \"%{Cn} %{SystemEmail}\". The conflicting event is \"%{EventTitle}\", and starts on %{StartDate}."]];
|
||||
|
||||
return [NSException exceptionWithHTTPStatus: 403
|
||||
reason: reason];
|
||||
}
|
||||
}
|
||||
else if (currentAttendee)
|
||||
{
|
||||
// No conflict, we auto-accept. We do this for resources automatically if no
|
||||
// double-booking is observed. If it's not the desired behavior, just don't
|
||||
// set the resource as one!
|
||||
[[currentAttendee attributes] removeObjectForKey: @"RSVP"];
|
||||
[currentAttendee setParticipationStatus: iCalPersonPartStatAccepted];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -608,27 +675,29 @@
|
|||
//
|
||||
//
|
||||
- (NSException *) _handleAddedUsers: (NSArray *) attendees
|
||||
fromEvent: (iCalEvent *) newEvent
|
||||
fromEvent: (iCalEvent *) newEvent
|
||||
{
|
||||
iCalPerson *currentAttendee;
|
||||
NSEnumerator *enumerator;
|
||||
NSString *currentUID;
|
||||
NSException *e;
|
||||
|
||||
|
||||
// We check for conflicts
|
||||
if ((e = [self _handleResourcesConflicts: attendees forEvent: newEvent]))
|
||||
return e;
|
||||
|
||||
if ((e = [self _handleAttendeeAvalability: attendees forEvent: newEvent]))
|
||||
return e;
|
||||
|
||||
enumerator = [attendees objectEnumerator];
|
||||
while ((currentAttendee = [enumerator nextObject]))
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
[self _addOrUpdateEvent: newEvent
|
||||
forUID: currentUID
|
||||
owner: owner];
|
||||
}
|
||||
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
[self _addOrUpdateEvent: newEvent
|
||||
forUID: currentUID
|
||||
owner: owner];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -709,8 +778,9 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
|
|||
withType: @"calendar:cancellation"];
|
||||
}
|
||||
|
||||
if ((ex = [self _handleResourcesConflicts: [newEvent attendees]
|
||||
forEvent: newEvent]))
|
||||
if ((ex = [self _handleResourcesConflicts: [newEvent attendees] forEvent: newEvent]))
|
||||
return ex;
|
||||
if ((ex = [self _handleAttendeeAvalability: [newEvent attendees] forEvent: newEvent]))
|
||||
return ex;
|
||||
|
||||
addedAttendees = [changes insertedAttendees];
|
||||
|
@ -783,7 +853,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
|
|||
// +------------> _handleUpdatedEvent:fromOldEvent: ---> _addOrUpdateEvent:forUID:owner: <-----------+
|
||||
// | | ^ |
|
||||
// v v | |
|
||||
// _handleRemovedUsers:withRecurrenceId: _handleSequenceUpdateInEvent:ignoringAttendees:fromOldEvent: |
|
||||
// _handleRemovedUsers:withRecurrenceId: _handleSequenceUpdateInEvent:ignoringAttendees:fromOldEvent: |
|
||||
// | |
|
||||
// | [DELETEAction:] |
|
||||
// | | {_handleAdded/Updated...}<--+ |
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
{
|
||||
id item;
|
||||
SOGoUser *user;
|
||||
SOGoUserSettings *us;
|
||||
NGSieveClient *client;
|
||||
|
||||
// Addressbook
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#import <SOGo/NSString+Utilities.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
#import <SOGo/SOGoUserSettings.h>
|
||||
#import <SOGo/SOGoDomainDefaults.h>
|
||||
#import <SOGo/SOGoSieveManager.h>
|
||||
#import <SOGo/SOGoSystemDefaults.h>
|
||||
|
@ -638,6 +639,23 @@ static NSArray *reminderValues = nil;
|
|||
return [userDefaults busyOffHours];
|
||||
}
|
||||
|
||||
- (void) setPreventInvitations: (BOOL) preventInvitations
|
||||
{
|
||||
SOGoUserSettings *us;
|
||||
|
||||
us = [user userSettings];
|
||||
[us setBool: preventInvitations forKey: @"PreventInvitations"];
|
||||
[us synchronize];
|
||||
}
|
||||
|
||||
- (BOOL) preventInvitations
|
||||
{
|
||||
SOGoUserSettings *us;
|
||||
us = [user userSettings];
|
||||
|
||||
return [[us objectForKey: @"PreventInvitations"] boolValue];
|
||||
}
|
||||
|
||||
- (NSArray *) firstWeekList
|
||||
{
|
||||
return [NSArray arrayWithObjects:
|
||||
|
|
|
@ -1,37 +1,42 @@
|
|||
<?xml version='1.0' standalone='yes'?>
|
||||
<var:component
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label"
|
||||
xmlns:uix="OGo:uix"
|
||||
className="UIxPageFrame"
|
||||
title="name"
|
||||
const:popup="YES"
|
||||
const:jsFiles="UIxMailEditor.js,SOGoAutoCompletion.js"
|
||||
>
|
||||
<script type="text/javascript">
|
||||
var activeAddressBook = '<var:string value="clientObject.container.nameInContainer"/>';
|
||||
</script>
|
||||
<div class="popupMenu" id="contactsMenu">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<form var:href="saveURL" name="editform" id="mainForm">
|
||||
<div id="listEditor">
|
||||
<span class="caption"><var:string label:value="List details" /></span>
|
||||
<table class="frame"><tr><td width="35%"><var:string label:value="List name:"/></td>
|
||||
<td><input type="text" const:id="listName" const:name="listName"
|
||||
var:value="listName" 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>
|
||||
<span class="caption"><var:string label:value="Members" /></span>
|
||||
<table class="frame"><tr><td>
|
||||
<var:component
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label"
|
||||
xmlns:uix="OGo:uix"
|
||||
className="UIxPageFrame"
|
||||
title="name"
|
||||
const:popup="YES"
|
||||
const:jsFiles="UIxMailEditor.js,SOGoAutoCompletion.js"
|
||||
>
|
||||
<script type="text/javascript">
|
||||
var activeAddressBook = '<var:string value="clientObject.container.nameInContainer"/>';
|
||||
</script>
|
||||
<div class="popupMenu" id="contactsMenu">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<form var:href="saveURL" name="editform" id="mainForm">
|
||||
<div id="listEditor">
|
||||
<span class="caption"><var:string label:value="List details" /></span>
|
||||
<table class="frame">
|
||||
<tr>
|
||||
<td width="35%"><var:string label:value="List name:"/></td>
|
||||
<td>
|
||||
<input type="text" const:id="listName" const:name="listName" var:value="listName" 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>
|
||||
|
||||
<span class="caption"><var:string label:value="Members" /></span>
|
||||
<table class="frame"><tr><td>
|
||||
<div id="referenceListWrapper">
|
||||
<table id="referenceList" cellspacing="0">
|
||||
<thead>
|
||||
|
@ -44,40 +49,40 @@
|
|||
<tbody>
|
||||
<var:foreach list="references" item="reference">
|
||||
<tr const:class="referenceListRow">
|
||||
<td const:class="referenceListCell">
|
||||
<input var:uid="reference.id"
|
||||
var:value="reference.name"
|
||||
const:style="display: none"/>
|
||||
<td const:class="referenceListCell">
|
||||
<input var:uid="reference.id"
|
||||
var:value="reference.name"
|
||||
const:style="display: none"/>
|
||||
<span><var:string var:value="reference.name"/></span>
|
||||
</td></tr>
|
||||
</td></tr>
|
||||
</var:foreach>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<div class="bottomToolbar">
|
||||
<a const:id="referenceAdd" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="add-icon.png" label:title="Add" />
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<div class="bottomToolbar">
|
||||
<a const:id="referenceAdd" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="add-icon.png" label:title="Add" />
|
||||
</span></a>
|
||||
<a const:id="referenceDelete" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="remove-icon.png" label:title="Delete" />
|
||||
<a const:id="referenceDelete" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="remove-icon.png" label:title="Delete" />
|
||||
</span></a>
|
||||
</div>
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<input type="hidden" name="referencesValue" id="referencesValue"
|
||||
var:value="referencesValue" />
|
||||
<div id="buttons">
|
||||
<var:if condition="canCreateOrModify"
|
||||
><a class="button actionButton" name="submit"
|
||||
id="submitButton" href="#" >
|
||||
<span><var:string label:value="Save"/></span>
|
||||
</div>
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<input type="hidden" name="referencesValue" id="referencesValue"
|
||||
var:value="referencesValue" />
|
||||
<div id="buttons">
|
||||
<var:if condition="canCreateOrModify"
|
||||
><a class="button actionButton" name="submit"
|
||||
id="submitButton" href="#" >
|
||||
<span><var:string label:value="Save"/></span>
|
||||
</a></var:if>
|
||||
<a const:id="cancelButton" class="button" name="cancel" href="#">
|
||||
<span><var:string label:value="Cancel"/></span>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</var:component>
|
||||
<a const:id="cancelButton" class="button" name="cancel" href="#">
|
||||
<span><var:string label:value="Cancel"/></span>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</var:component>
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
title="title"
|
||||
const:popup="YES"
|
||||
const:cssFiles="datepicker.css"
|
||||
const:jsFiles="RowEditionController.js,PasswordPolicy.js,ckeditor/ckeditor.js,datepicker.js"
|
||||
const:jsFiles="RowEditionController.js,PasswordPolicy.js,ckeditor/ckeditor.js,datepicker.js, SOGoAutoCompletion.js"
|
||||
>
|
||||
<script type="text/javascript">
|
||||
var localeCode = '<var:string value="localeCode"/>';
|
||||
</script>
|
||||
<div class="popupMenu" id="contactsMenu">
|
||||
<ul></ul>
|
||||
</div>
|
||||
|
||||
<div id="colorPickerDialog" style="display: none;" class="dialog right bottom">
|
||||
<div>
|
||||
|
@ -91,33 +94,33 @@
|
|||
<span class="blc-99FF99"><!-- --></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form id="mainForm" var:href="ownPath">
|
||||
<div class="tabsContainer" id="preferencesTabs">
|
||||
<ul>
|
||||
<li target="generalView"><span>
|
||||
<var:string label:value="General" /></span></li>
|
||||
<var:if condition="userHasCalendarAccess">
|
||||
<var:string label:value="General" /></span></li>
|
||||
<var:if condition="userHasCalendarAccess">
|
||||
<li target="calendarOptionsView"><span><var:string
|
||||
label:value="Calendar Options"/></span></li>
|
||||
</var:if
|
||||
><li target="contactsOptionsView"><span><var:string
|
||||
label:value="Contacts Options"/></span></li
|
||||
><var:if condition="userHasMailAccess">
|
||||
label:value="Calendar Options"/></span></li>
|
||||
</var:if
|
||||
><li target="contactsOptionsView"><span><var:string
|
||||
label:value="Contacts Options"/></span></li
|
||||
><var:if condition="userHasMailAccess">
|
||||
<li target="mailOptionsView"><span><var:string
|
||||
label:value="Mail Options"/></span></li>
|
||||
label:value="Mail Options"/></span></li>
|
||||
<li target="mailAccountsView"><span><var:string
|
||||
label:value="IMAP Accounts"/></span></li>
|
||||
label:value="IMAP Accounts"/></span></li>
|
||||
<var:if condition="isVacationEnabled"><li target="vacationView"><span><var:string
|
||||
label:value="Vacation"/></span></li></var:if
|
||||
><var:if condition="isForwardEnabled"><li target="forwardView"><span><var:string
|
||||
label:value="Forward"/></span></li></var:if>
|
||||
</var:if
|
||||
><var:if condition="shouldDisplayAdditionalPreferences">
|
||||
label:value="Vacation"/></span></li></var:if
|
||||
><var:if condition="isForwardEnabled"><li target="forwardView"><span><var:string
|
||||
label:value="Forward"/></span></li></var:if>
|
||||
</var:if
|
||||
><var:if condition="shouldDisplayAdditionalPreferences">
|
||||
<li target="additionalView"><span>
|
||||
<var:string label:value="Additional Parameters"/></span></li>
|
||||
</var:if
|
||||
><var:if condition="shouldDisplayPasswordChange">
|
||||
<var:string label:value="Additional Parameters"/></span></li>
|
||||
</var:if
|
||||
><var:if condition="shouldDisplayPasswordChange">
|
||||
<li target="passwordView"><span><var:string label:value="Password"/></span></li>
|
||||
</var:if>
|
||||
</ul>
|
||||
|
@ -128,38 +131,38 @@
|
|||
<dd><var:string value="sogoVersion"/></dd>
|
||||
<dt><var:string label:value="Language :"/></dt>
|
||||
<dd><var:popup list="languages" item="item"
|
||||
const:id="language"
|
||||
const:name="language"
|
||||
string="languageText"
|
||||
selection="language"
|
||||
label:noSelectionString="choose" /></dd>
|
||||
const:id="language"
|
||||
const:name="language"
|
||||
string="languageText"
|
||||
selection="language"
|
||||
label:noSelectionString="choose" /></dd>
|
||||
<dt><var:string label:value="Current Time Zone :"/></dt>
|
||||
<dd><var:popup list="timeZonesList" item="item"
|
||||
const:id="timezone"
|
||||
const:name="timezone"
|
||||
string="item" selection="userTimeZone" /></dd>
|
||||
const:id="timezone"
|
||||
const:name="timezone"
|
||||
string="item" selection="userTimeZone" /></dd>
|
||||
<dt><var:string label:value="Short Date Format :"/></dt>
|
||||
<dd><var:popup list="shortDateFormatsList" item="item"
|
||||
const:id="shortDateFormat"
|
||||
const:name="shortDateFormat"
|
||||
string="itemShortDateFormatText" selection="userShortDateFormat"/></dd>
|
||||
const:id="shortDateFormat"
|
||||
const:name="shortDateFormat"
|
||||
string="itemShortDateFormatText" selection="userShortDateFormat"/></dd>
|
||||
<dt><var:string label:value="Long Date Format :"/></dt>
|
||||
<dd><var:popup list="longDateFormatsList" item="item"
|
||||
const:id="longDateFormat"
|
||||
const:name="longDateFormat"
|
||||
string="itemLongDateFormatText" selection="userLongDateFormat"
|
||||
/></dd>
|
||||
const:id="longDateFormat"
|
||||
const:name="longDateFormat"
|
||||
string="itemLongDateFormatText" selection="userLongDateFormat"
|
||||
/></dd>
|
||||
<dt><var:string label:value="Time Format :"/></dt>
|
||||
<dd><var:popup list="timeFormatsList" item="item"
|
||||
const:id="timeFormat"
|
||||
const:name="timeFormat"
|
||||
string="itemTimeFormatText" selection="userTimeFormat"
|
||||
/></dd>
|
||||
const:id="timeFormat"
|
||||
const:name="timeFormat"
|
||||
string="itemTimeFormatText" selection="userTimeFormat"
|
||||
/></dd>
|
||||
<dt><var:string label:value="Default module :"/></dt>
|
||||
<dd><var:popup list="availableModules" item="item"
|
||||
const:id="defaultModule"
|
||||
const:name="defaultModule"
|
||||
string="itemModuleText" selection="userDefaultModule"/></dd>
|
||||
const:id="defaultModule"
|
||||
const:name="defaultModule"
|
||||
string="itemModuleText" selection="userDefaultModule"/></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<var:if condition="userHasCalendarAccess">
|
||||
|
@ -167,73 +170,103 @@
|
|||
<dl class="dl-horizontal">
|
||||
<dt><var:string label:value="Week begins on :"/></dt>
|
||||
<dd><var:popup list="daysList" item="item"
|
||||
const:id="weekStartDay"
|
||||
const:name="weekStartDay"
|
||||
string="itemWeekStartDay" selection="userWeekStartDay"/></dd>
|
||||
const:id="weekStartDay"
|
||||
const:name="weekStartDay"
|
||||
string="itemWeekStartDay" selection="userWeekStartDay"/></dd>
|
||||
<dt><var:string label:value="Day start time :"/></dt>
|
||||
<dd><var:popup list="hoursList" item="item"
|
||||
const:id="dayStartTime"
|
||||
const:name="dayStartTime"
|
||||
string="item" selection="userDayStartTime"/></dd>
|
||||
const:id="dayStartTime"
|
||||
const:name="dayStartTime"
|
||||
string="item" selection="userDayStartTime"/></dd>
|
||||
<dt><var:string label:value="Day end time :"/></dt>
|
||||
<dd><var:popup list="hoursList" item="item"
|
||||
const:id="dayEndTime"
|
||||
const:name="dayEndTime"
|
||||
string="item" selection="userDayEndTime"/></dd>
|
||||
const:id="dayEndTime"
|
||||
const:name="dayEndTime"
|
||||
string="item" selection="userDayEndTime"/></dd>
|
||||
<dt></dt>
|
||||
<dd><input type="checkbox"
|
||||
const:name="busyOffHours"
|
||||
const:id="busyOffHours"
|
||||
var:checked="busyOffHours" />
|
||||
<dd><input type="checkbox"
|
||||
const:name="busyOffHours"
|
||||
const:id="busyOffHours"
|
||||
var:checked="busyOffHours" />
|
||||
<var:string label:value="Show time as busy outside working hours"/></dd>
|
||||
<dt><var:string label:value="First week of year :"/></dt>
|
||||
<dd><var:popup list="firstWeekList" item="item"
|
||||
const:id="firstWeek"
|
||||
const:name="firstWeek"
|
||||
string="itemFirstWeekText" selection="userFirstWeek"/></dd>
|
||||
<dt><var:string label:value="Default calendar :"/></dt>
|
||||
<dd><var:popup list="defaultCalendarList" item="item"
|
||||
const:id="defaultCalendar"
|
||||
const:name="defaultCalendar"
|
||||
string="itemCalendarText" selection="userDefaultCalendar"/></dd>
|
||||
<dt><var:string label:value="Default events classification :"/></dt>
|
||||
<dd><var:popup list="calendarClassificationsList" item="item"
|
||||
const:id="eventsClassification"
|
||||
const:name="eventsClassification"
|
||||
string="itemClassificationText" selection="eventsDefaultClassification"/></dd>
|
||||
<dt><var:string label:value="Default tasks classification :"/></dt>
|
||||
<dd><var:popup list="calendarClassificationsList" item="item"
|
||||
const:id="tasksClassification"
|
||||
const:name="tasksClassification"
|
||||
string="itemClassificationText" selection="tasksDefaultClassification"/></dd>
|
||||
<dt><var:string label:value="Default reminder :"/></dt>
|
||||
<dd><var:popup list="reminderList" item="item"
|
||||
const:disabledValue="-"
|
||||
label:noSelectionString="reminder_NONE"
|
||||
const:name="reminderList"
|
||||
const:id="reminderList"
|
||||
string="itemReminderText" var:selection="reminder"/></dd>
|
||||
<dt><var:string label:value="First week of year :"/></dt>
|
||||
<dd><var:popup list="firstWeekList" item="item"
|
||||
const:id="firstWeek"
|
||||
const:name="firstWeek"
|
||||
string="itemFirstWeekText" selection="userFirstWeek"/></dd>
|
||||
<dt><var:string label:value="Default calendar :"/></dt>
|
||||
<dd><var:popup list="defaultCalendarList" item="item"
|
||||
const:id="defaultCalendar"
|
||||
const:name="defaultCalendar"
|
||||
string="itemCalendarText" selection="userDefaultCalendar"/></dd>
|
||||
<dt><var:string label:value="Default events classification :"/></dt>
|
||||
<dd><var:popup list="calendarClassificationsList" item="item"
|
||||
const:id="eventsClassification"
|
||||
const:name="eventsClassification"
|
||||
string="itemClassificationText" selection="eventsDefaultClassification"/></dd>
|
||||
<dt><var:string label:value="Default tasks classification :"/></dt>
|
||||
<dd><var:popup list="calendarClassificationsList" item="item"
|
||||
const:id="tasksClassification"
|
||||
const:name="tasksClassification"
|
||||
string="itemClassificationText" selection="tasksDefaultClassification"/></dd>
|
||||
<dt><var:string label:value="Default reminder :"/></dt>
|
||||
<dd><var:popup list="reminderList" item="item"
|
||||
const:disabledValue="-"
|
||||
label:noSelectionString="reminder_NONE"
|
||||
const:name="reminderList"
|
||||
const:id="reminderList"
|
||||
string="itemReminderText" var:selection="reminder"/></dd>
|
||||
<dt><var:string label:value="Appointments invitations:"/></dt>
|
||||
<dd><input type="checkbox"
|
||||
const:name="preventInvitations"
|
||||
const:id="preventInvitations"
|
||||
var:checked="preventInvitations" />
|
||||
<var:string label:value="Prevent from being invited to appointments"/></dd>
|
||||
</dl>
|
||||
|
||||
<label><var:string label:value="Categories"/></label>
|
||||
<div id="calendarCategoriesListWrapper" class="listWrapper"
|
||||
><table class="categoriesList" cellspacing="0">
|
||||
|
||||
<label id="whiteListLabel"><var:string label:value="White list for appointments invitations:"/></label>
|
||||
<div id="appointmentsWhiteListWrapper" class="listWrapper">
|
||||
<table class="tableview" id="tableViewWhiteList">
|
||||
<thead>
|
||||
<tr class="tableview"
|
||||
><th const:class="tbtv_headercell" const:id="nameTableHeader"
|
||||
><var:string label:value="Name"/></th
|
||||
><th const:class="tbtv_headercell" const:id="colorTableHeader"
|
||||
><var:string label:value="Color"/></th
|
||||
></tr
|
||||
></thead>
|
||||
<tr class="tableview">
|
||||
<th const:class="tbtv_headercell" const:id="whiteListTableHeader">
|
||||
<var:string label:value="Contacts names"/></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<var:foreach list="appointmentsWhiteList" item="contact">
|
||||
<tr const:class="whiteListRow">
|
||||
<td const:class="whiteListCell">
|
||||
<var:string var:value="contact"/></td>
|
||||
</tr>
|
||||
</var:foreach>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="whiteListToolbar">
|
||||
<a const:id="appointmentsWhiteListAdd" href="#">
|
||||
<img rsrc:src="add-icon.png" label:title="Add" id="WhiteListAdd"/></a>
|
||||
<a const:id="appointmentsWhiteListDelete" href="#">
|
||||
<img rsrc:src="remove-icon.png" label:title="Delete" id="WhiteListDelete" /></a>
|
||||
</div>
|
||||
|
||||
<label id="calendarCategoriesLabel"><var:string label:value="Categories"/></label>
|
||||
<div id="calendarCategoriesListWrapper" class="listWrapper">
|
||||
<table class="categoriesList" cellspacing="0">
|
||||
<thead>
|
||||
<tr class="tableview">
|
||||
<th const:class="tbtv_headercell" const:id="nameTableHeader">
|
||||
<var:string label:value="Name"/></th>
|
||||
<th const:class="tbtv_headercell" const:id="colorTableHeader">
|
||||
<var:string label:value="Color"/></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<var:foreach list="calendarCategoryList" item="category">
|
||||
<tr const:class="categoryListRow"
|
||||
><td const:class="categoryListCell"
|
||||
><var:string var:value="category"/></td
|
||||
><td const:class="categoryListCell"
|
||||
><div const:class="colorBox" var:data-color="categoryColor"><entity name="nbsp"/></div></td
|
||||
></tr>
|
||||
<tr const:class="categoryListRow">
|
||||
<td const:class="categoryListCell">
|
||||
<var:string var:value="category"/></td>
|
||||
<td const:class="categoryListCell">
|
||||
<div const:class="colorBox" var:data-color="categoryColor"><entity name="nbsp"/></div></td>
|
||||
</tr>
|
||||
</var:foreach>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -246,8 +279,8 @@
|
|||
<span><img rsrc:src="remove-icon.png" label:title="Delete" />
|
||||
</span></a>
|
||||
</div>
|
||||
<input type="hidden" const:id="calendarCategoriesValue"
|
||||
const:name="calendarCategoriesValue" var:value="calendarCategoriesValue"/>
|
||||
<input type="hidden" const:id="calendarCategoriesValue"
|
||||
const:name="calendarCategoriesValue" var:value="calendarCategoriesValue"/>
|
||||
</div>
|
||||
</var:if>
|
||||
<div id="contactsOptionsView" class="tab">
|
||||
|
@ -258,14 +291,14 @@
|
|||
<tr class="tableview"
|
||||
><th const:class="tbtv_headercell" const:id="nameTableHeader"
|
||||
><var:string label:value="Name"/></th
|
||||
></tr
|
||||
></thead>
|
||||
></tr
|
||||
></thead>
|
||||
<tbody>
|
||||
<var:foreach list="contactsCategoryList" item="category">
|
||||
<tr const:class="categoryListRow"
|
||||
><td const:class="categoryListCell"
|
||||
><var:string var:value="category"/></td
|
||||
></tr>
|
||||
></tr>
|
||||
</var:foreach>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -278,135 +311,135 @@
|
|||
<span><img rsrc:src="remove-icon.png" label:title="Delete" />
|
||||
</span></a>
|
||||
</div>
|
||||
<input type="hidden" const:id="contactsCategoriesValue"
|
||||
const:name="contactsCategoriesValue" var:value="contactsCategoriesValue"/>
|
||||
<input type="hidden" const:id="contactsCategoriesValue"
|
||||
const:name="contactsCategoriesValue" var:value="contactsCategoriesValue"/>
|
||||
</div>
|
||||
<var:if condition="userHasMailAccess">
|
||||
<div id="mailOptionsView" class="tab">
|
||||
<dl class="dl-horizontal">
|
||||
<dt></dt>
|
||||
<dd><input type="checkbox"
|
||||
const:name="subscribedFoldersOnly"
|
||||
const:id="subscribedFoldersOnly"
|
||||
var:checked="showSubscribedFoldersOnly" />
|
||||
<var:string label:value="Show subscribed mailboxes only"/></dd>
|
||||
<dt></dt>
|
||||
<dd><input type="checkbox"
|
||||
const:name="sortByThreads"
|
||||
const:id="sortByThreads"
|
||||
var:checked="sortByThreads" />
|
||||
<var:string label:value="Sort messages by threads"/></dd>
|
||||
<dd><input type="checkbox"
|
||||
const:name="addOutgoingAddresses"
|
||||
const:id="addOutgoingAddresses"
|
||||
var:checked="addOutgoingAddresses"
|
||||
onChange = "onAddOutgoingAddressesCheck(this);"/>
|
||||
<var:string label:value="When sending mail, add unknown recipients to my"/><br/>
|
||||
<var:popup list="addressBookList" item="item"
|
||||
const:id="addressBookList"
|
||||
const:name="addressBookList"
|
||||
string="itemAddressBookText" selection="userAddressBook"/></dd>
|
||||
const:name="subscribedFoldersOnly"
|
||||
const:id="subscribedFoldersOnly"
|
||||
var:checked="showSubscribedFoldersOnly" />
|
||||
<var:string label:value="Show subscribed mailboxes only"/></dd>
|
||||
<dt></dt>
|
||||
<dd><input type="checkbox"
|
||||
const:name="sortByThreads"
|
||||
const:id="sortByThreads"
|
||||
var:checked="sortByThreads" />
|
||||
<var:string label:value="Sort messages by threads"/></dd>
|
||||
<dd><input type="checkbox"
|
||||
const:name="addOutgoingAddresses"
|
||||
const:id="addOutgoingAddresses"
|
||||
var:checked="addOutgoingAddresses"
|
||||
onChange = "onAddOutgoingAddressesCheck(this);"/>
|
||||
<var:string label:value="When sending mail, add unknown recipients to my"/><br/>
|
||||
<var:popup list="addressBookList" item="item"
|
||||
const:id="addressBookList"
|
||||
const:name="addressBookList"
|
||||
string="itemAddressBookText" selection="userAddressBook"/></dd>
|
||||
<dt></dt>
|
||||
<dt><var:string label:value="Check for new mail:"/></dt>
|
||||
<dd><var:popup list="messageCheckList" item="item"
|
||||
const:id="messageCheck"
|
||||
const:name="messageCheck"
|
||||
string="itemMessageCheckText" selection="userMessageCheck"/></dd>
|
||||
const:id="messageCheck"
|
||||
const:name="messageCheck"
|
||||
string="itemMessageCheckText" selection="userMessageCheck"/></dd>
|
||||
<dt><var:string label:value="Forward messages:"/></dt>
|
||||
<dd><var:popup list="messageForwardingList" item="item"
|
||||
const:id="messageForwarding"
|
||||
const:name="messageForwarding"
|
||||
string="itemMessageForwardingText"
|
||||
selection="userMessageForwarding"/></dd>
|
||||
const:id="messageForwarding"
|
||||
const:name="messageForwarding"
|
||||
string="itemMessageForwardingText"
|
||||
selection="userMessageForwarding"/></dd>
|
||||
<dt><var:string label:value="When replying to a message:"/></dt>
|
||||
<dd><var:popup list="replyPlacementList" item="item"
|
||||
const:id="replyPlacementList"
|
||||
const:name="replyPlacementList"
|
||||
string="itemReplyPlacementText"
|
||||
selection="userReplyPlacement"/></dd>
|
||||
const:id="replyPlacementList"
|
||||
const:name="replyPlacementList"
|
||||
string="itemReplyPlacementText"
|
||||
selection="userReplyPlacement"/></dd>
|
||||
<dt><var:string label:value="And place my signature"/></dt>
|
||||
<dd><var:popup list="signaturePlacementList" item="item"
|
||||
const:id="signaturePlacementList"
|
||||
const:name="signaturePlacementList"
|
||||
string="itemSignaturePlacementText"
|
||||
selection="userSignaturePlacement"/></dd>
|
||||
const:id="signaturePlacementList"
|
||||
const:name="signaturePlacementList"
|
||||
string="itemSignaturePlacementText"
|
||||
selection="userSignaturePlacement"/></dd>
|
||||
<dt><var:string label:value="Compose messages in"/></dt>
|
||||
<dd><var:popup list="composeMessagesType" item="item"
|
||||
const:id="composeMessagesType"
|
||||
const:name="composeMessagesType"
|
||||
string="itemComposeMessagesText"
|
||||
selection="userComposeMessagesType"/></dd>
|
||||
const:id="composeMessagesType"
|
||||
const:name="composeMessagesType"
|
||||
string="itemComposeMessagesText"
|
||||
selection="userComposeMessagesType"/></dd>
|
||||
<dt><var:string label:value="Display remote inline images"/></dt>
|
||||
<dd><var:popup list="displayRemoteInlineImages" item="item"
|
||||
const:id="displayRemoteInlineImages"
|
||||
const:name="displayRemoteInlineImages"
|
||||
string="itemDisplayRemoteInlineImagesText"
|
||||
selection="userDisplayRemoteInlineImages"/></dd>
|
||||
const:id="displayRemoteInlineImages"
|
||||
const:name="displayRemoteInlineImages"
|
||||
string="itemDisplayRemoteInlineImagesText"
|
||||
selection="userDisplayRemoteInlineImages"/></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<div class="tabsContainer" id="mailOptionsTabs">
|
||||
<ul>
|
||||
<var:if condition="isSieveScriptsEnabled"
|
||||
><li target="mailFiltersView"><span><var:string
|
||||
label:value="Filters"/></span></li
|
||||
></var:if>
|
||||
><li target="mailFiltersView"><span><var:string
|
||||
label:value="Filters"/></span></li
|
||||
></var:if>
|
||||
<li target="mailLabelsView"><span><var:string
|
||||
label:value="Labels"/></span></li>
|
||||
label:value="Labels"/></span></li>
|
||||
</ul>
|
||||
<div class="tabs">
|
||||
<var:if condition="isSieveScriptsEnabled"
|
||||
><div id="mailFiltersView" class="tab">
|
||||
<script type="text/javascript">
|
||||
var sieveCapabilities = <var:string value="sieveCapabilities" const:escapeHTML="NO"/>;
|
||||
</script>
|
||||
<div id="filtersListWrapper" class="listWrapper">
|
||||
<table id="filtersList" cellspacing="0">
|
||||
<thead>
|
||||
<tr class="tableview">
|
||||
<th const:class="tbtv_headercell" const:id="nameTableHeader"
|
||||
><div id="mailFiltersView" class="tab">
|
||||
<script type="text/javascript">
|
||||
var sieveCapabilities = <var:string value="sieveCapabilities" const:escapeHTML="NO"/>;
|
||||
</script>
|
||||
<div id="filtersListWrapper" class="listWrapper">
|
||||
<table id="filtersList" cellspacing="0">
|
||||
<thead>
|
||||
<tr class="tableview">
|
||||
<th const:class="tbtv_headercell" const:id="nameTableHeader"
|
||||
><var:string label:value="Name" /></th>
|
||||
<th const:class="tbtv_headercell" const:id="activeTableHeader"
|
||||
<th const:class="tbtv_headercell" const:id="activeTableHeader"
|
||||
><var:string label:value="Active" /></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><!--space --></tbody>
|
||||
</table>
|
||||
<input type="hidden" const:name="sieveFilters" const:id="sieveFilters"
|
||||
var:value="sieveFiltersValue"/>
|
||||
</div><!-- #filtersListWrapper -->
|
||||
<div class="bottomToolbar">
|
||||
<a const:id="filterAdd" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="add-icon.png" label:title="Add" /></span></a>
|
||||
<a const:id="filterDelete" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="remove-icon.png" label:title="Delete" /></span></a>
|
||||
<a const:id="filterMoveUp" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="up-icon.png" label:title="Move Up" /></span></a>
|
||||
<a const:id="filterMoveDown" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="down-icon.png" label:title="Move Down" /></span></a>
|
||||
</div><!-- .bottomToolbar -->
|
||||
</div
|
||||
></var:if><!-- #mailFiltersView -->
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><!--space --></tbody>
|
||||
</table>
|
||||
<input type="hidden" const:name="sieveFilters" const:id="sieveFilters"
|
||||
var:value="sieveFiltersValue"/>
|
||||
</div><!-- #filtersListWrapper -->
|
||||
<div class="bottomToolbar">
|
||||
<a const:id="filterAdd" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="add-icon.png" label:title="Add" /></span></a>
|
||||
<a const:id="filterDelete" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="remove-icon.png" label:title="Delete" /></span></a>
|
||||
<a const:id="filterMoveUp" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="up-icon.png" label:title="Move Up" /></span></a>
|
||||
<a const:id="filterMoveDown" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="down-icon.png" label:title="Move Down" /></span></a>
|
||||
</div><!-- .bottomToolbar -->
|
||||
</div
|
||||
></var:if><!-- #mailFiltersView -->
|
||||
|
||||
<div id="mailLabelsView" class="tab">
|
||||
<div id="mailLabelsListWrapper" class="listWrapper">
|
||||
<table id="labelsList" cellspacing="0">
|
||||
<thead>
|
||||
<tr class="tableview">
|
||||
<th const:class="tbtv_headercell" const:id="labelTableHeader"
|
||||
><var:string label:value="Label"/></th>
|
||||
><var:string label:value="Label"/></th>
|
||||
<th const:class="tbtv_headercell" const:id="colorTableHeader"
|
||||
><var:string label:value="Color"/></th>
|
||||
><var:string label:value="Color"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<var:foreach list="mailLabelList" item="label"
|
||||
><tr var:data-name="label.name" const:class="labelListRow">
|
||||
<td const:class="labelListCell"
|
||||
><tr var:data-name="label.name" const:class="labelListRow">
|
||||
<td const:class="labelListCell"
|
||||
><var:string var:value="label.label"/></td>
|
||||
<td const:class="labelListCell">
|
||||
<div const:class="colorBox" var:data-color="label.color"><entity name="nbsp"/></div>
|
||||
</td>
|
||||
</tr>
|
||||
<td const:class="labelListCell">
|
||||
<div const:class="colorBox" var:data-color="label.color"><entity name="nbsp"/></div>
|
||||
</td>
|
||||
</tr>
|
||||
</var:foreach>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -414,33 +447,33 @@
|
|||
<div class="bottomToolbar">
|
||||
<a const:id="mailLabelAdd" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="add-icon.png" label:title="Add" />
|
||||
</span></a>
|
||||
</span></a>
|
||||
<a const:id="mailLabelDelete" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="remove-icon.png" label:title="Delete" />
|
||||
</span></a>
|
||||
</span></a>
|
||||
</div><!-- .bottomToolbar -->
|
||||
<input type="hidden" const:id="mailLabelsValue"
|
||||
const:name="mailLabelsValue" var:value="mailLabelsValue"/>
|
||||
const:name="mailLabelsValue" var:value="mailLabelsValue"/>
|
||||
</div><!-- #mailLabelsView -->
|
||||
</div><!-- .tabs -->
|
||||
</div><!-- #mailOptionsTabs -->
|
||||
</div><!-- #mailOptionsView -->
|
||||
|
||||
|
||||
<div id="mailAccountsView" class="tab">
|
||||
<input type="hidden" const:name="mailAccountsJSON" const:id="mailAccountsJSON"
|
||||
var:value="mailAccounts"/>
|
||||
var:value="mailAccounts"/>
|
||||
<div id="mailAccountsListWrapper" class="listWrapper"
|
||||
><ul id="mailAccountsList"
|
||||
><!-- space --></ul
|
||||
></div>
|
||||
><ul id="mailAccountsList"
|
||||
><!-- space --></ul
|
||||
></div>
|
||||
<var:if condition="mailAuxiliaryUserAccountsEnabled">
|
||||
<div const:id="mailAccountsToolbar" class="bottomToolbar">
|
||||
<a const:id="mailAccountAdd" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="add-icon.png" label:title="Add" />
|
||||
</span></a>
|
||||
</span></a>
|
||||
<a const:id="mailAccountDelete" class="bottomButton" href="#">
|
||||
<span><img rsrc:src="remove-icon.png" label:title="Delete" />
|
||||
</span></a>
|
||||
</span></a>
|
||||
</div>
|
||||
</var:if>
|
||||
<div id="mailAccountEditor">
|
||||
|
@ -448,15 +481,15 @@
|
|||
<dl class="dl-horizontal">
|
||||
<dt><var:string label:value="Server Name:"/></dt>
|
||||
<dd><input const:name="serverName" const:id="serverName" type="text" const:value=""/>
|
||||
<var:string label:value="Port:"/>
|
||||
<input const:name="port" const:id="port" type="text" const:value=""/></dd>
|
||||
<var:string label:value="Port:"/>
|
||||
<input const:name="port" const:id="port" type="text" const:value=""/></dd>
|
||||
<dt><var:string label:value="Encryption:"/></dt>
|
||||
<dd><input const:name="encryption" type="radio" const:value="none"/>
|
||||
<var:string label:value="None"/>
|
||||
<input const:name="encryption" type="radio" const:value="ssl"/>
|
||||
<var:string label:value="SSL"/>
|
||||
<input const:name="encryption" type="radio" const:value="tls"/>
|
||||
<var:string label:value="TLS"/></dd>
|
||||
<var:string label:value="None"/>
|
||||
<input const:name="encryption" type="radio" const:value="ssl"/>
|
||||
<var:string label:value="SSL"/>
|
||||
<input const:name="encryption" type="radio" const:value="tls"/>
|
||||
<var:string label:value="TLS"/></dd>
|
||||
<dt><var:string label:value="User Name:"/></dt>
|
||||
<dd><input const:name="userName" const:id="userName" type="text" const:value=""/></dd>
|
||||
<dt><var:string label:value="Password:"/></dt>
|
||||
|
@ -464,11 +497,11 @@
|
|||
</dl>
|
||||
<input const:name="encryption" type="hidden" const:value="none"/>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var mailCustomFromEnabled = <var:string value="mailCustomFromEnabled" const:escapeHTML="NO"/>;
|
||||
</script>
|
||||
|
||||
|
||||
<fieldset const:id="identityInfo">
|
||||
<dl class="dl-horizontal">
|
||||
<dt><var:string label:value="Full Name:"/></dt>
|
||||
|
@ -481,40 +514,40 @@
|
|||
<dd><span id="actSignature"><!--space --></span></dd>
|
||||
</dl>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<fieldset const:id="returnReceiptsInfo">
|
||||
<var:string
|
||||
label:value="When I receive a request for a return receipt:"
|
||||
/><br/>
|
||||
label:value="When I receive a request for a return receipt:"
|
||||
/><br/>
|
||||
<label><input const:name="receipt-action" const:id="receipt-action-ignore"
|
||||
type="radio" const:value="ignore"/>
|
||||
type="radio" const:value="ignore"/>
|
||||
<var:string
|
||||
label:value="Never send a return receipt"/></label
|
||||
><br/>
|
||||
label:value="Never send a return receipt"/></label
|
||||
><br/>
|
||||
<label><input const:name="receipt-action" const:id="receipt-action-allow"
|
||||
type="radio" const:value="allow"/>
|
||||
type="radio" const:value="allow"/>
|
||||
<var:string
|
||||
label:value="Allow return receipts for some messages"/></label
|
||||
><br/>
|
||||
label:value="Allow return receipts for some messages"/></label
|
||||
><br/>
|
||||
<div id="receiptOptions">
|
||||
<var:string
|
||||
label:value="If I'm not in the To or Cc of the message:"/>
|
||||
label:value="If I'm not in the To or Cc of the message:"/>
|
||||
<select name="receipt-non-recipient-action" id="receipt-non-recipient-action">
|
||||
<option const:value="ignore"><var:string label:value="Never send"/></option>
|
||||
<option const:value="send"><var:string label:value="Always send"/></option>
|
||||
<option const:value="ask"><var:string label:value="Ask me"/></option>
|
||||
</select><br/>
|
||||
|
||||
|
||||
<var:string
|
||||
label:value="If the sender is outside my domain:"/>
|
||||
label:value="If the sender is outside my domain:"/>
|
||||
<select name="receipt-outside-domain-action" id="receipt-outside-domain-action">
|
||||
<option const:value="ignore"><var:string label:value="Never send"/></option>
|
||||
<option const:value="send"><var:string label:value="Always send"/></option>
|
||||
<option const:value="ask"><var:string label:value="Ask me"/></option>
|
||||
</select><br/>
|
||||
|
||||
|
||||
<var:string
|
||||
label:value="In all other cases:"/>
|
||||
label:value="In all other cases:"/>
|
||||
<select name="receipt-any-action" id="receipt-any-action">
|
||||
<option const:value="ignore"><var:string label:value="Never send"/></option>
|
||||
<option const:value="send"><var:string label:value="Always send"/></option>
|
||||
|
@ -524,79 +557,79 @@
|
|||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<var:if condition="isVacationEnabled">
|
||||
<div id="vacationView" class="tab">
|
||||
<label><input type="checkbox"
|
||||
const:name="enableVacation"
|
||||
const:id="enableVacation"
|
||||
var:checked="enableVacation" />
|
||||
<label><input type="checkbox"
|
||||
const:name="enableVacation"
|
||||
const:id="enableVacation"
|
||||
var:checked="enableVacation" />
|
||||
<var:string label:value="Enable vacation auto reply"/></label>
|
||||
<div id="vacation">
|
||||
<label><var:string label:value="Auto reply message :"/><br/>
|
||||
<textarea const:name="autoReplyText"
|
||||
const:id="autoReplyText"
|
||||
var:value="autoReplyText"/>
|
||||
const:id="autoReplyText"
|
||||
var:value="autoReplyText"/>
|
||||
</label><br/>
|
||||
|
||||
<label><var:string label:value="Email addresses (separated by commas) :"/><br/>
|
||||
<input type="hidden"
|
||||
const:id="defaultEmailAddresses"
|
||||
var:value="defaultEmailAddresses" />
|
||||
const:id="defaultEmailAddresses"
|
||||
var:value="defaultEmailAddresses" />
|
||||
<textarea const:name="autoReplyEmailAddresses"
|
||||
const:id="autoReplyEmailAddresses"
|
||||
var:value="autoReplyEmailAddresses" /><br/>
|
||||
const:id="autoReplyEmailAddresses"
|
||||
var:value="autoReplyEmailAddresses" /><br/>
|
||||
<span><a href="#" class="button" id="addDefaultEmailAddresses"><span>
|
||||
<var:string label:value="Add default email addresses" /></span></a>
|
||||
<var:string label:value="Add default email addresses" /></span></a>
|
||||
</span>
|
||||
</label><br/>
|
||||
|
||||
<label><var:string label:value="Days between responses :"/>
|
||||
|
||||
<label><var:string label:value="Days between responses :"/>
|
||||
<var:popup list="daysBetweenResponsesList" item="item"
|
||||
const:id="daysBetweenResponsesList"
|
||||
const:name="daysBetweenResponsesList"
|
||||
string="item"
|
||||
selection="daysBetweenResponses" /></label><br/>
|
||||
|
||||
<label><input type="checkbox"
|
||||
const:name="ignoreLists"
|
||||
const:id="ignoreLists"
|
||||
var:checked="ignoreLists" />
|
||||
const:id="daysBetweenResponsesList"
|
||||
const:name="daysBetweenResponsesList"
|
||||
string="item"
|
||||
selection="daysBetweenResponses" /></label><br/>
|
||||
|
||||
<label><input type="checkbox"
|
||||
const:name="ignoreLists"
|
||||
const:id="ignoreLists"
|
||||
var:checked="ignoreLists" />
|
||||
<var:string label:value="Do not send responses to mailing lists" /></label><br/>
|
||||
|
||||
|
||||
<label class="timeDate"><input var:checked="enableVacationEndDate"
|
||||
const:name="enableVacationEndDate" const:id="enableVacationEndDate" type="checkbox" class="checkBox"
|
||||
/><var:string label:value="Disable auto reply on" /></label><var:component className="UIxTimeDateControl"
|
||||
const:displayTimeControl="0"
|
||||
var:disabled="disableVacationEndDate"
|
||||
const:controlID="vacationEndDate"
|
||||
date="vacationEndDate"
|
||||
const:dayStartHour="0"
|
||||
const:dayEndHour="23"
|
||||
const:name="enableVacationEndDate" const:id="enableVacationEndDate" type="checkbox" class="checkBox"
|
||||
/><var:string label:value="Disable auto reply on" /></label><var:component className="UIxTimeDateControl"
|
||||
const:displayTimeControl="0"
|
||||
var:disabled="disableVacationEndDate"
|
||||
const:controlID="vacationEndDate"
|
||||
date="vacationEndDate"
|
||||
const:dayStartHour="0"
|
||||
const:dayEndHour="23"
|
||||
/>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</var:if
|
||||
><var:if condition="isForwardEnabled">
|
||||
</var:if
|
||||
><var:if condition="isForwardEnabled">
|
||||
<div id="forwardView" class="tab">
|
||||
<label><input type="checkbox"
|
||||
const:name="enableForward"
|
||||
const:id="enableForward"
|
||||
var:checked="enableForward" />
|
||||
<label><input type="checkbox"
|
||||
const:name="enableForward"
|
||||
const:id="enableForward"
|
||||
var:checked="enableForward" />
|
||||
<var:string label:value="Forward incoming messages"/></label><br/>
|
||||
|
||||
<div id="forward">
|
||||
<label><var:string label:value="Email addresses (separated by commas) :"/><br/>
|
||||
<textarea const:name="forwardAddress"
|
||||
const:id="forwardAddress"
|
||||
var:value="forwardAddress" />
|
||||
const:id="forwardAddress"
|
||||
var:value="forwardAddress" />
|
||||
</label><br/>
|
||||
|
||||
<label><input type="checkbox"
|
||||
const:name="forwardKeepCopy"
|
||||
const:id="forwardKeepCopy"
|
||||
var:checked="forwardKeepCopy" />
|
||||
|
||||
<label><input type="checkbox"
|
||||
const:name="forwardKeepCopy"
|
||||
const:id="forwardKeepCopy"
|
||||
var:checked="forwardKeepCopy" />
|
||||
<var:string label:value="Keep a copy" /></label><br/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -605,23 +638,23 @@
|
|||
<var:if condition="shouldDisplayPasswordChange">
|
||||
<div id="passwordView" class="tab">
|
||||
<p id="passwordFields"><label><var:string label:value="New password:"
|
||||
/><input const:id="newPasswordField" class="textField"
|
||||
type="password" const:value=""/></label><br/>
|
||||
<label><var:string label:value="Confirmation:"
|
||||
/><input const:id="newPasswordConfirmationField" class="textField"
|
||||
type="password" const:value=""/></label><br/>
|
||||
<a href="#" class="button" id="changePasswordBtn"
|
||||
><span><var:string label:value="Change"/></span></a><br/>
|
||||
/><input const:id="newPasswordField" class="textField"
|
||||
type="password" const:value=""/></label><br/>
|
||||
<label><var:string label:value="Confirmation:"
|
||||
/><input const:id="newPasswordConfirmationField" class="textField"
|
||||
type="password" const:value=""/></label><br/>
|
||||
<a href="#" class="button" id="changePasswordBtn"
|
||||
><span><var:string label:value="Change"/></span></a><br/>
|
||||
</p>
|
||||
<p id="passwordError"><!-- space --></p>
|
||||
</div>
|
||||
</var:if
|
||||
><var:if condition="shouldDisplayAdditionalPreferences"
|
||||
</var:if
|
||||
><var:if condition="shouldDisplayAdditionalPreferences"
|
||||
><div id="additionalView" class="tab">
|
||||
<var:component className="UIxAdditionalPreferences"/>
|
||||
</div></var:if>
|
||||
<input type="hidden" id="hasChanged" name="hasChanged"
|
||||
var:value="hasChanged"/>
|
||||
var:value="hasChanged"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -2,277 +2,384 @@
|
|||
|
||||
// NOTE: The popup menu with id "contactsMenu" must exist before
|
||||
// using this interface.
|
||||
//
|
||||
//
|
||||
// This interface fires two events:
|
||||
// - autocompletion:changed : fired when a new contact is selected
|
||||
// - autocompletion:changedlist : fired when a new list is selected
|
||||
//
|
||||
var SOGoAutoCompletionInterface = {
|
||||
|
||||
// Attributes that could be changed from the object
|
||||
// inheriting the inteface
|
||||
uidField: "c_name",
|
||||
addressBook: null,
|
||||
excludeGroups: false,
|
||||
excludeLists: false,
|
||||
|
||||
// Internal attributes
|
||||
animationParent: null,
|
||||
selectedIndex: -1,
|
||||
delay: 0.750,
|
||||
delayedSearch: false,
|
||||
menu: null,
|
||||
|
||||
bind: function () {
|
||||
this.menu = $('contactsMenu');
|
||||
this.writeAttribute("autocomplete", "off");
|
||||
this.writeAttribute("container", null);
|
||||
this.confirmedValue = null;
|
||||
this.observe("keydown", this.onKeydown.bindAsEventListener(this));
|
||||
this.observe("blur", this.onBlur.bindAsEventListener(this));
|
||||
},
|
||||
|
||||
onKeydown: function (event) {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
this.focussed = true;
|
||||
return;
|
||||
}
|
||||
if (event.keyCode == Event.KEY_TAB) {
|
||||
if (this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
else
|
||||
this.writeAttribute("uid", null);
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
}
|
||||
else if (event.keyCode == 0
|
||||
|| event.keyCode == Event.KEY_BACKSPACE
|
||||
|| event.keyCode == Event.KEY_DELETE
|
||||
|| event.keyCode == 32 // Space
|
||||
|| event.keyCode > 47) {
|
||||
this.confirmedValue = null;
|
||||
this.selectedIndex = -1;
|
||||
if (this.delayedSearch)
|
||||
window.clearTimeout(this.delayedSearch);
|
||||
this.delayedSearch = this.performSearch.delay(this.delay, this);
|
||||
}
|
||||
else if (event.keyCode == Event.KEY_RETURN) {
|
||||
preventDefault(event);
|
||||
if (this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
else
|
||||
this.writeAttribute("uid", null);
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
this.selectedIndex = -1;
|
||||
if (this.readAttribute("container")) {
|
||||
this.confirmedValue = null;
|
||||
this.fire("autocompletion:changedlist", this.readAttribute("container"));
|
||||
}
|
||||
else
|
||||
this.fire("autocompletion:changed", event.keyCode);
|
||||
}
|
||||
else if (this.menu.getStyle('visibility') == 'visible') {
|
||||
if (event.keyCode == Event.KEY_UP) { // Up arrow
|
||||
if (this.selectedIndex > 0) {
|
||||
var contacts = this.menu.select("li");
|
||||
contacts[this.selectedIndex--].removeClassName("selected");
|
||||
this.value = contacts[this.selectedIndex].readAttribute("address");
|
||||
this.confirmedValue = this.value;
|
||||
this.writeAttribute("uid", contacts[this.selectedIndex].readAttribute("uid"));
|
||||
contacts[this.selectedIndex].addClassName("selected");
|
||||
var container = contacts[this.selectedIndex].readAttribute("container");
|
||||
if (container)
|
||||
this.writeAttribute("container", container);
|
||||
}
|
||||
}
|
||||
else if (event.keyCode == Event.KEY_DOWN) { // Down arrow
|
||||
var contacts = this.menu.select("li");
|
||||
if (contacts.size() - 1 > this.selectedIndex) {
|
||||
if (this.selectedIndex >= 0)
|
||||
contacts[this.selectedIndex].removeClassName("selected");
|
||||
this.selectedIndex++;
|
||||
this.value = contacts[this.selectedIndex].readAttribute("address");
|
||||
this.confirmedValue = this.value;
|
||||
this.writeAttribute("uid", contacts[this.selectedIndex].readAttribute("uid"));
|
||||
contacts[this.selectedIndex].addClassName("selected");
|
||||
var container = contacts[this.selectedIndex].readAttribute("container");
|
||||
if (container)
|
||||
this.writeAttribute("container", container);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onBlur: function (event) {
|
||||
if (this.delayedSearch)
|
||||
window.clearTimeout(this.delayedSearch);
|
||||
if (this.confirmedValue) {
|
||||
this.value = this.confirmedValue;
|
||||
if (this.readAttribute("container"))
|
||||
this.fire("autocompletion:changedlist", this.readAttribute("container"));
|
||||
else
|
||||
this.fire("autocompletion:changed", event.keyCode);
|
||||
}
|
||||
else
|
||||
this.writeAttribute("uid", null);
|
||||
},
|
||||
|
||||
performSearch: function (input) {
|
||||
// Perform address completion
|
||||
if (document.contactLookupAjaxRequest) {
|
||||
// Abort any pending request
|
||||
document.contactLookupAjaxRequest.aborted = true;
|
||||
document.contactLookupAjaxRequest.abort();
|
||||
}
|
||||
if (input.value.trim().length > minimumSearchLength) {
|
||||
var urlstr = UserFolderURL + "Contacts/";
|
||||
if (input.addressBook)
|
||||
urlstr += input.addressBook + "/contact";
|
||||
else
|
||||
urlstr += "allContact";
|
||||
urlstr += "Search?search=" + encodeURIComponent(input.value);
|
||||
if (input.excludeGroups)
|
||||
urlstr += "&excludeGroups=1";
|
||||
if (input.excludeLists)
|
||||
urlstr += "&excludeLists=1";
|
||||
if (input.animationParent)
|
||||
startAnimation(input.animationParent);
|
||||
document.contactLookupAjaxRequest =
|
||||
triggerAjaxRequest(urlstr, input.performSearchCallback.bind(input), input);
|
||||
}
|
||||
else {
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
}
|
||||
},
|
||||
|
||||
performSearchCallback: function (http) {
|
||||
if (http.readyState == 4) {
|
||||
var list = this.menu.down("ul");
|
||||
|
||||
var input = http.callbackData;
|
||||
|
||||
if (http.status == 200) {
|
||||
var start = input.value.length;
|
||||
var data = http.responseText.evalJSON(true);
|
||||
|
||||
if (data.contacts.length > 1) {
|
||||
list.select("li").each(function(item) {
|
||||
item.stopObserving("mousedown");
|
||||
item.remove();
|
||||
});
|
||||
|
||||
// Populate popup menu
|
||||
for (var i = 0; i < data.contacts.length; i++) {
|
||||
var contact = data.contacts[i];
|
||||
var completeEmail = contact["c_cn"];
|
||||
var uid = "" + contact[this.uidField];
|
||||
var c_name = "" + contact['c_name'];
|
||||
if (contact["c_mail"])
|
||||
completeEmail += " <" + contact["c_mail"] + ">";
|
||||
var node = new Element('li', { 'address': completeEmail,
|
||||
'uid': uid });
|
||||
var matchPosition = completeEmail.toLowerCase().indexOf(data.searchText.toLowerCase());
|
||||
if (matchPosition > -1) {
|
||||
var matchBefore = completeEmail.substring(0, matchPosition);
|
||||
var matchText = completeEmail.substring(matchPosition, matchPosition + data.searchText.length);
|
||||
var matchAfter = completeEmail.substring(matchPosition + data.searchText.length);
|
||||
node.appendChild(document.createTextNode(matchBefore));
|
||||
node.appendChild(new Element('strong').update(matchText));
|
||||
node.appendChild(document.createTextNode(matchAfter));
|
||||
}
|
||||
else {
|
||||
node.appendChild(document.createTextNode(completeEmail));
|
||||
}
|
||||
list.appendChild(node);
|
||||
if (c_name.endsWith(".vlf")) {
|
||||
// Keep track of list containers
|
||||
node.writeAttribute("container", contact['container']);
|
||||
}
|
||||
if (contact["contactInfo"])
|
||||
node.appendChild(document.createTextNode(" (" + contact["contactInfo"] + ")"));
|
||||
$(node).observe("mousedown", this.onAddressResultClick.bindAsEventListener(this));
|
||||
}
|
||||
|
||||
// Show popup menu
|
||||
var offsetScroll = Element.cumulativeScrollOffset(input);
|
||||
var offset = Element.positionedOffset(input);
|
||||
if ($(document.body).hasClassName("popup") && typeof initPopupMailer == 'undefined')
|
||||
// Hack for some situations where the offset must be computed differently
|
||||
offset = Element.cumulativeOffset(input);
|
||||
var top = offset.top - offsetScroll.top + node.offsetHeight + 3;
|
||||
var height = 'auto';
|
||||
var heightDiff = window.height() - offset[1];
|
||||
var nodeHeight = node.getHeight();
|
||||
|
||||
if ((data.contacts.length * nodeHeight) > heightDiff)
|
||||
// Limit the size of the popup to the window height, minus 12 pixels
|
||||
height = parseInt(heightDiff/nodeHeight) * nodeHeight - 12 + 'px';
|
||||
|
||||
this.menu.setStyle({ top: top + "px",
|
||||
left: offset[0] + "px",
|
||||
height: height,
|
||||
maxWidth: (window.width() - offset[0] - 12) + "px",
|
||||
visibility: "visible" });
|
||||
this.menu.scrollTop = 0;
|
||||
|
||||
document.currentPopupMenu = this.menu;
|
||||
$(document.body).stopObserving("click");
|
||||
$(document.body).observe("click", onBodyClickMenuHandler);
|
||||
}
|
||||
else {
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
|
||||
if (data.contacts.length == 1) {
|
||||
// Single result
|
||||
var contact = data.contacts[0];
|
||||
var uid = "" + contact[this.uidField];
|
||||
var c_name = "" + contact['c_name'];
|
||||
input.writeAttribute("uid", uid);
|
||||
if (c_name.endsWith(".vlf")) {
|
||||
this.writeAttribute("container", contact['container']);
|
||||
}
|
||||
var completeEmail = contact["c_cn"];
|
||||
if (contact["c_mail"])
|
||||
completeEmail += " <" + contact["c_mail"] + ">";
|
||||
if (contact["c_cn"].substring(0, input.value.length).toUpperCase()
|
||||
== input.value.toUpperCase())
|
||||
input.value = completeEmail;
|
||||
else
|
||||
// The result matches email address, not user name
|
||||
input.value += ' >> ' + completeEmail;
|
||||
input.confirmedValue = completeEmail;
|
||||
|
||||
var end = input.value.length;
|
||||
$(input).selectText(start, end);
|
||||
|
||||
this.selectedIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
document.contactLookupAjaxRequest = null;
|
||||
}
|
||||
},
|
||||
|
||||
onAddressResultClick: function(event) {
|
||||
var e = Event.element(event);
|
||||
if (e.tagName != 'LI')
|
||||
e = e.up('LI');
|
||||
if (e) {
|
||||
preventDefault(event);
|
||||
this.value = e.readAttribute("address");
|
||||
this.writeAttribute("uid", e.readAttribute("uid"));
|
||||
if (e.readAttribute("container"))
|
||||
this.fire("autocompletion:changedlist", e.readAttribute("container"));
|
||||
else {
|
||||
this.confirmedValue = this.value;
|
||||
this.fire("autocompletion:changed", Event.KEY_RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
// Attributes that could be changed from the object
|
||||
// inheriting the inteface
|
||||
uidField: "c_name",
|
||||
addressBook: null,
|
||||
SOGoUsersSearch: false,
|
||||
excludeGroups: false,
|
||||
excludeLists: false,
|
||||
|
||||
// Internal attributes
|
||||
animationParent: null,
|
||||
selectedIndex: -1,
|
||||
delay: 0.750,
|
||||
delayedSearch: false,
|
||||
menu: null,
|
||||
|
||||
bind: function () {
|
||||
this.menu = $('contactsMenu');
|
||||
this.writeAttribute("autocomplete", "off");
|
||||
this.writeAttribute("container", null);
|
||||
this.confirmedValue = null;
|
||||
this.observe("keydown", this.onKeydown.bindAsEventListener(this));
|
||||
this.observe("blur", this.onBlur.bindAsEventListener(this));
|
||||
},
|
||||
|
||||
onKeydown: function (event) {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
this.focussed = true;
|
||||
return;
|
||||
}
|
||||
if (event.keyCode == Event.KEY_TAB) {
|
||||
if (this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
else
|
||||
this.writeAttribute("uid", null);
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
}
|
||||
else if (event.keyCode == 0
|
||||
|| event.keyCode == Event.KEY_BACKSPACE
|
||||
|| event.keyCode == Event.KEY_DELETE
|
||||
|| event.keyCode == 32 // Space
|
||||
|| event.keyCode > 47) {
|
||||
this.confirmedValue = null;
|
||||
this.selectedIndex = -1;
|
||||
if (this.delayedSearch)
|
||||
window.clearTimeout(this.delayedSearch);
|
||||
this.delayedSearch = this.performSearch.delay(this.delay, this);
|
||||
}
|
||||
else if (event.keyCode == Event.KEY_RETURN) {
|
||||
preventDefault(event);
|
||||
if (this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
else
|
||||
this.writeAttribute("uid", null);
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
this.selectedIndex = -1;
|
||||
if (this.readAttribute("container")) {
|
||||
this.confirmedValue = null;
|
||||
this.fire("autocompletion:changedlist", this.readAttribute("container"));
|
||||
}
|
||||
else
|
||||
this.fire("autocompletion:changed", event.keyCode);
|
||||
}
|
||||
else if (this.menu.getStyle('visibility') == 'visible') {
|
||||
if (event.keyCode == Event.KEY_UP) { // Up arrow
|
||||
if (this.selectedIndex > 0) {
|
||||
var contacts = this.menu.select("li");
|
||||
contacts[this.selectedIndex--].removeClassName("selected");
|
||||
this.value = contacts[this.selectedIndex].readAttribute("address");
|
||||
this.confirmedValue = this.value;
|
||||
this.writeAttribute("uid", contacts[this.selectedIndex].readAttribute("uid"));
|
||||
contacts[this.selectedIndex].addClassName("selected");
|
||||
var container = contacts[this.selectedIndex].readAttribute("container");
|
||||
if (container)
|
||||
this.writeAttribute("container", container);
|
||||
}
|
||||
}
|
||||
else if (event.keyCode == Event.KEY_DOWN) { // Down arrow
|
||||
var contacts = this.menu.select("li");
|
||||
if (contacts.size() - 1 > this.selectedIndex) {
|
||||
if (this.selectedIndex >= 0)
|
||||
contacts[this.selectedIndex].removeClassName("selected");
|
||||
this.selectedIndex++;
|
||||
this.value = contacts[this.selectedIndex].readAttribute("address");
|
||||
this.confirmedValue = this.value;
|
||||
this.writeAttribute("uid", contacts[this.selectedIndex].readAttribute("uid"));
|
||||
contacts[this.selectedIndex].addClassName("selected");
|
||||
var container = contacts[this.selectedIndex].readAttribute("container");
|
||||
if (container)
|
||||
this.writeAttribute("container", container);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onBlur: function (event) {
|
||||
if (this.delayedSearch)
|
||||
window.clearTimeout(this.delayedSearch);
|
||||
if (this.confirmedValue) {
|
||||
this.value = this.confirmedValue;
|
||||
if (this.readAttribute("container"))
|
||||
this.fire("autocompletion:changedlist", this.readAttribute("container"));
|
||||
else
|
||||
this.fire("autocompletion:changed", event.keyCode);
|
||||
}
|
||||
else
|
||||
this.writeAttribute("uid", null);
|
||||
},
|
||||
|
||||
performSearch: function (input) {
|
||||
// Perform address completion
|
||||
if (document.contactLookupAjaxRequest) {
|
||||
// Abort any pending request
|
||||
document.contactLookupAjaxRequest.aborted = true;
|
||||
document.contactLookupAjaxRequest.abort();
|
||||
}
|
||||
if (input.value.trim().length > minimumSearchLength) {
|
||||
if (input.SOGoUsersSearch) {
|
||||
var urlstr = UserFolderURL + "usersSearch?search=" + encodeURIComponent(input.value);
|
||||
document.contactLookupAjaxRequest =
|
||||
triggerAjaxRequest(urlstr, input.performUsersSearchCallback.bind(input), input);
|
||||
}
|
||||
else {
|
||||
var urlstr = UserFolderURL + "Contacts/";
|
||||
if (input.addressBook)
|
||||
urlstr += input.addressBook + "/contact";
|
||||
else
|
||||
urlstr += "allContact";
|
||||
urlstr += "Search?search=" + encodeURIComponent(input.value);
|
||||
if (input.excludeGroups)
|
||||
urlstr += "&excludeGroups=1";
|
||||
if (input.excludeLists)
|
||||
urlstr += "&excludeLists=1";
|
||||
if (input.animationParent)
|
||||
startAnimation(input.animationParent);
|
||||
document.contactLookupAjaxRequest =
|
||||
triggerAjaxRequest(urlstr, input.performSearchCallback.bind(input), input);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
}
|
||||
},
|
||||
|
||||
performSearchCallback: function (http) {
|
||||
if (http.readyState == 4) {
|
||||
var list = this.menu.down("ul");
|
||||
|
||||
var input = http.callbackData;
|
||||
|
||||
if (http.status == 200) {
|
||||
var start = input.value.length;
|
||||
var data = http.responseText.evalJSON(true);
|
||||
|
||||
if (data.contacts.length > 1) {
|
||||
list.select("li").each(function(item) {
|
||||
item.stopObserving("mousedown");
|
||||
item.remove();
|
||||
});
|
||||
|
||||
// Populate popup menu
|
||||
for (var i = 0; i < data.contacts.length; i++) {
|
||||
var contact = data.contacts[i];
|
||||
var completeEmail = contact["c_cn"];
|
||||
var uid = "" + contact[this.uidField];
|
||||
var c_name = "" + contact['c_name'];
|
||||
if (contact["c_mail"])
|
||||
completeEmail += " <" + contact["c_mail"] + ">";
|
||||
var node = new Element('li', { 'address': completeEmail,
|
||||
'uid': uid });
|
||||
var matchPosition = completeEmail.toLowerCase().indexOf(data.searchText.toLowerCase());
|
||||
if (matchPosition > -1) {
|
||||
var matchBefore = completeEmail.substring(0, matchPosition);
|
||||
var matchText = completeEmail.substring(matchPosition, matchPosition + data.searchText.length);
|
||||
var matchAfter = completeEmail.substring(matchPosition + data.searchText.length);
|
||||
node.appendChild(document.createTextNode(matchBefore));
|
||||
node.appendChild(new Element('strong').update(matchText));
|
||||
node.appendChild(document.createTextNode(matchAfter));
|
||||
}
|
||||
else {
|
||||
node.appendChild(document.createTextNode(completeEmail));
|
||||
}
|
||||
list.appendChild(node);
|
||||
if (c_name.endsWith(".vlf")) {
|
||||
// Keep track of list containers
|
||||
node.writeAttribute("container", contact['container']);
|
||||
}
|
||||
if (contact["contactInfo"])
|
||||
node.appendChild(document.createTextNode(" (" + contact["contactInfo"] + ")"));
|
||||
$(node).observe("mousedown", this.onAddressResultClick.bindAsEventListener(this));
|
||||
}
|
||||
|
||||
// Show popup menu
|
||||
var offsetScroll = Element.cumulativeScrollOffset(input);
|
||||
var offset = Element.positionedOffset(input);
|
||||
if ($(document.body).hasClassName("popup") && typeof initPopupMailer == 'undefined')
|
||||
// Hack for some situations where the offset must be computed differently
|
||||
offset = Element.cumulativeOffset(input);
|
||||
var top = offset.top - offsetScroll.top + node.offsetHeight + 3;
|
||||
var height = 'auto';
|
||||
var heightDiff = window.height() - offset[1];
|
||||
var nodeHeight = node.getHeight();
|
||||
|
||||
if ((data.contacts.length * nodeHeight) > heightDiff)
|
||||
// Limit the size of the popup to the window height, minus 12 pixels
|
||||
height = parseInt(heightDiff/nodeHeight) * nodeHeight - 12 + 'px';
|
||||
|
||||
this.menu.setStyle({ top: top + "px",
|
||||
left: offset[0] + "px",
|
||||
height: height,
|
||||
maxWidth: (window.width() - offset[0] - 12) + "px",
|
||||
visibility: "visible" });
|
||||
this.menu.scrollTop = 0;
|
||||
|
||||
document.currentPopupMenu = this.menu;
|
||||
$(document.body).stopObserving("click");
|
||||
$(document.body).observe("click", onBodyClickMenuHandler);
|
||||
}
|
||||
else {
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
|
||||
if (data.contacts.length == 1) {
|
||||
// Single result
|
||||
var contact = data.contacts[0];
|
||||
var uid = "" + contact[this.uidField];
|
||||
var c_name = "" + contact['c_name'];
|
||||
input.writeAttribute("uid", uid);
|
||||
if (c_name.endsWith(".vlf")) {
|
||||
this.writeAttribute("container", contact['container']);
|
||||
}
|
||||
var completeEmail = contact["c_cn"];
|
||||
if (contact["c_mail"])
|
||||
completeEmail += " <" + contact["c_mail"] + ">";
|
||||
if (contact["c_cn"].substring(0, input.value.length).toUpperCase()
|
||||
== input.value.toUpperCase())
|
||||
input.value = completeEmail;
|
||||
else
|
||||
// The result matches email address, not user name
|
||||
input.value += ' >> ' + completeEmail;
|
||||
input.confirmedValue = completeEmail;
|
||||
|
||||
var end = input.value.length;
|
||||
$(input).selectText(start, end);
|
||||
|
||||
this.selectedIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
document.contactLookupAjaxRequest = null;
|
||||
}
|
||||
},
|
||||
|
||||
performUsersSearchCallback: function (http) {
|
||||
if (http.readyState == 4) {
|
||||
var list = this.menu.down("ul");
|
||||
var input = http.callbackData;
|
||||
if (http.status == 200) {
|
||||
var response = http.responseText.evalJSON();
|
||||
|
||||
if (response.length > 1) {
|
||||
list.select("li").each(function(item) {
|
||||
item.stopObserving("mousedown");
|
||||
item.remove();
|
||||
});
|
||||
|
||||
// Populate popup menu
|
||||
for (var i = 0; i < response.length; i++) {
|
||||
var c_name = response[i][1];
|
||||
var completeEmail = c_name;
|
||||
var c_mail = response[i][2];
|
||||
var uid = response[i][3];
|
||||
if (c_mail)
|
||||
completeEmail += " <" + c_mail + ">";
|
||||
var node = new Element('li', { 'address': completeEmail,
|
||||
'uid': uid });
|
||||
var matchPosition = completeEmail.toLowerCase().indexOf(input.getValue().toLowerCase());
|
||||
if (matchPosition > -1) {
|
||||
var matchBefore = completeEmail.substring(0, matchPosition);
|
||||
var matchText = completeEmail.substring(matchPosition, matchPosition + input.getValue().length);
|
||||
var matchAfter = completeEmail.substring(matchPosition + input.getValue().length);
|
||||
node.appendChild(document.createTextNode(matchBefore));
|
||||
node.appendChild(new Element('strong').update(matchText));
|
||||
node.appendChild(document.createTextNode(matchAfter));
|
||||
}
|
||||
else {
|
||||
node.appendChild(document.createTextNode(completeEmail));
|
||||
}
|
||||
list.appendChild(node);
|
||||
$(node).observe("mousedown", this.onAddressResultClick.bindAsEventListener(this));
|
||||
}
|
||||
|
||||
// Show popup menu
|
||||
var offsetScroll = Element.cumulativeScrollOffset(input);
|
||||
var offset = Element.positionedOffset(input);
|
||||
if ($(document.body).hasClassName("popup") && typeof initPopupMailer == 'undefined')
|
||||
// Hack for some situations where the offset must be computed differently
|
||||
offset = Element.cumulativeOffset(input);
|
||||
var top = offset.top - offsetScroll.top + node.offsetHeight + 3;
|
||||
var height = 'auto';
|
||||
var heightDiff = window.height() - offset[1];
|
||||
var nodeHeight = node.getHeight();
|
||||
|
||||
if ((response.length * nodeHeight) > heightDiff)
|
||||
// Limit the size of the popup to the window height, minus 12 pixels
|
||||
height = parseInt(heightDiff/nodeHeight) * nodeHeight - 12 + 'px';
|
||||
|
||||
this.menu.setStyle({ top: top + "px",
|
||||
left: offset[0] + "px",
|
||||
height: height,
|
||||
maxWidth: (window.width() - offset[0] - 12) + "px",
|
||||
visibility: "visible" });
|
||||
this.menu.scrollTop = 0;
|
||||
|
||||
document.currentPopupMenu = this.menu;
|
||||
$(document.body).stopObserving("click");
|
||||
$(document.body).observe("click", onBodyClickMenuHandler);
|
||||
}
|
||||
else {
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
|
||||
if (response.length == 1) {
|
||||
// Single result
|
||||
var c_name = response[0][1];
|
||||
var completeEmail = c_name;
|
||||
var c_mail = response[0][2];
|
||||
var c_uid = response[0][0];
|
||||
input.writeAttribute("uid", c_uid);
|
||||
if (c_mail)
|
||||
completeEmail += " <" + c_mail + ">";
|
||||
if (c_uid.substring(0, input.getValue().length).toUpperCase() == input.getValue().toUpperCase())
|
||||
input.value = completeEmail;
|
||||
else
|
||||
// The result matches email address, not user name
|
||||
input.value += ' >> ' + completeEmail;
|
||||
input.confirmedValue = completeEmail;
|
||||
|
||||
var end = input.getValue().length;
|
||||
$(input).selectText(start, end);
|
||||
|
||||
this.selectedIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (document.currentPopupMenu)
|
||||
hideMenu(document.currentPopupMenu);
|
||||
document.contactLookupAjaxRequest = null;
|
||||
}
|
||||
},
|
||||
|
||||
onAddressResultClick: function(event) {
|
||||
var e = Event.element(event);
|
||||
if (e.tagName != 'LI')
|
||||
e = e.up('LI');
|
||||
if (e) {
|
||||
preventDefault(event);
|
||||
this.value = e.readAttribute("address");
|
||||
this.writeAttribute("uid", e.readAttribute("uid"));
|
||||
if (e.readAttribute("container"))
|
||||
this.fire("autocompletion:changedlist", e.readAttribute("container"));
|
||||
else {
|
||||
this.confirmedValue = this.value;
|
||||
this.fire("autocompletion:changed", Event.KEY_RETURN);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -13,6 +13,23 @@ DIV.bottomToolbar
|
|||
left: 2em;
|
||||
right: 2em;
|
||||
bottom: 8px; }
|
||||
|
||||
#whiteListToolbar
|
||||
{ position: absolute;
|
||||
height: 20px;
|
||||
top: 286px;
|
||||
width: 275px;
|
||||
left: 235px;
|
||||
background-image: url("thead_bg.png");
|
||||
border: 1px solid #9B9B9B;
|
||||
background-color: #E6E7E6;
|
||||
}
|
||||
|
||||
#WhiteListAdd, #WhiteListDelete
|
||||
{
|
||||
border-bottom: 1px solid #9B9B9B;
|
||||
border-right: 1px solid #9B9B9B;
|
||||
}
|
||||
|
||||
#mailAccountsToolbar
|
||||
{ left: 5px;
|
||||
|
@ -47,17 +64,48 @@ DIV.listWrapper
|
|||
padding: 0px;
|
||||
margin-top: 2px;
|
||||
border-left: 1px solid #9b9b9b;
|
||||
border-right: 1px solid #9b9b9b;
|
||||
background: #ccddec;}
|
||||
|
||||
.listWrapper TABLE TD
|
||||
{ height: 22px; }
|
||||
|
||||
#whiteListLabel
|
||||
{
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
#calendarCategoriesLabel
|
||||
{
|
||||
position: absolute;
|
||||
top: 305px;
|
||||
left:0;
|
||||
}
|
||||
|
||||
#calendarCategoriesListWrapper
|
||||
{ top: 232px;
|
||||
{ top: 320px;
|
||||
bottom: 30px;
|
||||
right: 2em;
|
||||
left: 2em; }
|
||||
|
||||
#appointmentsWhiteListWrapper
|
||||
{ top: 230px;
|
||||
height: 54px;
|
||||
left:235px;
|
||||
width:275px;
|
||||
|
||||
}
|
||||
|
||||
#tableViewWhiteList
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#whiteListTableHeader
|
||||
{
|
||||
}
|
||||
|
||||
#contactsCategoriesListWrapper
|
||||
{ overflow: auto;
|
||||
position: absolute;
|
||||
|
|
|
@ -9,6 +9,9 @@ function savePreferences(sender) {
|
|||
if (sigList)
|
||||
sigList.disabled = false;
|
||||
|
||||
// if ($("appointmentsWhiteListWrapper"))
|
||||
// serializeAppointmentsWhiteList();
|
||||
|
||||
if ($("calendarCategoriesListWrapper"))
|
||||
serializeCalendarCategories();
|
||||
|
||||
|
@ -201,97 +204,110 @@ function addDefaultEmailAddresses(event) {
|
|||
}
|
||||
|
||||
function initPreferences() {
|
||||
var tabsContainer = $("preferencesTabs");
|
||||
var controller = new SOGoTabsController();
|
||||
controller.attachToTabsContainer(tabsContainer);
|
||||
|
||||
// Inner tabs on the mail module tab
|
||||
tabsContainer = $('mailOptionsTabs');
|
||||
if (tabsContainer) {
|
||||
var mailController = new SOGoTabsController();
|
||||
mailController.attachToTabsContainer(tabsContainer);
|
||||
}
|
||||
|
||||
_setupEvents();
|
||||
|
||||
// Optional function called when initializing the preferences
|
||||
// Typically defined inline in the UIxAdditionalPreferences.wox template
|
||||
if (typeof (initAdditionalPreferences) != "undefined")
|
||||
initAdditionalPreferences();
|
||||
|
||||
// Color picker
|
||||
$('colorPickerDialog').on('click', 'span', onColorPickerChoice);
|
||||
$(document.body).on("click", onBodyClickHandler);
|
||||
|
||||
// Calender categories
|
||||
var wrapper = $("calendarCategoriesListWrapper");
|
||||
if (wrapper) {
|
||||
var table = wrapper.childNodesWithTag("table")[0];
|
||||
resetCalendarCategoriesColors(null);
|
||||
var r = $$("#calendarCategoriesListWrapper tbody tr");
|
||||
for (var i= 0; i < r.length; i++)
|
||||
r[i].identify();
|
||||
table.multiselect = true;
|
||||
resetCalendarTableActions();
|
||||
$("calendarCategoryAdd").observe("click", onCalendarCategoryAdd);
|
||||
$("calendarCategoryDelete").observe("click", onCalendarCategoryDelete);
|
||||
wrapper.observe("scroll", onBodyClickHandler);
|
||||
}
|
||||
|
||||
// Mail labels/tags
|
||||
var wrapper = $("mailLabelsListWrapper");
|
||||
if (wrapper) {
|
||||
var table = wrapper.childNodesWithTag("table")[0];
|
||||
resetMailLabelsColors(null);
|
||||
var r = $$("#mailLabelsListWrapper tbody tr");
|
||||
for (var i= 0; i < r.length; i++)
|
||||
r[i].identify();
|
||||
table.multiselect = true;
|
||||
resetMailTableActions();
|
||||
$("mailLabelAdd").observe("click", onMailLabelAdd);
|
||||
$("mailLabelDelete").observe("click", onMailLabelDelete);
|
||||
}
|
||||
|
||||
// Contact categories
|
||||
wrapper = $("contactsCategoriesListWrapper");
|
||||
if (wrapper) {
|
||||
var table = wrapper.childNodesWithTag("table")[0];
|
||||
var r = $$("#contactsCategoriesListWrapper tbody tr");
|
||||
for (var i= 0; i < r.length; i++)
|
||||
r[i].identify();
|
||||
table.multiselect = true;
|
||||
resetContactsTableActions();
|
||||
$("contactsCategoryAdd").observe("click", onContactsCategoryAdd);
|
||||
$("contactsCategoryDelete").observe("click", onContactsCategoryDelete);
|
||||
}
|
||||
|
||||
if ($("replyPlacementList"))
|
||||
onReplyPlacementListChange();
|
||||
|
||||
var button = $("addDefaultEmailAddresses");
|
||||
if (button)
|
||||
button.observe("click", addDefaultEmailAddresses);
|
||||
|
||||
button = $("changePasswordBtn");
|
||||
if (button)
|
||||
button.observe("click", onChangePasswordClick);
|
||||
|
||||
initSieveFilters();
|
||||
|
||||
initMailAccounts();
|
||||
|
||||
button = $("enableVacationEndDate");
|
||||
if (button) {
|
||||
jQuery("#vacationEndDate_date").closest(".date").datepicker(
|
||||
{ autoclose: true, position: 'above', weekStart: $('weekStartDay').getValue() });
|
||||
button.on("click", function(event) {
|
||||
if (this.checked)
|
||||
$("vacationEndDate_date").enable();
|
||||
else
|
||||
$("vacationEndDate_date").disable();
|
||||
});
|
||||
}
|
||||
onAddOutgoingAddressesCheck();
|
||||
var tabsContainer = $("preferencesTabs");
|
||||
var controller = new SOGoTabsController();
|
||||
controller.attachToTabsContainer(tabsContainer);
|
||||
|
||||
// Inner tabs on the mail module tab
|
||||
tabsContainer = $('mailOptionsTabs');
|
||||
if (tabsContainer) {
|
||||
var mailController = new SOGoTabsController();
|
||||
mailController.attachToTabsContainer(tabsContainer);
|
||||
}
|
||||
|
||||
_setupEvents();
|
||||
|
||||
// Optional function called when initializing the preferences
|
||||
// Typically defined inline in the UIxAdditionalPreferences.wox template
|
||||
if (typeof (initAdditionalPreferences) != "undefined")
|
||||
initAdditionalPreferences();
|
||||
|
||||
// Color picker
|
||||
$('colorPickerDialog').on('click', 'span', onColorPickerChoice);
|
||||
$(document.body).on("click", onBodyClickHandler);
|
||||
|
||||
// Calendar whiteList
|
||||
var whiteList = $("appointmentsWhiteListWrapper");
|
||||
if(whiteList) {
|
||||
var table = whiteList.childNodesWithTag("table")[0];
|
||||
var r = $$("#appointmentsWhiteListWrapper tbody tr");
|
||||
for (var i= 0; i < r.length; i++)
|
||||
r[i].identify();
|
||||
table.multiselect = true;
|
||||
$("appointmentsWhiteListAdd").observe("click", onAppointmentsWhiteListAdd);
|
||||
$("appointmentsWhiteListDelete").observe("click", onAppointmentsWhiteListDelete);
|
||||
whiteList.observe("scroll", onBodyClickHandler);
|
||||
}
|
||||
|
||||
// Calendar categories
|
||||
var wrapper = $("calendarCategoriesListWrapper");
|
||||
if (wrapper) {
|
||||
var table = wrapper.childNodesWithTag("table")[0];
|
||||
resetCalendarCategoriesColors(null);
|
||||
var r = $$("#calendarCategoriesListWrapper tbody tr");
|
||||
for (var i= 0; i < r.length; i++)
|
||||
r[i].identify();
|
||||
table.multiselect = true;
|
||||
resetCalendarTableActions();
|
||||
$("calendarCategoryAdd").observe("click", onCalendarCategoryAdd);
|
||||
$("calendarCategoryDelete").observe("click", onCalendarCategoryDelete);
|
||||
wrapper.observe("scroll", onBodyClickHandler);
|
||||
}
|
||||
|
||||
// Mail labels/tags
|
||||
var wrapper = $("mailLabelsListWrapper");
|
||||
if (wrapper) {
|
||||
var table = wrapper.childNodesWithTag("table")[0];
|
||||
resetMailLabelsColors(null);
|
||||
var r = $$("#mailLabelsListWrapper tbody tr");
|
||||
for (var i= 0; i < r.length; i++)
|
||||
r[i].identify();
|
||||
table.multiselect = true;
|
||||
resetMailTableActions();
|
||||
$("mailLabelAdd").observe("click", onMailLabelAdd);
|
||||
$("mailLabelDelete").observe("click", onMailLabelDelete);
|
||||
}
|
||||
|
||||
// Contact categories
|
||||
wrapper = $("contactsCategoriesListWrapper");
|
||||
if (wrapper) {
|
||||
var table = wrapper.childNodesWithTag("table")[0];
|
||||
var r = $$("#contactsCategoriesListWrapper tbody tr");
|
||||
for (var i= 0; i < r.length; i++)
|
||||
r[i].identify();
|
||||
table.multiselect = true;
|
||||
resetContactsTableActions();
|
||||
$("contactsCategoryAdd").observe("click", onContactsCategoryAdd);
|
||||
$("contactsCategoryDelete").observe("click", onContactsCategoryDelete);
|
||||
}
|
||||
|
||||
if ($("replyPlacementList"))
|
||||
onReplyPlacementListChange();
|
||||
|
||||
var button = $("addDefaultEmailAddresses");
|
||||
if (button)
|
||||
button.observe("click", addDefaultEmailAddresses);
|
||||
|
||||
button = $("changePasswordBtn");
|
||||
if (button)
|
||||
button.observe("click", onChangePasswordClick);
|
||||
|
||||
initSieveFilters();
|
||||
|
||||
initMailAccounts();
|
||||
|
||||
button = $("enableVacationEndDate");
|
||||
if (button) {
|
||||
jQuery("#vacationEndDate_date").closest(".date").datepicker(
|
||||
{ autoclose: true, position: 'above', weekStart: $('weekStartDay').getValue() });
|
||||
button.on("click", function(event) {
|
||||
if (this.checked)
|
||||
$("vacationEndDate_date").enable();
|
||||
else
|
||||
$("vacationEndDate_date").disable();
|
||||
});
|
||||
}
|
||||
onAddOutgoingAddressesCheck();
|
||||
}
|
||||
|
||||
function initSieveFilters() {
|
||||
|
@ -977,6 +993,117 @@ function onCalendarColorEdit(e) {
|
|||
onCCE(e, "calendarCategoriesListWrapper");
|
||||
}
|
||||
|
||||
function makeEditable (element) {
|
||||
element.addClassName("editing");
|
||||
element.removeClassName("whiteListCell");
|
||||
|
||||
var span = element.down("SPAN");
|
||||
span.update();
|
||||
|
||||
var textField = element.down("INPUT");
|
||||
textField.show();
|
||||
textField.focus();
|
||||
textField.select();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function endAllEditables (e) {
|
||||
var r = $$("TABLE#tableViewWhiteList TBODY TR TD");
|
||||
for (var i = 0; i < r.length; i++) {
|
||||
var element = $(r[i]);
|
||||
if (r[i] != this && element.hasClassName("editing"))
|
||||
endEditable(null, element.down("INPUT"));
|
||||
}
|
||||
}
|
||||
|
||||
function onNameEdit (e) {
|
||||
endAllEditables();
|
||||
if (!this.hasClassName("editing")) {
|
||||
makeEditable (this);
|
||||
}
|
||||
}
|
||||
|
||||
function endEditable(event, textField) {
|
||||
if (!textField)
|
||||
textField = this;
|
||||
|
||||
var uid = textField.readAttribute("uid");
|
||||
var cell = textField.up("TD");
|
||||
var textSpan = cell.down("SPAN");
|
||||
|
||||
cell.removeClassName("editing");
|
||||
cell.addClassName("whiteListCell");
|
||||
textField.hide();
|
||||
|
||||
var tmp = textField.value;
|
||||
tmp = tmp.replace (/</, "<");
|
||||
tmp = tmp.replace (/>/, ">");
|
||||
if (!uid)
|
||||
cell.up("TR").addClassName("notfound");
|
||||
if (tmp)
|
||||
textSpan.update(tmp);
|
||||
else
|
||||
cell.up("TR").remove();
|
||||
|
||||
if (event)
|
||||
Event.stop(event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function onAppointmentsWhiteListAdd(e) {
|
||||
var tablebody = $("appointmentsWhiteListWrapper").childNodesWithTag("table")[0].tBodies[0];
|
||||
var row = new Element("tr");
|
||||
var td = new Element("td").update("");
|
||||
var textField = new Element("input");
|
||||
var span = new Element("span");
|
||||
|
||||
row.addClassName("whiteListRow");
|
||||
row.observe("mousedown", onRowClick);
|
||||
td.addClassName ("whiteListCell");
|
||||
td.observe("mousedown", endAllEditables);
|
||||
td.observe("dblclick", onNameEdit);
|
||||
textField.addInterface(SOGoAutoCompletionInterface);
|
||||
textField.SOGoUsersSearch = true;
|
||||
textField.observe("autocompletion:changed", endEditable);
|
||||
textField.addClassName("textField");
|
||||
|
||||
td.appendChild(textField);
|
||||
td.appendChild(span);
|
||||
row.appendChild (td);
|
||||
tablebody.appendChild(row);
|
||||
$(tablebody).deselectAll();
|
||||
row.selectElement();
|
||||
|
||||
makeEditable(td);
|
||||
}
|
||||
|
||||
function onAppointmentsWhiteListDelete(e) {
|
||||
var list = $('appointmentsWhiteListWrapper').down("TABLE").down("TBODY");
|
||||
var rows = list.getSelectedNodes();
|
||||
var count = rows.length;
|
||||
|
||||
for (var i=0; i < count; i++) {
|
||||
rows[i].editionController = null;
|
||||
rows[i].remove();
|
||||
}
|
||||
}
|
||||
|
||||
function serializeAppointmentsWhiteList() {
|
||||
var r = $$("#appointmentsWhiteListWrapper TBODY TR");
|
||||
|
||||
var values = [];
|
||||
for (var i = 0; i < r.length; i++) {
|
||||
var tds = r[i].childElements();
|
||||
var name = $(tds.first()).innerHTML;
|
||||
var email = "";
|
||||
values.push("\"" + name + "\": \"" + color + "\"");
|
||||
}
|
||||
|
||||
//$("calendarCategoriesValue").value = "{ " + values.join(",\n") + "}";
|
||||
}
|
||||
|
||||
function onCalendarCategoryAdd(e) {
|
||||
var row = new Element("tr");
|
||||
var nametd = new Element("td").update("");
|
||||
|
|
Loading…
Reference in New Issue