diff --git a/browser/common.py b/browser/common.py
index d6a9141..c224521 100644
--- a/browser/common.py
+++ b/browser/common.py
@@ -267,7 +267,10 @@ class BaseView(GenericView, I18NView):
def viewIterator(self, objs):
request = self.request
for o in objs:
- yield BaseView(o, request)
+ view = component.queryMultiAdapter((o, request), name='index.html')
+ if view is None:
+ view = BaseView(o, request)
+ yield view
def renderText(self, text, contentType):
typeKey = util.renderingFactories.get(contentType, None)
@@ -391,11 +394,10 @@ class BaseView(GenericView, I18NView):
if not checkPermission('loops.ManageSite', self.context):
# TODO: replace by more sensible permission
return result
- #statesDefs = ['loops.classification_quality', 'loops.simple_publishing']
if IResource.providedBy(self.target):
statesDefs = self.globalOptions('organize.stateful.resource', ())
else:
- statesDefs = ()
+ statesDefs = self.globalOptions('organize.stateful.concept', ())
for std in statesDefs:
stf = component.getAdapter(self.target, IStateful, name=std)
result.append(stf)
diff --git a/browser/form.py b/browser/form.py
index 37b967d..90e2b7d 100644
--- a/browser/form.py
+++ b/browser/form.py
@@ -111,8 +111,6 @@ class ObjectForm(NodeView):
@Lazy
def schema(self):
- #ti = self.typeInterface or IConceptSchema
- #schemaFactory = component.getAdapter(self.adapted, ISchemaFactory)
schemaFactory = ISchemaFactory(self.adapted)
return schemaFactory(self.typeInterface, manager=self,
request=self.request)
@@ -398,9 +396,7 @@ class EditObject(FormController, I18NView):
@Lazy
def schema(self):
- #schemaFactory = component.getAdapter(self.adapted, ISchemaFactory)
schemaFactory = ISchemaFactory(self.adapted)
- #return schemaFactory(self.typeInterface)
return schemaFactory(self.typeInterface, manager=self,
request=self.request)
diff --git a/expert/README.txt b/expert/README.txt
index e47ab3d..9c7eb7f 100644
--- a/expert/README.txt
+++ b/expert/README.txt
@@ -69,7 +69,7 @@ arguments, the name of the states definition and the state to search for.
As we have not yet set up any states definitions for our objects we get
an empty result.
- >>> qu = query.State('loops.classification_quality', 'classified')
+ >>> qu = query.State('classification_quality', 'classified')
>>> list(qu.apply())
[]
@@ -78,12 +78,12 @@ corresponding adapter and activate it for the current loops site.
>>> from loops.organize.stateful.quality import classificationQuality
>>> component.provideUtility(classificationQuality(),
- ... name='loops.classification_quality')
+ ... name='classification_quality')
>>> from loops.organize.stateful.quality import ClassificationQualityCheckable
>>> component.provideAdapter(ClassificationQualityCheckable,
- ... name='loops.classification_quality')
+ ... name='classification_quality')
- >>> loopsRoot.options = ['organize.stateful.resource:loops.classification_quality']
+ >>> loopsRoot.options = ['organize.stateful.resource:classification_quality']
We have now to reindex all documents so that the state index gets populated
according to the new settings.
@@ -97,7 +97,7 @@ according to the new settings.
Now the three documents we are working with are shown as classified (as
they have at least one concept assigned).
- >>> qu = query.State('loops.classification_quality', 'classified')
+ >>> qu = query.State('classification_quality', 'classified')
>>> list(qu.apply())
[23, 25, 27]
@@ -106,7 +106,7 @@ Using the stateful adapter for a resource we now manually execute the
>>> from cybertools.stateful.interfaces import IStateful
>>> statefulD001 = component.getAdapter(resources['d001.txt'], IStateful,
- ... name='loops.classification_quality')
+ ... name='classification_quality')
>>> statefulD001.doTransition('verify')
Now only two resources are still in the ``qualified`` state, the changed
@@ -114,13 +114,13 @@ one being in the ``verified`` state.
>>> list(qu.apply())
[25, 27]
- >>> qu = query.State('loops.classification_quality', 'verified')
+ >>> qu = query.State('classification_quality', 'verified')
>>> list(qu.apply())
[23]
We may also provide a sequence of states for querying.
- >>> qu = query.State('loops.classification_quality', ('classified', 'verified',))
+ >>> qu = query.State('classification_quality', ('classified', 'verified',))
>>> list(qu.apply())
[23, 25, 27]
diff --git a/expert/query.py b/expert/query.py
index 34b77cb..f7a0cec 100644
--- a/expert/query.py
+++ b/expert/query.py
@@ -31,7 +31,7 @@ from zope.component import adapts
from zope.interface import implements, implementer
from zope.cachedescriptors.property import Lazy
-from cybertools.catalog.query import Term, Eq, Between, Or
+from cybertools.catalog.query import Term, Eq, Between, And, Or
from cybertools.catalog.query import Text as BaseText
from cybertools.catalog.query import AnyOf
from loops.expert.interfaces import IQuery
diff --git a/organize/stateful/README.txt b/organize/stateful/README.txt
index 1be2694..7d737f2 100644
--- a/organize/stateful/README.txt
+++ b/organize/stateful/README.txt
@@ -32,17 +32,17 @@ making an object statful we'll use an adapter.
>>> from cybertools.stateful.interfaces import IStatesDefinition, IStateful
>>> from cybertools.stateful.publishing import simplePublishing
- >>> component.provideUtility(simplePublishing(), name='loops.simple_publishing')
+ >>> component.provideUtility(simplePublishing(), name='simple_publishing')
>>> from loops.organize.stateful.base import SimplePublishable
- >>> component.provideAdapter(SimplePublishable, name='loops.simple_publishing')
+ >>> component.provideAdapter(SimplePublishable, name='simple_publishing')
We may now take a document and adapt it to IStateful so that we may
check the document's state and perform transitions to other states.
>>> doc01 = resources['d001.txt']
>>> statefulDoc01 = component.getAdapter(doc01, IStateful,
- ... name='loops.simple_publishing')
+ ... name='simple_publishing')
>>> statefulDoc01.state
'draft'
@@ -55,7 +55,7 @@ Let's check if the state is really stored in the underlying object and
not just kept in the adapter.
>>> statefulDoc01_x = component.getAdapter(doc01, IStateful,
- ... name='loops.simple_publishing')
+ ... name='simple_publishing')
>>> statefulDoc01.state
'published'
@@ -68,10 +68,10 @@ We again first have to register states definitions and adapter classes.
>>> from loops.organize.stateful.quality import classificationQuality
>>> component.provideUtility(classificationQuality(),
- ... name='loops.classification_quality')
+ ... name='classification_quality')
>>> from loops.organize.stateful.quality import ClassificationQualityCheckable
>>> component.provideAdapter(ClassificationQualityCheckable,
- ... name='loops.classification_quality')
+ ... name='classification_quality')
>>> from loops.organize.stateful.quality import assign, deassign
>>> component.provideHandler(assign)
>>> component.provideHandler(deassign)
@@ -79,7 +79,7 @@ We again first have to register states definitions and adapter classes.
Now we can get a stateful adapter for a resource.
>>> qcheckedDoc01 = component.getAdapter(doc01, IStateful,
- ... name='loops.classification_quality')
+ ... name='classification_quality')
>>> qcheckedDoc01.state
'new'
@@ -99,7 +99,7 @@ When we change the concept assignments of the resource - i.e. its classification
>>> c01.assignResource(doc01)
>>> qcheckedDoc01 = component.getAdapter(doc01, IStateful,
- ... name='loops.classification_quality')
+ ... name='classification_quality')
>>> qcheckedDoc01.state
'classified'
@@ -138,7 +138,7 @@ We first need a node that provides us access to the resource as its target
The form view gives us access to the states of the object.
>>> loopsRoot.options = ['organize.stateful.resource:'
- ... 'loops.classification_quality,loops.simple_publishing']
+ ... 'classification_quality,simple_publishing']
>>> form = EditObjectForm(node, TestRequest())
>>> for st in form.states:
@@ -147,12 +147,12 @@ The form view gives us access to the states of the object.
... userTrans = st.getAvailableTransitionsForUser()
... print st.statesDefinition, sto.title, [t.title for t in transitions],
... print [t.title for t in userTrans]
- loops.classification_quality unclassified ['classify', 'verify'] ['verify']
- loops.simple_publishing published ['retract', 'archive'] ['retract', 'archive']
+ classification_quality unclassified ['classify', 'verify'] ['verify']
+ simple_publishing published ['retract', 'archive'] ['retract', 'archive']
Let's now update the form.
- >>> input = {'state.loops.classification_quality': 'verify'}
+ >>> input = {'state.classification_quality': 'verify'}
>>> proc = EditObject(form, TestRequest(form=input))
>>> proc.update()
False
@@ -160,6 +160,25 @@ Let's now update the form.
>>> qcheckedDoc01.state
'verified'
+Querying objects by state
+-------------------------
+
+ >>> stateQuery = addAndConfigureObject(concepts, Concept, 'state_query',
+ ... conceptType=concepts['query'], viewName='select_state.html')
+ >>> from loops.organize.stateful.browser import StateQuery
+ >>> view = StateQuery(stateQuery, TestRequest())
+
+ >>> view.statesDefinitions
+ {'concept': [], 'resource': [...StatesDefinition..., ...StatesDefinition...]}
+
+ >>> input = {'state.resource.classification_quality': ['verified']}
+ >>> view = StateQuery(stateQuery, TestRequest(form=input))
+ >>> view.selectedStates
+ {'state.resource.classification_quality': ['verified']}
+
+ >>> list(view.results)
+ [<...>]
+
Fin de partie
=============
diff --git a/organize/stateful/base.py b/organize/stateful/base.py
index d38e833..221cc9a 100644
--- a/organize/stateful/base.py
+++ b/organize/stateful/base.py
@@ -56,7 +56,7 @@ class StatefulLoopsObject(Stateful, StatefulAdapter):
class SimplePublishable(StatefulLoopsObject):
- statesDefinition = 'loops.simple_publishing'
+ statesDefinition = 'simple_publishing'
class StatefulResourceIndexInfo(IndexInfo):
diff --git a/organize/stateful/browser.py b/organize/stateful/browser.py
index 7551940..a2dd73a 100644
--- a/organize/stateful/browser.py
+++ b/organize/stateful/browser.py
@@ -27,16 +27,16 @@ from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from cybertools.browser.action import Action, actions
-from cybertools.stateful.interfaces import IStateful
+from cybertools.stateful.interfaces import IStateful, IStatesDefinition
from loops.browser.common import BaseView
from loops.browser.concept import ConceptView
-from loops.expert import query
+from loops.expert.query import And, Or, State, Type, getObjects
from loops.search.browser import template as search_template
from loops.util import _
-statefulActions = ('loops.classification_quality',
- 'loops.simple_publishing',)
+statefulActions = ('classification_quality',
+ 'simple_publishing',)
class StateAction(Action):
@@ -84,9 +84,48 @@ class StateQuery(BaseView):
def macro(self):
return self.template.macros['query']
+ @Lazy
+ def statesDefinitions(self):
+ result = {}
+ result['resource'] = [component.getUtility(IStatesDefinition, name=n)
+ for n in self.globalOptions('organize.stateful.resource', ())]
+ result['concept'] = [component.getUtility(IStatesDefinition, name=n)
+ for n in self.globalOptions('organize.stateful.concept', ())]
+ return result
+
+ @Lazy
+ def selectedStates(self):
+ result = {}
+ for k, v in self.request.form.items():
+ if k.startswith('state.') and v:
+ result[k] = v
+ return result
+
@Lazy
def results(self):
- uids = query.State('loops.classification_quality',
- #['new', 'unclassified', 'classified']).apply()
- ['new', 'unclassified']).apply()
- return self.viewIterator(query.getObjects(uids, self.loopsRoot))
+ conceptCriteria = {}
+ resourceCriteria = {}
+ q = None
+ for k, v in self.selectedStates.items():
+ k = k[len('state.'):]
+ type, statesDef = k.split('.')
+ if type == 'concept':
+ conceptCriteria[statesDef] = v
+ elif type == 'resource':
+ resourceCriteria[statesDef] = v
+ if conceptCriteria:
+ conceptQuery = And(Type('loops:concept:*'),
+ *[State(c, v) for c, v in conceptCriteria.items()])
+ if resourceCriteria:
+ resourceQuery = And(Type('loops:resource:*'),
+ *[State(c, v) for c, v in resourceCriteria.items()])
+ if conceptCriteria:
+ q = Or(conceptQuery, resourceQuery)
+ else:
+ q = resourceQuery
+ elif conceptCriteria:
+ q = conceptQuery
+ if q is not None:
+ uids = q.apply()
+ return self.viewIterator(getObjects(uids, self.loopsRoot))
+ return []
diff --git a/organize/stateful/configure.zcml b/organize/stateful/configure.zcml
index 5c23a31..5f84a96 100644
--- a/organize/stateful/configure.zcml
+++ b/organize/stateful/configure.zcml
@@ -16,11 +16,11 @@
+ name="simple_publishing" />
+ name="simple_publishing" trusted="True" />
@@ -30,11 +30,11 @@
+ name="classification_quality" />
+ name="classification_quality" trusted="True" />
diff --git a/organize/stateful/quality.py b/organize/stateful/quality.py
index 132aca3..f78955b 100644
--- a/organize/stateful/quality.py
+++ b/organize/stateful/quality.py
@@ -39,7 +39,7 @@ from loops.versioning.interfaces import IVersionable
@implementer(IStatesDefinition)
def classificationQuality():
- return StatesDefinition('classificationQuality',
+ return StatesDefinition('classification_quality',
State('new', 'new', ('classify', 'verify',
'change_classification', 'remove_classification'),
color='red'),
@@ -60,7 +60,7 @@ def classificationQuality():
class ClassificationQualityCheckable(StatefulLoopsObject):
- statesDefinition = 'loops.classification_quality'
+ statesDefinition = 'classification_quality'
def getAvailableTransitionsForUser(self):
return [tr for tr in self.getAvailableTransitions()
@@ -127,11 +127,11 @@ class ClassificationQualityCheckable(StatefulLoopsObject):
@adapter(ILoopsObject, IAssignmentEvent)
def assign(obj, event):
stf = component.getAdapter(event.relation.second, IStateful,
- name='loops.classification_quality')
+ name='classification_quality')
stf.assign(event.relation)
@adapter(ILoopsObject, IDeassignmentEvent)
def deassign(obj, event):
stf = component.getAdapter(event.relation.second, IStateful,
- name='loops.classification_quality')
+ name='classification_quality')
stf.deassign(event.relation)
diff --git a/organize/stateful/view_macros.pt b/organize/stateful/view_macros.pt
index 227843b..41aa2c7 100644
--- a/organize/stateful/view_macros.pt
+++ b/organize/stateful/view_macros.pt
@@ -2,5 +2,49 @@
-
+
+
+
+
+
+
diff --git a/search/browser.py b/search/browser.py
index b5ba843..1f523fb 100644
--- a/search/browser.py
+++ b/search/browser.py
@@ -34,6 +34,7 @@ from cybertools.ajax import innerHtml
from cybertools.relation.interfaces import IRelationRegistry
from cybertools.typology.interfaces import ITypeManager
from loops.browser.common import BaseView
+from loops.browser.node import NodeView
from loops.common import adapted
from loops.query import ConceptQuery, FullQuery
from loops import util
@@ -137,7 +138,8 @@ class Search(BaseView):
'%s/.target%s/@@searchresults.html' % (view.url, self.uniqueId))
-class SearchResults(BaseView):
+#class SearchResults(BaseView):
+class SearchResults(NodeView):
""" Provides results as inner HTML """
@Lazy
diff --git a/search/search.pt b/search/search.pt
index f0e3f83..670f19e 100644
--- a/search/search.pt
+++ b/search/search.pt
@@ -44,7 +44,9 @@