See ChangeLog

Monotone-Parent: c4a5b31204ccd4c09e85262d9b5609b788a8380a
Monotone-Revision: 9057f51730136ddbcf1d8e64c8029ea9a4e6c991

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2009-04-22T21:02:11
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Francis Lachapelle
2009-04-22 21:02:11 +00:00
parent 143c91bc2d
commit 6e5d968de3
18 changed files with 375 additions and 65 deletions
@@ -41,3 +41,9 @@
"You are not allowed to access this module or this system. Please contact your system administrator." = "U hebt geen toegang tot deze module of dit systeem. Neem contact op met uw systeem beheerder.";
"You don't have the required privileges to perform the operation." = "Voor deze actie heeft u niet de benodigde rechten.";
/* alarms */
"Reminder:" = "Alarm:";
"Start:" = "Begin:";
"Due Date:" = "Verloopdatum:";
"Location:" = "Plaats:";
@@ -46,3 +46,9 @@
= "You are not allowed to access this module or this system. Please contact your system administrator.";
"You don't have the required privileges to perform the operation."
= "You don't have the required privileges to perform the operation.";
/* alarms */
"Reminder:" = "Reminder:";
"Start:" = "Start:";
"Due Date:" = "Due Date:";
"Location:" = "Location:";
@@ -43,3 +43,9 @@
= "Vous n'êtes pas autorisé à accéder à ce module ou ce système. Veuillez contacter votre administrateur système.";
"You don't have the required privileges to perform the operation."
= "Vous n'avez pas les privilèges requis pour compléter l'opération.";
/* alarms */
"Reminder:" = "Rappel :";
"Start:" = "Début :";
"Due Date:" = "Échéance :";
"Location:" = "Lieu :";
@@ -46,3 +46,9 @@
= "You are not allowed to access this module or this system. Please contact your system administrator.";
"You don't have the required privileges to perform the operation."
= "Sie haben nicht die benötigte Berechtigung für diesen Befehl.";
/* alarms */
"Reminder:" = "Alarm:";
"Start:" = "Beginn:";
"Due Date:" = "Fällig:";
"Location:" = "Ort:";
@@ -40,3 +40,9 @@
= "Non sei abilitato ad accedere a questo modulo. Contatta il tuo amministratore di sistema.";
"You don't have the required privileges to perform the operation."
= "Non disponi dei privilegi richiesti per eseguire questa operazione.";
/* alarms */
"Reminder:" = "Promemoria:";
"Start:" = "Inizio:";
"Due Date:" = "Scadenza:";
"Location:" = "Luogo:";
@@ -50,3 +50,9 @@
= "You are not allowed to access this module or this system. Please contact your system administrator.";
"You don't have the required privileges to perform the operation."
= "You don't have the required privileges to perform the operation.";
/* alarms */
"Reminder:" = "Recordatorio:";
"Start:" = "Desde:";
"Due Date:" = "Vencimiento:";
"Location:" = "Lugar:";
@@ -46,3 +46,9 @@
= "Nid oes gennych caniatad mynediad i'r modiwl hwn na'r system hwn. Cysylltwch a'r Gweinyddwr Systemau os gwelwch yn dda.";
"You don't have the required privileges to perform the operation."
= "Nid oes gennych y breintiau gofynnol i berfformio'r gweithrediad.";
/* alarms */
"Reminder:" = "Atgoffa:";
"Start:" = "Dechrau:";
"Due Date:" = "Dyddiad dyledus:";
"Location:" = "Lleoliad:";
+17
View File
@@ -34,9 +34,11 @@
#import <NGObjWeb/NSException+HTTP.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGCards/iCalAlarm.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTrigger.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <SoObjects/SOGo/NSDictionary+Utilities.h>
@@ -394,6 +396,7 @@
SOGoUser *user;
SOGoCalendarComponent *co;
iCalEvent *master;
BOOL resetAlarm;
signed int daylightOffset;
[self event];
@@ -406,6 +409,19 @@
[eventDate setTimeZone: timeZone];
co = [self clientObject];
resetAlarm = [[[context request] formValueForKey: @"resetAlarm"] boolValue];
if (resetAlarm && [event hasAlarms] && ![event hasRecurrenceRules])
{
iCalAlarm *anAlarm;
iCalTrigger *aTrigger;
anAlarm = [[event alarms] objectAtIndex: 0];
aTrigger = [anAlarm trigger];
[aTrigger setValue: 0 ofAttribute: @"x-webstatus" to: @"triggered"];
[co saveComponent: event];
}
if ([co isNew] && [co isKindOfClass: [SOGoAppointmentOccurence class]])
{
// This is a new exception in a recurrent event -- compute the daylight
@@ -421,6 +437,7 @@
}
}
data = [NSDictionary dictionaryWithObjectsAndKeys:
[event tag], @"component",
[dateFormatter formattedDate: eventDate], @"startDate",
[dateFormatter formattedTime: eventDate], @"startTime",
([event hasRecurrenceRules]? @"1": @"0"), @"isReccurent",
+24 -25
View File
@@ -43,6 +43,7 @@
#import <SoObjects/SOGo/NSObject+Utilities.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoAppointmentFolders.h>
#import <SoObjects/Appointments/SOGoAppointmentObject.h>
#import <UI/Common/WODirectAction+SOGo.h>
@@ -367,7 +368,7 @@ static NSArray *tasksFields = nil;
//
// We return:
//
// {complete Event ID (full path) => Fire date (UTC)}
// [[calendar name (full path), complete Event ID (full path), Fire date (UTC)], ..]
//
// Called when each module is loaded or whenever a calendar component is created, modified, deleted
// or whenever there's a {un}subscribe to a calendar.
@@ -375,11 +376,9 @@ static NSArray *tasksFields = nil;
// Workflow :
//
// - for ALL subscribed and ACTIVE calendars
// - returns alarms for which the (event end date > browserTime) OR (browserTime < c_nextalarm)
// - if it's a recurring event and that condition isn't met
// - set date range from X (now) until Y (now+2 days)
// - compute the c_nextalarm and if it is met, store it in c_nextalarm
//
// - returns alarms that will occur in the next 48 hours or the non-triggered alarms
// for non-completed events
// - recurring events are currently ignored
//
- (WOResponse *) alarmsListAction
{
@@ -388,9 +387,11 @@ static NSArray *tasksFields = nil;
NSMutableArray *allAlarms;
NSEnumerator *folders;
WOResponse *response;
int browserTime;
unsigned int browserTime, laterTime;
// We look for alarms in the next 48 hours
browserTime = [[[context request] formValueForKey: @"browserTime"] intValue];
laterTime = browserTime + 60*60*48;
clientObject = [self clientObject];
allAlarms = [NSMutableArray array];
@@ -399,34 +400,32 @@ static NSArray *tasksFields = nil;
{
if ([currentFolder isActive])
{
NSDictionary *entry;;
NSDictionary *entry;
NSArray *alarms;
int i, v;
BOOL isCycle;
int i;
// Let's compute everything +2 days in case we hit recurring components
alarms = [currentFolder fetchFields: [NSArray arrayWithObjects: @"c_nextalarm", @"c_iscycle", nil]
from: [NSCalendarDate date]
to: [[NSCalendarDate date] dateByAddingYears: 0 months: 0 days: 2 hours: 0 minutes: 0 seconds: 0]
title: nil
component: nil
additionalFilters: nil
includeProtectedInformation: NO];
alarms = [currentFolder fetchAlarmInfosFrom: [NSNumber numberWithInt: browserTime]
to: [NSNumber numberWithInt: laterTime]];
for (i = 0; i < [alarms count]; i++)
{
entry = [alarms objectAtIndex: i];
v = [[entry objectForKey: @"c_nextalarm"] intValue];
if (([[entry objectForKey: @"c_enddate"] intValue] > browserTime) ||
browserTime < v)
isCycle = [[entry objectForKey: @"c_iscycle"] boolValue];
if (!isCycle)
{
[allAlarms addObject: [NSDictionary dictionaryWithObject: [entry objectForKey: @"c_nextalarm"]
forKey: [entry objectForKey: @"c_name"]]];
[allAlarms addObject: [NSArray arrayWithObjects:
[currentFolder nameInContainer],
[entry objectForKey: @"c_name"],
[entry objectForKey: @"c_nextalarm"],
nil]];
}
}
}
}
response = [self responseWithStatus: 200];
[response appendContentString: [allAlarms jsonRepresentation]];
+60 -1
View File
@@ -20,6 +20,8 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSDictionary.h>
#import <NGObjWeb/SoObject.h>
#import <NGObjWeb/SoPermissions.h>
#import <NGObjWeb/SoSecurityManager.h>
@@ -28,12 +30,16 @@
#import <NGObjWeb/NSException+HTTP.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGCards/iCalAlarm.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalToDo.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalToDo.h>
#import <NGCards/iCalTrigger.h>
#import <SoObjects/SOGo/NSDictionary+Utilities.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoContentObject.h>
#import <SoObjects/SOGo/SOGoDateFormatter.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoTaskObject.h>
@@ -377,6 +383,59 @@
// return [self jsCloseWithRefreshMethod: @"refreshTasks()"];
// }
- (id <WOActionResults>) viewAction
{
WOResponse *result;
NSDictionary *data;
NSCalendarDate *startDate, *dueDate;
NSTimeZone *timeZone;
SOGoDateFormatter *dateFormatter;
SOGoUser *user;
BOOL resetAlarm;
[self todo];
result = [self responseWithStatus: 200];
user = [context activeUser];
timeZone = [user timeZone];
dateFormatter = [user dateFormatterInContext: context];
startDate = [todo startDate];
[startDate setTimeZone: timeZone];
dueDate = [todo due];
[dueDate setTimeZone: timeZone];
resetAlarm = [[[context request] formValueForKey: @"resetAlarm"] boolValue];
if (resetAlarm && [todo hasAlarms] && ![todo hasRecurrenceRules])
{
iCalAlarm *anAlarm;
iCalTrigger *aTrigger;
SOGoCalendarComponent *co;
anAlarm = [[todo alarms] objectAtIndex: 0];
aTrigger = [anAlarm trigger];
[aTrigger setValue: 0 ofAttribute: @"x-webstatus" to: @"triggered"];
co = [self clientObject];
[co saveComponent: todo];
}
data = [NSDictionary dictionaryWithObjectsAndKeys:
[todo tag], @"component",
(startDate? [dateFormatter formattedDate: startDate] : @""), @"startDate",
(startDate? [dateFormatter formattedTime: startDate] : @""), @"startTime",
(dueDate? [dateFormatter formattedDate: dueDate] : @""), @"dueDate",
(dueDate? [dateFormatter formattedTime: dueDate] : @""), @"dueTime",
([todo hasRecurrenceRules]? @"1": @"0"), @"isReccurent",
[todo summary], @"summary",
[todo location], @"location",
[todo comment], @"description",
nil];
[result appendContentString: [data jsonRepresentation]];
return result;
}
- (BOOL) shouldTakeValuesFromRequest: (WORequest *) request
inContext: (WOContext*) context
{
+5
View File
@@ -216,6 +216,11 @@
};
};
methods = {
view = {
protectedBy = "ViewAllComponent";
pageName = "UIxTaskEditor";
actionName = "view";
};
edit = {
protectedBy = "ViewAllComponent";
pageName = "UIxTaskEditor";
+6 -3
View File
@@ -1081,7 +1081,7 @@ function _drawMonthCalendarEvents(events, eventsData) {
function newMonthEventDIV(eventRep, event) {
var eventText;
if (event[7])
if (event[7]) // all-day event
eventText = event[3];
else
eventText = eventRep.starthour + " - " + event[3];
@@ -1209,7 +1209,7 @@ function _loadEventHref(href) {
document.eventsListAjaxRequest.aborted = true;
document.eventsListAjaxRequest.abort();
}
var url = ApplicationBaseURL + "/" + href;
var url = ApplicationBaseURL + href;
document.eventsListAjaxRequest
= triggerAjaxRequest(url, eventsListCallback, href);
@@ -1279,7 +1279,9 @@ function refreshEvents() {
titleSearch = "&search=" + escape(value.utf8encode());
else
titleSearch = "";
refreshAlarms();
return _loadEventHref("eventslist?asc=" + sorting["ascending"]
+ "&sort=" + sorting["attribute"]
+ "&day=" + currentDay
@@ -1288,6 +1290,7 @@ function refreshEvents() {
}
function refreshTasks() {
refreshAlarms();
return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks);
}
+102
View File
@@ -38,6 +38,10 @@ var lastClickedRow = -1;
// logArea = null;
var allDocumentElements = null;
// Alarms
var nextAlarm = null;
var Alarms = new Array();
// Ajax requests counts
var activeAjaxRequests = 0;
var removeFolderRequestCount = 0;
@@ -1215,6 +1219,103 @@ function initTabs() {
}
}
function reverseSortByAlarmTime(a, b) {
var x = parseInt(a[2]);
var y = parseInt(b[2]);
return (y - x);
}
function refreshAlarms() {
var url;
var now = new Date();
var utc = Math.floor(now.getTime()/1000);
if (document.alarmsListAjaxRequest) {
document.alarmsListAjaxRequest.aborted = true;
document.alarmsListAjaxRequest.abort();
}
url = UserFolderURL + "Calendar/alarmslist?browserTime=" + utc;
document.alarmsListAjaxRequest
= triggerAjaxRequest(url, refreshAlarmsCallback);
return true;
}
function refreshAlarmsCallback(http) {
if (http.readyState == 4
&& http.status == 200) {
document.alarmsListAjaxRequest = null;
if (http.responseText.length > 0) {
Alarms = http.responseText.evalJSON(true);
Alarms.sort(reverseSortByAlarmTime);
triggerNextAlarm();
}
}
else
log ("refreshAlarmsCallback Ajax error");
}
function triggerNextAlarm() {
if (Alarms.length > 0) {
var next = Alarms.pop();
var now = new Date();
var utc = Math.floor(now.getTime()/1000);
var url = next[0] + '/' + next[1];
var alarmTime = parseInt(next[2]);
var delay = alarmTime;
if (alarmTime > 0) delay -= utc;
var d = new Date(alarmTime*1000);
log ("now = " + now.toUTCString());
log ("next event " + url + " in " + delay + " seconds (on " + d.toUTCString() + ")");
showAlarm.delay(delay, url);
}
}
function showAlarm(url) {
url = UserFolderURL + "Calendar/" + url + "/view?resetAlarm=yes";
if (document.viewAlarmAjaxRequest) {
document.viewAlarmAjaxRequest.aborted = true;
document.viewAlarmAjaxRequest.abort();
}
document.viewAlarmAjaxRequest = triggerAjaxRequest(url, showAlarmCallback);
}
function showAlarmCallback(http) {
if (http.readyState == 4
&& http.status == 200) {
if (http.responseText.length) {
var data = http.responseText.evalJSON(true);
var msg = clabels["Reminder:"] + " " + data["summary"] + "\n";
if (data["startDate"]) {
msg += clabels["Start:"] + " " + data["startDate"];
if (parseInt(data["isAllDay"]) == 0)
msg += " - " + data["startTime"];
msg += "\n";
}
if (data["dueDate"]) {
msg += clabels["Due Date:"] + " " + data["dueDate"];
if (data["dueTime"])
msg += " - " + data["dueTime"];
msg += "\n";
}
if (data["location"].length)
msg += "\n" + clabels["Location:"] + " " + data["location"];
if (data["description"].length)
msg += "\n\n" + data["description"];
window.alert(msg);
}
else
log("showAlarmCallback ajax error: no data received");
}
else {
log("showAlarmCallback ajax error (" + http.status + "): " + http.url);
}
triggerNextAlarm();
}
function initMenus() {
var menus = getMenus();
if (menus) {
@@ -1435,6 +1536,7 @@ function onLoadHandler(event) {
queryParameters = parseQueryParameters('' + window.location);
if (!$(document.body).hasClassName("popup")) {
initLogConsole();
refreshAlarms();
}
initCriteria();
configureSearchField();