diff --git a/ChangeLog b/ChangeLog index c7be8c25a..18a80e335 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2007-06-07 Wolfgang Sourdeau + * UI/Scheduler/UIxCalListingActions.m ([UIxCalListingActions + -_setupContext]): take the range of dates specified by the popup + into account. + + * UI/Scheduler/UIxCalListingActions.[hm]: new subclass of + WODirectAction that returns WOResponse objects with the events or + todos satisfying the parameters passed in the url. + * UI/Scheduler/UIxAppointmentEditor.m ([UIxAppointmentEditor -takeValuesFromRequest:_rqinContext:_ctx]): take the new ivar "isAllDay" into account and compute the amount of days to pass to diff --git a/UI/Scheduler/GNUmakefile b/UI/Scheduler/GNUmakefile index 66c045d8e..830b6972f 100644 --- a/UI/Scheduler/GNUmakefile +++ b/UI/Scheduler/GNUmakefile @@ -20,8 +20,6 @@ SchedulerUI_OBJC_FILES = \ \ UIxComponent+Scheduler.m \ UIxCalView.m \ - UIxCalAptListView.m \ - UIxCalTasksListView.m \ UIxCalDayView.m \ UIxCalMulticolumnDayView.m \ UIxCalWeekView.m \ @@ -29,6 +27,8 @@ SchedulerUI_OBJC_FILES = \ UIxCalMonthViewOld.m \ UIxAptTableView.m \ \ + UIxCalListingActions.m \ + \ UIxAttendeesEditor.m \ UIxComponentEditor.m \ UIxCalendarSelector.m \ diff --git a/UI/Scheduler/UIxCalAptListView.h b/UI/Scheduler/UIxCalAptListView.h deleted file mode 100644 index b2205239f..000000000 --- a/UI/Scheduler/UIxCalAptListView.h +++ /dev/null @@ -1,43 +0,0 @@ -/* UIxCalAptListView.h - this file is part of SOGo - * - * Copyright (C) 2006 Inverse groupe conseil - * - * Author: Wolfgang Sourdeau - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef UIXCALAPTLISTVIEW_H -#define UIXCALAPTLISTVIEW_H - -#import "UIxCalView.h" - -@class NSDictionary; - -@interface UIxCalAptListView : UIxCalView -{ - NSCalendarDate *startDate; - NSCalendarDate *endDate; - - NSDictionary *currentAppointment; -} - -- (void) setCurrentAppointment: (NSDictionary *) apt; -- (NSDictionary *) currentAppointment; - -@end - -#endif /* UIXCALAPTLIST_H */ diff --git a/UI/Scheduler/UIxCalAptListView.m b/UI/Scheduler/UIxCalAptListView.m deleted file mode 100644 index 92d227d8f..000000000 --- a/UI/Scheduler/UIxCalAptListView.m +++ /dev/null @@ -1,183 +0,0 @@ -/* UIxCalAptListView.m - this file is part of SOGo - * - * Copyright (C) 2006 Inverse groupe conseil - * - * Author: Wolfgang Sourdeau - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#import -#import -#import - -#import -#import - -#import - -#import "UIxCalAptListView.h" - -@implementation UIxCalAptListView - -- (id) init -{ - if ((self = [super init])) - { - startDate = nil; - endDate = nil; - } - - return self; -} - -- (void) setCurrentAppointment: (NSDictionary *) apt -{ - currentAppointment = apt; -} - -- (NSDictionary *) currentAppointment -{ - return currentAppointment; -} - -- (NSCalendarDate *) startDate -{ - NSCalendarDate *today; - NSString *filterPopup; - - if (!startDate) - { - filterPopup = [self queryParameterForKey: @"filterpopup"]; - today = [[NSCalendarDate date] beginOfDay]; - if (!filterPopup || ![filterPopup length]) - startDate = today; - else if ([filterPopup isEqualToString: @"view_selectedday"]) - startDate = [[self selectedDate] beginOfDay]; - else if ([filterPopup isEqualToString: @"view_thismonth"]) - startDate = [today firstDayOfMonth]; - else if ([filterPopup isEqualToString: @"view_all"]) - startDate = [NSCalendarDate dateWithTimeIntervalSince1970: 0]; - else - startDate = today; - } - - return startDate; -} - -- (NSCalendarDate *) endDate -{ - NSCalendarDate *today; - NSString *filterPopup; - - if (!endDate) - { - filterPopup = [self queryParameterForKey: @"filterpopup"]; - - today = [[NSCalendarDate date] endOfDay]; - if (!filterPopup || ![filterPopup length] - || [filterPopup isEqualToString: @"view_today"]) - endDate = today; - else if ([filterPopup isEqualToString: @"view_all"] - || [filterPopup isEqualToString: @"view_future"]) - endDate = [NSCalendarDate dateWithTimeIntervalSince1970: 0x7fffffff]; - else if ([filterPopup isEqualToString: @"view_thismonth"]) - endDate = [today lastDayOfMonth]; - else if ([filterPopup isEqualToString: @"view_selectedday"]) - endDate = [[self selectedDate] endOfDay]; - else if ([filterPopup isEqualToString: @"view_next7"]) - endDate = [today dateByAddingYears: 0 months: 0 days: 7]; - else if ([filterPopup isEqualToString: @"view_next14"]) - endDate = [today dateByAddingYears: 0 months: 0 days: 14]; - else if ([filterPopup isEqualToString: @"view_next31"]) - endDate = [today dateByAddingYears: 0 months: 1 days: 0]; - else - endDate = today; - } - - return endDate; -} - -- (SOGoDateFormatter *) itemDateFormatter -{ - SOGoDateFormatter *fmt; - - fmt = [[SOGoDateFormatter alloc] initWithLocale: [self locale]]; - [fmt autorelease]; - [fmt setFullWeekdayNameAndDetails]; - - return fmt; -} - -- (NSString *) currentStartTime -{ - NSCalendarDate *date; - - date = [NSCalendarDate dateWithTimeIntervalSince1970: - [[currentAppointment objectForKey: @"startdate"] - intValue]]; - [date setTimeZone: timeZone]; - - return [[self itemDateFormatter] stringForObjectValue: date]; -} - -- (NSString *) currentEndTime -{ - NSCalendarDate *date; - - date = [NSCalendarDate dateWithTimeIntervalSince1970: - [[currentAppointment objectForKey: @"enddate"] - intValue]]; - [date setTimeZone: timeZone]; - - return [[self itemDateFormatter] stringForObjectValue: date]; -} - -- (NSString *) currentLocation -{ - return [currentAppointment objectForKey: @"location"]; -} - -- (NSString *) currentSerialDay -{ - NSCalendarDate *date; - int intDate; - - intDate = [[currentAppointment objectForKey: @"startdate"] intValue]; - date = [NSCalendarDate dateWithTimeIntervalSince1970: intDate]; - [date setTimeZone: timeZone]; - - return [NSString stringWithFormat: @"%d%.2d%.2d", - [date yearOfCommonEra], - [date monthOfYear], - [date dayOfMonth]]; -} - -- (NSString *) currentSerialHour -{ - NSCalendarDate *date; - int intDate; - - intDate = [[currentAppointment objectForKey: @"startdate"] intValue]; - date = [NSCalendarDate dateWithTimeIntervalSince1970: intDate]; - [date setTimeZone: timeZone]; - - return [NSString stringWithFormat: @"%.2d%.2d", - [date hourOfDay], - [date minuteOfHour]]; -} - -@end diff --git a/UI/Scheduler/UIxCalTasksListView.h b/UI/Scheduler/UIxCalListingActions.h similarity index 67% rename from UI/Scheduler/UIxCalTasksListView.h rename to UI/Scheduler/UIxCalListingActions.h index 59b94dd77..c222ec0c1 100644 --- a/UI/Scheduler/UIxCalTasksListView.h +++ b/UI/Scheduler/UIxCalListingActions.h @@ -1,4 +1,4 @@ -/* UIxCalTasksListView.h - this file is part of SOGo +/* UIxCalListingActions.h - this file is part of SOGo * * Copyright (C) 2006 Inverse groupe conseil * @@ -20,29 +20,32 @@ * Boston, MA 02111-1307, USA. */ -#ifndef UIXCALTASKSLISTVIEW_H -#define UIXCALTASKSLISTVIEW_H +#ifndef UIXCALLISTINGACTIONVIEW_H +#define UIXCALLISTINGACTIONVIEW_H -#import "UIxCalView.h" -@class NSDictionary; +#import + +@class NSCalendarDate; @class NSMutableDictionary; +@class NSString; +@class NSTimeZone; -@interface UIxCalTasksListView : UIxCalView +@class WOResponse; +@class WORequest; + +@interface UIxCalListingActions : WODirectAction { + NSMutableDictionary *componentsData; NSCalendarDate *startDate; NSCalendarDate *endDate; - - BOOL knowsToShow; - BOOL showCompleted; - - NSDictionary *currentTask; + NSString *userLogin; + WORequest *request; } -- (void) setCurrentTask: (NSDictionary *) task; -- (NSDictionary *) currentTask; +- (WOResponse *) eventsListAction; - (WOResponse *) tasksListAction; @end -#endif /* UIXCALTASKSLIST_H */ +#endif /* UIXCALLISTINGACTION_H */ diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m new file mode 100644 index 000000000..246462dc4 --- /dev/null +++ b/UI/Scheduler/UIxCalListingActions.m @@ -0,0 +1,404 @@ +/* UIxCalListingActions.m - this file is part of SOGo + * + * Copyright (C) 2006 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import + +#import "UIxCalListingActions.h" + +@implementation UIxCalListingActions + +- (id) init +{ + if ((self = [super init])) + { + componentsData = [NSMutableDictionary new]; + startDate = nil; + endDate = nil; + request = nil; +// knowsToShow = NO; +// showCompleted = NO; + } + + return self; +} + +- (void) dealloc +{ + [componentsData release]; + [startDate release]; + [endDate release]; + [super dealloc]; +} + +- (void) _setupDatesWithPopup: (NSString *) popupValue + andUserTZ: (NSTimeZone *) userTZ +{ + NSCalendarDate *newDate; + NSString *param; + + if ([popupValue isEqualToString: @"view_today"]) + { + newDate = [NSCalendarDate calendarDate]; + [newDate setTimeZone: userTZ]; + startDate = [newDate beginOfDay]; + endDate = [newDate endOfDay]; + } + else if ([popupValue isEqualToString: @"view_all"]) + { + startDate = nil; + endDate = nil; + } + else if ([popupValue isEqualToString: @"view_next7"]) + { + newDate = [NSCalendarDate calendarDate]; + [newDate setTimeZone: userTZ]; + startDate = [newDate beginOfDay]; + endDate = [[startDate dateByAddingYears: 0 months: 0 days: 6] endOfDay]; + } + else if ([popupValue isEqualToString: @"view_next14"]) + { + newDate = [NSCalendarDate calendarDate]; + [newDate setTimeZone: userTZ]; + startDate = [newDate beginOfDay]; + endDate = [[startDate dateByAddingYears: 0 months: 0 days: 13] endOfDay]; + } + else if ([popupValue isEqualToString: @"view_next31"]) + { + newDate = [NSCalendarDate calendarDate]; + [newDate setTimeZone: userTZ]; + startDate = [newDate beginOfDay]; + endDate = [[startDate dateByAddingYears: 0 months: 0 days: 30] endOfDay]; + } + else if ([popupValue isEqualToString: @"view_thismonth"]) + { + newDate = [NSCalendarDate calendarDate]; + [newDate setTimeZone: userTZ]; + startDate = [[newDate firstDayOfMonth] beginOfDay]; + endDate = [[newDate lastDayOfMonth] endOfDay]; + } + else if ([popupValue isEqualToString: @"view_future"]) + { + newDate = [NSCalendarDate calendarDate]; + [newDate setTimeZone: userTZ]; + startDate = [newDate beginOfDay]; + endDate = [NSCalendarDate distantFuture]; + } + else if ([popupValue isEqualToString: @"view_selectedday"]) + { + param = [request formValueForKey: @"day"]; + if ([param length] > 0) + startDate = [[NSCalendarDate dateFromShortDateString: param + andShortTimeString: nil + inTimeZone: userTZ] beginOfDay]; + else + { + newDate = [NSCalendarDate calendarDate]; + [newDate setTimeZone: userTZ]; + startDate = [newDate beginOfDay]; + } + endDate = [startDate endOfDay]; + } +} + +- (void) _setupContext +{ + SOGoUser *user; + NSTimeZone *userTZ; + NSString *param; + + user = [context activeUser]; + userLogin = [user login]; + userTZ = [user timeZone]; + + request = [context request]; + param = [request formValueForKey: @"filterpopup"]; + if ([param length] > 0) + [self _setupDatesWithPopup: param andUserTZ: userTZ]; + else + { + param = [request formValueForKey: @"sd"]; + if ([param length] > 0) + startDate = [[NSCalendarDate dateFromShortDateString: param + andShortTimeString: nil + inTimeZone: userTZ] beginOfDay]; + else + startDate = nil; + + param = [request formValueForKey: @"sd"]; + if ([param length] > 0) + endDate = [[NSCalendarDate dateFromShortDateString: param + andShortTimeString: nil + inTimeZone: userTZ] endOfDay]; + else + endDate = nil; + } +} + +- (void) _updatePrivacyInComponent: (NSMutableDictionary *) component + fromFolder: (SOGoAppointmentFolder *) folder +{ + int privacyFlag; + NSString *roleString; + + privacyFlag = [[component objectForKey: @"classification"] intValue]; + roleString = [folder roleForComponentsWithAccessClass: privacyFlag + forUser: userLogin]; + if ([roleString isEqualToString: @"ComponentDAndTViewer"]) + { + [component setObject: @"" forKey: @"title"]; + [component setObject: @"" forKey: @"location"]; + } +} + +- (SOGoAppointmentFolder *) _aptFolder: (NSString *) folder + withClientObject: (SOGoAppointmentFolder *) clientObject +{ + SOGoAppointmentFolder *aptFolder; + NSArray *folderParts; + + if ([folder isEqualToString: @"/"]) + aptFolder = clientObject; + else + { + folderParts = [folder componentsSeparatedByString: @":"]; + aptFolder + = [clientObject lookupCalendarFolderForUID: + [folderParts objectAtIndex: 0]]; + } + + return aptFolder; +} + +- (NSArray *) _activeCalendarFolders +{ + NSMutableArray *activeFolders; + NSEnumerator *folders; + NSDictionary *currentFolderDict; + SOGoAppointmentFolder *currentFolder, *clientObject; + + activeFolders = [NSMutableArray new]; + [activeFolders autorelease]; + + clientObject = [self clientObject]; + + folders = [[clientObject calendarFolders] objectEnumerator]; + currentFolderDict = [folders nextObject]; + while (currentFolderDict) + { + if ([[currentFolderDict objectForKey: @"active"] boolValue]) + { + currentFolder + = [self _aptFolder: [currentFolderDict objectForKey: @"folder"] + withClientObject: clientObject]; + [activeFolders addObject: currentFolder]; + } + + currentFolderDict = [folders nextObject]; + } + + return activeFolders; +} + +- (NSArray *) _fetchFields: (NSArray *) fields + forComponentOfType: (NSString *) component +{ + NSEnumerator *folders, *currentInfos; + SOGoAppointmentFolder *currentFolder; + NSMutableDictionary *infos, *currentInfo, *newInfo; + NSString *owner, *uid; + NSNull *marker; + + marker = [NSNull null]; + + infos = [NSMutableDictionary dictionary]; + folders = [[self _activeCalendarFolders] objectEnumerator]; + currentFolder = [folders nextObject]; + while (currentFolder) + { + owner = [currentFolder ownerInContext: context]; + currentInfos = [[currentFolder fetchCoreInfosFrom: startDate + to: endDate + component: component] objectEnumerator]; + newInfo = [currentInfos nextObject]; + while (newInfo) + { + uid = [newInfo objectForKey: @"uid"]; + currentInfo = [infos objectForKey: uid]; + if (!currentInfo + || [owner isEqualToString: userLogin]) + { + [self _updatePrivacyInComponent: newInfo + fromFolder: currentFolder]; + [newInfo setObject: owner forKey: @"owner"]; + [infos setObject: [newInfo objectsForKeys: fields + notFoundMarker: marker] + forKey: uid]; + } + newInfo = [currentInfos nextObject]; + } + currentFolder = [folders nextObject]; + } + + return [infos allValues]; +} + +- (WOResponse *) _responseWithData: (NSArray *) data +{ + WOResponse *response; + + response = [context response]; + [response setHeader: @"text/plain; charset=utf-8" + forKey: @"content-type"]; + [response setStatus: 200]; + [response appendContentString: [data jsonRepresentation]]; + + return response; +} + +- (WOResponse *) eventsListAction +{ + NSArray *fields; + NSArray *events; + + [self _setupContext]; + + fields = [NSArray arrayWithObjects: @"c_name", @"owner", @"status", + @"title", @"startdate", @"enddate", @"location", nil]; + events = [self _fetchFields: fields forComponentOfType: @"vevent"]; + + return [self _responseWithData: events]; +} + +- (NSString *) _getStatusClassForStatusCode: (int) statusCode + andEndDateStamp: (unsigned int) endDateStamp +{ + NSCalendarDate *taskDate, *now; + NSString *statusClass; + + if (statusCode == 1) + statusClass = @"completed"; + else + { + if (endDateStamp) + { + now = [NSCalendarDate calendarDate]; + taskDate + = [NSCalendarDate dateWithTimeIntervalSince1970: endDateStamp]; + if ([taskDate earlierDate: now] == taskDate) + statusClass = @"overdue"; + else + { + if ([taskDate isToday]) + statusClass = @"duetoday"; + else + statusClass = @"duelater"; + } + } + else + statusClass = @"duelater"; + } + + return statusClass; +} + +- (WOResponse *) tasksListAction +{ + NSEnumerator *tasks; + NSMutableArray *filteredTasks, *filteredTask; + BOOL showCompleted; + NSArray *fields, *task; + int statusCode; + unsigned int endDateStamp; + NSString *statusFlag; + + filteredTasks = [NSMutableArray array]; + + [self _setupContext]; + + fields = [NSArray arrayWithObjects: @"c_name", @"owner", @"status", + @"title", @"enddate", nil]; + + tasks = [[self _fetchFields: fields + forComponentOfType: @"vtodo"] objectEnumerator]; + showCompleted = [[request formValueForKey: @"show-completed"] intValue]; + + task = [tasks nextObject]; + while (task) + { + statusCode = [[task objectAtIndex: 2] intValue]; + if (statusCode != 1 || showCompleted) + { + filteredTask = [NSMutableArray arrayWithArray: task]; + endDateStamp = [[task objectAtIndex: 4] intValue]; + statusFlag = [self _getStatusClassForStatusCode: statusCode + andEndDateStamp: endDateStamp]; + [filteredTask addObject: statusFlag]; + [filteredTasks addObject: filteredTask]; + } + task = [tasks nextObject]; + } + + return [self _responseWithData: filteredTasks]; +} + +// - (BOOL) shouldDisplayCurrentTask +// { +// if (!knowsToShow) +// { +// showCompleted +// = [[self queryParameterForKey: @"show-completed"] intValue]; +// knowsToShow = YES; +// } + +// return ([[currentTask objectForKey: @"status"] intValue] != 1 +// || showCompleted); +// } + +// - (BOOL) shouldShowCompletedTasks +// { +// if (!knowsToShow) +// { +// showCompleted +// = [[self queryParameterForKey: @"show-completed"] intValue]; +// knowsToShow = YES; +// } + +// return showCompleted; +// } + +@end diff --git a/UI/Scheduler/UIxCalTasksListView.m b/UI/Scheduler/UIxCalTasksListView.m deleted file mode 100644 index 7c10d8c89..000000000 --- a/UI/Scheduler/UIxCalTasksListView.m +++ /dev/null @@ -1,177 +0,0 @@ -/* UIxCalTasksListView.m - this file is part of SOGo - * - * Copyright (C) 2006 Inverse groupe conseil - * - * Author: Wolfgang Sourdeau - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#import -#import -#import -#import - -#import -#import -#import - -#import "UIxCalTasksListView.h" - -@implementation UIxCalTasksListView - -- (id) init -{ - if ((self = [super init])) - { - startDate = nil; - endDate = nil; - knowsToShow = NO; - showCompleted = NO; - } - - return self; -} - -- (void) setCurrentTask: (NSDictionary *) task -{ - currentTask = task; -} - -- (NSDictionary *) currentTask -{ - return currentTask; -} - -- (NSCalendarDate *) startDate -{ - return nil; -} - -- (NSCalendarDate *) endDate -{ - return nil; -} - -- (NSString *) getStatusClassForTask: (NSDictionary *) task -{ - NSCalendarDate *taskDate, *now; - NSString *statusClass, *allClasses; - NSNumber *taskDueStamp; - - if ([[task objectForKey: @"status"] intValue] == 1) - statusClass = @"completed"; - else - { - taskDueStamp = [task objectForKey: @"enddate"]; - if ([taskDueStamp intValue]) - { - now = [NSCalendarDate calendarDate]; - taskDate = [NSCalendarDate dateWithTimeIntervalSince1970: - [taskDueStamp intValue]]; - if ([taskDate earlierDate: now] == taskDate) - statusClass = @"overdue"; - else - { - if ([taskDate isToday]) - statusClass = @"duetoday"; - else - statusClass = @"duelater"; - } - } - else - statusClass = @"duelater"; - } - - allClasses = [NSString stringWithFormat: @"%@ ownerIs%@", - statusClass, - [task objectForKey: @"owner"]]; - - return allClasses; -} - -- (WOResponse *) tasksListAction -{ - WOResponse *response; - NSDictionary *tasks; - NSMutableArray *filteredTasks; - BOOL showCompleted; - unsigned i, count; - - response = [context response]; - filteredTasks = [NSMutableArray new]; - [filteredTasks autorelease]; - tasks = [self _fetchCoreInfosForComponent: @"vtodo"]; - showCompleted = [[self queryParameterForKey: @"show-completed"] intValue]; - - count = [tasks count]; - for (i = 0; i < count; i++) { - NSDictionary *task; - NSArray *filteredTask; - - task = [tasks objectAtIndex: i]; - - if ([[task objectForKey: @"status"] intValue] != 1 - || showCompleted) - { - filteredTask = [NSArray arrayWithObjects: - [task objectForKey: @"c_name"], - [task objectForKey: @"owner"], - [task objectForKey: @"status"], - [task objectForKey: @"title"], - [self getStatusClassForTask: task], - nil]; - [filteredTasks addObject: filteredTask]; - } - } - - [response setStatus: 200]; - [response appendContentString: [filteredTasks jsonRepresentation]]; - - return response; -} - -- (BOOL) shouldDisplayCurrentTask -{ - if (!knowsToShow) - { - showCompleted - = [[self queryParameterForKey: @"show-completed"] intValue]; - knowsToShow = YES; - } - - return ([[currentTask objectForKey: @"status"] intValue] != 1 - || showCompleted); -} - -- (BOOL) shouldShowCompletedTasks -{ - if (!knowsToShow) - { - showCompleted - = [[self queryParameterForKey: @"show-completed"] intValue]; - knowsToShow = YES; - } - - return showCompleted; -} - -- (BOOL) isCurrentTaskCompleted -{ - return ([[currentTask objectForKey: @"status"] intValue] == 1); -} - -@end diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index 1a4a61d34..63d85f5ef 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -1,224 +1,226 @@ -{ +{ /* -*-javascript-*- */ requires = ( MAIN, MainUI, CommonUI, Appointments, Contacts, ContactsUI ); publicResources = ( - previous_week.gif, - next_week.gif, - icon_view_overview.gif, - icon_view_overview_inactive.gif, - icon_view_chart.gif, - icon_view_chart_inactive.gif, - icon_view_list.gif, - icon_view_list_inactive.gif, - icon_view_columns.gif, - icon_view_columns_inactive.gif, - icon_popupcalendar.gif, - first.gif, - previous.gif, - next.gif, - last.gif, - skycalendar.html, - skycalendar.js, - green_corner.gif, - invisible_space_2.gif, - cycles.plist, + previous_week.gif, + next_week.gif, + icon_view_overview.gif, + icon_view_overview_inactive.gif, + icon_view_chart.gif, + icon_view_chart_inactive.gif, + icon_view_list.gif, + icon_view_list_inactive.gif, + icon_view_columns.gif, + icon_view_columns_inactive.gif, + icon_popupcalendar.gif, + first.gif, + previous.gif, + next.gif, + last.gif, + skycalendar.html, + skycalendar.js, + green_corner.gif, + invisible_space_2.gif, + cycles.plist, ); factories = { }; categories = { - SOGoAppointmentFolder = { - slots = { - toolbar = { - protectedBy = "View"; - value = "SOGoAppointmentFolder.toolbar"; - }; - }; - methods = { - view = { - protectedBy = "View"; - pageName = "UIxCalMainView"; - }; - dateselector = { - protectedBy = "View"; - pageName = "UIxCalDateSelector"; - }; - aptlist = { - protectedBy = "View"; - pageName = "UIxCalAptListView"; - }; - taskslist = { - protectedBy = "View"; - pageName = "UIxCalTasksListView"; - }; - dayview = { - protectedBy = "View"; - pageName = "UIxCalDayView"; - }; - multicolumndayview = { - protectedBy = "View"; - pageName = "UIxCalMulticolumnDayView"; - }; - weekview = { - protectedBy = "View"; - pageName = "UIxCalWeekView"; - }; - monthview = { - protectedBy = "View"; - pageName = "UIxCalMonthView"; - }; - newevent = { - protectedBy = "Add Documents, Images, and Files"; - pageName = "UIxAppointmentEditor"; - actionName = "new"; - }; - newtask = { - protectedBy = "Add Documents, Images, and Files"; - pageName = "UIxTaskEditor"; - actionName = "new"; - }; - show = { - protectedBy = "View"; - pageName = "UIxCalView"; - actionName = "redirectForUIDs"; - }; - proposal = { - protectedBy = "View"; - pageName = "UIxAppointmentProposal"; - }; - proposalSearch = { - protectedBy = "View"; - pageName = "UIxAppointmentProposal"; - actionName = "proposalSearch"; - }; - batchDelete = { - protectedBy = "Delete Objects"; - pageName = "UIxCalMainView"; - actionName = "batchDelete"; - }; - updateCalendars = { - protectedBy = "View"; - pageName = "UIxCalMainView"; - actionName = "updateCalendars"; - }; - editAttendees = { - protectedBy = "View"; - pageName = "UIxAttendeesEditor"; + SOGoAppointmentFolder = { + slots = { + toolbar = { + protectedBy = "View"; + value = "SOGoAppointmentFolder.toolbar"; + }; }; - userRights = { - protectedBy = "ReadAcls"; - pageName = "UIxCalUserRightsEditor"; - }; - saveUserRights = { - protectedBy = "SaveAcls"; - pageName = "UIxCalUserRightsEditor"; - actionName = "saveUserRights"; + methods = { + view = { + protectedBy = "View"; + pageName = "UIxCalMainView"; + }; + dateselector = { + protectedBy = "View"; + pageName = "UIxCalDateSelector"; + }; + eventslist = { + protectedBy = "View"; + actionClass = "UIxCalListingActions"; + actionName = "eventsList"; + }; + taskslist = { + protectedBy = "View"; + actionClass = "UIxCalListingActions"; + actionName = "tasksList"; + }; + dayview = { + protectedBy = "View"; + pageName = "UIxCalDayView"; + }; + multicolumndayview = { + protectedBy = "View"; + pageName = "UIxCalMulticolumnDayView"; + }; + weekview = { + protectedBy = "View"; + pageName = "UIxCalWeekView"; + }; + monthview = { + protectedBy = "View"; + pageName = "UIxCalMonthView"; + }; + newevent = { + protectedBy = "Add Documents, Images, and Files"; + pageName = "UIxAppointmentEditor"; + actionName = "new"; + }; + newtask = { + protectedBy = "Add Documents, Images, and Files"; + pageName = "UIxTaskEditor"; + actionName = "new"; + }; + show = { + protectedBy = "View"; + pageName = "UIxCalView"; + actionName = "redirectForUIDs"; + }; + proposal = { + protectedBy = "View"; + pageName = "UIxAppointmentProposal"; + }; + proposalSearch = { + protectedBy = "View"; + pageName = "UIxAppointmentProposal"; + actionName = "proposalSearch"; + }; + batchDelete = { + protectedBy = "Delete Objects"; + pageName = "UIxCalMainView"; + actionName = "batchDelete"; + }; + updateCalendars = { + protectedBy = "View"; + pageName = "UIxCalMainView"; + actionName = "updateCalendars"; + }; + editAttendees = { + protectedBy = "View"; + pageName = "UIxAttendeesEditor"; + }; + userRights = { + protectedBy = "ReadAcls"; + pageName = "UIxCalUserRightsEditor"; + }; + saveUserRights = { + protectedBy = "SaveAcls"; + pageName = "UIxCalUserRightsEditor"; + actionName = "saveUserRights"; + }; }; - }; - }; - SOGoCalendarComponent = { - }; + }; + SOGoCalendarComponent = { + }; - SOGoAppointmentObject = { - slots = { - toolbar = { - protectedBy = "View"; - value = "SOGoAppointmentObject.toolbar"; - }; - }; - methods = { - view = { - protectedBy = "ViewAllComponent"; - pageName = "UIxAppointmentView"; - }; - delete = { - protectedBy = "Delete Objects"; - pageName = "UIxAppointmentView"; - actionName = "delete"; - }; - edit = { - protectedBy = "ViewAllComponent"; - pageName = "UIxAppointmentEditor"; - }; - editAsAppointment = { - protectedBy = "ViewAllComponent"; - pageName = "UIxAppointmentEditor"; - }; - save = { - protectedBy = "ModifyComponent"; - pageName = "UIxAppointmentEditor"; - actionName = "save"; - }; - saveAsAppointment = { - protectedBy = "ModifyComponent"; - pageName = "UIxAppointmentEditor"; - actionName = "save"; - }; - accept = { - protectedBy = "RespondToComponent"; - pageName = "UIxAppointmentEditor"; - actionName = "accept"; - }; - decline = { - protectedBy = "RespondToComponent"; - pageName = "UIxAppointmentEditor"; - actionName = "decline"; - }; - }; - }; + SOGoAppointmentObject = { + slots = { + toolbar = { + protectedBy = "View"; + value = "SOGoAppointmentObject.toolbar"; + }; + }; + methods = { + view = { + protectedBy = "ViewAllComponent"; + pageName = "UIxAppointmentView"; + }; + delete = { + protectedBy = "Delete Objects"; + pageName = "UIxAppointmentView"; + actionName = "delete"; + }; + edit = { + protectedBy = "ViewAllComponent"; + pageName = "UIxAppointmentEditor"; + }; + editAsAppointment = { + protectedBy = "ViewAllComponent"; + pageName = "UIxAppointmentEditor"; + }; + save = { + protectedBy = "ModifyComponent"; + pageName = "UIxAppointmentEditor"; + actionName = "save"; + }; + saveAsAppointment = { + protectedBy = "ModifyComponent"; + pageName = "UIxAppointmentEditor"; + actionName = "save"; + }; + accept = { + protectedBy = "RespondToComponent"; + pageName = "UIxAppointmentEditor"; + actionName = "accept"; + }; + decline = { + protectedBy = "RespondToComponent"; + pageName = "UIxAppointmentEditor"; + actionName = "decline"; + }; + }; + }; - SOGoTaskObject = { - slots = { - toolbar = { - protectedBy = "View"; - value = "SOGoAppointmentObject.toolbar"; - }; - }; - methods = { - view = { - protectedBy = "ViewAllComponent"; - pageName = "UIxTaskView"; - }; - delete = { - protectedBy = "Delete Objects"; - pageName = "UIxTaskView"; - actionName = "delete"; - }; - edit = { - protectedBy = "ViewAllComponent"; - pageName = "UIxTaskEditor"; - }; - editAsTask = { - protectedBy = "ViewAllComponent"; - pageName = "UIxTaskEditor"; - }; - save = { - protectedBy = "ModifyComponent"; - pageName = "UIxTaskEditor"; - actionName = "save"; - }; - saveAsTask = { - protectedBy = "ModifyComponent"; - pageName = "UIxTaskEditor"; - actionName = "save"; - }; - changeStatus = { - protectedBy = "ModifyComponent"; - pageName = "UIxTaskEditor"; - actionName = "changeStatus"; - }; - accept = { - protectedBy = "RespondToComponent"; - pageName = "UIxTaskEditor"; - actionName = "accept"; - }; - decline = { - protectedBy = "RespondToComponent"; - pageName = "UIxTaskEditor"; - actionName = "decline"; - }; - }; - }; + SOGoTaskObject = { + slots = { + toolbar = { + protectedBy = "View"; + value = "SOGoAppointmentObject.toolbar"; + }; + }; + methods = { + view = { + protectedBy = "ViewAllComponent"; + pageName = "UIxTaskView"; + }; + delete = { + protectedBy = "Delete Objects"; + pageName = "UIxTaskView"; + actionName = "delete"; + }; + edit = { + protectedBy = "ViewAllComponent"; + pageName = "UIxTaskEditor"; + }; + editAsTask = { + protectedBy = "ViewAllComponent"; + pageName = "UIxTaskEditor"; + }; + save = { + protectedBy = "ModifyComponent"; + pageName = "UIxTaskEditor"; + actionName = "save"; + }; + saveAsTask = { + protectedBy = "ModifyComponent"; + pageName = "UIxTaskEditor"; + actionName = "save"; + }; + changeStatus = { + protectedBy = "ModifyComponent"; + pageName = "UIxTaskEditor"; + actionName = "changeStatus"; + }; + accept = { + protectedBy = "RespondToComponent"; + pageName = "UIxTaskEditor"; + actionName = "accept"; + }; + decline = { + protectedBy = "RespondToComponent"; + pageName = "UIxTaskEditor"; + actionName = "decline"; + }; + }; + }; }; } diff --git a/UI/Templates/SchedulerUI/UIxCalAptListView.wox b/UI/Templates/SchedulerUI/UIxCalAptListView.wox deleted file mode 100644 index 1a73d0d52..000000000 --- a/UI/Templates/SchedulerUI/UIxCalAptListView.wox +++ /dev/null @@ -1,61 +0,0 @@ - - - - - -
diff --git a/UI/Templates/SchedulerUI/UIxCalMainView.wox b/UI/Templates/SchedulerUI/UIxCalMainView.wox index 6c075ace7..fe34f7e23 100644 --- a/UI/Templates/SchedulerUI/UIxCalMainView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMainView.wox @@ -28,7 +28,7 @@ > - -
+
+ +
+
-
+
+ + + + + + + +
+
diff --git a/UI/Templates/SchedulerUI/UIxCalTasksListView.wox b/UI/Templates/SchedulerUI/UIxCalTasksListView.wox deleted file mode 100644 index a6371bd7d..000000000 --- a/UI/Templates/SchedulerUI/UIxCalTasksListView.wox +++ /dev/null @@ -1,18 +0,0 @@ - - -

- -
    -
- -
diff --git a/UI/WebServerResources/JavascriptAPIExtensions.js b/UI/WebServerResources/JavascriptAPIExtensions.js index 088a7f10a..4e581cb91 100644 --- a/UI/WebServerResources/JavascriptAPIExtensions.js +++ b/UI/WebServerResources/JavascriptAPIExtensions.js @@ -77,6 +77,28 @@ Date.prototype.daysUpTo = function(otherDate) { return days; } +Date.prototype.getDayString = function() { + var newString = this.getYear() + 1900; + var month = '' + (this.getMonth() + 1); + if (month.length == 1) + month = '0' + month; + newString += month; + var day = '' + this.getDate(); + if (day.length == 1) + day = '0' + day; + newString += day; + + return newString; +} + +Date.prototype.getHourString = function() { + var newString = this.getHours() + '00'; + if (newString.length == 3) + newString = '0' + newString; + + return newString; +} + Date.prototype.stringWithSeparator = function(separator) { var month = '' + (this.getMonth() + 1); var day = '' + this.getDate(); diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 3eea8d0cb..8e0231cc7 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -74,10 +74,10 @@ function editEvent() { for (var i = 0; i < nodes.length; i++) _editEventId(nodes[i].getAttribute("id"), - nodes[i].getAttribute("owner")); + nodes[i].owner); } else if (selectedCalendarCell) { _editEventId(selectedCalendarCell.getAttribute("aptCName"), - selectedCalendarCell.getAttribute("owner")); + selectedCalendarCell.owner); } return false; /* stop following the link */ @@ -102,7 +102,7 @@ function deleteEvent() { if (listOfSelection == $("tasksList")) label = labels["taskDeleteConfirmation"].decodeEntities(); else - label = labels["appointmentDeleteConfirmation"].decodeEntities(); + label = labels["eventDeleteConfirmation"].decodeEntities(); if (confirm(label)) { if (document.deleteEventAjaxRequest) { @@ -113,7 +113,7 @@ function deleteEvent() { var owners = new Array(); for (var i = 0; i < nodes.length; i++) { - var owner = nodes[i].getAttribute("owner"); + var owner = nodes[i].owner; if (!sortedNodes[owner]) { sortedNodes[owner] = new Array(); owners.push(owner); @@ -129,14 +129,14 @@ function deleteEvent() { } } else if (selectedCalendarCell) { - var label = labels["appointmentDeleteConfirmation"].decodeEntities(); + var label = labels["eventDeleteConfirmation"].decodeEntities(); if (confirm(label)) { if (document.deleteEventAjaxRequest) { document.deleteEventAjaxRequest.aborted = true; document.deleteEventAjaxRequest.abort(); } eventsToDelete.push([selectedCalendarCell.getAttribute("aptCName")]); - ownersOfEventsToDelete.push(selectedCalendarCell.getAttribute("owner")); + ownersOfEventsToDelete.push(selectedCalendarCell.owner); _batchDeleteEvents(); } } @@ -177,7 +177,7 @@ function modifyEventCallback(http) { if (queryParameters["mail-invitation"].toLowerCase() == "yes") closeInvitationWindow(); else { - window.opener.setTimeout("refreshAppointmentsAndDisplay();", 100); + window.opener.setTimeout("refreshEventsAndDisplay();", 100); window.setTimeout("window.close();", 100); } } @@ -202,7 +202,7 @@ function deleteEventCallback(http) { _batchDeleteEvents(); else { document.deleteEventAjaxRequest = null; - refreshAppointments(); + refreshEvents(); refreshTasks(); changeCalendarDisplay(); } @@ -213,21 +213,21 @@ function deleteEventCallback(http) { function editDoubleClickedEvent() { _editEventId(this.getAttribute("id"), - this.getAttribute("owner")); + this.owner); return false; } function onSelectAll() { - var list = $("appointmentsList"); - list.selectRowsMatchingClass("appointmentRow"); + var list = $("eventsList"); + list.selectRowsMatchingClass("eventRow"); return false; } -function displayAppointment(event) { +function displayEvent(event) { _editEventId(this.getAttribute("aptCName"), - this.getAttribute("owner")); + this.owner); preventDefault(event); event.stopPropagation(); @@ -253,7 +253,7 @@ function onDaySelect(node) { changeCalendarDisplay( { "day": day } ); if (needRefresh) - refreshAppointments(); + refreshEvents(); return false; } @@ -302,22 +302,62 @@ function dateSelectorCallback(http) { log ("dateSelectorCallback Ajax error"); } -function appointmentsListCallback(http) { - var div = $("appointmentsListView"); +function eventsListCallback(http) { + var div = $("eventsListView"); if (http.readyState == 4 && http.status == 200) { - document.appointmentsListAjaxRequest = null; - div.innerHTML = http.responseText; + document.eventsListAjaxRequest = null; + var table = $("eventsList").tBodies[0]; var params = parseQueryParameters(http.callbackData); sortKey = params["sort"]; sortOrder = params["desc"]; - var list = $("appointmentsList"); - Event.observe(list, "mousedown", onAppointmentsSelectionChange.bindAsEventListener(list), true); configureSortableTableHeaders(); + + var data = http.responseText.evalJSON(true); + for (var i = 0; i < data.length; i++) { + var row = document.createElement("tr"); + table.appendChild(row); + $(row).addClassName("eventRow"); + row.setAttribute("id", data[i][0]); + row.owner = data[i][1]; + + var startDate = new Date(); + startDate.setTime(data[i][4] * 1000); + row.day = startDate.getDayString(); + row.hour = startDate.getHourString(); + Event.observe(row, "click", onEventClick.bindAsEventListener(row)); + Event.observe(row, "dblclick", editDoubleClickedEvent.bindAsEventListener(row)); + Event.observe(row, "contextmenu", + onEventContextMenu.bindAsEventListener(row)); + + var td = document.createElement("td"); + row.appendChild(td); + Event.observe(td, "mousedown", + listRowMouseDownHandler.bindAsEventListener(td), true); + td.appendChild(document.createTextNode(data[i][3])); + + td = document.createElement("td"); + row.appendChild(td); + Event.observe(td, "mousedown", + listRowMouseDownHandler.bindAsEventListener(td), true); + td.appendChild(document.createTextNode(data[i][4])); + + td = document.createElement("td"); + row.appendChild(td); + Event.observe(td, "mousedown", + listRowMouseDownHandler.bindAsEventListener(td), true); + td.appendChild(document.createTextNode(data[i][5])); + + td = document.createElement("td"); + row.appendChild(td); + Event.observe(td, "mousedown", + listRowMouseDownHandler.bindAsEventListener(td), true); + td.appendChild(document.createTextNode(data[i][6])); + } } else - log ("appointmentsListCallback Ajax error"); + log ("eventsListCallback Ajax error"); } function tasksListCallback(http) { @@ -327,23 +367,20 @@ function tasksListCallback(http) { && http.status == 200) { document.tasksListAjaxRequest = null; var list = $("tasksList"); - var newList = document.createElement("ul"); - newList.setAttribute("multiselect", "yes"); - newList.setAttribute("id", "tasksList"); - var scroll = list.scrollTop; - var data = http.responseText.evalJSON(true); for (var i = 0; i < data.length; i++) { //log(i + " = " + data[i][3]); var listItem = document.createElement("li"); - newList.appendChild(listItem); + list.appendChild(listItem); //Event.observe(listItem, "mousedown", listRowMouseDownHandler); // causes problem with Safari Event.observe(listItem, "click", onRowClick); Event.observe(listItem, "dblclick", editDoubleClickedEvent.bindAsEventListener(listItem)); listItem.setAttribute("id", data[i][0]); - listItem.setAttribute("owner", data[i][1]); - $(listItem).addClassName(data[i][4]); + $(listItem).addClassName(data[i][5]); + var owner = data[i][1]; + listItem.owner = owner; + $(listItem).addClassName("ownerIs" + owner); var input = document.createElement("input"); input.setAttribute("type", "checkbox"); listItem.appendChild(input); @@ -355,10 +392,7 @@ function tasksListCallback(http) { listItem.appendChild(document.createTextNode(data[i][3])); } - Event.observe(newList, "mousedown", onTasksSelectionChange.bindAsEventListener(newList), true); - newList.scrollTop = scroll; - - list.parentNode.replaceChild(newList, list); + list.scrollTop = list.previousScroll; if (http.callbackData) { var selectedNodesId = http.callbackData; @@ -533,11 +567,11 @@ function calendarDisplayCallback(http) { scrollDayView(hour); contentView = $("daysView"); } - var appointments = document.getElementsByClassName("appointment", contentView); - for (var i = 0; i < appointments.length; i++) { - Event.observe(appointments[i], "mousedown", listRowMouseDownHandler); - Event.observe(appointments[i], "click", onCalendarSelectAppointment.bindAsEventListener(appointments[i])); - Event.observe(appointments[i], "dblclick", displayAppointment.bindAsEventListener(appointments[i])); + var events = document.getElementsByClassName("event", contentView); + for (var i = 0; i < events.length; i++) { + Event.observe(events[i], "mousedown", listRowMouseDownHandler); + Event.observe(events[i], "click", onCalendarSelectEvent.bindAsEventListener(events[i])); + Event.observe(events[i], "dblclick", displayEvent.bindAsEventListener(events[i])); } var days = document.getElementsByClassName("day", contentView); if (currentView == "monthview") @@ -578,27 +612,27 @@ function popupCalendar(node) { return false; } -function onAppointmentContextMenu(event, element) { - var topNode = $("appointmentsList"); +function onEventContextMenu(event) { + var topNode = $("eventsList"); // log(topNode); - var menu = $("appointmentsListMenu"); + var menu = $("eventsListMenu"); - Event.observe(menu, "hideMenu", onAppointmentContextMenuHide); - popupMenu(event, "appointmentsListMenu", element); + Event.observe(menu, "hideMenu", onEventContextMenuHide); + popupMenu(event, "eventsListMenu", this); - var topNode = $("appointmentsList"); + var topNode = $("eventsList"); var selectedNodes = topNode.getSelectedRows(); topNode.menuSelectedRows = selectedNodes; for (var i = 0; i < selectedNodes.length; i++) selectedNodes[i].deselect(); - topNode.menuSelectedEntry = element; - element.select(); + topNode.menuSelectedEntry = this; + this.select(); } -function onAppointmentContextMenuHide(event) { - var topNode = $("appointmentsList"); +function onEventContextMenuHide(event) { + var topNode = $("eventsList"); if (topNode.menuSelectedEntry) { topNode.menuSelectedEntry.deselect(); @@ -614,7 +648,7 @@ function onAppointmentContextMenuHide(event) { } } -function onAppointmentsSelectionChange() { +function onEventsSelectionChange() { listOfSelection = this; this.removeClassName("_unfocused"); $("tasksList").addClassName("_unfocused"); @@ -623,17 +657,21 @@ function onAppointmentsSelectionChange() { function onTasksSelectionChange() { listOfSelection = this; this.removeClassName("_unfocused"); - $("appointmentsList").addClassName("_unfocused"); + $("eventsList").addClassName("_unfocused"); } -function _loadAppointmentHref(href) { - if (document.appointmentsListAjaxRequest) { - document.appointmentsListAjaxRequest.aborted = true; - document.appointmentsListAjaxRequest.abort(); +function _loadEventHref(href) { + if (document.eventsListAjaxRequest) { + document.eventsListAjaxRequest.aborted = true; + document.eventsListAjaxRequest.abort(); } var url = ApplicationBaseURL + href; - document.appointmentsListAjaxRequest - = triggerAjaxRequest(url, appointmentsListCallback, href); + document.eventsListAjaxRequest + = triggerAjaxRequest(url, eventsListCallback, href); + + var table = $("eventsList").tBodies[0]; + while (table.rows.length > 1) + table.removeChild(table.rows[1]); return false; } @@ -645,33 +683,42 @@ function _loadTasksHref(href) { } url = ApplicationBaseURL + href; - var selectedIds = $("tasksList").getSelectedNodesId(); + var tasksList = $("tasksList"); + var selectedIds; + if (tasksList) + selectedIds = tasksList.getSelectedNodesId(); + else + selectedIds = null; document.tasksListAjaxRequest = triggerAjaxRequest(url, tasksListCallback, selectedIds); + tasksList.previousScroll = tasksList.scrollTop; + while (tasksList.childNodes.length) + tasksList.removeChild(tasksList.childNodes[0]); + return true; } function onHeaderClick(event) { // log("onHeaderClick: " + this.link); - _loadAppointmentHref(this.link); + _loadEventHref(this.link); preventDefault(event); } -function refreshAppointments() { - return _loadAppointmentHref("aptlist?desc=" + sortOrder - + "&sort=" + sortKey - + "&day=" + currentDay - + "&filterpopup=" + listFilter); +function refreshEvents() { + return _loadEventHref("eventslist?desc=" + sortOrder + + "&sort=" + sortKey + + "&day=" + currentDay + + "&filterpopup=" + listFilter); } function refreshTasks() { return _loadTasksHref("taskslist?show-completed=" + showCompletedTasks); } -function refreshAppointmentsAndDisplay() { - refreshAppointments(); +function refreshEventsAndDisplay() { + refreshEvents(); changeCalendarDisplay(); } @@ -681,10 +728,10 @@ function onListFilterChange() { listFilter = node.value; // log ("listFilter = " + listFilter); - return refreshAppointments(); + return refreshEvents(); } -function onAppointmentClick(event) { +function onEventClick(event) { var target = getTarget(event); var node = target.getParentWithTagName("tr"); var day = node.getAttribute("day"); @@ -771,8 +818,8 @@ function onSearchFormSubmit() { return false; } -function onCalendarSelectAppointment() { - var list = $("appointmentsList"); +function onCalendarSelectEvent() { + var list = $("eventsList"); list.deselectAll(); var aptCName = this.getAttribute("aptCName"); @@ -809,7 +856,7 @@ function onCalendarSelectDay(event) { } if (needRefresh) - refreshAppointments(); + refreshEvents(); } function changeWeekCalendarDisplayOfSelectedDay(node) { @@ -849,15 +896,15 @@ function changeMonthCalendarDisplayOfSelectedDay(node) { node.addClassName("selectedDay"); } -function onShowCompletedTasks(node) { - showCompletedTasks = (node.checked ? 1 : 0); +function onShowCompletedTasks(event) { + showCompletedTasks = (this.checked ? 1 : 0); - return refreshTasks(); + return refreshTasks(); } function updateTaskStatus(event) { var taskId = this.parentNode.getAttribute("id"); - var taskOwner = this.parentNode.getAttribute("owner"); + var taskOwner = this.parentNode.owner; var newStatus = (this.checked ? 1 : 0); var http = createHTTPClient(); @@ -917,7 +964,7 @@ function updateCalendarStatus(event) { } else { updateCalendarsList(); - refreshAppointments(); + refreshEvents(); refreshTasks(); changeCalendarDisplay(); } @@ -930,7 +977,7 @@ function calendarStatusCallback(http) { if (http.status == 204 || (isSafari() && typeof(http.status) == 'undefined') || http.status == 1223) { - refreshAppointments(); + refreshEvents(); refreshTasks(); changeCalendarDispla4y(); } @@ -1022,7 +1069,7 @@ function getMenus() { dateMenu.push(onYearMenuItemClick); menus["yearListMenu"] = dateMenu; - menus["appointmentsListMenu"] = new Array(onMenuNewEventClick, "-", + menus["eventsListMenu"] = new Array(onMenuNewEventClick, "-", onMenuNewTaskClick, editEvent, deleteEvent, "-", onSelectAll, "-", @@ -1058,7 +1105,7 @@ function configureDragHandles() { handle = $("rightDragHandle"); if (handle) { handle.addInterface(SOGoDragHandlesInterface); - handle.upperBlock=$("appointmentsListView"); + handle.upperBlock=$("eventsListView"); handle.lowerBlock=$("calendarView"); } } @@ -1166,10 +1213,30 @@ function configureSearchField() { Event.observe(searchValue, "keydown", onSearchKeyDown.bindAsEventListener(searchValue)); } +function configureLists() { + var list = $("tasksList"); + list.multiselect = true; + Event.observe(list, "mousedown", + onTasksSelectionChange.bindAsEventListener(list)); + + var input = $("showHideCompletedTasks"); + Event.observe(input, "change", + onShowCompletedTasks.bindAsEventListener(input)); + + list = $("eventsList"); + list.multiselect = true; + Event.observe(list, "mousedown", + onEventsSelectionChange.bindAsEventListener(list)); + var div = list.parentNode; + Event.observe(div, "contextmenu", + onEventContextMenu.bindAsEventListener(div)); +} + function initCalendars() { if (!document.body.hasClassName("popup")) { initCalendarSelector(); configureSearchField(); + configureLists(); var selector = $("calendarSelector"); if (selector) selector.attachMenu("calendarsMenu"); diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index 79b8a4f18..951f5819e 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -387,6 +387,7 @@ td.tbtv_actcell padding-left: 4px; padding-right: 4px; } +TD.headerCell, TD.tbtv_headercell, TD.tbtv_navcell { background-color: #d4d0c8; @@ -397,12 +398,14 @@ TD.tbtv_navcell -moz-border-bottom-colors: #000 #9c9a94 transparent; -moz-border-right-colors: #000 #9c9a94 transparent; } +TD.headerCell:active, TD.tbtv_headercell:active { background-color: #DCDAD5; border: 1px solid #9c9a94; -moz-border-bottom-colors: #9c9a94; -moz-border-right-colors: #9c9a94; } +TD.headerCell SPAN, td.tbtv_headercell SPAN { float: left; width: 100%; } @@ -422,6 +425,7 @@ td.tbtv_headercell a:hover /* background-color: #C4C0B8; */ } +TD.headerCell IMG.tbtv_sortcell, td.tbtv_headercell img.tbtv_sortcell { float: right; text-align: right; diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index b8966feec..97a58fccb 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -424,9 +424,17 @@ function isNodeSelected(node) { } function acceptMultiSelect(node) { - var accept = ('' + node.getAttribute('multiselect')).toLowerCase(); + var response = false; + var attribute = node.getAttribute('multiselect'); + if (attribute) { + log("node '" + node.getAttribute("id") + + "' is still using old-stylemultiselect!"); + response = (attribute.toLowerCase() == 'yes'); + } + else + response = node.multiselect; - return (accept == 'yes'); + return response; } function onRowClick(event) { @@ -1170,12 +1178,8 @@ function onBodyClickContextMenu(event) { function configureSortableTableHeaders() { var headers = document.getElementsByClassName("sortableTableHeader"); for (var i = 0; i < headers.length; i++) { - var anchor = $(headers[i]).childNodesWithTag("a")[0]; - if (!anchor.link) { - anchor.link = anchor.getAttribute("href"); - anchor.href = "#"; - Event.observe(anchor, "click", onHeaderClick.bindAsEventListener(anchor), true); - } + var header = headers[i]; + Event.observe(header, "click", onHeaderClick.bindAsEventListener(header)); } }