Monotone-Parent: 044582e9ad4ddb9d86e36c14f35c91195c979b7c

Monotone-Revision: 8f6b1948a4de37d255b2c1ab1d3f1baa780f455d

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2010-05-06T19:30:14
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2010-05-06 19:30:14 +00:00
parent 861190b68f
commit 320e9256d1
21 changed files with 227 additions and 10 deletions

View File

@ -1,3 +1,29 @@
2010-05-06 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Tests/Integration/test-caldav-scheduling.py
(CalDAVPropertiesTest): new class for testing caldav-specific
properties
(CalDAVPropertiesTest.testDavScheduleCalendarTransparency): new
test method for testing "schedule-calendar-transp".
* UI/Scheduler/UIxCalendarProperties.m (-includeFreeBusy)
(-setIncludeFreeBusy): new template accessors for the equivalent
methods below.
(-userIsOwner): new accessor that returns whether the current user
is the calendar's owner.
* SoObjects/Appointments/SOGoFreeBusyObject.m
(-fetchFreeBusyInfosFrom:to:): test whether the listed calendars
must be included in the freebusy.
* SoObjects/Appointments/SOGoAppointmentFolder.m
(-setIncludeInFreeBusy, -includeInFreeBusy): new accessors that
determines whether the current calendar is included in the
computing of its owner's freebusy.
(-davScheduleCalendarTransparency)
(-setDavScheduleCalendarTransparency:): equivalent DAV accessors
for the above.
2010-05-05 Francis Lachapelle <flachapelle@inverse.ca>
* UI/WebServerResources/SchedulerUI.js (tasksListCallback):

View File

@ -7812,16 +7812,17 @@ Index: sope-appserver/NGObjWeb/DAVPropMap.plist
===================================================================
--- sope-appserver/NGObjWeb/DAVPropMap.plist (revision 1664)
+++ sope-appserver/NGObjWeb/DAVPropMap.plist (working copy)
@@ -157,6 +157,8 @@
@@ -157,6 +157,9 @@
"{urn:ietf:params:xml:ns:caldav}supported-calendar-data" =
davSupportedCalendarDataTypes;
"{urn:ietf:params:xml:ns:caldav}calendar-description" = davDescription;
+ "{urn:ietf:params:xml:ns:caldav}calendar-timezone" = davCalendarTimeZone;
+ "{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL" = davScheduleDefaultCalendarURL;
+ "{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp" = davScheduleCalendarTransparency;
/* CardDAV */
"{urn:ietf:params:xml:ns:carddav}addressbook-home-set" = davAddressbookHomeSet;
@@ -168,6 +170,8 @@
@@ -168,6 +171,8 @@
"{http://calendarserver.org/ns/}dropbox-home-URL" = davDropboxHomeURL;
"{http://calendarserver.org/ns/}notifications-URL" = davNotificationsURL;
"{http://calendarserver.org/ns/}getctag" = davCollectionTag;

View File

@ -156,6 +156,9 @@ typedef enum {
- (BOOL) synchronizeCalendar;
- (void) setSynchronizeCalendar: (BOOL) new;
- (BOOL) includeInFreeBusy;
- (void) setIncludeInFreeBusy: (BOOL) newInclude;
- (BOOL) importComponent: (iCalEntityObject *) event;
- (int) importCalendar: (iCalCalendar *) calendar;

View File

@ -396,6 +396,26 @@ static NSNumber *sharedYes = nil;
inCategory: @"FolderSynchronize"];
}
- (BOOL) includeInFreeBusy
{
NSNumber *excludeFromFreeBusy;
excludeFromFreeBusy
= [self folderPropertyValueInCategory: @"FreeBusyExclusions"];
return ![excludeFromFreeBusy boolValue];
}
- (void) setIncludeInFreeBusy: (BOOL) newInclude
{
NSNumber *excludeFromFreeBusy;
excludeFromFreeBusy = [NSNumber numberWithBool: !newInclude];
[self setFolderPropertyValue: excludeFromFreeBusy
inCategory: @"FreeBusyExclusions"];
}
/* selection */
- (NSArray *) calendarUIDs
@ -2285,6 +2305,34 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
return @"";
}
- (NSArray *) davScheduleCalendarTransparency
{
const NSString *opacity;
opacity = ([self includeInFreeBusy] ? @"opaque" : @"transparent");
return [NSArray arrayWithObject: [NSArray arrayWithObjects: opacity,
XMLNS_CALDAV,
nil]];
}
- (NSException *) setDavScheduleCalendarTransparency: (id) newName
{
NSException *error;
error = nil;
if ([newName rangeOfString: @"opaque"].location != NSNotFound)
[self setIncludeInFreeBusy: YES];
else if ([newName rangeOfString: @"transparent"].location != NSNotFound)
[self setIncludeInFreeBusy: NO];
else
error = [NSException exceptionWithHTTPStatus: 400
reason: @"Bad transparency value."];
return error;
}
/* vevent UID handling */
- (NSString *) resourceNameForEventUID: (NSString *) uid

View File

@ -254,9 +254,9 @@
for (count = 0; count < max; count++)
{
calFolder = [folders objectAtIndex: count];
if (![calFolder isSubscription])
if (![calFolder isSubscription] && [calFolder includeInFreeBusy])
[infos addObjectsFromArray: [calFolder fetchFreeBusyInfosFrom: startDate
to: endDate]];
to: endDate]];
}
return infos;

View File

@ -37,6 +37,88 @@ def fetchUserInfo(login):
return (displayName, email_nodes[0].childNodes[0].nodeValue)
class CalDAVPropertiesTest(unittest.TestCase):
def setUp(self):
self.client = webdavlib.WebDAVClient(hostname, port,
username, password)
self.test_calendar \
= "/SOGo/dav/%s/Calendar/test-dav-properties/" % username
mkcol = webdavlib.WebDAVMKCOL(self.test_calendar)
self.client.execute(mkcol)
def tearDown(self):
delete = webdavlib.WebDAVDELETE(self.test_calendar)
self.client.execute(delete)
def testDavScheduleCalendarTransparency(self):
"""{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp"""
## PROPFIND
propfind = webdavlib.WebDAVPROPFIND(self.test_calendar,
["{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp"],
0)
self.client.execute(propfind)
propfind.xpath_namespace = { "D": "DAV:",
"C": "urn:ietf:params:xml:ns:caldav" }
propstats = propfind.xpath_evaluate('/D:multistatus/D:response/D:propstat/D:prop/C:schedule-calendar-transp')
self.assertTrue(len(propstats) > 0,
"schedule-calendar-transp not present in response")
node = propstats[0]
status = propfind.xpath_evaluate('D:status',
node.parentNode.parentNode)[0] \
.childNodes[0].nodeValue[9:12]
self.assertEquals(status, "200",
"schedule-calendar-transp marked as 'Not Found' in response")
values = node.childNodes
nvalues = len(values)
self.assertEquals(nvalues, 1,
"expected 1 value (%d received)" % nvalues)
value = values[0]
self.assertEquals(value.__class__.__name__, "Element",
"schedule-calendar-transp must be an instance of" \
" %s, not %s"
% ("Element", value.__class__.__name__))
self.assertEquals(value.namespaceURI, "urn:ietf:params:xml:ns:caldav",
"schedule-calendar-transp must have a value in"\
" namespace '%s', not '%s'"
% ("urn:ietf:params:xml:ns:caldav",
value.namespaceURI))
self.assertTrue(value.tagName == "opaque",
"schedule-calendar-transp must be 'opaque' on new" \
" collections, not '%s'" % value.tagName)
## PROPPATCH
newValueNode = "{urn:ietf:params:xml:ns:caldav}thisvaluedoesnotexist"
proppatch = webdavlib.WebDAVPROPPATCH(self.test_calendar,
{"{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp": \
{ newValueNode: True }})
self.client.execute(proppatch)
self.assertEquals(proppatch.response["status"], 400,
"expecting failure when setting transparency to" \
" an invalid value")
newValueNode = "{urn:ietf:params:xml:ns:caldav}transparent"
proppatch = webdavlib.WebDAVPROPPATCH(self.test_calendar,
{"{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp": \
{ newValueNode: True }})
self.client.execute(proppatch)
self.assertEquals(proppatch.response["status"], 207,
"failure (%s) setting transparency to" \
" 'transparent': '%s'"
% (proppatch.response["status"],
proppatch.response["body"]))
newValueNode = "{urn:ietf:params:xml:ns:caldav}opaque"
proppatch = webdavlib.WebDAVPROPPATCH(self.test_calendar,
{"{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp": \
{ newValueNode: True }})
self.client.execute(proppatch)
self.assertEquals(proppatch.response["status"], 207,
"failure (%s) setting transparency to" \
" 'transparent': '%s'"
% (proppatch.response["status"],
proppatch.response["body"]))
class CalDAVITIPDelegationTest(unittest.TestCase):
def setUp(self):
self.client = webdavlib.WebDAVClient(hostname, port,

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Tarefa Confidencial)";
"Name:" = "Nome:";
"Color:" = "Cor:";
"Include in free-busy" = "Incluir na disponibilidade";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Marca:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Důvěrný úkol)";
"Name:" = "Název:";
"Color:" = "Barva:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synchronizace";
"Synchronize" = "Synchronizovat";
"Tag:" = "Štítek:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Vertrouwelijke taak)";
"Name:" = "Naam:";
"Color:" = "Kleur:";
"Include in free-busy" = "In de beschikbaarheid insluiten";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Markering:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Confidential task)";
"Name:" = "Name:";
"Color:" = "Color:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Tag:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Tâche confidentielle)";
"Name:" = "Nom :";
"Color:" = "Couleur :";
"Include in free-busy" = "Inclure dans la disponibilité";
"Synchronization" = "Synchronisation";
"Synchronize" = "Synchroniser";
"Tag:" = "Label :";
@ -521,12 +523,12 @@ vtodo_class2 = "(Tâche confidentielle)";
"Show tasks" = "Afficher les tâches";
/* Error messages */
"dayFieldInvalid" = "Veuillez spécifier un chiffre superieur ou égal à 1 dans le champ Jours.";
"weekFieldInvalid" = "Veuillez spécifier un chiffre superieur ou égal à 1 dans le champ Semaine(s).";
"monthFieldInvalid" = "Veuillez spécifier un chiffre superieur ou égal à 1 dans le champ Mois.";
"monthDayFieldInvalid" = "Veuillez spécifier un chiffre superieur ou égal à 1 dans la journée du mois.";
"yearFieldInvalid" = "Veuillez spécifier un chiffre superieur ou égal à 1 dans le champ Année(s).";
"appointmentFieldInvalid" = "Veuillez spécifier un chiffre superieur ou égal à 1 dans le champ rendez-vous.";
"dayFieldInvalid" = "Veuillez spécifier un chiffre supérieur ou égal à 1 dans le champ Jours.";
"weekFieldInvalid" = "Veuillez spécifier un chiffre supérieur ou égal à 1 dans le champ Semaine(s).";
"monthFieldInvalid" = "Veuillez spécifier un chiffre supérieur ou égal à 1 dans le champ Mois.";
"monthDayFieldInvalid" = "Veuillez spécifier un chiffre supérieur ou égal à 1 dans la journée du mois.";
"yearFieldInvalid" = "Veuillez spécifier un chiffre supérieur ou égal à 1 dans le champ Année(s).";
"appointmentFieldInvalid" = "Veuillez spécifier un chiffre supérieur ou égal à 1 dans le champ rendez-vous.";
"recurrenceUnsupported" = "Ce type de récurrence n\\'est pas supporté.";
"tagNotDefined" = "Vous devez spécifier un label si vous désirez synchroniser ce calendrier.";
"tagAlreadyExists" = "Le label spécifié est déjà associé à un autre calendrier. Choisissez-en un autre.";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Vertrauliche Aufgabe)";
"Name:" = "Name:";
"Color:" = "Farbe:";
"Include in free-busy" = "In der Verfügbarkeit einschließen";
"Synchronization" = "Synchronisation";
"Synchronize" = "Synchronisieren";
"Tag:" = "Tag:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Bizalmas feladat)";
"Name:" = "Név:";
"Color:" = "Szín:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Cimke:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Attività confidenziale)";
"Name:" = "Nome:";
"Color:" = "Colore:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Etichetta:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Confidential task)";
"Name:" = "Название:";
"Color:" = "Цвет:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Tag:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Tarea confidencial)";
"Name:" = "Nombre:";
"Color:" = "Color:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Redacción:";

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Konfidentiell uppgift)";
"Name:" = "Namn:";
"Color:" = "Färg:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synkronisering";
"Synchronize" = "Synkronisera";
"Tag:" = "Etikett:";

View File

@ -70,6 +70,16 @@
[calendar setCalendarColor: newColor];
}
- (BOOL) includeInFreeBusy
{
return [calendar includeInFreeBusy];
}
- (void) setIncludeInFreeBusy: (BOOL) newInclude
{
[calendar setIncludeInFreeBusy: newInclude];
}
- (BOOL) synchronizeCalendar
{
return [self mustSynchronize] || [calendar synchronizeCalendar];
@ -177,6 +187,15 @@
return rc;
}
- (BOOL) userIsOwner
{
NSString *userLogin;
userLogin = [[context activeUser] login];
return ([userLogin isEqualToString: [calendar ownerInContext: context]]);
}
- (BOOL) isWebCalendar
{
return ([calendar isKindOfClass: [SOGoWebAppointmentFolder class]]);

View File

@ -512,6 +512,8 @@ vtodo_class2 = "(Tasg gyhoeddus)";
"Name:" = "Enw:";
"Color:" = "Lliw:";
"Include in free-busy" = "Include in free-busy";
"Synchronization" = "Synchronization";
"Synchronize" = "Synchronize";
"Tag:" = "Tag:";

View File

@ -37,6 +37,16 @@
id="calendarColor"
var:value="calendarColor"
/></span></div>
<var:if condition="userIsOwner"
><div
><label><input type="checkbox" const:class="checkBox"
name="includeInFreeBusy"
id="includeInFreeBusy"
var:checked="includeInFreeBusy"
/><var:string label:value="Include in free-busy"
/></label
></div
></var:if>
</fieldset>
<fieldset>
<legend><var:string label:value="Synchronization"/></legend>

View File

@ -2167,6 +2167,10 @@ function onCalendarModify(event) {
isWebCalendar = true;
}
}
var owner = selected.getAttribute("owner");
if (owner == UserLogin) {
height += 24;
}
if (isWebCalendar)
height += 41;
else if (calendarID == "/personal")