let user provide search criteria for states query

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2599 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2008-05-16 10:10:28 +00:00
parent 8b5df16afc
commit 9b8b0096fd
12 changed files with 160 additions and 48 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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]

View file

@ -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

View file

@ -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
=============

View file

@ -56,7 +56,7 @@ class StatefulLoopsObject(Stateful, StatefulAdapter):
class SimplePublishable(StatefulLoopsObject):
statesDefinition = 'loops.simple_publishing'
statesDefinition = 'simple_publishing'
class StatefulResourceIndexInfo(IndexInfo):

View file

@ -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 []

View file

@ -16,11 +16,11 @@
<zope:utility
factory="cybertools.stateful.publishing.simplePublishing"
name="loops.simple_publishing" />
name="simple_publishing" />
<zope:adapter
factory="loops.organize.stateful.base.SimplePublishable"
name="loops.simple_publishing" trusted="True" />
name="simple_publishing" trusted="True" />
<zope:class class="loops.organize.stateful.base.SimplePublishable">
<require permission="zope.View"
interface="cybertools.stateful.interfaces.IStateful" />
@ -30,11 +30,11 @@
<zope:utility
factory="loops.organize.stateful.quality.classificationQuality"
name="loops.classification_quality" />
name="classification_quality" />
<zope:adapter
factory="loops.organize.stateful.quality.ClassificationQualityCheckable"
name="loops.classification_quality" trusted="True" />
name="classification_quality" trusted="True" />
<zope:class class="loops.organize.stateful.quality.ClassificationQualityCheckable">
<require permission="zope.View"
interface="cybertools.stateful.interfaces.IStateful" />

View file

@ -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)

View file

@ -2,5 +2,49 @@
<metal:query define-macro="query">
<metal:results use-macro="item/search_macros/results" />
<div>
<form method="post">
<input type="hidden" name="search_submitted" value="yes" />
<h1 i18n:translate="">Select Objects by State</h1>
<br />
<table class="listing"
tal:define="defs item/statesDefinitions">
<tr>
<th i18n:translate="">Object Type</th>
<th i18n:translate="">Workflow</th>
<th i18n:translate="">States</th>
</tr>
<tal:def repeat="deftype defs">
<tr tal:repeat="def defs/?deftype">
<td valign="top">
<span tal:condition="repeat/def/start"
tal:content="deftype"
i18n:translate="" />
</td>
<td tal:content="def/name"
i18n:translate=""></td>
<td>
<tal:state repeat="state def/states">
<input type="checkbox"
tal:define="name string:state.$deftype.${def/name};
value state/name"
tal:attributes="name string:$name:list;
value value;
checked python:
value in item.selectedStates.get(name, ())"
/><span tal:content="state/title"
i18n:translate="" />
&nbsp;
</tal:state>
</td>
</tr>
</tal:def>
</table>
<input type="submit" name="button.search" value="Search" class="submit"
i18n:attributes="value" />
</form>
</div>
<tal:results condition="request/search_submitted|nothing">
<metal:results use-macro="item/search_macros/results" />
</tal:results>
</metal:query>

View file

@ -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

View file

@ -44,7 +44,9 @@
<div metal:define-macro="search_results" id="1.search.results"
tal:attributes="id resultsId | request/search.resultsId"
i18n:domain="loops"
tal:define="item nocall:view">
tal:define="item nocall:view;
controller nocall:view/@@controller;
resourceBase controller/resourceBase;">
<fieldset class="box"
tal:condition="request/search.submitted | nothing">
<metal:results define-macro="results">
@ -60,6 +62,8 @@
<th i18n:translate="">Size</th>
<th i18n:translate="">Modification Date</th>
<th i18n:translate="">Author(s)</th>
<th i18n:translate=""
tal:condition="view/showObjectActions">Info</th>
</tr>
</thead>
<tbody>
@ -88,6 +92,12 @@
</td>
<td><span tal:replace="row/modified">modified</span></td>
<td><span tal:replace="row/creators">John</span></td>
<td style="white-space: nowrap"
tal:define="target nocall:row;
style nothing"
tal:condition="view/showObjectActions">
<div metal:use-macro="views/node_macros/object_actions" />
</td>
</tr>
</tal:item>
</tal:items>