See Changelog.

Monotone-Parent: f13b039579047763006c2956ddf349f1bff203a3
Monotone-Revision: f6c7d4502b60b66206223a822d4911218f4bbacf

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2010-08-26T14:14:10
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Francis Lachapelle 2010-08-26 14:14:10 +00:00
parent d2b696fcfa
commit c512f1240f
49 changed files with 507 additions and 139 deletions

View File

@ -1,3 +1,39 @@
2010-08-25 Francis Lachapelle <flachapelle@inverse.ca>
* UI/WebServerResources/SchedulerUI.js (copyEventToClipboard)
(copyEventFromClipboard, copyEventToPersonalCalendar, copyEvents):
new functions to allow the copy/paste of events.
(selectCalendarEvent): fixed various bugs with the selection of
events.
(onMenuCurrentViewPrepareVisibility): new function to disable the
delete option when no event is selected and to disable the copy
option when the event is owned by the user.
(onDocumentKeydown): added actions for Ctrl-C and Ctrl-V.
(deleteEvent): avoid showing a confirmation dialog with recurrent
events that the user can't erase.
* UI/WebServerResources/SOGoDataTable.js: Overrided methods from
HTMLElement (selectRange, selectAll) to handle selection based on rows ID.
* UI/WebServerResources/MailerUI.js: selected messages are now
identified by their row ID to handle live loading.
* UI/WebServerResources/HTMLElement.js (getSelectedNodesId): take
advantage of the selectedIds attribute.
(selectElement): also verify if the element is in the selectedIds
array.
(deselectAll): performance improvement; unselect elements based on
the _selected class.
* UI/Scheduler/UIxAppointmentActions.m (-copyAction): new method
to copy the appointment to a different calendar.
* SoObjects/Appointments/SOGoCalendarComponent.m
(-copyComponent:toFolder:): was copyToFolder. This new method
accepts a specific calendar component.
(-copyToFolder:): uses the above method with the current calendar.
2010-08-25 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/Contacts/UIxListEditor.m: slightly improved code at various

View File

@ -55,6 +55,9 @@
- (BOOL) expandGroupsInEvent: (iCalEvent *) theEvent;
- (NSException *) copyComponent: (iCalCalendar *) calendar
toFolder: (SOGoGCSFolder *) newFolder;
- (void) saveComponent: (iCalRepeatableEntityObject *) newObject;
/* mail notifications */

View File

@ -1,6 +1,6 @@
/* SOGoCalendarComponent.m - this file is part of SOGo
*
* Copyright (C) 2006-2009 Inverse inc.
* Copyright (C) 2006-2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -1041,16 +1041,20 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence,
}
- (NSException *) copyToFolder: (SOGoGCSFolder *) newFolder
{
return [self copyComponent: [self calendar: NO secure: NO]
toFolder: newFolder];
}
- (NSException *) copyComponent: (iCalCalendar *) calendar
toFolder: (SOGoGCSFolder *) newFolder
{
NSArray *elements;
NSString *newUID;
unsigned int count, max;
iCalCalendar *calendar;
SOGoCalendarComponent *newComponent;
newUID = [self globallyUniqueObjectId];
calendar = [self calendar: NO secure: NO];
elements = [calendar allObjects];
max = [elements count];
for (count = 0; count < max; count++)

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Você não está liberado para acessar este módulo ou este sistema. Por favor, contate seu administrador de sistemas.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Nemáte oprávnění pro přístup k tomuto modulu nebo systému. Kontaktujte prosím svého systémového administrátora.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"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.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "You are not allowed to access this module or this system. Please contact your system administrator.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "Un dossier du même nom existe déjà.";
"You cannot create a list in a shared address book."
= "Impossible de créer une liste dans un dossier partagé.";
"Warning" = "Avertissement";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Vous n'êtes pas autorisé à accéder à ce module ou ce système. Veuillez contacter votre administrateur système.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "Ein Ordner mit diesem Namen existiert bereits.";
"You cannot create a list in a shared address book."
= "Es ist nicht möglich, eine Liste in einem gemeinsamen Adressbuch zu erstellen.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Sie sind nicht berechtigt auf dieses Modul oder System zuzugreifen. Bitte kontaktieren Sie ihren Systemadministrator.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Önnek nem engedélyezett a hozzáférés ehhez a modulhoz vagy rendszerhez. Kérem lépjen kapcsolatba a rendszergazdával.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Non sei abilitato ad accedere a questo modulo. Contatta il tuo amministratore di sistema.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "Folder o tej nazwie już istnieje.";
"You cannot create a list in a shared address book."
= "Nie możesz tworzyć list w udostępnionej książce adresowej.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Nie masz pozwolenia na dostęp do tego modułu lub tego systemu. Skontaktuj się ze swoim administratorem.";
@ -65,6 +66,12 @@
"delegate is a participant" = "Delegat jest już uczestnikiem.";
"delegate is a group" = "Wskazany adres jest grupą. Możesz oddelegować tylko pojedynczną osobę.";
/* common buttons */
"OK" = "OK";
"Cancel" = "Cancel";
"Yes" = "Yes";
"No" = "No";
/* alarms */
"Reminder:" = "Przypomnienie:";
"Start:" = "Początek:";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Вам не предоставлено право доступа к этому модулю/системе. Пожалуйста, свяжитесь с администратором.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "You are not allowed to access this module or this system. Please contact your system administrator.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "En mapp med det namnet finns redan.";
"You cannot create a list in a shared address book."
= "Du kan inte skapa en lista i en delad adressbok.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Du har inte åtkomsträttighet till modulen eller systemet. Kontakta din systemadministratör.";

View File

@ -54,6 +54,7 @@
"A folder by that name already exists." = "A folder by that name already exists.";
"You cannot create a list in a shared address book."
= "You cannot create a list in a shared address book.";
"Warning" = "Warning";
"You are not allowed to access this module or this system. Please contact your system administrator."
= "Nid oes gennych caniatad mynediad i'r modiwl hwn na'r system hwn. Cysylltwch a'r Gweinyddwr Systemau os gwelwch yn dda.";

View File

@ -38,7 +38,7 @@
"invalidemailwarn" = "Podany adres e-mail jest nieprawidłowy";
"invaliddatewarn" = "Podana data jest nieprawidłowa.";
"new" = "nowy";
"Preferred Phone" = "Preferowany telefon";
"Preferred Phone" = "Preferowany telefon";
"Move To" = "Przenieś do";
"Copy To" = "Kopiuj do";

View File

@ -26,6 +26,7 @@ Tentative = "Niepewny";
"Delegate ..." = "Przekaż ...";
"Delegated to" = "Przekazane do";
"Update status in calendar" = "Zaktualizuj status w kalendarzu";
"delegated from" = "delegated from";
reply_info_no_attendee = "Otrzymałeś odpowiedź do wydarzenia ale nadawca nie jest uczestnikiem.";
reply_info = "To jest odpowiedź do utworzonego przez ciebie wydarzenia";

View File

@ -26,6 +26,7 @@ Tentative = "попередьно погодитись";
"Delegate ..." = "Делегуват ...";
"Delegated to" = "Делегувати";
"Update status in calendar" = "Поновити статус в календарі";
"delegated from" = "delegated from";
reply_info_no_attendee = "Ви отримали відповідь на запланований захід, але відправник повідомлення відсутній серед запрошених.";
reply_info = "Це відповідь на Ваше запрошення взяти участь у заході.";

View File

@ -45,7 +45,7 @@
"Home" = "Початок";
"Calendar" = "Календар";
"Addressbook" = "Адресна";
"Addressbook" = "Адресна книга";
"Mail" = "Пошта";
"Right Administration" = "Права доступу";
@ -136,6 +136,7 @@
"View" = "Перегляд";
"All" = "Всі";
"Unread" = "Непрочитані";
"No message" = "No message";
"messages" = "повідомлення";
"first" = "перша";

View File

@ -134,7 +134,7 @@
"Port:" = "Port:";
"User Name:" = "User Name:";
"Password:" = "Senha:";
"Full Name:" = "Full Name:";
"Email:" = "Email:";
"Signature:" = "Assinatura:";

View File

@ -134,7 +134,7 @@
"Port:" = "Port:";
"User Name:" = "User Name:";
"Password:" = "Password:";
"Full Name:" = "Full Name:";
"Email:" = "Email:";
"Signature:" = "Firma:";

View File

@ -134,7 +134,7 @@
"Port:" = "Port:";
"User Name:" = "User Name:";
"Password:" = "Lösenord:";
"Full Name:" = "Full Name:";
"Email:" = "Email:";
"Signature:" = "Signatur:";

View File

@ -16,7 +16,6 @@
"Add" = "Додати";
"Delete" = "Вилучити";
/* vacation (auto-reply) */
"Enable vacation auto reply" = "Увімкнути повідомлення про мою відсутність";
"Auto reply message :" = "Текст автоматичної відповіді:";
@ -34,7 +33,6 @@
"Please specify an address to which you want to forward your messages."
= "Будь ласка, зазначте адресу, на яку потрібно перенаправляти повідомлення, адресовані Вам.";
/* d & t */
"Current Time Zone :" = "Поточна часова зона :";
"Short Date Format :" = "Стислий формат дати :";
@ -136,7 +134,7 @@
"Port:" = "Port:";
"User Name:" = "User Name:";
"Password:" = "Пароль:";
"Full Name:" = "Full Name:";
"Email:" = "Email:";
"Signature:" = "Підпис:";
@ -145,7 +143,6 @@
"Signature" = "Підпис";
"Please enter your signature below:" = "Please enter your signature below:";
/* Additional Parameters */
"Additional Parameters" = "Додаткові параметри";
@ -163,7 +160,7 @@
"Contacts" = "Адресна книга";
"Mail" = "Електронна пошта";
"Last" = "Останнє";
"Default module :" = "Модуль за замовчанням :";
"Default module :" = "Модуль за замовчанням :";
"Language :" = "Language :";
"choose" = "Choose ...";

View File

@ -81,7 +81,8 @@
"Day start time must be prior to day end time." = "Day start time must be prior to day end time.";
"First week of year :" = "Wythnos cyntaf y flwyddyn :";
"Enable reminders for Calendar items" = "Galluogu atgoffa ar gyfer eitemau calendr";
"Play a sound when a reminder comes due" = "Chwarae swn pan fydd amser atgoffa";
"Play a sound when a reminder comes due"
= "Chwarae swn pan fydd amser atgoffa";
"Default reminder :" = "Atgoffa gwreiddiol :";
"firstWeekOfYear_January1" = "Dechrau ar Ionawr 1";
@ -133,7 +134,7 @@
"Port:" = "Port:";
"User Name:" = "User Name:";
"Password:" = "Cyfrinair:";
"Full Name:" = "Full Name:";
"Email:" = "Email:";
"Signature:" = "Llofnod:";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Tarefa Confidencial)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"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.";
"Open Task..." = "Open Task...";
"Mark Completed" = "Mark Completed";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Důvěrný úkol)";
"tagHasChanged" = "Změníte-li štítek svého kalendáře, budete muset znovu načíst data do svého mobilního zařízení.\nPokračovat?";
"tagWasAdded" = "Chcete-li synchronizovat tento kalendář, budete muset znovu načíst data do svého mobilního zařízení.\nPokračovat?";
"tagWasRemoved" = "Odstraníte-li u tohoto kalendáře synchronizaci, budete muset znovu načíst data do svého mobilního zařízení.\nPokračovat?";
"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.";
"Open Task..." = "Otevřít úkol...";
"Mark Completed" = "Označit jako dokončené";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Vertrouwelijke taak)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"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.";
"Open Task..." = "Taak openen...";
"Mark Completed" = "Mark Completed";

View File

@ -555,6 +555,8 @@ vtodo_class2 = "(Confidential task)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"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.";
"Open Task..." = "Open Task...";
"Mark Completed" = "Mark Completed";

View File

@ -555,6 +555,8 @@ vtodo_class2 = "(Tâche confidentielle)";
"tagHasChanged" = "En changeant le label de ce calendrier, vous devrez recharger les données sur votre appareil mobile.\nVoulez-vous continuer?";
"tagWasAdded" = "Afin de synchroniser ce calendrier, vous devrez recharger les données sur votre appareil mobile.\nVoulez-vous continuer?";
"tagWasRemoved" = "Afin de ne plus synchroniser ce calendrier, vous devrez recharger les données sur votre appareil mobile.\nVoulez-vous continuer?";
"DestinationCalendarError" = "Le calendrier de destination est le même que celui de l'événement. Choisissez un calendrier de destination différent.";
"EventCopyError" = "La copie a échouée. Choisissez un calendrier de destination différent.";
"Open Task..." = "Ouvrir la tâche...";
"Mark Completed" = "Marquer comme accomplie";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Vertrauliche Aufgabe)";
"tagHasChanged" = "Wenn der Tag des Kalenders geändert wird, müssen die Daten erneut auf das Mobilgerät geladen werden.\nFortfahren?";
"tagWasAdded" = "Wenn der Kalender synchronisiert werden soll, müssen die Daten erneut auf das Mobilgerät geladen werden.\nFortfahren?";
"tagWasRemoved" = "Wenn der Kalender aus der Synchronisation entfernt wird, müssen die Daten erneut auf das Mobilgerät geladen werden.\nFortfahren?";
"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.";
"Open Task..." = "Aufgabe öffnen...";
"Mark Completed" = "Als abgeschlossen markieren";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Bizalmas feladat)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"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.";
"Open Task..." = "Open Task...";
"Mark Completed" = "Mark Completed";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Attività confidenziale)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"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.";
"Open Task..." = "Open Task...";
"Mark Completed" = "Mark Completed";

View File

@ -555,6 +555,8 @@ vtodo_class2 = "(Zadanie poufne)";
"tagHasChanged" = "Jeśli zmienisz znacznik kalendarza, musisz przeładować dane na swoim urządzeniu mobilnym.\nKontynuować?";
"tagWasAdded" = "Jeśli chesz synchronizować ten kalendarz, będziesz musiał(a) przeładować dane na swoim urządzeniu mobilnym.\nKontynuować?";
"tagWasRemoved" = "Jeśli usuniesz ten kalendarz z synchronizacji, będziesz musiał(a) przeładować dane na swoim urządzeniu mobilnym.\nKontynuować?";
"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.";
"Open Task..." = "Otwórz zadanie...";
"Mark Completed" = "Oznacz jako ukończone";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Confidential task)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"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.";
"Open Task..." = "Open Task...";
"Mark Completed" = "Mark Completed";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Tarea confidencial)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"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.";
"Open Task..." = "Open Task...";
"Mark Completed" = "Mark Completed";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Konfidentiell uppgift)";
"tagHasChanged" = "Om du ändrar etiketten på din kalender, behöver du ladda om datat i din mobiltelefon.\nFortsätta?";
"tagWasAdded" = "Om du vill synkronisera kalendern, behöver du ladda om datat i din mobiltelefon.\nFortsätta?";
"tagWasRemoved" = "Om du tar bort kalendern från synkronisering, behöver du ladda om datat i din mobiltelefon.\nFortsätta?";
"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.";
"Open Task..." = "Öppna uppgift...";
"Mark Completed" = "Märk utförd";

View File

@ -24,9 +24,12 @@
#import <Foundation/NSString.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/SoPermissions.h>
#import <NGObjWeb/SoSecurityManager.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalEvent.h>
#import <SOGo/NSCalendarDate+SOGo.h>
@ -108,4 +111,83 @@
return response;
}
- (WOResponse *) copyAction
{
NSString *destination;
NSArray *events;
iCalCalendar *calendar;
iCalRepeatableEntityObject *masterOccurence;
SOGoAppointmentObject *thisEvent;
SOGoAppointmentFolder *sourceCalendar, *destinationCalendar;
SoSecurityManager *sm;
WOResponse *response;
WORequest *rq;
rq = [context request];
destination = [rq formValueForKey: @"destination"];
if (![destination length])
destination = @"personal";
thisEvent = [self clientObject];
sourceCalendar = [thisEvent container];
destinationCalendar = [[sourceCalendar container] lookupName: destination
inContext: context
acquire: NO];
if (destinationCalendar)
{
// Verify access rights to destination calendar
sm = [SoSecurityManager sharedSecurityManager];
if ([sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
onObject: destinationCalendar
inContext: context])
{
response = [NSException exceptionWithHTTPStatus: 403
reason: @"Can't add event to destination calendar."];
}
// Verify that the destination calendar is not the source calendar
else if ([[destinationCalendar nameInContainer] isEqualToString: [sourceCalendar nameInContainer]])
{
response = [NSException exceptionWithHTTPStatus: 400
reason: @"Destination calendar is the source calendar."];
}
else
{
// Remove attendees, recurrence exceptions and single occurences from the event
calendar = [thisEvent calendar: NO secure: NO];
events = [calendar events];
masterOccurence = [events objectAtIndex: 0];
if ([masterOccurence hasAlarms])
[masterOccurence removeAllAlarms];
if ([masterOccurence hasRecurrenceRules])
{
[masterOccurence removeAllExceptionRules];
[masterOccurence removeAllExceptionDates];
}
if ([[masterOccurence attendees] count] > 0)
{
[masterOccurence setOrganizer: nil];
[masterOccurence removeAllAttendees];
}
[calendar setUniqueChild: masterOccurence];
// Perform the copy
if ([thisEvent copyComponent: calendar
toFolder: (SOGoGCSFolder *) destinationCalendar])
response = [NSException exceptionWithHTTPStatus: 500
reason: @"Can't copy event to destination calendar."];
else
response = [self responseWith204];
}
}
else
{
response = [NSException exceptionWithHTTPStatus: 404
reason: @"Can't find destination calendar."];
}
return response;
}
@end

View File

@ -540,6 +540,8 @@ vtodo_class2 = "(Конфіденційне завдання)";
"tagHasChanged" = "Якщо Ви змінете теґ вашого календаря, то потрібно буде перевантажити дані на Вашому мобільному пристрої.\nПродовжити?";
"tagWasAdded" = "Якшр Ви хочете синхронізувати цей календар, то потрібно буде перевантажити дані на Вашому мобільному пристрої.\nПродовжити?";
"tagWasRemoved" = "Якщо Ви скасуєте режим синхронізації для цього календаря, то потрібно буде перевантажити дані на Вашому мобільному пристрої.\nПродовжити?";
"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.";
"Open Task..." = "Відкрити завдання...";
"Mark Completed" = "Позначити виконаним";

View File

@ -554,6 +554,8 @@ vtodo_class2 = "(Tasg gyhoeddus)";
"tagHasChanged" = "If you change your calendar's tag, you'll need to perform a slow sync on your mobile device.\nContinue?";
"tagWasAdded" = "If you want to synchronize this calendar, you'll need to reload the data on your mobile device.\nContinue?";
"tagWasRemoved" = "If you remove this calendar from synchronization, you'll need to perform a slow sync 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.";
"Open Task..." = "Open Task...";
"Mark Completed" = "Mark Completed";

View File

@ -220,6 +220,11 @@
pageName = "UIxAppointmentEditor";
actionName = "save";
};
copy = {
protectedBy = "ViewAllComponent";
actionClass = "UIxAppointmentActions";
actionName = "copy";
};
accept = {
protectedBy = "RespondToComponent";
pageName = "UIxAppointmentEditor";

View File

@ -16,6 +16,7 @@
<li><var:string label:value="Next Day"/></li>
<li><!-- separator --></li>
<li><var:string label:value="Delete Event"/></li>
<li><var:string label:value="Copy event to my calendar"/></li>
</ul>
</div>
<a href="#"

View File

@ -16,6 +16,7 @@
<li><var:string label:value="Next Month"/></li>
<li><!-- separator --></li>
<li><var:string label:value="Delete Event"/></li>
<li><var:string label:value="Copy event to my calendar"/></li>
</ul>
</div>
<a href="#"

View File

@ -15,6 +15,7 @@
<li><var:string label:value="Next Week"/></li>
<li><!-- separator --></li>
<li><var:string label:value="Delete Event"/></li>
<li><var:string label:value="Copy event to my calendar"/></li>
</ul>
</div>
<a href="#"

View File

@ -120,15 +120,17 @@ Element.addMethods({
getSelectedNodesId: function(element) {
element = $(element);
var selArray = new Array();
if (element.selectedElements) {
var selArray = null;
if (element.selectedIds) {
selArray = element.selectedIds;
}
else if (element.selectedElements) {
selArray = new Array();
for (var i = 0; i < element.selectedElements.length; i++) {
var node = element.selectedElements[i];
selArray.push(node.getAttribute("id"));
}
}
else
element.selectedElements = new Array();
return selArray;
},
@ -180,7 +182,7 @@ Element.addMethods({
element.addClassName('_selected');
var parent = element.up();
if (!parent.selectedElements) {
if (!parent.selectedElements || !parent.selectedIds) {
// Selected nodes are kept in a array at the
// container level.
parent.selectedElements = new Array();
@ -188,6 +190,8 @@ Element.addMethods({
}
for (var i = 0; i < parent.selectedElements.length; i++)
if (parent.selectedElements[i] == element) return;
for (var i = 0; i < parent.selectedIds.length; i++)
if (parent.selectedIds[i] == element.id) return;
parent.selectedElements.push(element); // use index instead ?
parent.selectedIds.push(element.id);
},
@ -226,7 +230,7 @@ Element.addMethods({
for (var i = 0; i < rows.length; i++)
if (rows[i].nodeType == 1)
$(rows[i]).selectElement();
},
},
deselect: function(element) {
element = $(element);
@ -240,20 +244,11 @@ Element.addMethods({
deselectAll: function(element) {
element = $(element);
if (element.selectedElements) {
for (var i = 0; i < element.selectedElements.length; i++)
element.selectedElements[i].removeClassName('_selected');
element.selectedElements = null;
element.selectedIds = null;
}
else if (element.selectedIds) {
for (var i = 0; i < element.selectedIds.length; i++) {
var e = element.down('#' + element.selectedIds[i]);
if (e && e.hasClassName('_selected'))
e.removeClassName('_selected');
}
element.selectedIds = null;
}
var s = element.select("._selected");
for (var i = 0; i < s.length; i++)
s[i].removeClassName("_selected");
element.selectedElements = null;
element.selectedIds = null;
},
refreshSelectionByIds: function(element) {

View File

@ -318,13 +318,13 @@ function onUnload(event) {
function onDocumentKeydown(event) {
var target = Event.element(event);
if (target.tagName != "INPUT")
if (event.keyCode == Event.KEY_DELETE ||
if (target.tagName != "INPUT") {
if (event.keyCode == Event.KEY_DELETE ||
event.keyCode == Event.KEY_BACKSPACE && isMac()) {
deleteSelectedMessages();
Event.stop(event);
}
else if (event.keyCode == Event.KEY_DOWN ||
else if (event.keyCode == Event.KEY_DOWN ||
event.keyCode == Event.KEY_UP) {
if (Mailer.currentMessages[Mailer.currentMailbox]) {
var row = $("row_" + Mailer.currentMessages[Mailer.currentMailbox]);
@ -357,30 +357,44 @@ function onDocumentKeydown(event) {
Event.stop(event);
}
}
else if (event.ctrlKey == 1 && event.keyCode == 65) { // Ctrl-A
$("messageListBody").down("TBODY").selectAll();
Event.stop(event);
}
}
}
/* bulk delete of messages */
function deleteSelectedMessages(sender) {
var messageList = $("messageListBody").down("TBODY");
var rows = messageList.getSelectedNodes();
var rowIds = messageList.getSelectedNodesId();
var uids = new Array(); // message IDs
var paths = new Array(); // row IDs
var unseenCount = 0;
if (rows.length > 0) {
for (var i = 0; i < rows.length; i++) {
var uid = rows[i].readAttribute("id").substr(4);
var path = Mailer.currentMailbox + "/" + uid;
if (rowIds.length > 0) {
for (var i = 0; i < rowIds.length; i++) {
if (unseenCount < 1) {
var rows = messageList.select('#' + rowIds[i]);
if (rows.length > 0) {
var row = rows.first();
row.hide();
if (row.hasClassName("mailer_unreadmail"))
unseenCount--;
}
else {
unseenCount = 1;
}
}
deleteMessageRequestCount++;
rows[i].hide();
var uid = rowIds[i].substr(4); // drop "row_"
var path = Mailer.currentMailbox + "/" + uid;
uids.push(uid);
paths.push(path);
if (rows[i].hasClassName("mailer_unreadmail"))
unseenCount--;
}
messageList.deselectAll();
updateMessageListCounter(0 - rows.length, true);
updateMessageListCounter(0 - rowIds.length, true);
if (unseenCount < 0) {
var node = mailboxTree.getMailboxNode(Mailer.currentMailbox);
if (node) {
@ -389,7 +403,7 @@ function deleteSelectedMessages(sender) {
}
var url = ApplicationBaseURL + encodeURI(Mailer.currentMailbox) + "/batchDelete";
var parameters = "uid=" + uids.join(",");
var data = { "id": uids, "mailbox": Mailer.currentMailbox, "path": paths };
var data = { "id": uids, "mailbox": Mailer.currentMailbox, "path": paths, "refreshUnseenCount": (unseenCount > 0) };
triggerAjaxRequest(url, deleteSelectedMessagesCallback, data, parameters,
{ "Content-type": "application/x-www-form-urlencoded" });
}
@ -436,6 +450,8 @@ function deleteSelectedMessagesCallback(http) {
}
}
}
if (data["refreshUnseenCount"])
getUnseenCountForFolder(data["mailbox"]);
}
else {
log ("deleteSelectedMessagesCallback: problem during ajax request " + http.status);
@ -470,11 +486,11 @@ function deleteMessageWithDelay(url, id, mailbox, messageId) {
function onPrintCurrentMessage(event) {
var messageList = $("messageListBody").down("TBODY");
var rowIds = messageList.getSelectedNodes();
if (rowIds.length == 0) {
var rows = messageList.getSelectedNodes();
if (rows.length == 0) {
showAlertDialog(_("Please select a message to print."));
}
else if (rowIds.length > 1) {
else if (rows.length > 1) {
showAlertDialog(_("Please select only one message to print."));
}
else
@ -531,7 +547,7 @@ function toggleAddressColumn(search, replace) {
function onMailboxMenuMove(event) {
var targetMailbox;
var messageList = $("messageListBody").down("TBODY");
var rows = messageList.getSelectedNodes();
var rowIds = messageList.getSelectedNodesId();
var uids = new Array(); // message IDs
var paths = new Array(); // row IDs
@ -543,10 +559,12 @@ function onMailboxMenuMove(event) {
else // from DnD
targetMailbox = this.readAttribute("dataname");
for (var i = 0; i < rows.length; i++) {
var uid = rows[i].readAttribute("id").substr(4);
for (var i = 0; i < rowIds.length; i++) {
var uid = rowIds[i].substr(4);
var path = Mailer.currentMailbox + "/" + uid;
rows[i].hide();
var rows = messageList.select('#' + rowIds[i]);
if (rows.length > 0)
rows.first().hide();
uids.push(uid);
paths.push(path);
// Remove references to closed popups
@ -576,7 +594,7 @@ function onMailboxMenuMove(event) {
function onMailboxMenuCopy(event) {
var messageList = $("messageListBody").down("TBODY");
var rows = messageList.getSelectedNodes();
var rowIds = messageList.getSelectedNodesId();
var uids = new Array(); // message IDs
var paths = new Array(); // row IDs
@ -585,8 +603,8 @@ function onMailboxMenuCopy(event) {
targetMailbox = this.mailbox.fullName();
else // from DnD
targetMailbox = this.readAttribute("dataname");
for (var i = 0; i < rows.length; i++) {
var uid = rows[i].readAttribute("id").substr(4);
for (var i = 0; i < rowIds.length; i++) {
var uid = rowIds[i].substr(4);
var path = Mailer.currentMailbox + "/" + uid;
uids.push(uid);
paths.push(path);
@ -2099,9 +2117,7 @@ function onMenuEmptyTrash(event) {
triggerAjaxRequest(urlstr, folderOperationCallback, errorLabel);
if (folderID == Mailer.currentMailbox) {
var div = $('messageContent');
for (var i = div.childNodes.length - 1; i > -1; i--)
div.removeChild(div.childNodes[i]);
$('messageContent').update();
}
var msgID = Mailer.currentMessages[folderID];
if (msgID)
@ -2230,6 +2246,7 @@ function folderRefreshCallback(http) {
var oldMailbox = http.callbackData.mailbox;
if (http.callbackData.refresh
&& oldMailbox == Mailer.currentMailbox) {
getUnseenCountForFolder(oldMailbox);
if (http.callbackData.id) {
var s = http.callbackData.id + "";
var uids = s.split(",");
@ -2248,7 +2265,8 @@ function folderRefreshCallback(http) {
var uids = s.split(",");
for (var i = 0; i < uids.length; i++) {
var row = $("row_" + uids[i]);
row.show();
if (row)
row.show();
}
}
showAlertDialog(_("Operation failed"));
@ -2622,7 +2640,7 @@ function startDragging (itm, e) {
var handle = $("dragDropVisual");
var count = $("messageListBody").getSelectedRowsId().length;
handle.update (count);
handle.update(count);
if (Mailer.currentMailbox) {
var parts = Mailer.currentMailbox.split("/");
handle.addClassName("account" + parts[1]);

View File

@ -33,9 +33,51 @@ var SOGoDataTableInterface = {
this.body = this.down("tbody");
this.rowModel = this.body.down("tr");
/**
* Overrided methods from HTMLElement.js
* Handle selection based on rows ID.
*/
this.body.selectRange = function(startIndex, endIndex) {
var element = $(this);
var s;
var e;
var rows;
var div = this.up('div');
var uid = lastClickedRowId.substr(4);
startIndex = div.dataSource.indexOf(uid);
uid = div.down('tr', endIndex).id.substr(4);
endIndex = div.dataSource.indexOf(uid);
if (startIndex > endIndex) {
s = endIndex;
e = startIndex;
}
else {
s = startIndex;
e = endIndex;
}
while (s <= e) {
uid = "row_" + div.dataSource.uids[s];
if (this.selectedIds.indexOf(uid) < 0)
this.selectedIds.push(uid);
s++;
}
this.refreshSelectionByIds();
};
this.body.selectAll = function() {
var div = this.up('div');
this.selectedIds = new Array();
for (var i = 0; i < div.dataSource.uids.length; i++)
this.selectedIds.push("row_" + div.dataSource.uids[i]);
this.refreshSelectionByIds();
},
// Since we use the fixed table layout, the first row must have the
// proper CSS classes that will define the columns width.
this.rowTop = new Element('tr', {'id': 'rowTop'});//.update(new Element('td'));
this.rowTop = new Element('tr', {'id': 'rowTop'});
this.body.insertBefore(this.rowTop, this.rowModel); // IE requires the element to be inside the DOM before appending new children
var cells = this.rowModel.select('TD');
for (var i = 0; i < cells.length; i++) {
@ -60,6 +102,7 @@ var SOGoDataTableInterface = {
setSource: function(ds) {
this.dataSource = ds;
this.currentRenderID = "";
this._emptyTable();
this.scrollTop = 0;
},
@ -135,7 +178,6 @@ var SOGoDataTableInterface = {
var scroll;
scroll = this.scrollTop;
lastClickedRow = -1; // defined in generic.js
h = start * this.rowHeight;
if (Prototype.Browser.IE)

View File

@ -3,7 +3,7 @@
var listFilter = 'view_today';
var listOfSelection = null;
var selectedCalendarCell;
var selectedCalendarCell = null;
var showCompletedTasks;
@ -32,6 +32,9 @@ var calendarHeaderAdjusted = false;
var categoriesStyles = new Hash();
var categoriesStyleSheet = null;
var clipboard = null;
var eventsToCopy = [];
function newEvent(type, day, hour, duration) {
var folder = getSelectedFolder();
var folderID = folder.readAttribute("id");
@ -129,7 +132,7 @@ function getSelectedFolder() {
if (nodes.length > 0)
folder = nodes[0];
else
folder = list.down("li");
folder = list.down("li"); // personal calendar
return folder;
}
@ -198,10 +201,6 @@ function deleteEvent() {
var nodes = listOfSelection.getSelectedRows();
if (nodes.length > 0) {
var label = "";
if (!nodes[0].erasable && !IsSuperUser) {
showAlertDialog(_("You don't have the required privileges to perform the operation."));
return false;
}
if (listOfSelection == $("tasksList"))
label = _("taskDeleteConfirmation");
else
@ -209,17 +208,18 @@ function deleteEvent() {
if (nodes.length == 1
&& nodes[0].recurrenceTime) {
_editRecurrenceDialog(nodes[0], "confirmDeletion");
if (nodes[0].erasable)
_editRecurrenceDialog(nodes[0], "confirmDeletion");
else
showAlertDialog(_("You don't have the required privileges to perform the operation."));
}
else {
if (confirm(label)) {
if (document.deleteEventAjaxRequest) {
document.deleteEventAjaxRequest.aborted = true;
document.deleteEventAjaxRequest.abort();
}
var sortedNodes = [];
var calendars = [];
for (var i = 0; i < nodes.length; i++) {
var canDelete;
var sortedNodes = [];
var calendars = [];
for (var i = 0; i < nodes.length; i++) {
canDelete = nodes[i].erasable || IsSuperUser;
if (canDelete) {
var calendar = nodes[i].calendar;
if (!sortedNodes[calendar]) {
sortedNodes[calendar] = [];
@ -227,32 +227,34 @@ function deleteEvent() {
}
sortedNodes[calendar].push(nodes[i].cname);
}
for (var i = 0; i < calendars.length; i++) {
calendarsOfEventsToDelete.push(calendars[i]);
eventsToDelete.push(sortedNodes[calendars[i]]);
}
_batchDeleteEvents();
}
for (i = 0; i < calendars.length; i++) {
calendarsOfEventsToDelete.push(calendars[i]);
eventsToDelete.push(sortedNodes[calendars[i]]);
}
if (i > 0)
showConfirmDialog(_("Warning"), label, deleteEventFromListConfirm);
else
showAlertDialog(_("You don't have the required privileges to perform the operation."));
}
} else {
showAlertDialog(_("Please select an event or a task."));
}
else
showAlertDialog(_("Please select an event or a task."));
}
else if (selectedCalendarCell) {
if (selectedCalendarCell.length == 1
&& selectedCalendarCell[0].recurrenceTime) {
_editRecurrenceDialog(selectedCalendarCell[0], "confirmDeletion");
if (selectedCalendarCell[0].erasable)
_editRecurrenceDialog(selectedCalendarCell[0], "confirmDeletion");
else
showAlertDialog(_("You don't have the required privileges to perform the operation."));
}
else if (confirm(_("eventDeleteConfirmation"))) {
if (document.deleteEventAjaxRequest) {
document.deleteEventAjaxRequest.aborted = true;
document.deleteEventAjaxRequest.abort();
}
var canDelete = true;
else {
var canDelete;
var sortedNodes = [];
var calendars = [];
for (var i = 0; i < selectedCalendarCell.length; i++) {
canDelete = canDelete && (selectedCalendarCell[i].erasable || IsSuperUser);
canDelete = selectedCalendarCell[i].erasable || IsSuperUser;
if (canDelete) {
var calendar = selectedCalendarCell[i].calendar;
if (!sortedNodes[calendar]) {
@ -263,11 +265,14 @@ function deleteEvent() {
}
}
for (var i = 0; i < calendars.length; i++) {
for (i = 0; i < calendars.length; i++) {
calendarsOfEventsToDelete.push(calendars[i]);
eventsToDelete.push(sortedNodes[calendars[i]]);
}
_batchDeleteEvents();
if (i > 0)
showConfirmDialog(_("Warning"), _("eventDeleteConfirmation"), deleteEventFromViewConfirm);
else
showAlertDialog(_("You don't have the required privileges to perform the operation."));
}
}
else
@ -276,6 +281,84 @@ function deleteEvent() {
return false;
}
function deleteEventFromListConfirm() {
var nodes = listOfSelection.getSelectedRows();
if (document.deleteEventAjaxRequest) {
document.deleteEventAjaxRequest.aborted = true;
document.deleteEventAjaxRequest.abort();
}
_batchDeleteEvents();
disposeDialog();
}
function deleteEventFromViewConfirm() {
if (document.deleteEventAjaxRequest) {
document.deleteEventAjaxRequest.aborted = true;
document.deleteEventAjaxRequest.abort();
}
selectedCalendarCell = null;
_batchDeleteEvents();
disposeDialog();
}
function copyEventToClipboard() {
if (listOfSelection) {
clipboard = new Array();
var nodes = listOfSelection.getSelectedRows();
for (var i = 0; i < nodes.length; i++)
clipboard.push(nodes[i].calendar + "/" + nodes[i].cname);
}
else if (selectedCalendarCell) {
clipboard = new Array();
for (var i = 0; i < selectedCalendarCell.length; i++)
clipboard.push(selectedCalendarCell[i].calendar + "/" + selectedCalendarCell[i].cname);
}
log ("clipboard : " + clipboard.join(", "));
}
function copyEventFromClipboard() {
if (clipboard && clipboard.length > 0) {
var folder = getSelectedFolder();
var folderID = folder.readAttribute("id").substr(1);
eventsToCopy = [];
for (var i = 0; i < clipboard.length; i++)
eventsToCopy[i] = clipboard[i] + "/copy?destination=" + folderID;
copyEvents();
}
}
function copyEventToPersonalCalendar(event) {
var calendar = selectedCalendarCell[0].calendar;
var cname = selectedCalendarCell[0].cname;
eventsToCopy = [calendar + "/" + cname + "/copy"];
copyEvents();
}
function copyEvents() {
var path = eventsToCopy.shift();
var urlstr = ApplicationBaseURL + path; log (urlstr);
triggerAjaxRequest(urlstr,
copyEventCallback);
}
function copyEventCallback(http) {
if (http.readyState == 4) {
if (isHttpStatus204(http.status)) {
if (eventsToCopy.length)
copyEvents();
else
refreshEventsAndDisplay();
}
else if (parseInt(http.status) == 403)
showAlertDialog(_("You don't have the required privileges to perform the operation."));
else if (parseInt(http.status) == 400)
showAlertDialog(_("DestinationCalendarError"));
else
showAlertDialog(_("EventCopyError"));
}
}
function modifyEvent(sender, modification, parameters) {
var currentLocation = '' + window.location;
var arr = currentLocation.split("/");
@ -1313,6 +1396,7 @@ function newBaseEventDIV(eventRep, event, eventText) {
eventCell.calendar = event[1];
if (eventRep.recurrenceTime)
eventCell.recurrenceTime = eventRep.recurrenceTime;
//eventCell.owner = event[12];
eventCell.isException = event[16];
eventCell.editable = event[17];
eventCell.erasable = event[18];
@ -1533,36 +1617,22 @@ function calendarDisplayCallback(http) {
currentDay = http.callbackData["day"];
// Initialize contextual menu
var menu;
var observer;
if (currentView == 'dayview') {
menu = new Array(onMenuNewEventClick,
var menu = new Array(onMenuNewEventClick,
onMenuNewTaskClick,
"-",
loadPreviousView,
loadNextView,
"-",
deleteEvent);
deleteEvent,
copyEventToPersonalCalendar);
var observer;
if (currentView == 'dayview') {
observer = $("daysView");
}
else if (currentView == 'weekview') {
menu = new Array(onMenuNewEventClick,
onMenuNewTaskClick,
"-",
loadPreviousView,
loadNextView,
"-",
deleteEvent);
observer = $("daysView");
}
else {
menu = new Array(onMenuNewEventClick,
onMenuNewTaskClick,
"-",
loadPreviousView,
loadNextView,
"-",
deleteEvent);
observer = $("monthDaysView");
}
@ -1588,8 +1658,10 @@ function calendarDisplayCallback(http) {
attachDragControllers(contentView);
// Attach contextual menu
initMenu($("currentViewMenu"), menu);
var currentViewMenu = $("currentViewMenu");
initMenu(currentViewMenu, menu);
observer.observe("contextmenu", onMenuCurrentView);
currentViewMenu.prepareVisibility = onMenuCurrentViewPrepareVisibility;
restoreSelectedDay();
@ -1654,12 +1726,20 @@ function onEventsSelectionChange() {
this.removeClassName("_unfocused");
$("tasksList").addClassName("_unfocused");
deselectAll(true);
var rows = $(this.tBodies[0]).getSelectedNodes();
if (rows.length == 1) {
var row = rows[0];
changeCalendarDisplay( { "day": row.day,
"scrollEvent": row.getAttribute("id") } );
changeDateSelectorDisplay(row.day);
changeDateSelectorDisplay(row.day, true);
}
else {
// Select visible events cells
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
selectCalendarEvent(row.calendar, row.cname, row.recurrenceTime);
}
}
}
@ -1862,8 +1942,9 @@ function selectCalendarEvent(calendar, cname, recurrenceTime) {
if (selection) {
for (var i = 0; i < selection.length; i++)
selection[i].selectElement();
if (selectedCalendarCell)
if (selectedCalendarCell) {
selectedCalendarCell = selectedCalendarCell.concat(selection);
}
else
selectedCalendarCell = selection;
}
@ -1894,8 +1975,18 @@ function onSelectAll(event) {
return false;
}
function deselectAll(cellsOnly) {
if (!cellsOnly && listOfSelection) {
listOfSelection.deselectAll();
}
if (selectedCalendarCell) {
for (var i = 0; i < selectedCalendarCell.length; i++)
selectedCalendarCell[i].deselect();
selectedCalendarCell = null;
}
}
function onCalendarSelectEvent(event) {
var list = $("eventsList").down("TBODY");
var alreadySelected = false;
// Look for event in events list
@ -1927,13 +2018,11 @@ function onCalendarSelectEvent(event) {
}
else if (event.shiftKey == 0) {
// Unselect entries in events list and calendar view
list.deselectAll();
if (selectedCalendarCell) {
for (var i = 0; i < selectedCalendarCell.length; i++)
if (selectedCalendarCell[i] != this)
selectedCalendarCell[i].deselect();
}
selectedCalendarCell = [this];
listOfSelection = $("eventsList");
deselectAll();
this.selectElement();
if (alreadySelected)
selectedCalendarCell = [this];
}
if (!alreadySelected) {
@ -1951,10 +2040,21 @@ function onCalendarSelectEvent(event) {
function onCalendarSelectDay(event) {
var day = this.getAttribute("day");
setSelectedDayDate(day);
var needRefresh = (listFilter == 'view_selectedday' && day != currentDay);
changeDateSelectorDisplay(day);
var target = Event.findElement(event);
var div = target.up('div');
if (div && !div.hasClassName('event') && !div.hasClassName('eventInside') && !div.hasClassName('text') && !div.hasClassName('gradient')) {
// Target is not an event -- unselect all events.
listOfSelection = $("eventsList");
deselectAll();
listOfSelection = null;
preventDefault(event);
return false;
}
var needRefresh = (listFilter == 'view_selectedday' && day != currentDay);
if (listOfSelection) {
listOfSelection.addClassName("_unfocused");
listOfSelection = null;
@ -2170,6 +2270,26 @@ function onCalendarsMenuPrepareVisibility() {
return false;
}
function onMenuCurrentViewPrepareVisibility() {
var options = $(this).down("ul");
var deleteOption = options.down("li", 6);
var copyOption = options.down("li", 7);
if (!selectedCalendarCell) {
deleteOption.addClassName("disabled");
copyOption.addClassName("disabled");
}
else {
deleteOption.removeClassName("disabled");
var calendarEntry = $("/" + selectedCalendarCell[0].calendar);
if (calendarEntry.getAttribute("owner") == UserLogin)
copyOption.addClassName("disabled");
else
copyOption.removeClassName("disabled");
}
return true;
}
function getMenus() {
var menus = {};
@ -2245,10 +2365,11 @@ function onMenuSharing(event) {
function onMenuCurrentView(event) {
$("eventDialog").hide();
var onClick = onCalendarSelectEvent.bind(this);
onClick(event);
if (this.hasClassName('event')) {
var onClick = onCalendarSelectEvent.bind(this);
onClick(event);
}
popupMenu(event, 'currentViewMenu', this);
}
function onMenuAllDayView(event) {
@ -2728,6 +2849,14 @@ function onDocumentKeydown(event) {
onSelectAll(event);
Event.stop(event);
}
else if (((isMac() && event.metaKey == 1) || (!isMac() && event.ctrlKey == 1))
&& event.keyCode == 67) { // Ctrl-C
copyEventToClipboard();
}
else if (((isMac() && event.metaKey == 1) || (!isMac() && event.ctrlKey == 1))
&& event.keyCode == 86) { // Ctrl-V
copyEventFromClipboard();
}
}
}

View File

@ -33,6 +33,7 @@ var dialogActive = false;
var dialogsStack = new Array();
var lastClickedRow = -1;
var lastClickedRowId = -1;
// logArea = null;
var allDocumentElements = null;
@ -552,10 +553,10 @@ function onRowClick(event) {
return true;
}
var initialSelection = $(node.parentNode).getSelectedNodes();
var initialSelection = $(node.parentNode).getSelectedNodesId();
if (initialSelection.length > 0
&& initialSelection.indexOf(node) >= 0
if (initialSelection && initialSelection.length > 0
&& initialSelection.indexOf(node.id) >= 0
&& !eventIsLeftClick(event))
// Ignore non primary-click (ie right-click) inside current selection
return true;
@ -578,7 +579,7 @@ function onRowClick(event) {
$(node.parentNode).deselectAll();
$(node).selectElement();
if (initialSelection != $(node.parentNode).getSelectedNodes()) {
if (initialSelection != $(node.parentNode).getSelectedNodesId()) {
// Selection has changed; fire mousedown event
var parentNode = node.parentNode;
if (parentNode.tagName == 'TBODY')
@ -586,8 +587,10 @@ function onRowClick(event) {
parentNode.fire("mousedown");
}
}
if (rowIndex != null)
lastClickedRow = rowIndex;
if (rowIndex != null) {
lastClickedRow = rowIndex;
lastClickedRowId = node.getAttribute("id");
}
return true;
}