diff --git a/browser/common.py b/browser/common.py
index 641ee5f..1e400cb 100644
--- a/browser/common.py
+++ b/browser/common.py
@@ -613,16 +613,18 @@ class BaseView(GenericView, I18NView):
# states
+ viewStatesPermission = 'zope.ManageContent'
+
@Lazy
def states(self):
result = []
- if not checkPermission('loops.ManageSite', self.context):
- # TODO: replace by more sensible permission
+ if not checkPermission(self.viewStatesPermission, self.context):
return result
if IResource.providedBy(self.target):
statesDefs = self.globalOptions('organize.stateful.resource', ())
else:
- statesDefs = self.globalOptions('organize.stateful.concept', ())
+ statesDefs = (self.globalOptions('organize.stateful.concept', []) +
+ self.typeOptions('organize.stateful', []))
for std in statesDefs:
stf = component.getAdapter(self.target, IStateful, name=std)
result.append(stf)
diff --git a/browser/concept.py b/browser/concept.py
index 9265492..0c1fe97 100644
--- a/browser/concept.py
+++ b/browser/concept.py
@@ -505,9 +505,9 @@ class ConceptView(BaseView):
def getObjectActions(self, page=None, target=None):
acts = ['info']
- acts.extend('state.' + st.statesDefinition for st in self.states)
if self.globalOptions('organize.allowSendEmail'):
acts.append('send_email')
+ acts.extend('state.' + st.statesDefinition for st in self.states)
return actions.get('object', acts, view=self, page=page, target=target)
actions = dict(object=getObjectActions)
diff --git a/browser/concept_macros.pt b/browser/concept_macros.pt
index dd5e50b..5123243 100644
--- a/browser/concept_macros.pt
+++ b/browser/concept_macros.pt
@@ -116,7 +116,7 @@
|
Title |
- Type |
+ Type |
Modification Date |
Author(s) |
2011-01-10
|
Author |
-
diff --git a/browser/node.py b/browser/node.py
index 8c4ea1d..bbc975e 100644
--- a/browser/node.py
+++ b/browser/node.py
@@ -514,6 +514,12 @@ class NodeView(BaseView):
if target is not None:
return BaseView(target, self.request).url
+ @Lazy
+ def typeProvider(self):
+ if self.virtualTargetObject is not None:
+ return IType(self.virtualTargetObject).typeProvider
+ return None
+
# target viewing and editing support
def getUrlForTarget(self, target):
diff --git a/browser/skin/lobo/lobo.css b/browser/skin/lobo/lobo.css
index 98eee30..317bf01 100644
--- a/browser/skin/lobo/lobo.css
+++ b/browser/skin/lobo/lobo.css
@@ -387,7 +387,7 @@ div.menu-1, div.menu-2 {
.listing .object-actions {
float: none;
padding: 0;
- text-align: center;
+ /*text-align: center;*/
}
.icon-action {
diff --git a/data/loops_std.dmp b/data/loops_std.dmp
deleted file mode 100644
index 2cd4bc2..0000000
--- a/data/loops_std.dmp
+++ /dev/null
@@ -1,31 +0,0 @@
-type(u'classifier', u'Classifier', options=u'', typeInterface='loops.classifier.interfaces.IClassifier', viewName=u'classifier.html')
-type(u'documenttype', u'Document Type', options=u'', typeInterface=u'', viewName=u'')
-type(u'domain', u'Domain', options=u'', typeInterface=u'', viewName=u'')
-type(u'extcollection', u'External Collection', options=u'', typeInterface='loops.integrator.interfaces.IExternalCollection', viewName=u'collection.html')
-type(u'extfile', u'External File', options=u'', typeInterface='loops.interfaces.IExternalFile', viewName=u'')
-type(u'file', u'File', options=u'', typeInterface='loops.interfaces.IFile', viewName=u'')
-type(u'glossaryitem', u'Glossary Item', options=u'', typeInterface='loops.knowledge.interfaces.ITopic', viewName=u'glossaryitem.html')
-type(u'note', u'Note', options=u'', typeInterface='loops.interfaces.INote', viewName='note.html')
-type(u'person', u'Person', options=u'', typeInterface='loops.knowledge.interfaces.IPerson', viewName=u'')
-type(u'predicate', u'Predicate', options=u'', typeInterface=u'', viewName=u'')
-type(u'process', u'Prozess', options=u'', typeInterface=u'', viewName=u'')
-type(u'query', u'Query', options=u'', typeInterface='loops.expert.concept.IQueryConcept', viewName=u'')
-type(u'textdocument', u'Text', options=u'', typeInterface='loops.interfaces.ITextDocument', viewName=u'')
-type(u'topic', u'Topic', options=u'', typeInterface='loops.knowledge.interfaces.ITopic', viewName=u'')
-type(u'type', u'Type', options=u'', typeInterface='loops.interfaces.ITypeConcept', viewName=u'')
-concept(u'hasType', u'has Type', u'predicate')
-concept(u'ispartof', u'is Part of', u'predicate')
-concept(u'ownedby', u'owned by', u'predicate')
-concept(u'glossary', u'Glossary', u'query', options=u'', viewName=u'glossary.html')
-concept(u'search', u'Suche', u'query', options=u'', viewName=u'search')
-concept(u'standard', u'subobject', u'predicate')
-concept(u'general', u'General', u'domain')
-concept(u'system', u'System', u'domain')
-child(u'general', u'documenttype', u'standard')
-child(u'system', u'classifier', u'standard')
-child(u'system', u'extcollection', u'standard')
-node(u'home', u'Home', '', 'menu', body=u'Welcome\n=======')
-node(u'participants', u'Participants', u'home', 'page', body=u'Participants\n============', target=u'concepts/person', viewName=u'listchildren')
-node(u'topics', u'Topics', u'home', 'page', body=u'Topics\n======', target=u'concepts/topic', viewName=u'listchildren')
-node(u'glossary', u'Glossary', u'home', 'page', target=u'concepts/glossary')
-node(u'search', u'Search', u'home', 'page', target=u'concepts/search')
diff --git a/data/loops_std_de.dmp b/data/loops_std_de.dmp
index ba1ee19..a79d673 100644
--- a/data/loops_std_de.dmp
+++ b/data/loops_std_de.dmp
@@ -1,76 +1,59 @@
-type(u'query', u'Abfrage', options=u'', typeInterface='loops.expert.concept.IQueryConcept', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:03', created='2011-04-25T17:01')]
-type(u'task', u'Aufgabe', options=u'', typeInterface='loops.knowledge.interfaces.ITask', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:02', created='2011-04-25T17:01')]
-type(u'domain', u'Bereich', options=u'', typeInterface=u'', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:02', created='2011-04-25T17:01')]
-type(u'classifier', u'Classifier', options=u'', typeInterface='loops.classifier.interfaces.IClassifier', viewName=u'classifier.html')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'documenttype', u'Document Type', options=u'', typeInterface=u'', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'extcollection', u'External Collection', options=u'', typeInterface='loops.integrator.interfaces.IExternalCollection', viewName=u'collection.html')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'glossaryitem', u'Glossareintrag', options=u'', typeInterface='loops.knowledge.interfaces.ITopic', viewName=u'glossaryitem.html')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'media_asset', u'Media Asset', options=u'storage:varsubdir\nstorage_parameters:extfiles/sites_zzz\nasset_transform.minithumb: size(105)\nasset_transform.small: size(230)\nasset_transform.medium: size(480)', typeInterface='loops.media.interfaces.IMediaAsset', viewName=u'image_medium.html')[
- annotations(creators=(u'loops.admin',), modified='2011-07-27T12:00', created='2011-04-25T17:08')]
-type(u'note', u'Note', options=u'', typeInterface='loops.interfaces.INote', viewName='note.html')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'person', u'Person', options=u'', typeInterface='loops.knowledge.interfaces.IPerson', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'predicate', u'Predicate', options=u'', typeInterface=u'', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'event', u'Termin', options=u'', typeInterface='loops.organize.interfaces.ITask', viewName=u'task.html')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:12', created='2011-04-25T17:11')]
-type(u'textdocument', u'Text', options=u'', typeInterface='loops.interfaces.ITextDocument', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-type(u'topic', u'Thema', options=u'', typeInterface='loops.knowledge.interfaces.ITopic', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:03', created='2011-04-25T17:01')]
-type(u'type', u'Type', options=u'', typeInterface='loops.interfaces.ITypeConcept', viewName=u'')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'depends', u'depends', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'follows', u'follows', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'general', u'Allgemein', u'domain')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'glossary', u'Glossar', u'query', options=u'', viewName=u'glossary.html')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'hasType', u'has Type', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'ispartof', u'is Part of', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'knows', u'knows', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'ownedby', u'owned by', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'personal_info', u'Pers\xf6nliche Information', u'query', options=u'', viewName=u'personal_info.html')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:07', created='2011-04-25T17:07')]
-concept(u'provides', u'provides', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'querytarget', u'is Query Target', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'requires', u'requires', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'search', u'Suche', u'query', options=u'', viewName=u'search')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'standard', u'subobject', u'predicate')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-concept(u'system', u'System', u'domain')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
+type(u'query', u'Abfrage', options=u'',
+ typeInterface='loops.expert.concept.IQueryConcept', viewName=u'')
+type(u'task', u'Aufgabe', options=u'',
+ typeInterface='loops.knowledge.interfaces.ITask', viewName=u'')
+type(u'domain', u'Bereich', options=u'', typeInterface=u'', viewName=u'')
+type(u'classifier', u'Classifier', options=u'',
+ typeInterface='loops.classifier.interfaces.IClassifier', viewName=u'classifier.html')
+type(u'documenttype', u'Document Type', options=u'', typeInterface=u'', viewName=u'')
+type(u'extcollection', u'External Collection', options=u'',
+ typeInterface='loops.integrator.interfaces.IExternalCollection',
+ viewName=u'collection.html')
+type(u'glossaryitem', u'Glossareintrag', options=u'',
+ typeInterface='loops.knowledge.interfaces.ITopic', viewName=u'glossaryitem.html')
+type(u'media_asset', u'Media Asset',
+ options=u'storage:varsubdir\nstorage_parameters:extfiles/sites_zzz\nasset_transform.minithumb: size(105)\nasset_transform.small: size(230)\nasset_transform.medium: size(480)', typeInterface='loops.media.interfaces.IMediaAsset', viewName=u'image_medium.html')
+type(u'note', u'Note', options=u'', typeInterface='loops.interfaces.INote',
+ viewName='note.html')
+type(u'person', u'Person', options=u'',
+ typeInterface='loops.knowledge.interfaces.IPerson', viewName=u'')
+type(u'predicate', u'Predicate', options=u'',
+ typeInterface=u'loops.interfaces.IPredicate', viewName=u'')
+type(u'event', u'Termin', options=u'', typeInterface='loops.organize.interfaces.ITask',
+ viewName=u'task.html')
+type(u'textdocument', u'Text', options=u'', typeInterface='loops.interfaces.ITextDocument', viewName=u'')
+type(u'topic', u'Thema', options=u'', typeInterface='loops.knowledge.interfaces.ITopic',
+ viewName=u'')
+type(u'type', u'Type', options=u'', typeInterface='loops.interfaces.ITypeConcept',
+ viewName=u'')
+concept(u'depends', u'depends', u'predicate')
+concept(u'follows', u'follows', u'predicate')
+concept(u'general', u'Allgemein', u'domain')
+concept(u'glossary', u'Glossar', u'query', options=u'', viewName=u'glossary.html')
+concept(u'hasType', u'has Type', u'predicate')
+concept(u'ispartof', u'is Part of', u'predicate')
+concept(u'issubtype', u'is Subtype', u'predicate')
+concept(u'knows', u'knows', u'predicate')
+concept(u'ownedby', u'owned by', u'predicate')
+concept(u'personal_info', u'Pers\xf6nliche Information', u'query', options=u'',
+ viewName=u'personal_info.html')
+concept(u'provides', u'provides', u'predicate')
+concept(u'querytarget', u'is Query Target', u'predicate')
+concept(u'requires', u'requires', u'predicate')
+concept(u'search', u'Suche', u'query', options=u'', viewName=u'search')
+concept(u'standard', u'subobject', u'predicate')
+concept(u'system', u'System', u'domain')
child(u'general', u'documenttype', u'standard')
child(u'general', u'event', u'standard')
child(u'system', u'classifier', u'standard')
child(u'system', u'extcollection', u'standard')
+child(u'system', u'issubtype', u'standard')
child(u'system', u'media_asset', u'standard')
child(u'system', u'personal_info', u'standard')
-node(u'home', u'Startseite', '', 'menu', body=u'Willkommen\n==========')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-node(u'participants', u'Teilnehmer', u'home', 'page', body=u'Teilnehmer\n==========', target=u'concepts/person', viewName=u'listchildren')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-node(u'topics', u'Themen', u'home', 'page', body=u'Themen\n======', target=u'concepts/topic', viewName=u'listchildren')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-node(u'glossary', u'Glossar', u'home', 'page', target=u'concepts/glossary')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
-node(u'search', u'Suche', u'home', 'page', target=u'concepts/search')[
- annotations(creators=(u'loops.admin',), modified='2011-04-25T17:01', created='2011-04-25T17:01')]
+node(u'home', u'Startseite', '', 'menu', body=u'Willkommen\n==========')
+node(u'participants', u'Teilnehmer', u'home', 'page', body=u'Teilnehmer\n==========',
+ target=u'concepts/person', viewName=u'listchildren')
+node(u'topics', u'Themen', u'home', 'page', body=u'Themen\n======',
+ target=u'concepts/topic', viewName=u'listchildren')
+node(u'glossary', u'Glossar', u'home', 'page', target=u'concepts/glossary')
+node(u'search', u'Suche', u'home', 'page', target=u'concepts/search')
diff --git a/data/loops_std_en.dmp b/data/loops_std_en.dmp
new file mode 100644
index 0000000..a982ee7
--- /dev/null
+++ b/data/loops_std_en.dmp
@@ -0,0 +1,60 @@
+type(u'query', u'Query', options=u'',
+ typeInterface='loops.expert.concept.IQueryConcept', viewName=u'')
+type(u'task', u'Task', options=u'',
+ typeInterface='loops.knowledge.interfaces.ITask', viewName=u'')
+type(u'domain', u'Domain', options=u'', typeInterface=u'', viewName=u'')
+type(u'classifier', u'Classifier', options=u'',
+ typeInterface='loops.classifier.interfaces.IClassifier', viewName=u'classifier.html')
+type(u'documenttype', u'Document Type', options=u'', typeInterface=u'', viewName=u'')
+type(u'extcollection', u'External Collection', options=u'',
+ typeInterface='loops.integrator.interfaces.IExternalCollection',
+ viewName=u'collection.html')
+type(u'glossaryitem', u'Glossary Item', options=u'',
+ typeInterface='loops.knowledge.interfaces.ITopic', viewName=u'glossaryitem.html')
+type(u'media_asset', u'Media Asset',
+ options=u'storage:varsubdir\nstorage_parameters:extfiles/sites_zzz\nasset_transform.minithumb: size(105)\nasset_transform.small: size(230)\nasset_transform.medium: size(480)', typeInterface='loops.media.interfaces.IMediaAsset', viewName=u'image_medium.html')
+type(u'note', u'Note', options=u'', typeInterface='loops.interfaces.INote',
+ viewName='note.html')
+type(u'person', u'Person', options=u'',
+ typeInterface='loops.knowledge.interfaces.IPerson', viewName=u'')
+type(u'predicate', u'Predicate', options=u'',
+ typeInterface=u'loops.interfaces.IPredicate', viewName=u'')
+type(u'event', u'Event', options=u'', typeInterface='loops.organize.interfaces.ITask',
+ viewName=u'task.html')
+type(u'textdocument', u'Text', options=u'', typeInterface='loops.interfaces.ITextDocument', viewName=u'')
+type(u'topic', u'Topy', options=u'', typeInterface='loops.knowledge.interfaces.ITopic',
+ viewName=u'')
+type(u'type', u'Type', options=u'', typeInterface='loops.interfaces.ITypeConcept',
+ viewName=u'')
+concept(u'depends', u'depends', u'predicate')
+concept(u'follows', u'follows', u'predicate')
+concept(u'general', u'General', u'domain')
+concept(u'glossary', u'Glossary', u'query', options=u'', viewName=u'glossary.html')
+concept(u'hasType', u'has Type', u'predicate')
+concept(u'ispartof', u'is Part of', u'predicate')
+concept(u'issubtype', u'is Subtype', u'predicate')
+concept(u'knows', u'knows', u'predicate')
+concept(u'ownedby', u'owned by', u'predicate')
+concept(u'personal_info', u'Personal Information', u'query', options=u'',
+ viewName=u'personal_info.html')
+concept(u'provides', u'provides', u'predicate')
+concept(u'querytarget', u'is Query Target', u'predicate')
+concept(u'requires', u'requires', u'predicate')
+concept(u'search', u'Search', u'query', options=u'', viewName=u'search')
+concept(u'standard', u'subobject', u'predicate')
+concept(u'system', u'System', u'domain')
+child(u'general', u'documenttype', u'standard')
+child(u'general', u'event', u'standard')
+child(u'system', u'classifier', u'standard')
+child(u'system', u'extcollection', u'standard')
+child(u'system', u'issubtype', u'standard')
+child(u'system', u'media_asset', u'standard')
+child(u'system', u'personal_info', u'standard')
+node(u'home', u'Homepage', '', 'menu', body=u'Welcome\n=======)
+node(u'participants', u'Participants', u'home', 'page',
+ body=u'Participants\n============', target=u'concepts/person',
+ viewName=u'listchildren')
+node(u'topics', u'Topics', u'home', 'page', body=u'Topics\n======',
+ target=u'concepts/topic', viewName=u'listchildren')
+node(u'glossary', u'Glossary', u'home', 'page', target=u'concepts/glossary')
+node(u'search', u'Search', u'home', 'page', target=u'concepts/search')
diff --git a/organize/stateful/base.py b/organize/stateful/base.py
index faafcda..f6da53b 100644
--- a/organize/stateful/base.py
+++ b/organize/stateful/base.py
@@ -31,6 +31,7 @@ from cybertools.meta.interfaces import IOptions
from cybertools.stateful.base import Stateful as BaseStateful
from cybertools.stateful.base import StatefulAdapter, IndexInfo
from cybertools.stateful.interfaces import IStatesDefinition, ITransitionEvent
+from loops.common import adapted
from loops.interfaces import ILoopsObject, IConcept, IResource
from loops import util
@@ -65,8 +66,10 @@ class StatefulConceptIndexInfo(IndexInfo):
@property
def availableStatesDefinitions(self):
- options = IOptions(self.context.getLoopsRoot())
- return options('organize.stateful.concept', ())
+ globalOptions = IOptions(self.context.getLoopsRoot())
+ typeOptions = IOptions(adapted(self.context.conceptType))
+ return (globalOptions('organize.stateful.concept', []) +
+ typeOptions('organize.stateful', []))
class StatefulResourceIndexInfo(IndexInfo):
diff --git a/organize/stateful/browser.py b/organize/stateful/browser.py
index 1db6c49..1e4c49b 100644
--- a/organize/stateful/browser.py
+++ b/organize/stateful/browser.py
@@ -37,7 +37,8 @@ from loops.util import _
statefulActions = ('classification_quality',
- 'simple_publishing',)
+ 'simple_publishing',
+ 'task_states',)
class StateAction(Action):
diff --git a/organize/stateful/configure.zcml b/organize/stateful/configure.zcml
index 5bd50ab..e5cd542 100644
--- a/organize/stateful/configure.zcml
+++ b/organize/stateful/configure.zcml
@@ -35,6 +35,20 @@
set_schema="cybertools.stateful.interfaces.IStateful" />
+
+
+
+
+
+
+
+
diff --git a/organize/stateful/task.py b/organize/stateful/task.py
new file mode 100644
index 0000000..7a99273
--- /dev/null
+++ b/organize/stateful/task.py
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2012 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
+#
+
+"""
+Basic implementations for stateful objects and adapters.
+"""
+
+from zope import component
+from zope.component import adapter
+from zope.interface import implementer
+from zope.traversing.api import getName
+
+from cybertools.stateful.definition import StatesDefinition
+from cybertools.stateful.definition import State, Transition
+from cybertools.stateful.interfaces import IStatesDefinition, IStateful
+from loops.common import adapted
+from loops.organize.stateful.base import StatefulLoopsObject
+
+
+@implementer(IStatesDefinition)
+def taskStates():
+ return StatesDefinition('task_states',
+ State('planned', 'planned', ('finish', 'cancel'),
+ color='yellow'),
+ State('finished', 'finished', ('reopen'),
+ color='green'),
+ State('cancelled', 'cancelled', ('reopen'),
+ color='grey'),
+ Transition('finish', 'finish', 'finished'),
+ Transition('cancel', 'cancel', 'cancelled'),
+ Transition('reopen', 're-open', 'planned'),
+ initialState='planned')
+
+
+class StatefulTask(StatefulLoopsObject):
+
+ statesDefinition = 'task_states'
+
|