From 154f2dcead1e18ea3d854c2c6583ec5b789f847b Mon Sep 17 00:00:00 2001 From: helmutm Date: Mon, 20 Aug 2007 10:03:32 +0000 Subject: [PATCH] minor modifictaions and extensions for the tum.sm project git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1936 fd906abe-77d9-0310-91a1-e0d9ade77398 --- composer/schema/browser/common.py | 2 +- organize/browser/service.py | 55 +++++++++++++++++++++++++---- organize/interfaces.py | 2 ++ organize/service.py | 58 +++++++++++++++++++++++++++---- stateful/base.py | 4 +-- stateful/definition.py | 8 +++-- stateful/interfaces.py | 2 +- util/jeep.py | 12 +++++++ 8 files changed, 123 insertions(+), 20 deletions(-) diff --git a/composer/schema/browser/common.py b/composer/schema/browser/common.py index 1e1ddca..fb1fcb8 100644 --- a/composer/schema/browser/common.py +++ b/composer/schema/browser/common.py @@ -72,7 +72,7 @@ class BaseView(object): @Lazy def url(self): from zope.traversing.browser import absoluteURL - url = absoluteURL(self.context, self.request) + return absoluteURL(self.context, self.request) buttonActions = dict( submit_previous=getPreviousTemplate, diff --git a/organize/browser/service.py b/organize/browser/service.py index 25f9c6f..8197976 100644 --- a/organize/browser/service.py +++ b/organize/browser/service.py @@ -26,16 +26,27 @@ from zope import component from zope.cachedescriptors.property import Lazy from cybertools.organize.interfaces import IClientRegistrations, IRegistrationTemplate -from cybertools.composer.schema.browser.common import BaseView +from cybertools.composer.schema.browser.common import BaseView as SchemaBaseView from cybertools.composer.schema.interfaces import IClientFactory -class ServiceManagerView(object): +class BaseView(object): def __init__(self, context, request): self.context = context self.request = request + @Lazy + def url(self): + return self.getUrlForObject(self.context) + + def getUrlForObject(self, obj): + from zope.traversing.browser import absoluteURL + return absoluteURL(obj, self.request) + + +class ServiceManagerView(BaseView): + def findRegistrationTemplate(self, service): """ Find a registration template that provides the registration for the service given. @@ -46,18 +57,48 @@ class ServiceManagerView(object): return tpl return None + def overview(self): + result = [] + classific = [] + category = None + maxLevel = 0 + svcs = sorted(self.context.getServices(), + key=lambda x: (x.getCategory(), x.getClassification())) + for svc in svcs: + cat = svc.getCategory() + if cat != category: + result.append(dict(isHeadline=True, title=cat, level=0)) + category = cat + classific = [] + clsf = svc.getClassification() + for idx, element in enumerate(clsf): + level = idx + 1 + if (len(classific) <= idx or + classific[idx].name != element.name): + result.append(dict(isHeadline=True, title=element.title, + level=level)) + classific = clsf + if level > maxLevel: + maxLevel = level + result.append(dict(isHeadline=False, level=maxLevel+1, + title=svc.title or svc.getName(), + object=svc)) + return result -class ServiceView(object): - def __init__(self, context, request): - self.context = context - self.request = request +class ServiceView(BaseView): def getRegistrations(self): return self.context.registrations + def registrationUrl(self): + context = self.context + man = context.getManager() + tpl = ServiceManagerView(man, self.request).findRegistrationTemplate(context) + return self.getUrlForObject(tpl) -class RegistrationTemplateView(BaseView): + +class RegistrationTemplateView(SchemaBaseView): @Lazy def services(self): diff --git a/organize/interfaces.py b/organize/interfaces.py index e70583f..5654a40 100644 --- a/organize/interfaces.py +++ b/organize/interfaces.py @@ -141,6 +141,8 @@ class IService(Interface): """ A service that clients may register with. """ + title = Attribute('A descriptive but short title') + description = schema.Text( title=_(u'Description'), description=_(u'A brief description of the item.'), diff --git a/organize/service.py b/organize/service.py index 1cf1805..b0cbfab 100644 --- a/organize/service.py +++ b/organize/service.py @@ -29,6 +29,9 @@ from zope.component import adapts from zope.interface import implements from cybertools.composer.interfaces import IInstance from cybertools.composer.schema.interfaces import IClientManager, IClient +from cybertools.stateful.definition import registerStatesDefinition +from cybertools.stateful.definition import StatesDefinition +from cybertools.stateful.definition import State, Transition from cybertools.util.jeep import Jeep from cybertools.util.randomname import generateName @@ -87,11 +90,30 @@ class Service(object): registrationsFactory = OOBTree - def __init__(self, name=None, capacity=-1): - self.name = name + manager = None + category = None + + def __init__(self, name=None, title=u'', capacity=-1, **kw): + self.name = self.__name__ = name + self.title = title self.capacity = capacity if self.registrationsFactory is not None: self.registrations = self.registrationsFactory() + self.classification = [] + for k, v in kw.items(): + setattr(self, k, v) + + def getName(self): + return self.name + + def getManager(self): + return self.manager + + def getClassification(self): + return self.classification + + def getCategory(self): + return self.category @property def token(self): @@ -110,11 +132,12 @@ class Service(object): clientName = client.__name__ if clientName in self.registrations: return self.registrations[clientName] - if self.availableCapacity: - reg = Registration(client, self) - self.registrations[clientName] = reg - return reg - return None + reg = Registration(client, self) + self.registrations[clientName] = reg + return reg + #if self.availableCapacity: + # TODO: handle case when no capacity available - + # probably on 'submit' transition; UI feedback? def unregister(self, client): clientName = client.__name__ @@ -188,6 +211,27 @@ class ClientRegistrations(object): return getattr(self.context, self.registrationsAttributeName, []) +# registration states definition + +registerStatesDefinition( + StatesDefinition('organize.service.registration', + State('temporary', 'temporary', ('submit', 'cancel',)), + State('submitted', 'submitted', ('retract', 'setwaiting', 'confirm', 'reject',)), + State('cancelled', 'cancelled', ('submit',)), + State('retracted', 'retracted', ('submit',)), + State('waiting', 'waiting', ('retract', 'confirm', 'reject',)), + State('confirmed', 'confirmed', ('retract', 'reject',)), + State('rejected', 'rejected', ('retract', 'setwaiting', 'confirm',)), + Transition('cancel', 'Cancel registration', 'cancelled'), + Transition('submit', 'Submit registration', 'submitted'), + Transition('retract', 'Retract registration', 'retracted'), + Transition('setwaiting', 'Set on waiting list', 'waiting'), + Transition('confirm', 'Confirm registration', 'confirmed'), + Transition('reject', 'Reject registration', 'rejected'), + initialState='temporary', +)) + + # event handlers def clientRemoved(obj, event): diff --git a/stateful/base.py b/stateful/base.py index 0bbcd8b..c71a34a 100644 --- a/stateful/base.py +++ b/stateful/base.py @@ -62,12 +62,12 @@ class Stateful(object): class StatefulAdapter(Stateful): - """ An adapter for persistent objects to make the stateful. + """ An adapter for persistent objects to make them stateful. """ adapts(IPersistent) - statesAttributeName = '__states__' + statesAttributeName = '__stateful_states__' def __init__(self, context): self.context = context diff --git a/stateful/definition.py b/stateful/definition.py index 705aca0..a5eba54 100644 --- a/stateful/definition.py +++ b/stateful/definition.py @@ -33,20 +33,24 @@ class State(object): implements(IState) - def __init__(self, name, title, transitions): + def __init__(self, name, title, transitions, **kw): self.name = self.__name__ = name self.title = title self.transitions = transitions + for k, v in kw.items(): + setattr(self, k, v) class Transition(object): implements(ITransition) - def __init__(self, name, title, targetState): + def __init__(self, name, title, targetState, **kw): self.name = self.__name__ = name self.title = title self.targetState = targetState + for k, v in kw.items(): + setattr(self, k, v) class StatesDefinition(object): diff --git a/stateful/interfaces.py b/stateful/interfaces.py index 3ca7b2e..79102ae 100644 --- a/stateful/interfaces.py +++ b/stateful/interfaces.py @@ -60,7 +60,7 @@ class IStateful(Interface): def getAvailableTransitions(): """ Return the transitions for this object that are available in the current state. The implementation of the returned transition - objects is not specified, they may be an action dictionaries or + objects is not specified, they may be action dictionaries or special Transition objects. """ diff --git a/util/jeep.py b/util/jeep.py index c88dc01..9d90166 100644 --- a/util/jeep.py +++ b/util/jeep.py @@ -122,3 +122,15 @@ class Jeep(object): if idx < 0: raise ValueError('list.index(x): x not in list') return idx + + +class Term(object): + """ A simple name/title association that may be put in a jeep object. + """ + + def __init__(self, name, title, **kw): + self.name = self.__name__ = name + self.title = title + for k, v in kw.items(): + setattr(self, k, v) +