Monotone-Parent: 82c1108954dbd812828ef1b00b0345b524a062a7

Monotone-Revision: 1bc4da9c10aec9ded2d443f77aedb8ceeaaf7ce8

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2008-08-18T22:45:59
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Francis Lachapelle 2008-08-18 22:45:59 +00:00
parent 5f2d61a0d7
commit 0bede69b36
10 changed files with 223 additions and 51 deletions

1
NEWS
View File

@ -6,6 +6,7 @@
- fixed a bug where deleting a contact would leave it listed in the contact list until the next refresh - fixed a bug where deleting a contact would leave it listed in the contact list until the next refresh
- fixed a bug where events shared among different attendees would no longer be updated automatically - fixed a bug where events shared among different attendees would no longer be updated automatically
- changed the look of the Calendar module to match the look of Lightning 0.9 - changed the look of the Calendar module to match the look of Lightning 0.9
- the event details now appear when clicking on it
0.9.0-20080729 (1.0 rc7) 0.9.0-20080729 (1.0 rc7)
------------------------ ------------------------

View File

@ -22,6 +22,8 @@
#include <math.h> #include <math.h>
#import <Foundation/NSDictionary.h>
#import <NGObjWeb/SoObject.h> #import <NGObjWeb/SoObject.h>
#import <NGObjWeb/SoPermissions.h> #import <NGObjWeb/SoPermissions.h>
#import <NGObjWeb/SoSecurityManager.h> #import <NGObjWeb/SoSecurityManager.h>
@ -36,6 +38,7 @@
#import <NGCards/iCalRecurrenceRule.h> #import <NGCards/iCalRecurrenceRule.h>
#import <SoObjects/SOGo/SOGoUser.h> #import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoDateFormatter.h>
#import <SoObjects/SOGo/SOGoContentObject.h> #import <SoObjects/SOGo/SOGoContentObject.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h> #import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoAppointmentsFolder.h> #import <SoObjects/Appointments/SOGoAppointmentsFolder.h>
@ -267,6 +270,34 @@
return [self jsCloseWithRefreshMethod: @"refreshEventsAndDisplay()"]; return [self jsCloseWithRefreshMethod: @"refreshEventsAndDisplay()"];
} }
- (id <WOActionResults>) viewAction
{
id <WOActionResults> result;
NSDictionary *data;
SOGoAppointmentFolder *co;
SOGoDateFormatter *dateFormatter;
SOGoUser *user;
result = [context response];
user = [context activeUser];
co = [self clientObject];
dateFormatter = [user dateFormatterInContext: context];
[self event];
data = [NSDictionary dictionaryWithObjectsAndKeys:
[dateFormatter formattedDate: [event startDate]], @"startDate",
[dateFormatter formattedTime: [event startDate]], @"startTime",
([event hasRecurrenceRules]?@"1":@"0"), @"isReccurent",
([event isAllDay]?@"1":@"0"), @"isAllDay",
[event summary], @"summary",
[event location], @"location",
[event comment], @"description",
nil];
[(WOResponse*)result appendContentString: [data jsonRepresentation]];
return result;
}
- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request - (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
inContext: (WOContext*) context inContext: (WOContext*) context
{ {

View File

@ -172,6 +172,11 @@
}; };
}; };
methods = { methods = {
view = {
protectedBy = "ViewAllComponent";
pageName = "UIxAppointmentEditor";
actionName = "view";
};
edit = { edit = {
protectedBy = "ViewAllComponent"; protectedBy = "ViewAllComponent";
pageName = "UIxAppointmentEditor"; pageName = "UIxAppointmentEditor";

View File

@ -76,6 +76,15 @@
<li><var:string label:value="Sharing..." /></li> <li><var:string label:value="Sharing..." /></li>
</ul> </ul>
</div> </div>
<div id="eventDialog" style="display: none;">
<div>
<h1><!-- space --></h1>
<p id="startTime"><span class="label"><var:string label:value="Start:" /></span> <span><!-- space --></span></p>
<p id="location"><span class="label"><var:string label:value="Location:" /></span> <span><!-- space --></span></p>
<p id="description"><!-- space --></p>
</div>
</div>
<div id="leftPanel"> <div id="leftPanel">
<div class="tabsContainer" id="schedulerTabs"> <div class="tabsContainer" id="schedulerTabs">

View File

@ -6,6 +6,7 @@
xmlns:const="http://www.skyrix.com/od/constant" xmlns:const="http://www.skyrix.com/od/constant"
xmlns:rsrc="OGo:url" xmlns:rsrc="OGo:url"
xmlns:label="OGo:label"> xmlns:label="OGo:label">
<a href="#" <a href="#"
class="leftNavigationArrow" class="leftNavigationArrow"
var:date="prevMonthQueryParameters.day" var:date="prevMonthQueryParameters.day"

View File

@ -1,4 +1,3 @@
DIV#leftPanel DIV#leftPanel
{ position: absolute; { position: absolute;
top: 5.5em; top: 5.5em;
@ -282,6 +281,51 @@ TABLE#eventsList TH
TABLE#eventsList TH TABLE#eventsList TH
{ white-space: pre; } { white-space: pre; }
DIV#eventDialog
{ position: absolute;
top: 100px;
left: 75px;
width: 200px;
z-index: 50; }
DIV#eventDialog DIV
{ border: 1px solid #444;
/*height: 100px;*/
background-color: #fff;
padding: 5px; }
DIV#eventDialog.left
{ background-image: url("dialog-left.png");
background-repeat: no-repeat;
background-position: top left; }
DIV#eventDialog.left DIV
{ border-left: 0;
margin-left: 19px;
text-align: left; }
DIV#eventDialog.right
{ background-image: url("dialog-right.png");
background-repeat: no-repeat;
background-position: top right; }
DIV#eventDialog.right DIV
{ border-right: 0;
margin-right: 19px;
text-align: right; }
DIV#eventDialog H1,
DIV#eventDialog P
{ font-size: 10px;
margin: 0;
padding: 0; }
DIV#eventDialog SPAN.label
{ color: #444; }
DIV#eventDialog p#description
{ margin-top: 1em; }
._unfocused#dateSelector TD._selected, ._unfocused#dateSelector TD._selected,
UL._unfocused > LI._selected, UL._unfocused > LI._selected,
TABLE._unfocused#eventsList TR._selected TD TABLE._unfocused#eventsList TR._selected TD
@ -354,19 +398,13 @@ SPAN.monthsHeader A:active
border-right: 1px solid #fff; } border-right: 1px solid #fff; }
SPAN.week2, SPAN.month2 SPAN.week2, SPAN.month2
{ { font-size: small; }
font-size: small;
}
SPAN.day2, SPAN.week1, SPAN.month1 SPAN.day2, SPAN.week1, SPAN.month1
{ { font-size: medium; }
font-size: medium;
}
SPAN.day1, SPAN.week0, SPAN.month0 SPAN.day1, SPAN.week0, SPAN.month0
{ { font-size: large; }
font-size: large;
}
SPAN.day0 SPAN.day0
{ font-size: x-large; } { font-size: x-large; }
@ -891,6 +929,9 @@ DIV.monthView DIV.event
padding: 1px; padding: 1px;
height: 1.2em; } height: 1.2em; }
DIV#calendarHeader DIV.event
{ height: 1.5em; }
DIV.event DIV.text DIV.event DIV.text
{ font-size: 92%; } { font-size: 92%; }

View File

@ -77,7 +77,7 @@ function _editEventId(id, calendar, recurrence) {
urlstr += "/" + recurrence; urlstr += "/" + recurrence;
targetname += recurrence; targetname += recurrence;
} }
urlstr += "/edit"; urlstr += "/edit"; log (urlstr);
var win = window.open(urlstr, "_blank", var win = window.open(urlstr, "_blank",
"width=490,height=470,resizable=0"); "width=490,height=470,resizable=0");
if (win) if (win)
@ -315,14 +315,96 @@ function _editRecurrenceDialog(eventDiv, method) {
win.focus(); win.focus();
} }
function onViewEvent(event) {
if (event.detail == 2) return;
var url = ApplicationBaseURL + this.calendar + "/" + this.cname + "/view";
if (document.viewEventAjaxRequest) {
document.viewEventAjaxRequest.aborted = true;
document.viewEventAjaxRequest.abort();
}
document.viewEventAjaxRequest = triggerAjaxRequest(url, onViewEventCallback, this);
}
function onViewEventCallback(http) {
if (http.readyState == 4
&& http.status == 200) {
if (http.responseText.length > 0) {
var data = http.responseText.evalJSON(true);
// $H(data).keys().each(function(key) {
// log (key + " = " + data[key]);
// });
var cell = http.callbackData;
var cellPosition = cell.cumulativeOffset();
var cellDimensions = cell.getDimensions();
var div = $("eventDialog");
var divDimensions = div.getDimensions();
var view;
var left = cellPosition[0];
var top = cellPosition[1];
if (currentView != "monthview") {
view = $("daysView");
var viewPosition = view.cumulativeOffset();
if (parseInt(data["isAllDay"]) == 0) {
top -= view.scrollTop;
if (viewPosition[1] > top + 2) {
view.stopObserving("scroll", onBodyClickHandler);
view.scrollTop = cell.offsetTop;
top = viewPosition[1];
Event.observe.delay(0.1, view, "scroll", onBodyClickHandler);
}
}
}
else {
view = $("calendarView");
top -= cell.up("DIV.day").scrollTop;
}
if (left > parseInt(window.width()*0.75)) {
left = left - divDimensions["width"] + 10;
div.removeClassName("left");
div.addClassName("right");
}
else {
left = left + cellDimensions["width"] - parseInt(cellDimensions["width"]/3);
div.removeClassName("right");
div.addClassName("left");
}
// Put the event's data in the DIV
div.down("h1").update(data["summary"]);
if (parseInt(data["isAllDay"]) == 0) {
div.down("P", 0).down("SPAN", 1).update(data["startTime"]);
div.down("P", 0).show();
} else
div.down("P", 0).hide();
if (data["location"].length) {
div.down("P", 1).down("SPAN", 1).update(data["location"]);
div.down("P", 1).show();
} else
div.down("P", 1).hide();
if (data["description"].length) {
div.down("P", 2).update(data["description"]);
div.down("P", 2).show();
} else
div.down("P", 2).hide();
div.setStyle({ left: left + "px",
top: top + "px" });
div.show();
}
}
}
function editDoubleClickedEvent(event) { function editDoubleClickedEvent(event) {
if (this.recurrenceTime) if (this.recurrenceTime)
_editRecurrenceDialog(this, "confirmEditing"); _editRecurrenceDialog(this, "confirmEditing");
else else
_editEventId(this.cname, this.calendar); _editEventId(this.cname, this.calendar);
preventDefault(event); Event.stop(event);
event.cancelBubble = true;
} }
function performEventEdition(folder, event, recurrence) { function performEventEdition(folder, event, recurrence) {
@ -667,7 +749,7 @@ function changeCalendarDisplay(data, newView) {
day = currentDay; day = currentDay;
if (day) { if (day) {
if (data && newView != "monthview") { if (data) {
var divs = $$('div.day[day='+day+']'); var divs = $$('div.day[day='+day+']');
if (divs.length) { if (divs.length) {
// Don't reload the view if the event is present in current view // Don't reload the view if the event is present in current view
@ -703,14 +785,10 @@ function changeCalendarDisplay(data, newView) {
} }
url += "?day=" + day; url += "?day=" + day;
} }
// if (newView)
// log ("switching to view: " + newView);
// log ("changeCalendarDisplay: " + url);
selectedCalendarCell = null; selectedCalendarCell = null;
if (document.dayDisplayAjaxRequest) { if (document.dayDisplayAjaxRequest) {
// log ("aborting day ajaxrq");
document.dayDisplayAjaxRequest.aborted = true; document.dayDisplayAjaxRequest.aborted = true;
document.dayDisplayAjaxRequest.abort(); document.dayDisplayAjaxRequest.abort();
} }
@ -747,39 +825,30 @@ function onMonthOverview() {
} }
function scrollDayView(scrollEvent) { function scrollDayView(scrollEvent) {
var divs;
// Select event in calendar view
if (scrollEvent) { if (scrollEvent) {
var contentView;
var eventRow = $(scrollEvent); var eventRow = $(scrollEvent);
selectCalendarEvent(eventRow.calendar, eventRow.cname, eventRow.recurrenceTime); var eventBlocks = selectCalendarEvent(eventRow.calendar, eventRow.cname, eventRow.recurrenceTime);
var firstEvent = eventBlocks.first();
if (currentView == "monthview")
contentView = firstEvent.up("DIV.day");
else
contentView = $("daysView");
var top = firstEvent.cumulativeOffset()[1] - contentView.scrollTop;
// Don't scroll if the event is visible to the user
if (top < contentView.cumulativeOffset()[1])
contentView.scrollTop = firstEvent.cumulativeOffset()[1] - contentView.cumulativeOffset()[1];
else if (top > contentView.cumulativeOffset()[1] + contentView.getHeight() - firstEvent.getHeight())
contentView.scrollTop = firstEvent.cumulativeOffset()[1] - contentView.cumulativeOffset()[1];
} }
else if (currentView != "monthview") {
// Don't scroll if in month view var contentView = $("daysView");
if (currentView == "monthview") var hours = (contentView.childNodesWithTag("div")[0]).childNodesWithTag("div");
return; contentView.scrollTop = hours[dayStartHour].offsetTop;
var offset = 0;
var daysView = $("daysView");
var hours = $(daysView.childNodesWithTag("div")[0])
.childNodesWithTag("div");
offset = hours[dayStartHour].offsetTop;
if (scrollEvent && calendarEvents) {
var event = calendarEvents[scrollEvent];
if (event) {
// FIXME siblings
var classes = $w(event.siblings[0].className);
for (var i = 0; i < classes.length; i++)
if (classes[i].startsWith("starts")) {
var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
offset = hours[starts].offsetTop;
}
}
} }
daysView.scrollTop = offset - 5;
} }
function onClickableCellsDblClick(event) { function onClickableCellsDblClick(event) {
@ -916,6 +985,7 @@ function newBaseEventDIV(eventRep, event, eventText) {
eventDiv.observe("mousedown", listRowMouseDownHandler); eventDiv.observe("mousedown", listRowMouseDownHandler);
eventDiv.observe("click", onCalendarSelectEvent); eventDiv.observe("click", onCalendarSelectEvent);
eventDiv.observe("dblclick", editDoubleClickedEvent); eventDiv.observe("dblclick", editDoubleClickedEvent);
eventDiv.observe("click", onViewEvent);
event.blocks.push(eventDiv); event.blocks.push(eventDiv);
@ -1015,9 +1085,11 @@ function calendarDisplayCallback(http) {
var contentView; var contentView;
if (currentView == "monthview") if (currentView == "monthview")
contentView = $("calendarContent"); contentView = $("calendarContent");
else else {
contentView = $("daysView"); contentView = $("daysView");
contentView.observe("scroll", onBodyClickHandler);
}
refreshCalendarEvents(http.callbackData.scrollEvent); refreshCalendarEvents(http.callbackData.scrollEvent);
var days = document.getElementsByClassName("day", contentView); var days = document.getElementsByClassName("day", contentView);
@ -1027,6 +1099,8 @@ function calendarDisplayCallback(http) {
days[i].observe("dblclick", onClickableCellsDblClick); days[i].observe("dblclick", onClickableCellsDblClick);
days[i].observe("selectstart", listRowMouseDownHandler); days[i].observe("selectstart", listRowMouseDownHandler);
//days[i].down(".dayHeader").observe("selectstart", listRowMouseDownHandler); //days[i].down(".dayHeader").observe("selectstart", listRowMouseDownHandler);
if (currentView == "monthview")
days[i].observe("scroll", onBodyClickHandler);
} }
else { else {
var headerDivs = $("calendarHeader").childNodesWithTag("div"); var headerDivs = $("calendarHeader").childNodesWithTag("div");
@ -1307,6 +1381,8 @@ function selectCalendarEvent(calendar, cname, recurrenceTime) {
selection[i].selectElement(); selection[i].selectElement();
selectedCalendarCell = selection; selectedCalendarCell = selection;
} }
return selection;
} }
function onCalendarSelectEvent() { function onCalendarSelectEvent() {
@ -1863,6 +1939,10 @@ function initDateSelectorEvents() {
menuButton.observe("click", popupMonthMenu); menuButton.observe("click", popupMonthMenu);
} }
function onBodyClickHandler(event) {
$("eventDialog").hide();
}
function initCalendars() { function initCalendars() {
sorting["attribute"] = "start"; sorting["attribute"] = "start";
sorting["ascending"] = true; sorting["ascending"] = true;
@ -1875,6 +1955,7 @@ function initCalendars() {
var selector = $("calendarSelector"); var selector = $("calendarSelector");
if (selector) if (selector)
selector.attachMenu("calendarsMenu"); selector.attachMenu("calendarsMenu");
$(document.body).observe("click", onBodyClickHandler);
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

View File

@ -870,13 +870,16 @@ function setSearchCriteria(event) {
var searchValue = $("searchValue"); var searchValue = $("searchValue");
var searchCriteria = $("searchCriteria"); var searchCriteria = $("searchCriteria");
if (searchValue.ghostPhrase == searchValue.value)
searchValue.value = this.innerHTML;
searchValue.ghostPhrase = this.innerHTML; searchValue.ghostPhrase = this.innerHTML;
searchCriteria.value = this.getAttribute('id'); searchCriteria.value = this.getAttribute('id');
if (this.parentNode.chosenNode) if (this.parentNode.chosenNode)
this.parentNode.chosenNode.removeClassName("_chosen"); this.parentNode.chosenNode.removeClassName("_chosen");
this.addClassName("_chosen"); this.addClassName("_chosen");
if (this.parentNode.chosenNode != this) { if (this.parentNode.chosenNode != this) {
searchValue.lastSearch = ""; searchValue.lastSearch = "";
this.parentNode.chosenNode = this; this.parentNode.chosenNode = this;
@ -959,7 +962,7 @@ function onSearchKeyDown(event) {
function onSearchFormSubmit(event) { function onSearchFormSubmit(event) {
var searchValue = $("searchValue"); var searchValue = $("searchValue");
var searchCriteria = $("searchCriteria"); var searchCriteria = $("searchCriteria");
if (searchValue.value != searchValue.ghostPhrase if (searchValue.value != searchValue.ghostPhrase
&& (searchValue.value != searchValue.lastSearch && (searchValue.value != searchValue.lastSearch
|| searchValue.value.strip().length > 0)) { || searchValue.value.strip().length > 0)) {