diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index 32dc2db3d..8fb9bd5b0 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -542,6 +542,12 @@ vtodo_class2 = "(Confidential task)"; "tagWasRemoved" = "If you remove this calendar from synchronization, you'll need to reload the data on your mobile device.\nContinue?"; "DestinationCalendarError" = "The source and destination calendars are the same. Please try to copy to a different calendar."; "EventCopyError" = "The copy failed. Please try to copy to a difference calendar."; +"Please select at least one calendar" = "Please select at least one calendar"; +"notice:" = "notice:"; +"error:" = "error:"; +"success:" = "success:"; +"warning:" = "warning:"; + "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; diff --git a/UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar b/UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar index 54a5eae10..14e5fcd5e 100644 --- a/UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar +++ b/UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar @@ -21,12 +21,11 @@ onclick = "return onDayOverview();"; image = "day-view.png"; tooltip = "Switch to day view"; }, - /* disabled until we fix the view */ - /* { link = "#"; - label="Multicolumn Day View"; - onclick = "return onMulticolumnDayOverview();"; - image = "day-view-multicolumn.png"; - tooltip = ""; }, */ + { link = "#"; + label="Multi-Columns View"; + onclick = "return onMulticolumnDayOverview();"; + image = "day-view-multicolumn.png"; + tooltip = "Switch to multi-columns day view"; }, { link = "#"; label="Week View"; onclick = "return onWeekOverview();"; diff --git a/UI/Scheduler/UIxCalDayTable.h b/UI/Scheduler/UIxCalDayTable.h index 88ab136e8..57d91e846 100644 --- a/UI/Scheduler/UIxCalDayTable.h +++ b/UI/Scheduler/UIxCalDayTable.h @@ -35,27 +35,27 @@ @interface UIxCalDayTable : UIxCalView { - unsigned int numberOfDays; - NSCalendarDate *startDate; - NSCalendarDate *currentTableDay; - NSString *currentTableHour; - NSMutableArray *daysToDisplay; - NSMutableArray *hoursToDisplay; - NSArray *weekDays; SOGoDateFormatter *dateFormatter; - NSString *timeFormat; + NSArray *weekDays; + NSString *currentView, *timeFormat, *currentTableHour; + NSCalendarDate *startDate, *currentTableDay; + NSMutableArray *daysToDisplay, *calendarsToDisplay, *currentCalendar, *hoursToDisplay; + unsigned int numberOfDays; } - (void) setNumberOfDays: (NSNumber *) aNumber; - (NSNumber *) numberOfDays; +- (NSString *) currentView; - (void) setStartDate: (NSCalendarDate *) aStartDate; - (NSCalendarDate *) startDate; - (NSCalendarDate *) endDate; - (NSArray *) daysToDisplay; +- (NSArray *) calendarsToDisplay; - (void) setCurrentTableDay: (NSCalendarDate *) aTableDay; - (NSCalendarDate *) currentTableDay; +- (NSMutableArray *) currentCalendar; @end diff --git a/UI/Scheduler/UIxCalDayTable.m b/UI/Scheduler/UIxCalDayTable.m index 174e1d1ea..7b05e06c5 100644 --- a/UI/Scheduler/UIxCalDayTable.m +++ b/UI/Scheduler/UIxCalDayTable.m @@ -55,9 +55,12 @@ ASSIGN (timeFormat, [ud timeFormat]); daysToDisplay = nil; + calendarsToDisplay = nil; hoursToDisplay = nil; numberOfDays = 1; startDate = nil; + currentView = nil; + currentCalendar = nil; currentTableDay = nil; currentTableHour = nil; weekDays = [locale objectForKey: NSShortWeekDayNameArray]; @@ -75,6 +78,9 @@ // [allAppointments release]; [weekDays release]; [daysToDisplay release]; + [calendarsToDisplay release]; + [currentView release]; + [currentCalendar release]; [hoursToDisplay release]; [dateFormatter release]; [timeFormat release]; @@ -119,6 +125,16 @@ return [endDate endOfDay]; } +- (void) setCurrentView: (NSString *) aView +{ + currentView = [NSString stringWithString:aView]; +} + +- (NSString *) currentView +{ + return currentView; +} + - (NSArray *) hoursToDisplay { unsigned int currentHour, lastHour; @@ -148,22 +164,67 @@ { NSCalendarDate *currentDate; int count; - + if (!daysToDisplay) + { + daysToDisplay = [NSMutableArray new]; + currentDate = [[self startDate] hour: [self dayStartHour] + minute: 0]; + + for (count = 0; count < numberOfDays; count++) { - daysToDisplay = [NSMutableArray new]; - currentDate = [[self startDate] hour: [self dayStartHour] - minute: 0]; - for (count = 0; count < numberOfDays; count++) - { - [daysToDisplay addObject: currentDate]; - currentDate = [currentDate tomorrow]; - } + [daysToDisplay addObject: currentDate]; + currentDate = [currentDate tomorrow]; } - + } + return daysToDisplay; } +- (NSArray *) calendarsToDisplay +{ + if (!calendarsToDisplay) { + int max=0, i; + NSArray *folders; + SOGoAppointmentFolders *co; + SOGoAppointmentFolder *folder; + NSMutableDictionary *calendar; + unsigned int count, foldersCount; + NSString *folderName, *fDisplayName; + NSNumber *isActive; + + co = [self clientObject]; + folders = [co subFolders]; + foldersCount = [folders count]; + calendarsToDisplay = [[NSMutableArray alloc] initWithCapacity: foldersCount]; + for (count = 0; count < foldersCount; count++) + { + folder = [folders objectAtIndex: count]; + isActive = [NSNumber numberWithBool: [folder isActive]]; + if ([isActive intValue] != 0) { + calendar = [NSMutableDictionary dictionary]; + folderName = [folder nameInContainer]; + fDisplayName = [folder displayName]; + if (fDisplayName == nil) + fDisplayName = @""; + if ([fDisplayName isEqualToString: [co defaultFolderName]]) + fDisplayName = [self labelForKey: fDisplayName]; + [calendar setObject: [NSString stringWithFormat: @"/%@", folderName] + forKey: @"id"]; + [calendar setObject: fDisplayName forKey: @"displayName"]; + [calendar setObject: folderName forKey: @"folder"]; + [calendar setObject: [folder calendarColor] forKey: @"color"]; + [calendar setObject: isActive forKey: @"active"]; + [calendar setObject: [folder ownerInContext: context] + forKey: @"owner"]; + [calendarsToDisplay addObject: calendar]; + } + } + } + + return calendarsToDisplay; +} + - (void) setCurrentTableDay: (NSCalendarDate *) aTableDay { currentTableDay = aTableDay; @@ -174,6 +235,16 @@ return currentTableDay; } +- (void) setCurrentCalendar: (NSMutableArray *) aCalendar +{ + currentCalendar = aCalendar; +} + +- (NSMutableArray *) currentCalendar +{ + return currentCalendar; +} + - (void) setCurrentTableHour: (NSString *) aTableHour { currentTableHour = aTableHour; @@ -226,6 +297,16 @@ return [dateFormatter shortFormattedDate: currentTableDay]; } +- (NSString *) labelForCalendar +{ + return [NSString stringWithFormat:[currentCalendar objectForKey:@"displayName"]]; +} + +- (NSString *) colorForCalendar +{ + return [NSString stringWithFormat:[currentCalendar objectForKey:@"color"]]; +} + // - (NSDictionary *) _adjustedAppointment: (NSDictionary *) anAppointment // forStart: (NSCalendarDate *) start // andEnd: (NSCalendarDate *) end @@ -318,7 +399,15 @@ - (NSString *) daysViewClasses { - return [NSString stringWithFormat: @"daysView daysViewFor%dDays", numberOfDays]; + NSString *daysView; + + if ([currentView isEqualToString:@"multicolumndayview"]) + daysView = @"daysView daysViewForMultipleDays"; + + else + daysView = [NSString stringWithFormat: @"daysView daysViewFor%dDays", numberOfDays]; + + return daysView; } - (NSString *) dayClasses @@ -326,19 +415,25 @@ NSMutableString *classes; unsigned int currentDayNbr, realDayOfWeek; - currentDayNbr = [daysToDisplay indexOfObject: currentTableDay]; - realDayOfWeek = [currentTableDay dayOfWeek]; - classes = [NSMutableString string]; - [classes appendFormat: @"day day%d", currentDayNbr]; - if (numberOfDays > 1) + if ([currentView isEqualToString:@"multicolumndayview"]) + [classes appendFormat:@"day dayColumn"]; + + else { + currentDayNbr = [daysToDisplay indexOfObject: currentTableDay]; + realDayOfWeek = [currentTableDay dayOfWeek]; + + [classes appendFormat: @"day day%d", currentDayNbr]; + + if (numberOfDays > 1) { if (realDayOfWeek == 0 || realDayOfWeek == 6) [classes appendString: @" weekEndDay"]; if ([currentTableDay isToday]) [classes appendString: @" dayOfToday"]; } - + } + return classes; } @@ -358,4 +453,24 @@ return cellClass; } +- (BOOL) isMultiColumnView +{ + BOOL flag = NO; + + if ([currentView isEqualToString:@"multicolumndayview"]) + flag = YES; + + return flag; +} + +- (BOOL) isNotMultiColumnView +{ + BOOL flag = NO; + + if ([currentView isEqualToString:@"dayview"] || [currentView isEqualToString:@"weekview"]) + flag = YES; + + return flag; +} + @end diff --git a/UI/Scheduler/UIxCalListingActions.h b/UI/Scheduler/UIxCalListingActions.h index 4f12d8cfe..41c27cecd 100644 --- a/UI/Scheduler/UIxCalListingActions.h +++ b/UI/Scheduler/UIxCalListingActions.h @@ -43,6 +43,7 @@ NSString *value; NSString *criteria; NSString *userLogin; + NSString *currentView; BOOL dayBasedView; WORequest *request; SOGoDateFormatter *dateFormatter; diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index 8670dc383..b3026d3ed 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -78,6 +78,8 @@ static NSArray *tasksFields = nil; #define maxBlocks (offsetBlocks * 2) // maximum number of blocks to search // for a free slot (10 days) +@class SOGoAppointment; + @implementation UIxCalListingActions + (void) initialize @@ -121,6 +123,7 @@ static NSArray *tasksFields = nil; ASSIGN (dateFormatter, [user dateFormatterInContext: context]); ASSIGN (userTimeZone, [[user userDefaults] timeZone]); dayBasedView = NO; + currentView = nil; } return self; @@ -239,6 +242,7 @@ static NSArray *tasksFields = nil; endDate = nil; param = [request formValueForKey: @"view"]; + currentView = param; dayBasedView = ![param isEqualToString: @"monthview"]; } } @@ -1044,47 +1048,116 @@ _computeBlocksPosition (NSArray *blocks) /* ... _computeBlocksMultiplier() ... */ } +- (NSArray *) _selectedCalendars { + SOGoAppointmentFolders *co; + SOGoAppointmentFolder *folder; + NSMutableArray *selectedCalendars; + NSArray *folders; + NSString *fDisplayName; + NSNumber *isActive; + unsigned int count, foldersCount; + int max=0, i; + + co = [self clientObject]; + folders = [co subFolders]; + foldersCount = [folders count]; + selectedCalendars = [[NSMutableArray alloc] initWithCapacity: foldersCount]; + for (count = 0; count < foldersCount; count++) + { + folder = [folders objectAtIndex: count]; + isActive = [NSNumber numberWithBool: [folder isActive]]; + if ([isActive intValue] != 0) { + fDisplayName = [folder displayName]; + if (fDisplayName == nil) + fDisplayName = @""; + if ([fDisplayName isEqualToString: [co defaultFolderName]]) + fDisplayName = [self labelForKey: fDisplayName]; + [selectedCalendars addObject: fDisplayName]; + } + } + return selectedCalendars; +} + - (WOResponse *) eventsBlocksAction { int count, max; NSArray *events, *event, *eventsBlocks; - NSMutableArray *allDayBlocks, *blocks, *currentDay; + NSMutableArray *allDayBlocks, *blocks, *currentDay, *calendars, *eventsByCalendars, *eventsForCalendar; NSNumber *eventNbr; BOOL isAllDay; + int i, j; [self _setupContext]; - [self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks]; - events = [self _fetchFields: eventsFields - forComponentOfType: @"vevent"]; - eventsBlocks = [NSArray arrayWithObjects: events, allDayBlocks, blocks, nil]; - max = [events count]; - for (count = 0; count < max; count++) - { - event = [events objectAtIndex: count]; - // NSLog(@"***[UIxCalListingActions eventsBlocksAction] %i = %@ : %@ / %@ / %@", count, - // [event objectAtIndex: eventTitleIndex], - // [event objectAtIndex: eventStartDateIndex], - // [event objectAtIndex: eventEndDateIndex], - // [event objectAtIndex: eventRecurrenceIdIndex]); - eventNbr = [NSNumber numberWithUnsignedInt: count]; - isAllDay = [[event objectAtIndex: eventIsAllDayIndex] boolValue]; - if (dayBasedView && isAllDay) - [self _fillBlocks: allDayBlocks withEvent: event withNumber: eventNbr]; - else - [self _fillBlocks: blocks withEvent: event withNumber: eventNbr]; - } + events = [self _fetchFields: eventsFields forComponentOfType: @"vevent"]; - max = [blocks count]; - for (count = 0; count < max; count++) + if ([currentView isEqualToString: @"multicolumndayview"]) { - currentDay = [blocks objectAtIndex: count]; - [currentDay sortUsingSelector: @selector (compareEventByStart:)]; - [self _addBlocksWidth: currentDay]; + calendars = [self _selectedCalendars]; + eventsByCalendars = [NSMutableArray arrayWithCapacity:[calendars count]]; + for (i = 0; i < [calendars count]; i++) // For each calendar + { + eventsForCalendar = [NSMutableArray array]; + [self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks]; + for (j = 0; j < [events count]; j++) { + if ([[[events objectAtIndex:j] objectAtIndex:2] isEqualToString:[calendars objectAtIndex:i]]) { + [eventsForCalendar addObject: [events objectAtIndex:j]]; + } + } + eventsBlocks = [NSArray arrayWithObjects:eventsForCalendar, allDayBlocks, blocks, nil]; + max = [eventsForCalendar count]; + for (count = 0; count < max; count++) + { + event = [eventsForCalendar objectAtIndex: count]; + eventNbr = [NSNumber numberWithUnsignedInt: count]; + isAllDay = [[event objectAtIndex: eventIsAllDayIndex] boolValue]; + if (dayBasedView && isAllDay) + [self _fillBlocks: allDayBlocks withEvent: event withNumber: eventNbr]; + else + [self _fillBlocks: blocks withEvent: event withNumber: eventNbr]; + } + max = [blocks count]; + for (count = 0; count < max; count++) + { + currentDay = [blocks objectAtIndex: count]; + [currentDay sortUsingSelector: @selector (compareEventByStart:)]; + [self _addBlocksWidth: currentDay]; + } + + [eventsByCalendars insertObject:eventsBlocks atIndex:i]; + } + return [self _responseWithData: eventsByCalendars]; + } + else + { + [self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks]; + eventsBlocks = [NSArray arrayWithObjects: events, allDayBlocks, blocks, nil]; + max = [events count]; + for (count = 0; count < max; count++) + { + event = [events objectAtIndex: count]; + // NSLog(@"***[UIxCalListingActions eventsBlocksAction] %i = %@ : %@ / %@ / %@", count, + // [event objectAtIndex: eventTitleIndex], + // [event objectAtIndex: eventStartDateIndex], + // [event objectAtIndex: eventEndDateIndex], + // [event objectAtIndex: eventRecurrenceIdIndex]); + eventNbr = [NSNumber numberWithUnsignedInt: count]; + isAllDay = [[event objectAtIndex: eventIsAllDayIndex] boolValue]; + if (dayBasedView && isAllDay) + [self _fillBlocks: allDayBlocks withEvent: event withNumber: eventNbr]; + else + [self _fillBlocks: blocks withEvent: event withNumber: eventNbr]; + } + + max = [blocks count]; + for (count = 0; count < max; count++) + { + currentDay = [blocks objectAtIndex: count]; + [currentDay sortUsingSelector: @selector (compareEventByStart:)]; + [self _addBlocksWidth: currentDay]; + } + return [self _responseWithData: eventsBlocks]; } - - return [self _responseWithData: eventsBlocks]; - // timeIntervalSinceDate: } - (NSString *) _getStatusClassForStatusCode: (int) statusCode diff --git a/UI/Scheduler/UIxCalMulticolumnDayView.m b/UI/Scheduler/UIxCalMulticolumnDayView.m index 6c1683d1a..b96241686 100644 --- a/UI/Scheduler/UIxCalMulticolumnDayView.m +++ b/UI/Scheduler/UIxCalMulticolumnDayView.m @@ -39,25 +39,25 @@ - (id) init { if ((self = [super init])) - { -// allAppointments = nil; - subscriptionUsers = nil; - hoursToDisplay = nil; - currentTableUser = nil; - currentTableHour = nil; -// dateFormatter = [[SOGoDateFormatter alloc] -// initWithLocale: [self locale]]; - } - + { + // allAppointments = nil; + subscriptionUsers = nil; + hoursToDisplay = nil; + currentTableUser = nil; + currentTableHour = nil; + // dateFormatter = [[SOGoDateFormatter alloc] + // initWithLocale: [self locale]]; + } + return self; } - (void) dealloc { -// [allAppointments release]; + // [allAppointments release]; [subscriptionUsers release]; [hoursToDisplay release]; -// [dateFormatter release]; + // [dateFormatter release]; [super dealloc]; } @@ -188,16 +188,6 @@ /* fetching */ -// - (NSCalendarDate *) startDate -// { -// return [[self selectedDate] beginOfDay]; -// } - -// - (NSCalendarDate *) endDate -// { -// return [[self selectedDate] endOfDay]; -// } - // - (NSArray *) appointmentsForCurrentUser // { // NSMutableArray *filteredAppointments; @@ -292,4 +282,11 @@ * (100.0 / [users count]))]; } +- (id ) defaultAction +{ + [super setCurrentView: @"multicolumndayview"]; + + return self; +} + @end diff --git a/UI/Scheduler/UIxCalendarSelector.m b/UI/Scheduler/UIxCalendarSelector.m index 7da4392b3..d5d9a56b1 100644 --- a/UI/Scheduler/UIxCalendarSelector.m +++ b/UI/Scheduler/UIxCalendarSelector.m @@ -96,34 +96,34 @@ _intValueFromHex (NSString *hexString) NSNumber *isActive; if (!calendars) + { + co = [self clientObject]; + folders = [co subFolders]; + max = [folders count]; + calendars = [[NSMutableArray alloc] initWithCapacity: max]; + for (count = 0; count < max; count++) { - co = [self clientObject]; - folders = [co subFolders]; - max = [folders count]; - calendars = [[NSMutableArray alloc] initWithCapacity: max]; - for (count = 0; count < max; count++) - { - folder = [folders objectAtIndex: count]; - calendar = [NSMutableDictionary dictionary]; - folderName = [folder nameInContainer]; - fDisplayName = [folder displayName]; - if (fDisplayName == nil) - fDisplayName = @""; - if ([fDisplayName isEqualToString: [co defaultFolderName]]) - fDisplayName = [self labelForKey: fDisplayName]; - [calendar setObject: [NSString stringWithFormat: @"/%@", folderName] - forKey: @"id"]; - [calendar setObject: fDisplayName forKey: @"displayName"]; - [calendar setObject: folderName forKey: @"folder"]; - [calendar setObject: [folder calendarColor] forKey: @"color"]; - isActive = [NSNumber numberWithBool: [folder isActive]]; - [calendar setObject: isActive forKey: @"active"]; - [calendar setObject: [folder ownerInContext: context] - forKey: @"owner"]; - [calendars addObject: calendar]; - } + folder = [folders objectAtIndex: count]; + calendar = [NSMutableDictionary dictionary]; + folderName = [folder nameInContainer]; + fDisplayName = [folder displayName]; + if (fDisplayName == nil) + fDisplayName = @""; + if ([fDisplayName isEqualToString: [co defaultFolderName]]) + fDisplayName = [self labelForKey: fDisplayName]; + [calendar setObject: [NSString stringWithFormat: @"/%@", folderName] + forKey: @"id"]; + [calendar setObject: fDisplayName forKey: @"displayName"]; + [calendar setObject: folderName forKey: @"folder"]; + [calendar setObject: [folder calendarColor] forKey: @"color"]; + isActive = [NSNumber numberWithBool: [folder isActive]]; + [calendar setObject: isActive forKey: @"active"]; + [calendar setObject: [folder ownerInContext: context] + forKey: @"owner"]; + [calendars addObject: calendar]; } - + } + return calendars; } diff --git a/UI/Templates/SchedulerUI/UIxCalDayTable.wox b/UI/Templates/SchedulerUI/UIxCalDayTable.wox index 5bb9f63ee..3f488286d 100644 --- a/UI/Templates/SchedulerUI/UIxCalDayTable.wox +++ b/UI/Templates/SchedulerUI/UIxCalDayTable.wox @@ -7,51 +7,105 @@ xmlns:rsrc="OGo:url" xmlns:label="OGo:label">
-

-
-
+ + + + +
+ +
+ +
+
+
+ + +
+ +
+
+ +
+
+
+ + +
+ + +
+
+
+
+
+ + + + +
+ +
+
+ +
+
+
+ + +
+ +
+
+
+
- + + +
-
-
- -
-
-
-
- - - -
-
+
+ +
+
+
+ + + + +
+
+ +
+ + + +
+
+
+
+
+
+
+
+ + +
+
+ +
+ + + +
+
+
+
+
+
+
+
diff --git a/UI/Templates/SchedulerUI/UIxCalDayView.wox b/UI/Templates/SchedulerUI/UIxCalDayView.wox index 676d65d54..83cf7c21c 100644 --- a/UI/Templates/SchedulerUI/UIxCalDayView.wox +++ b/UI/Templates/SchedulerUI/UIxCalDayView.wox @@ -40,6 +40,7 @@ className="UIxCalDayTable" startDate="startDate" const:CSSClass="dayOverview" - const:numberOfDays="1" /> + const:numberOfDays="1" + const:currentView="dayview"/>
diff --git a/UI/Templates/SchedulerUI/UIxCalMulticolumnDayView.wox b/UI/Templates/SchedulerUI/UIxCalMulticolumnDayView.wox index 62ee604e3..862a0026b 100644 --- a/UI/Templates/SchedulerUI/UIxCalMulticolumnDayView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMulticolumnDayView.wox @@ -5,40 +5,33 @@ xmlns:const="http://www.skyrix.com/od/constant" xmlns:rsrc="OGo:url" xmlns:label="OGo:label"> - + + + - - + + + + + + + + + + - + +
-
-
-
:00
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
+
- + \ No newline at end of file diff --git a/UI/Templates/SchedulerUI/UIxCalWeekView.wox b/UI/Templates/SchedulerUI/UIxCalWeekView.wox index 6b5debbb1..6e36775ef 100644 --- a/UI/Templates/SchedulerUI/UIxCalWeekView.wox +++ b/UI/Templates/SchedulerUI/UIxCalWeekView.wox @@ -40,6 +40,7 @@ className="UIxCalDayTable" startDate="startDate" const:CSSClass="weekOverview" - const:numberOfDays="7" /> + const:numberOfDays="7" + const:currentView="weekview"/>
diff --git a/UI/WebServerResources/SchedulerUI.css b/UI/WebServerResources/SchedulerUI.css index 52eedff6b..c4cd4d8f7 100644 --- a/UI/WebServerResources/SchedulerUI.css +++ b/UI/WebServerResources/SchedulerUI.css @@ -392,7 +392,7 @@ DIV#daysView left: 0px; } DIV#daysView -{ top: 120px; +{ top: 97px; bottom: 0px; border-top: 1px solid #ccc; overflow: auto; @@ -400,11 +400,12 @@ DIV#daysView right: 0px;} DIV#calendarHeader -{ top: 50px; +{ top: 25px; border: 0px; - height: 100px; + height: 85px; right: 0px; } +DIV#calendarHeader DIV.calendarLabels, DIV#calendarHeader DIV.dayLabels, DIV#calendarHeader DIV.days { position: absolute; @@ -414,8 +415,16 @@ DIV#calendarHeader DIV.days /* 'right' is computed from JS code when daysView is first drawn */ overflow: hidden; } +DIV#calendarHeader DIV.calendarLabels +{ top: 11px; + height: 20px; + border-left: 1px solid #ccc; + text-align: center; + font-style:italic; + font-size:150%; +} DIV#calendarHeader DIV.dayLabels -{ top: 0px; +{ top: 32px; height: 35px; } DIV#calendarHeader DIV.dayLabels DIV.day @@ -432,7 +441,11 @@ DIV#calendarHeader DIV.dayLabels DIV#calendarHeader DIV.days { cursor: pointer; bottom: 0px; - top: 35px; } + top: 67px; + z-index:0; + border-bottom:1px solid #ccc; + background:white; + } DIV#calendarHeader DIV.day, DIV#daysView DIV.day @@ -530,7 +543,8 @@ DIV.monthView DIV.dayHeader text-align: right; cursor: pointer; color: #666; - -moz-user-select: none; } + -moz-user-select: none; + } DIV#monthDaysView DIV.selectedDay DIV.dayHeader { font-weight: bold; } @@ -540,7 +554,8 @@ DIV.monthView DIV.days cursor: pointer; bottom: 0px; left: 0px; - right: 0px; } + right: 0px; + } DIV.monthView DIV.day { position: absolute; @@ -1471,7 +1486,7 @@ DIV.event.draggable:hover DIV.rightDragGrip #ghostEndHour { bottom: -14px; } -DIV#nowLineDisplay +DIV.nowLineDisplay { position: relative; width: 100%; height: 2px; @@ -1486,3 +1501,38 @@ DIV#freeBusyReplicas DIV { display: inline-block; height: 2em; } TD.attendees A.button { float: left; left: 19px; margin-top: 5px; } + +DIV#calendarContent .alert-box { + color:#555; + border-radius:10px; + font-family:Tahoma,Geneva,Arial,sans-serif;font-size:11px; + padding:10px 10px 10px 36px; + margin:10px; +} + +DIV#calendarContent .alert-box span { + font-weight:bold; + text-transform:uppercase; +} + +.error { + background:#ffecec url('error.png') no-repeat 10px 50%; + border:1px solid #f5aca6; +} +.success { + background:#e9ffd9 url('success.png') no-repeat 10px 50%; + border:1px solid #a6ca8a; +} +.warning { + background:#fff8c4 url('warning.png') no-repeat 10px 50%; + border:1px solid #f2c779; +} +.notice { + background:#e3f7fc url('notice.png') no-repeat 10px 50%; + border:1px solid #8ed9f6; +} + + + + + diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 8a3a44215..be7ced9b5 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -34,6 +34,8 @@ var categoriesStyleSheet = null; var clipboard = null; var eventsToCopy = []; + +// This should probably go in the generic.js function printView() { window.open("printView","","width=660,height=470"); @@ -43,6 +45,9 @@ function printView() { function newEvent(type, day, hour, duration) { var folder = null; + /* if (currentView == "multicolumndayview") { + Need to find where the click register is saved + }*/ if (UserDefaults['SOGoDefaultCalendar'] == 'personal') folder = $("calendarList").down("li"); else if (UserDefaults['SOGoDefaultCalendar'] == 'first') { @@ -911,8 +916,8 @@ function onDaySelect(node) { && day != currentDay); var td = $(node).getParentWithTagName("td"); - var table = $(td).getParentWithTagName("table"); - + + // var table = $(td).getParentWithTagName("table"); // log ("table.selected: " + table.selected); if (document.selectedDate) @@ -1589,7 +1594,7 @@ function refreshCalendarEvents(scrollEvent) { if (!currentDay) currentDay = todayDate.getDayString(); - if (currentView == "dayview") { + if (currentView == "dayview" || currentView == "multicolumndayview") { sd = currentDay; ed = sd; } @@ -1627,28 +1632,54 @@ function refreshCalendarEvents(scrollEvent) { "scrollEvent": scrollEvent}); } -function _parseEvents(list) { +function _parseEvents(list, calendars) { var newCalendarEvents = {}; - for (var i = 0; i < list.length; i++) { + if (currentView == "multicolumndayview") { + var list; + for (var i = 0; i < calendars.length; i++) { + list = calendars[i][0]; + for (var j = 0; j < list.length; j++) { + var event = list[j]; + var cname = event[0]; + var calendar = event[1]; + // log("parsed cname: " + cname + "; calendar: " + calendar); + var calendarDict = newCalendarEvents[calendar]; + if (!calendarDict) { + calendarDict = {}; + newCalendarEvents[calendar] = calendarDict; + } + var occurences = calendarDict[cname]; + if (!occurences) { + occurences = []; + calendarDict[cname] = occurences; + } + event.blocks = []; + occurences.push(event); + } + } + } + else { + for (var i = 0; i < list.length; i++) { var event = list[i]; var cname = event[0]; var calendar = event[1]; // log("parsed cname: " + cname + "; calendar: " + calendar); var calendarDict = newCalendarEvents[calendar]; if (!calendarDict) { - calendarDict = {}; - newCalendarEvents[calendar] = calendarDict; + calendarDict = {}; + newCalendarEvents[calendar] = calendarDict; } var occurences = calendarDict[cname]; if (!occurences) { - occurences = []; - calendarDict[cname] = occurences; + occurences = []; + calendarDict[cname] = occurences; } event.blocks = []; occurences.push(event); + } + } - return newCalendarEvents; } @@ -1680,15 +1711,28 @@ function refreshCalendarEventsCallback(http) { if (http.readyState == 4 && http.status == 200) { if (http.responseText.length > 0) { - var eventsBlocks = http.responseText.evalJSON(true); - calendarEvents = _parseEvents(eventsBlocks[0]); - if (currentView == "monthview") - _drawMonthCalendarEvents(eventsBlocks[2], eventsBlocks[0]); - else { - _drawCalendarAllDayEvents(eventsBlocks[1], eventsBlocks[0]); - _drawCalendarEvents(eventsBlocks[2], eventsBlocks[0]); - } - _setupEventsDragAndDrop(eventsBlocks[0]); + var eventsBlocks = http.responseText.evalJSON(true); + + if (currentView == "multicolumndayview") { + calendarEvents = _parseEvents(null, eventsBlocks); + _drawCalendarAllDayEvents(null, null, eventsBlocks); + _drawCalendarEvents(null, null, eventsBlocks); + for (var i = 0 ; i < eventsBlocks.length; i++) { + _setupEventsDragAndDrop(eventsBlocks[i][0]); + } + } + else { + calendarEvents = _parseEvents(eventsBlocks[0], null); + allDayEventsList = eventsBlocks[1]; + eventsList = eventsBlocks[2]; + if (currentView == "monthview") + _drawMonthCalendarEvents(eventsList, eventsBlocks[0], null); + else { + _drawCalendarAllDayEvents(allDayEventsList, eventsBlocks[0], null); + _drawCalendarEvents(eventsList, eventsBlocks[0], null); + } + _setupEventsDragAndDrop(eventsBlocks[0]); + } resetCategoriesStyles(); onWindowResize(null); } @@ -1851,20 +1895,37 @@ function newBaseEventDIV(eventRep, event, eventText) { return eventCell; } -function _drawCalendarAllDayEvents(events, eventsData) { +function _drawCalendarAllDayEvents(events, eventsData, columnsData) { var headerView = $("calendarHeader"); var subdivs = headerView.childNodesWithTag("div"); - var days = subdivs[1].childNodesWithTag("div"); - for (var i = 0; i < days.length; i++) { + + if (currentView == "multicolumndayview"){ + var days = subdivs[2].childNodesWithTag("div"); + for (var i = 0; i < days.length; i++) { + var parentDiv = days[i]; + var calendar = columnsData[i]; + var calendarAllDayEvents = calendar[1][0]; + var calendarAllDayEventsData = calendar[0]; + for (var j = 0; j < calendarAllDayEvents.length; j++) { + var eventRep = calendarAllDayEvents[j]; + var nbr = eventRep.nbr; + var eventCell = newAllDayEventDIV(eventRep, calendarAllDayEventsData[nbr]); + parentDiv.appendChild(eventCell); + } + } + } + else { + var days = subdivs[1].childNodesWithTag("div"); + for (var i = 0; i < days.length; i++) { var parentDiv = days[i]; for (var j = 0; j < events[i].length; j++) { - var eventRep = events[i][j]; - var nbr = eventRep.nbr; - var eventCell = newAllDayEventDIV(eventRep, eventsData[nbr]); - parentDiv.appendChild(eventCell); + var eventRep = events[i][j]; + var nbr = eventRep.nbr; + var eventCell = newAllDayEventDIV(eventRep, eventsData[nbr]); + parentDiv.appendChild(eventCell); } + } } - resizeCalendarHeaderDIV(); } @@ -1876,15 +1937,17 @@ function resizeCalendarHeaderDIV() { var daysView = $("daysView"); if (headerView && daysView) { /* consts */ - var headerViewBaseHeight = 70; - var daysViewBaseTop = 120; - var maxDelta = 80; + var headerViewBaseHeight = 90; + var daysViewBaseTop = 95; /* /consts */ var maxEventPerDay = 0; var subdivs = headerView.childNodesWithTag("div"); - var days = subdivs[1].childNodesWithTag("div"); + if (currentView == "multicolumndayview") + var days = subdivs[2].childNodesWithTag("div"); + else + var days = subdivs[1].childNodesWithTag("div"); for (var i = 0; i < days.length; i++) { var parentDiv = days[i]; var divs = parentDiv.childNodesWithTag("div"); @@ -1892,16 +1955,31 @@ function resizeCalendarHeaderDIV() { maxEventPerDay = divs.length; } } - - if (maxEventPerDay > 2) { - var delta = ((maxEventPerDay - 2) * 22) + 10; - if (delta > maxDelta) { - delta = maxDelta; - } - daysView.style.top = String(delta + daysViewBaseTop) + "px"; - headerView.style.height = String(delta + headerViewBaseHeight) + "px"; + if (maxEventPerDay > 0 && maxEventPerDay <= 4) { + var moveDaysView = (maxEventPerDay * 19.5); + var expendHeaderHeight = ((maxEventPerDay - 1) * 20); + var deltaMax = 60; + if (expendHeaderHeight > deltaMax){ + expendHeaderHeight = deltaMax; + moveDaysView = deltaMax; + } + daysView.style.top = String(daysViewBaseTop + moveDaysView) + "px"; + headerView.style.height = String(headerViewBaseHeight + expendHeaderHeight) + "px"; + } + + else if (maxEventPerDay > 4) { + var deltaMax = 60; + daysView.style.top = String(daysViewBaseTop + deltaMax + 19) + "px"; + headerView.style.height = String(headerViewBaseHeight + deltaMax) + "px"; } else { + var headerDays = document.getElementsByClassName("days")[0]; + headerDays.observe("mouseenter", function(event){ + headerDays.style.zIndex = "1"; + }); + headerDays.observe("mouseleave", function(event){ + headerDays.style.zIndex = "0"; + }); daysView.style.top = null; headerView.style.height = null; } @@ -1916,21 +1994,37 @@ function newAllDayEventDIV(eventRep, event) { return eventCell; } -function _drawCalendarEvents(events, eventsData) { +function _drawCalendarEvents(events, eventsData, columnsData) { var daysView = $("daysView"); var subdivs = daysView.childNodesWithTag("div"); for (var i = 0; i < subdivs.length; i++) { var subdiv = subdivs[i]; if (subdiv.hasClassName("days")) { var days = subdiv.childNodesWithTag("div"); - for (var j = 0; j < days.length; j++) { + if (currentView == "multicolumndayview") { + for (var j = 0; j < days.length; j++) { + var parentDiv = days[j].childNodesWithTag("div")[0]; + var calendar = columnsData[j]; + var calendarEvents = calendar[2][0]; + var calendarEventsData = calendar[0]; + for (var k = 0; k < calendarEvents.length; k++) { + var eventRep = calendarEvents[k]; + var nbr = eventRep.nbr; + var eventCell = newEventDIV(eventRep, calendarEventsData[nbr]); + parentDiv.appendChild(eventCell); + } + } + } + else { + for (var j = 0; j < days.length; j++) { var parentDiv = days[j].childNodesWithTag("div")[0]; for (var k = 0; k < events[j].length; k++) { - var eventRep = events[j][k]; - var nbr = eventRep.nbr; - var eventCell = newEventDIV(eventRep, eventsData[nbr]); - parentDiv.appendChild(eventCell); + var eventRep = events[j][k]; + var nbr = eventRep.nbr; + var eventCell = newEventDIV(eventRep, eventsData[nbr]); + parentDiv.appendChild(eventCell); } + } } } } @@ -2009,7 +2103,8 @@ function adjustCalendarHeaderDIV() { var delta = ch.clientWidth - dv.clientWidth - 1; var styleElement = document.createElement("style"); styleElement.type = "text/css"; - var selectors = ["DIV#calendarHeader DIV.dayLabels", + var selectors = ["DIV#calendarHeader DIV.calendarLabels", + "DIV#calendarHeader DIV.dayLabels", "DIV#calendarHeader DIV.days"]; var rule = ("right: " + delta + "px"); if (styleElement.styleSheet && styleElement.styleSheet.addRule) { @@ -2026,6 +2121,37 @@ function adjustCalendarHeaderDIV() { } } +function adjustMultiColumnCalendarHeaderDIV() { + + var ch = $("calendarHeader"); + var calendarLabels = ch.getElementsByClassName("calendarLabels")[0]; + var calendarsToDisplay = calendarLabels.getElementsByClassName("calendarsToDisplay"); + var dayLabels = ch.getElementsByClassName("dayLabels")[0].getElementsByClassName("dayColumn")[0]; + var days = ch.getElementsByClassName("days")[0].getElementsByClassName("dayColumn"); + var daysView = $("daysView").getElementsByClassName("dayColumn"); + + var nbCalendars = calendarsToDisplay.length; + + if (nbCalendars > 0) { + var width = 100/nbCalendars; + var left = 0; + var position = "absolute"; + for(var i=0; i < nbCalendars; i++){ + calendarsToDisplay[i].setStyle({ width: width + '%', left: left + '%', position: position}).show(); + days[i].setStyle({ width: width + '%', left: left + '%'}).show(); + daysView[i].setStyle({ width: width + '%', left: left + '%'}).show(); + left += width; + } + dayLabels.setStyle({ width: '100%'}).show(); + } + else { + $("calendarHeader").remove(); + $("daysView").remove(); + var htmlText = "
" + _("notice:") + ""+_("Please go ahead and select calendars")+"
"; + $("calendarContent").innerHTML = htmlText; + } +} + function calendarDisplayCallback(http) { var div = $("calendarView"); var daysView = $("daysView"); @@ -2054,6 +2180,9 @@ function calendarDisplayCallback(http) { currentView = http.callbackData["view"]; if (http.callbackData["day"]) currentDay = http.callbackData["day"]; + + if (currentView == "multicolumndayview") + adjustMultiColumnCalendarHeaderDIV(); // Initialize contextual menu var menu = new Array(onMenuNewEventClick, @@ -2067,10 +2196,7 @@ function calendarDisplayCallback(http) { onMenuRawEvent ); var observer; - if (currentView == 'dayview') { - observer = $("daysView"); - } - else if (currentView == 'weekview') { + if (currentView == 'dayview' || currentView == 'weekview' || currentView == 'multicolumndayview') { observer = $("daysView"); } else { @@ -2249,9 +2375,9 @@ function onHeaderClick(event) { function refreshCurrentFolder(id) { if (id == 'tasks') - refreshTasks(); + refreshTasks(); else - refreshEvents(); + refreshEvents(); } /* refreshes the "unifinder" list */ @@ -3367,24 +3493,42 @@ function drawNowLine() { d = "0" + d; var day = today.getFullYear() + "" + m + "" + d; var targets = $$("DIV#daysView DIV.days DIV.day[day=" + day - + "] DIV.clickableHourCell"); + + "] DIV.hourCells"); + } + else if (currentView == "multicolumndayview") { + var targets = $$("DIV#daysView DIV.hourCells"); } else if (currentView == "weekview") - var targets = $$("DIV#daysView DIV.days DIV.dayOfToday DIV.clickableHourCell"); + var targets = $$("DIV#daysView DIV.days DIV.dayOfToday DIV.hourCells"); - if (targets) { - var target = targets[hours]; + if (targets[0]) { + if (currentView == "multicolumndayview") { + var nbCalendars = targets.length; + for(var i = 0; i < nbCalendars; i++){ + var target = targets[i].getElementsByClassName("clickableHourCell")[hours]; - if (target) { - var div = $("nowLineDisplay"); + if (target) { + var div = targets[i].getElementsByClassName("nowLineDisplay")[0]; + if (!div) + div = new Element("div", {'class': 'nowLineDisplay'}); + + div.style.top = parseInt((minutes * target.offsetHeight / 60) - 1) + "px"; + target.insertBefore(div, target.firstChild); + } + } + } + else { + var target = targets[0].getElementsByClassName("clickableHourCell")[hours]; + if (target) { + var div = targets[0].getElementsByClassName("nowLineDisplay")[0]; if (!div) - div = new Element("div", {'id': 'nowLineDisplay'}); + div = new Element("div", {'class': 'nowLineDisplay'}); - div.style.top = parseInt((minutes * target.offsetHeight / 60) - 1) + "px"; - target.insertBefore(div, target.firstChild); - - setTimeout("drawNowLine ();", 60000); // 1 min. + div.style.top = parseInt((minutes * target.offsetHeight / 60) - 1) + "px"; + target.insertBefore(div, target.firstChild); + } } + setTimeout("drawNowLine ();", 60000); // 1 min. } }