diff --git a/organize/browser/service.py b/organize/browser/service.py index 8197976..0b9757a 100644 --- a/organize/browser/service.py +++ b/organize/browser/service.py @@ -22,12 +22,16 @@ Basic browser view classes for composer.schema. $Id$ """ +from datetime import datetime +import time from zope import component from zope.cachedescriptors.property import Lazy from cybertools.organize.interfaces import IClientRegistrations, IRegistrationTemplate +from cybertools.organize.interfaces import serviceCategories from cybertools.composer.schema.browser.common import BaseView as SchemaBaseView from cybertools.composer.schema.interfaces import IClientFactory +from cybertools.util.format import formatDate class BaseView(object): @@ -44,6 +48,25 @@ class BaseView(object): from zope.traversing.browser import absoluteURL return absoluteURL(obj, self.request) + def getLanguage(self): + # TODO: take from request or whatever... + return 'en' + + def getFormattedDate(self, date=None, type='date', variant='medium'): + date = time.localtime(date)[:6] + date = datetime(*date) + return formatDate(date, type=type, variant=variant, lang=self.getLanguage()) + + def getFromTo(self, service=None): + if service is None: + service = self.context + if service.start and service.end: + return ('%s - %s' % + (self.getFormattedDate(service.start, type='dateTime', variant='short'), + self.getFormattedDate(service.end, type='time', variant='short'))) + else: + return '-' + class ServiceManagerView(BaseView): @@ -63,11 +86,15 @@ class ServiceManagerView(BaseView): category = None maxLevel = 0 svcs = sorted(self.context.getServices(), - key=lambda x: (x.getCategory(), x.getClassification())) + key=lambda x: (x.getCategory(), + x.getClassification(), + x.title)) for svc in svcs: cat = svc.getCategory() if cat != category: - result.append(dict(isHeadline=True, title=cat, level=0)) + term = serviceCategories.getTermByToken(cat) + result.append(dict(isHeadline=True, level=0, title=term.title, + object=None)) category = cat classific = [] clsf = svc.getClassification() @@ -75,13 +102,15 @@ class ServiceManagerView(BaseView): level = idx + 1 if (len(classific) <= idx or classific[idx].name != element.name): - result.append(dict(isHeadline=True, title=element.title, - level=level)) + result.append(dict(isHeadline=True, level=level, + title=element.title, + object=element.object)) classific = clsf if level > maxLevel: maxLevel = level result.append(dict(isHeadline=False, level=maxLevel+1, title=svc.title or svc.getName(), + fromTo=self.getFromTo(svc), object=svc)) return result diff --git a/organize/interfaces.py b/organize/interfaces.py index 5654a40..387af8d 100644 --- a/organize/interfaces.py +++ b/organize/interfaces.py @@ -22,10 +22,13 @@ Interfaces for organizational stuff like persons, addresses, tasks, services... $Id$ """ -from zope.interface import Interface, Attribute from zope import schema +from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm +from zope.interface import Interface, Attribute from zope.i18nmessageid import MessageFactory +from cybertools.util.jeep import Jeep, Term + _ = MessageFactory('zope') @@ -126,6 +129,15 @@ class IServiceManager(Interface): """ A manager or container for a set of services. """ + start = schema.Date( + title=_(u'Start date/time'), + description=_(u'The start date/time for providing services.'), + required=False,) + end = schema.Date( + title=_(u'End date/time'), + description=_(u'The end date/time for providing services.'), + required=False,) + services = Attribute('A collection of services managed by this object.') @@ -137,6 +149,11 @@ class IServiceGroup(Interface): services = Attribute('A collection of services belonging to this object.') +serviceCategories = SimpleVocabulary(( + SimpleTerm('event', 'event', u'Event'), + SimpleTerm('transport', 'transport', u'Transport'), +)) + class IService(Interface): """ A service that clients may register with. """ @@ -147,10 +164,12 @@ class IService(Interface): title=_(u'Description'), description=_(u'A brief description of the item.'), required=False,) - category = schema.TextLine( + category = schema.Choice( title=_(u'Category'), - description=_(u'A tokenized term characterizing the type of ' + description=_(u'The type of ' 'this service, e.g. an event or a transport.'), + vocabulary=serviceCategories, + default='event', required=False,) capacity = schema.Int( title=_(u'Capacity'), @@ -193,10 +212,12 @@ class IScheduledService(IService): title=_(u'Start date/time'), description=_(u'The date/time when the service starts'), required=False,) + start.default_method = 'getStartFromManager' end = schema.Date( title=_(u'End date/time'), description=_(u'The date/time when the service ends'), required=False,) + end.default_method = 'getEndFromManager' duration = Attribute('Time delta between start and end date/time.') diff --git a/organize/service.py b/organize/service.py index b0cbfab..48d27ef 100644 --- a/organize/service.py +++ b/organize/service.py @@ -149,6 +149,13 @@ class ScheduledService(Service): implements(IScheduledService) + start = end = None + + def getStartFromManager(self): + return getattr(self.getManager(), 'start', None) + def getEndFromManager(self): + return getattr(self.getManager(), 'end', None) + # registration diff --git a/util/format.py b/util/format.py new file mode 100644 index 0000000..9bd984a --- /dev/null +++ b/util/format.py @@ -0,0 +1,50 @@ +# +# Copyright (c) 2007 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Some simple standard formatting routines. + +$Id$ +""" + +from zope.i18n.locales import locales +from datetime import datetime + + +def nl2br(text): + if not text: return text + if '\n' in text: # Unix or DOS line endings + return '
\n'.join(x.replace('\r', '') for x in text.split('\n')) + else: # gracefully handle Mac line endigns + return '
\n'.join(text.split('\r')) + + +def formatDate(dt=None, type='date', variant='medium', lang='de'): + """ type: date, time, dateTime; + variant: full, long, medium, short. + """ + loc = locales.getLocale(lang) + fmt = loc.dates.getFormatter(type, variant) + return fmt.format(dt or datetime.now()) + + +def formatNumber(num, type='decimal', lang='de'): + loc = locales.getLocale(lang) + fmt = de.numbers.getFormatter(type) + return fmt.format(num) + diff --git a/util/format.txt b/util/format.txt new file mode 100644 index 0000000..3bb7fb2 --- /dev/null +++ b/util/format.txt @@ -0,0 +1,17 @@ +========================== +Basic Formatting Functions +========================== + +$Id$ + + >>> from cybertools.util import format + >>> from datetime import datetime + + >>> time = datetime(2006, 8, 21, 17, 37, 13) + + >>> format.formatDate(time, type='time', variant='medium') + u'17:37:13' + + >>> format.formatDate(time, type='dateTime', variant='medium') + u'21.08.2006 17:37:13' + diff --git a/util/jeep.py b/util/jeep.py index 9d90166..d1e8b61 100644 --- a/util/jeep.py +++ b/util/jeep.py @@ -32,9 +32,13 @@ class Jeep(object): def __init__(self, seq=[]): sequence = self._sequence = [] - for attr, value in seq: - sequence.append(attr) - object.__setattr__(self, attr, value) + for item in seq: + if isinstance(item, (list, tuple)) and len(item) == 2: + attr, value = item + sequence.append(attr) + object.__setattr__(self, attr, value) + else: + self.append(item) def __len__(self): return len(self._sequence) @@ -129,8 +133,11 @@ class Term(object): """ def __init__(self, name, title, **kw): - self.name = self.__name__ = name + self.name = self.__name__ = self.value = self.token = name self.title = title for k, v in kw.items(): setattr(self, k, v) + def __str__(self): + return self.title + diff --git a/util/tests.py b/util/tests.py index 621a6cc..8a42664 100755 --- a/util/tests.py +++ b/util/tests.py @@ -20,6 +20,7 @@ def test_suite(): #doctest.DocTestSuite(cybertools.util.property, optionflags=flags), doctest.DocFileSuite('adapter.txt', optionflags=flags), doctest.DocFileSuite('defer.txt', optionflags=flags), + doctest.DocFileSuite('format.txt', optionflags=flags), doctest.DocFileSuite('property.txt', optionflags=flags), doctest.DocFileSuite('jeep.txt', optionflags=flags), doctest.DocFileSuite('randomname.txt', optionflags=flags),