See ChangeLog
Monotone-Parent: 6909119bf676c36ec9130366c9880eea70ad1841 Monotone-Revision: 91077f9a3b3dec2d983310daef5d9923ce41255f Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2010-07-08T04:13:56 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
9c79bd5473
commit
a8a0084614
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2010-07-09 Francis Lachapelle <flachapelle@inverse.ca>
|
||||
|
||||
* UI/WebServerResources/UIxAttendeesEditor.js (onContactKeydown):
|
||||
reset left scroll uppon autocompletion (fix for IE).
|
||||
(onAttendeeResultClick): idem.
|
||||
(prepareAttendees): add the organizer at the top of the attendees list.
|
||||
|
||||
* UI/Scheduler/UIxComponentEditor.m (-jsonOrganizer): new method
|
||||
that returns a JSON representation of a dictionary describing the
|
||||
organizer of the event.
|
||||
|
||||
2010-07-07 Francis Lachapelle <flachapelle@inverse.ca>
|
||||
|
||||
* UI/WebServerResources/HTMLInputElement.js: renamed valueAsDate
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
#import <SOGo/NSDictionary+Utilities.h>
|
||||
|
||||
#import <Common/UIxPageFrame.h>
|
||||
|
||||
#import "UIxAttendeesEditor.h"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* UIxComponentEditor.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2006-2009 Inverse inc.
|
||||
* Copyright (C) 2006-2010 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
|
@ -812,6 +812,65 @@ iRANGE(2);
|
|||
return [jsonAttendees jsonRepresentation];
|
||||
}
|
||||
|
||||
- (NSString *) jsonOrganizer
|
||||
{
|
||||
NSMutableDictionary *jsonOrganizer;
|
||||
NSDictionary *ownerIdentity;
|
||||
NSString *uid, *name, *email, *partstat, *role;
|
||||
SOGoUserManager *um;
|
||||
SOGoCalendarComponent *co;
|
||||
SOGoUser *ownerUser;
|
||||
|
||||
jsonOrganizer = [NSMutableDictionary dictionary];
|
||||
email = [organizer rfc822Email];
|
||||
role = nil;
|
||||
partstat = nil;
|
||||
|
||||
if ([email length])
|
||||
{
|
||||
um = [SOGoUserManager sharedUserManager];
|
||||
|
||||
name = [organizer cn];
|
||||
uid = [um getUIDForEmail: email];
|
||||
|
||||
partstat = [[organizer partStat] lowercaseString];
|
||||
role = [[organizer role] lowercaseString];
|
||||
}
|
||||
else
|
||||
{
|
||||
// No organizer defined in vEvent
|
||||
co = [self clientObject];
|
||||
uid = [[co container] ownerInContext: context];
|
||||
ownerUser = [SOGoUser userWithLogin: uid roles: nil];
|
||||
ownerIdentity = [ownerUser defaultIdentity];
|
||||
|
||||
name = [ownerIdentity objectForKey: @"fullName"];
|
||||
email = [ownerIdentity objectForKey: @"email"];
|
||||
}
|
||||
|
||||
if (uid != nil)
|
||||
[jsonOrganizer setObject: uid
|
||||
forKey: @"uid"];
|
||||
|
||||
[jsonOrganizer setObject: name
|
||||
forKey: @"name"];
|
||||
|
||||
[jsonOrganizer setObject: email
|
||||
forKey: @"email"];
|
||||
|
||||
if (partstat == nil || ![partstat length])
|
||||
partstat = @"accepted";
|
||||
[jsonOrganizer setObject: partstat
|
||||
forKey: @"partstat"];
|
||||
|
||||
if (role == nil || ![role length])
|
||||
role = @"chair";
|
||||
[jsonOrganizer setObject: role
|
||||
forKey: @"role"];
|
||||
|
||||
return [jsonOrganizer jsonRepresentation];
|
||||
}
|
||||
|
||||
- (void) setLocation: (NSString *) _value
|
||||
{
|
||||
ASSIGN (location, _value);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
const:popup="YES"
|
||||
const:jsFiles="skycalendar.js">
|
||||
<div class="popupMenu" id="attendeesMenu">
|
||||
<ul></ul>
|
||||
<ul><!-- space --></ul>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var dayStartHour = <var:string value="dayStartHour"/>;
|
||||
|
@ -21,20 +21,22 @@
|
|||
<div id="attendeesView">
|
||||
<form const:href=""
|
||||
><div id="freeBusyViewButtons">
|
||||
<var:string label:value="Suggest time slot:"/>
|
||||
<span id="freeBusyViewOptions">
|
||||
<var:string label:value="Suggest time slot:"/>
|
||||
|
||||
<span id="freeBusyTimeRange">
|
||||
<var:string label:value="Between"/>
|
||||
<select const:id="timeSlotStartLimitHour"><!--space --></select>
|
||||
<select const:id="timeSlotStartLimitMinute"><!--space --></select>
|
||||
<var:string label:value="and"/>
|
||||
<select const:id="timeSlotEndLimitHour"><!--space --></select>
|
||||
<select const:id="timeSlotEndLimitMinute"><!--space --></select>
|
||||
</span>
|
||||
|
||||
<span id="freeBusyTimeRange">
|
||||
<var:string label:value="Between"/>
|
||||
<select const:id="timeSlotStartLimitHour"><!-- space --></select>
|
||||
<select const:id="timeSlotStartLimitMinute"><!-- space --></select>
|
||||
<var:string label:value="and"/>
|
||||
<select const:id="timeSlotEndLimitHour"><!-- space --></select>
|
||||
<select const:id="timeSlotEndLimitMinute"><!-- space --></select>
|
||||
</span>
|
||||
<label><input type="checkbox" const:id="workDaysOnly" const:checked="YES"
|
||||
/><var:string label:value="Work days only"/></label>
|
||||
</span>
|
||||
|
||||
<label><input type="checkbox" const:id="workDaysOnly"
|
||||
const:checked="YES"
|
||||
/><var:string label:value="Work days only"/></label>
|
||||
<a id="nextSlot" href="#" class="button"
|
||||
><span><var:string label:value="Next slot" /></span></a>
|
||||
<a id="previousSlot" href="#" class="button"
|
||||
|
@ -77,8 +79,8 @@
|
|||
<td class="freeBusyData">
|
||||
<div><table id="freeBusyData" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr class="futureData"></tr>
|
||||
<tr class="dataModel"></tr>
|
||||
<tr class="futureData"><!-- space --></tr>
|
||||
<tr class="dataModel"><!-- space --></tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
</td>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
const:negate="YES">false</var:if>;
|
||||
var attendees = <var:string value="jsonAttendees" const:escapeHTML="NO"/>;
|
||||
var ownerLogin = '<var:string value="ownerLogin"/>';
|
||||
var organizer = <var:string value="jsonOrganizer" const:escapeHTML="NO"/>;
|
||||
</script>
|
||||
|
||||
<var:if condition="eventIsReadOnly" const:negate="YES">
|
||||
|
|
|
@ -164,7 +164,7 @@ function addContact(tag, fullContactName, contactId, contactName, contactEmail)
|
|||
|
||||
function saveEvent(sender) {
|
||||
if (validateAptEditor()) {
|
||||
document.forms['editform'].attendees.value = $(attendees).toJSON();
|
||||
document.forms['editform'].attendees.value = Object.toJSON($(attendees));
|
||||
document.forms['editform'].submit();
|
||||
}
|
||||
|
||||
|
@ -324,7 +324,7 @@ function refreshAttendees(newAttendees) {
|
|||
|
||||
if (!attendeesHref)
|
||||
return refreshAttendeesRO();
|
||||
|
||||
|
||||
if (attendeesMenu)
|
||||
attendeesMenu = $("attendeesMenu").down("ul");
|
||||
|
||||
|
@ -337,12 +337,12 @@ function refreshAttendees(newAttendees) {
|
|||
if (menuItems && attendeesMenu)
|
||||
for (var i = 0; i < menuItems.length; i++)
|
||||
attendeesMenu.removeChild(menuItems[i]);
|
||||
|
||||
if (newAttendees) {
|
||||
|
||||
if (newAttendees)
|
||||
// Update global variable
|
||||
attendees = $H(newAttendees.evalJSON());
|
||||
}
|
||||
|
||||
if (attendees.keys().length > 0) {
|
||||
if (attendees.keys().length > 0) {
|
||||
// Update attendees link and show label
|
||||
var names = new Array();
|
||||
attendees.values().each(function(attendee) {
|
||||
|
|
|
@ -243,13 +243,15 @@ TABLE#freeBusyData TD.noFreeBusy
|
|||
{ margin: 0px;
|
||||
text-align: left; }
|
||||
|
||||
SPAN#freeBusyViewOptions
|
||||
{ float: left; }
|
||||
|
||||
#freeBusyViewButtons SELECT
|
||||
{ width: 50px; }
|
||||
|
||||
SPAN.hidden
|
||||
{ display: none; }
|
||||
|
||||
#freeBusyViewButtons > DIV.buttons
|
||||
{ margin: 0px;
|
||||
margin-top: 4px; }
|
||||
|
||||
DIV#freeBusyReplicas
|
||||
{ position: absolute;
|
||||
top: 2px;
|
||||
|
|
|
@ -106,8 +106,10 @@ function onContactKeydown(event) {
|
|||
this.focussed = true;
|
||||
return;
|
||||
}
|
||||
if (event.keyCode == 9 || event.keyCode == 13) { // Tab
|
||||
if (event.keyCode == Event.KEY_TAB || event.keyCode == Event.KEY_RETURN) {
|
||||
preventDefault(event);
|
||||
this.scrollLeft = 0;
|
||||
$(this).up('DIV').scrollLeft = 0;
|
||||
if (this.confirmedValue)
|
||||
this.value = this.confirmedValue;
|
||||
this.hasfreebusy = false;
|
||||
|
@ -128,7 +130,7 @@ function onContactKeydown(event) {
|
|||
}
|
||||
}
|
||||
else if (event.keyCode == 0
|
||||
|| event.keyCode == 8 // Backspace
|
||||
|| event.keyCode == Event.KEY_BACKSPACE
|
||||
|| event.keyCode == 32 // Space
|
||||
|| event.keyCode > 47) {
|
||||
this.modified = true;
|
||||
|
@ -349,6 +351,8 @@ function onAttendeeResultClick(event) {
|
|||
input.confirmedValue = input.value = this.address;
|
||||
initializeAttendeeRole(input);
|
||||
checkAttendee(input);
|
||||
this.scrollLeft = 0;
|
||||
$(this).up('DIV').scrollLeft = 0;
|
||||
|
||||
this.parentNode.input = null;
|
||||
}
|
||||
|
@ -440,7 +444,7 @@ function rotateAttendeeStatus(row) {
|
|||
idx++;
|
||||
}
|
||||
row.setAttribute(attributeName, values[idx]);
|
||||
if (Prototype.Browser.IE) {
|
||||
if (!Prototype.Browser.Gecko) {
|
||||
/* This hack enables a refresh of the row element right after the
|
||||
click. Otherwise, this occurs only when leaving the element with
|
||||
them mouse cursor. */
|
||||
|
@ -1289,7 +1293,7 @@ function onEditorOkClick(event) {
|
|||
var inputs = $("freeBusy").getElementsByTagName("input");
|
||||
for (var i = 0; i < inputs.length - 1; i++) {
|
||||
var input = inputs[i];
|
||||
if (input.uid) {
|
||||
if (!input.disabled && input.uid) {
|
||||
uids.push(input.uid);
|
||||
}
|
||||
}
|
||||
|
@ -1321,6 +1325,8 @@ function _confirmEditorOkClick() {
|
|||
var newAttendees = new Hash();
|
||||
var inputs = $("freeBusy").getElementsByTagName("input");
|
||||
for (var i = 0; i < inputs.length - 1; i++) {
|
||||
if (inputs[i].disabled)
|
||||
continue;
|
||||
var row = $(inputs[i]).up("tr");
|
||||
var name = extractEmailName(inputs[i].value);
|
||||
var email = extractEmailAddress(inputs[i].value);
|
||||
|
@ -1348,7 +1354,7 @@ function _confirmEditorOkClick() {
|
|||
attendee["role"] = role;
|
||||
newAttendees.set(email, attendee);
|
||||
}
|
||||
window.opener.refreshAttendees(newAttendees.toJSON());
|
||||
window.opener.refreshAttendees(Object.toJSON(newAttendees));
|
||||
|
||||
updateParentDateFields("startTime", "startTime");
|
||||
updateParentDateFields("endTime", "endTime");
|
||||
|
@ -1481,16 +1487,48 @@ function prepareTableRows() {
|
|||
function prepareAttendees() {
|
||||
var tableAttendees = $("freeBusyAttendees");
|
||||
var tableData = $("freeBusyData");
|
||||
var organizer = window.opener.organizer;
|
||||
var attendees = window.opener.attendees;
|
||||
var attendeesKeys = (attendees ? attendees.keys() : null);
|
||||
if (attendeesKeys && attendeesKeys.length > 0) {
|
||||
var tbodyAttendees = tableAttendees.tBodies[0];
|
||||
var modelAttendee = tbodyAttendees.rows[tbodyAttendees.rows.length - 1];
|
||||
var newAttendeeRow = tbodyAttendees.rows[tbodyAttendees.rows.length - 2];
|
||||
|
||||
var tbodyData = tableData.tBodies[0];
|
||||
var modelData = tbodyData.rows[tbodyData.rows.length - 1];
|
||||
var newDataRow = tbodyData.rows[tbodyData.rows.length - 2];
|
||||
var tbodyAttendees = tableAttendees.tBodies[0];
|
||||
var modelAttendee = tbodyAttendees.rows[tbodyAttendees.rows.length - 1];
|
||||
var newAttendeeRow = tbodyAttendees.rows[tbodyAttendees.rows.length - 2];
|
||||
|
||||
var tbodyData = tableData.tBodies[0];
|
||||
var modelData = tbodyData.rows[tbodyData.rows.length - 1];
|
||||
var newDataRow = tbodyData.rows[tbodyData.rows.length - 2];
|
||||
|
||||
// Unconditionaly add the organizer
|
||||
var row = $(modelAttendee.cloneNode(true));
|
||||
tbodyAttendees.insertBefore(row, newAttendeeRow);
|
||||
row.removeClassName("attendeeModel");
|
||||
row.setAttribute("partstat", organizer["partstat"]);
|
||||
row.setAttribute("role", organizer["role"]);
|
||||
var uid = organizer["uid"];
|
||||
row.addClassName("organizer-row");
|
||||
row.removeClassName("attendee-row");
|
||||
row.isOrganizer = true;
|
||||
var input = row.down("input");
|
||||
var value = organizer["name"];
|
||||
if (value)
|
||||
value += " ";
|
||||
else
|
||||
value = "";
|
||||
value += "<" + organizer["email"] + ">";
|
||||
input.value = value;
|
||||
input.uid = uid;
|
||||
//input.cname = organizer["cname"];
|
||||
input.setAttribute("name", "");
|
||||
input.modified = false;
|
||||
input.disable();
|
||||
|
||||
row = $(modelData.cloneNode(true));
|
||||
tbodyData.insertBefore(row, newDataRow);
|
||||
row.removeClassName("dataModel");
|
||||
displayFreeBusyForNode(input);
|
||||
|
||||
if (attendeesKeys && attendeesKeys.length > 0) {
|
||||
|
||||
attendeesKeys.each(function(atKey) {
|
||||
var attendee = attendees.get(atKey);
|
||||
|
@ -1524,7 +1562,7 @@ function prepareAttendees() {
|
|||
value = "";
|
||||
value += "<" + attendee["email"] + ">";
|
||||
input.value = value;
|
||||
input.uid = attendee["uid"];
|
||||
input.uid = uid;
|
||||
input.cname = attendee["cname"];
|
||||
input.setAttribute("name", "");
|
||||
input.modified = false;
|
||||
|
@ -1535,7 +1573,7 @@ function prepareAttendees() {
|
|||
row = $(modelData.cloneNode(true));
|
||||
tbodyData.insertBefore(row, newDataRow);
|
||||
row.removeClassName("dataModel");
|
||||
displayFreeBusyForNode(input);
|
||||
displayFreeBusyForNode(input);
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -352,7 +352,6 @@ function initMailEditor() {
|
|||
|
||||
var subjectField = $$("div#subjectRow input").first();
|
||||
initTabIndex($("addressList"), subjectField, textarea);
|
||||
//onWindowResize.defer();
|
||||
|
||||
var focusField = (mailIsReply ? textarea : $("addr_0"));
|
||||
focusField.focus();
|
||||
|
@ -517,18 +516,18 @@ function onWindowResize(event) {
|
|||
|
||||
var attachmentsarea = $("attachmentsArea");
|
||||
var attachmentswidth = 0;
|
||||
var subjectfield = headerarea.down("div#subjectRow span.headerField");
|
||||
var subjectinput = headerarea.down("div#subjectRow input.textField");
|
||||
if (attachmentsarea.style.display) {
|
||||
// Resize attachments list
|
||||
attachmentswidth = attachmentsarea.getWidth();
|
||||
fromfield = $(document).getElementsByClassName('headerField', headerarea)[0];
|
||||
var height = headerarea.getHeight() - fromfield.getHeight() - 10;
|
||||
var height = headerarea.getHeight() - fromfield.getHeight() - subjectfield.getHeight() - 10;
|
||||
if (Prototype.Browser.IE)
|
||||
$("attachments").setStyle({ height: (height - 13) + 'px' });
|
||||
else
|
||||
$("attachments").setStyle({ height: height + 'px' });
|
||||
}
|
||||
var subjectfield = headerarea.down("div#subjectRow span.headerField");
|
||||
var subjectinput = headerarea.down("div#subjectRow input.textField");
|
||||
|
||||
// Resize subject field
|
||||
subjectinput.setStyle({ width: (window.width()
|
||||
|
|
Loading…
Reference in New Issue