CalDAV: more properties, hide WebCal support
WebCal entries, although permitted by the protocol, confuse some badly implemented CalDAV clients, so hide them with an option at the calendar definition. bzr revid: p_christ@hol.gr-20101012104044-rjx63ucwjk0ys98r
This commit is contained in:
parent
f7ce71c475
commit
95de197440
|
@ -24,6 +24,7 @@ from document_webdav import nodes
|
|||
from document.nodes import _str2time
|
||||
import logging
|
||||
import StringIO
|
||||
from orm_utils import get_last_modified
|
||||
|
||||
from tools.dict_tools import dict_merge, dict_merge2
|
||||
|
||||
|
@ -64,21 +65,24 @@ class node_calendar_collection(nodes.node_dir):
|
|||
for cal in fil_obj.browse(cr, uid, ids, context=ctx):
|
||||
if (not name) or not ext:
|
||||
res.append(node_calendar(cal.name, self, self.context, cal))
|
||||
if (not name) or ext:
|
||||
if cal.has_webcal and (not name) or ext:
|
||||
res.append(res_node_calendar(cal.name+'.ics', self, self.context, cal))
|
||||
# May be both of them!
|
||||
return res
|
||||
|
||||
def _get_dav_owner(self, cr):
|
||||
# Todo?
|
||||
return False
|
||||
|
||||
def _get_ttag(self, cr):
|
||||
return 'calen-dir-%d' % self.dir_id
|
||||
|
||||
def _get_dav_getctag(self, cr):
|
||||
result = self.get_etag(cr)
|
||||
return str(result)
|
||||
dirobj = self.context._dirobj
|
||||
uid = self.context.uid
|
||||
ctx = self.context.context.copy()
|
||||
ctx.update(self.dctx)
|
||||
where = [('collection_id','=',self.dir_id)]
|
||||
bc_obj = dirobj.pool.get('basic.calendar')
|
||||
|
||||
res = get_last_modified(bc_obj, cr, uid, where, context=ctx)
|
||||
return _str2time(res)
|
||||
|
||||
class node_calendar_res_col(nodes.node_res_obj):
|
||||
""" Calendar collection, as a dynamically created node
|
||||
|
@ -116,7 +120,7 @@ class node_calendar_res_col(nodes.node_res_obj):
|
|||
for cal in fil_obj.browse(cr, uid, ids, context=ctx):
|
||||
if (not name) or not ext:
|
||||
res.append(node_calendar(cal.name, self, self.context, cal))
|
||||
if (not name) or ext:
|
||||
if cal.has_webcal and (not name) or ext:
|
||||
res.append(res_node_calendar(cal.name+'.ics', self, self.context, cal))
|
||||
# May be both of them!
|
||||
return res
|
||||
|
@ -125,8 +129,15 @@ class node_calendar_res_col(nodes.node_res_obj):
|
|||
return 'calen-dir-%d' % self.dir_id
|
||||
|
||||
def _get_dav_getctag(self, cr):
|
||||
result = self.get_etag(cr)
|
||||
return str(result)
|
||||
dirobj = self.context._dirobj
|
||||
uid = self.context.uid
|
||||
ctx = self.context.context.copy()
|
||||
ctx.update(self.dctx)
|
||||
where = [('collection_id','=',self.dir_id)]
|
||||
bc_obj = dirobj.pool.get('basic.calendar')
|
||||
|
||||
res = get_last_modified(bc_obj, cr, uid, where, context=ctx)
|
||||
return _str2time(res)
|
||||
|
||||
class node_calendar(nodes.node_class):
|
||||
our_type = 'collection'
|
||||
|
@ -138,7 +149,9 @@ class node_calendar(nodes.node_class):
|
|||
"urn:ietf:params:xml:ns:caldav" : (
|
||||
'calendar-description',
|
||||
'supported-calendar-component-set',
|
||||
)}
|
||||
),
|
||||
"http://apple.com/ns/ical/": ("calendar-color", "calendar-order"),
|
||||
}
|
||||
DAV_PROPS_HIDDEN = {
|
||||
"urn:ietf:params:xml:ns:caldav" : (
|
||||
'calendar-data',
|
||||
|
@ -154,7 +167,9 @@ class node_calendar(nodes.node_class):
|
|||
# "http://cal.me.com/_namespace/": '_get_dav',
|
||||
'http://groupdav.org/': '_get_gdav',
|
||||
"http://calendarserver.org/ns/" : '_get_dav',
|
||||
"urn:ietf:params:xml:ns:caldav" : '_get_caldav'}
|
||||
"urn:ietf:params:xml:ns:caldav" : '_get_caldav',
|
||||
"http://apple.com/ns/ical/": '_get_apple_cal',
|
||||
}
|
||||
|
||||
http_options = { 'DAV': ['calendar-access'] }
|
||||
|
||||
|
@ -167,8 +182,12 @@ class node_calendar(nodes.node_class):
|
|||
self.content_length = 0
|
||||
self.displayname = calendar.name
|
||||
self.cal_type = calendar.type
|
||||
# TODO owner
|
||||
|
||||
self.cal_color = calendar.calendar_color or None
|
||||
self.cal_order = calendar.calendar_order or None
|
||||
try:
|
||||
self.uuser = (calendar.user_id and calendar.user_id.login) or 'nobody'
|
||||
except Exception:
|
||||
self.uuser = 'nobody'
|
||||
|
||||
def _get_dav_getctag(self, cr):
|
||||
dirobj = self.context._dirobj
|
||||
|
@ -186,8 +205,9 @@ class node_calendar(nodes.node_class):
|
|||
|
||||
def get_dav_resourcetype(self, cr):
|
||||
res = [ ('collection', 'DAV:'),
|
||||
('calendar', 'urn:ietf:params:xml:ns:caldav'),
|
||||
(str(self.cal_type + '-collection'), 'http://groupdav.org/'),
|
||||
('calendar', 'urn:ietf:params:xml:ns:caldav') ]
|
||||
]
|
||||
return res
|
||||
|
||||
def get_domain(self, cr, filters):
|
||||
|
@ -373,6 +393,12 @@ class node_calendar(nodes.node_class):
|
|||
|
||||
def _get_caldav_max_date_time(self, cr):
|
||||
return "21001231T235959Z" # I will be dead by then
|
||||
|
||||
def _get_apple_cal_calendar_color(self, cr):
|
||||
return self.cal_color
|
||||
|
||||
def _get_apple_cal_calendar_order(self, cr):
|
||||
return self.cal_order
|
||||
|
||||
class res_node_calendar(nodes.node_class):
|
||||
our_type = 'file'
|
||||
|
@ -445,7 +471,6 @@ class res_node_calendar(nodes.node_class):
|
|||
res = '%d' % (self.calendar_id)
|
||||
return res
|
||||
|
||||
|
||||
def rm(self, cr):
|
||||
uid = self.context.uid
|
||||
res = False
|
||||
|
|
|
@ -74,6 +74,9 @@
|
|||
<field name="type"/>
|
||||
<field name="user_id"/>
|
||||
<field name="collection_id" required="1"/>
|
||||
<field name="has_webcal" groups="base.group_extended" />
|
||||
<field name="calendar_color" groups="base.group_extended" />
|
||||
<field name="calendar_order" groups="base.group_extended" />
|
||||
<notebook colspan="4">
|
||||
<page string="Calendar Lines">
|
||||
<field name="line_ids" mode="form,tree" colspan="4" nolabel="1">
|
||||
|
|
|
@ -32,6 +32,7 @@ import tools
|
|||
import time
|
||||
import logging
|
||||
from caldav_node import res_node_calendar
|
||||
from orm_utils import get_last_modified
|
||||
from tools.safe_eval import safe_eval as eval
|
||||
|
||||
try:
|
||||
|
@ -552,33 +553,6 @@ class CalDAV(object):
|
|||
self.ical_reset('value')
|
||||
return res
|
||||
|
||||
if True: # we need this indentation level ;)
|
||||
|
||||
def get_last_modified(self, cr, user, args, context=None, access_rights_uid=None):
|
||||
"""Return the last modification date of objects in 'domain'
|
||||
This function has similar semantics to orm.search(), apart from the
|
||||
limit, offset and order arguments, which make no sense here.
|
||||
It is useful when we want to find if the table (aka set of records)
|
||||
has any modifications we should update at the client.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
self.pool.get('ir.model.access').check(cr, access_rights_uid or user, self._name, 'read', context=context)
|
||||
|
||||
query = self._where_calc(cr, user, args, context=context)
|
||||
self._apply_ir_rules(cr, user, query, 'read', context=context)
|
||||
from_clause, where_clause, where_clause_params = query.get_sql()
|
||||
|
||||
where_str = where_clause and (" WHERE %s" % where_clause) or ''
|
||||
|
||||
cr.execute('SELECT MAX(COALESCE("%s".write_date, "%s".create_date)) FROM ' % (self._table, self._table) +
|
||||
from_clause + where_str ,
|
||||
where_clause_params,
|
||||
debug=self._debug)
|
||||
res = cr.fetchall()
|
||||
return res[0][0]
|
||||
|
||||
|
||||
class Calendar(CalDAV, osv.osv):
|
||||
_name = 'basic.calendar'
|
||||
_calname = 'calendar'
|
||||
|
@ -607,6 +581,13 @@ class Calendar(CalDAV, osv.osv):
|
|||
'create_date': fields.datetime('Created Date', readonly=True),
|
||||
'write_date': fields.datetime('Modifided Date', readonly=True),
|
||||
'description': fields.text("description"),
|
||||
'calendar_color': fields.char('Color', size=20, help="For supporting clients, the color of the calendar entries"),
|
||||
'calendar_order': fields.integer('Order', help="For supporting clients, the order of this folder among the calendars"),
|
||||
'has_webcal': fields.boolean('WebCal', required=True, help="Also export a <name>.ics entry next to the calendar folder, with WebCal content."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'has_webcal': False,
|
||||
}
|
||||
|
||||
def get_calendar_objects(self, cr, uid, ids, parent=None, domain=None, context=None):
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2010 OpenERP SA (www.openerp.com)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
if True: # we need this indentation level ;)
|
||||
|
||||
def get_last_modified(self, cr, user, args, context=None, access_rights_uid=None):
|
||||
"""Return the last modification date of objects in 'domain'
|
||||
This function has similar semantics to orm.search(), apart from the
|
||||
limit, offset and order arguments, which make no sense here.
|
||||
It is useful when we want to find if the table (aka set of records)
|
||||
has any modifications we should update at the client.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
self.pool.get('ir.model.access').check(cr, access_rights_uid or user, self._name, 'read', context=context)
|
||||
|
||||
query = self._where_calc(cr, user, args, context=context)
|
||||
self._apply_ir_rules(cr, user, query, 'read', context=context)
|
||||
from_clause, where_clause, where_clause_params = query.get_sql()
|
||||
|
||||
where_str = where_clause and (" WHERE %s" % where_clause) or ''
|
||||
|
||||
cr.execute('SELECT MAX(COALESCE("%s".write_date, "%s".create_date)) FROM ' % (self._table, self._table) +
|
||||
from_clause + where_str ,
|
||||
where_clause_params,
|
||||
debug=self._debug)
|
||||
res = cr.fetchall()
|
||||
return res[0][0]
|
||||
|
||||
#eof
|
Loading…
Reference in New Issue