add option-based filtering (overridable via request params

This commit is contained in:
Helmut Merz 2012-11-23 12:43:21 +01:00
parent 1e46a7dc67
commit 757a1cd60c
5 changed files with 51 additions and 9 deletions

View file

@ -132,6 +132,7 @@ class BaseView(GenericView, I18NView):
actions = {} actions = {}
portlet_actions = [] portlet_actions = []
parts = () parts = ()
filter_input = ()
icon = None icon = None
modeName = 'view' modeName = 'view'
isToplevel = False isToplevel = False
@ -563,16 +564,22 @@ class BaseView(GenericView, I18NView):
return DummyOptions() return DummyOptions()
return component.queryAdapter(self.adapted, IOptions) or DummyOptions() return component.queryAdapter(self.adapted, IOptions) or DummyOptions()
@Lazy
def globalOptions(self):
return IOptions(self.loopsRoot)
@Lazy @Lazy
def typeOptions(self): def typeOptions(self):
if self.typeProvider is None: if self.typeProvider is None:
return DummyOptions() return DummyOptions()
return IOptions(adapted(self.typeProvider)) return IOptions(adapted(self.typeProvider))
@Lazy
def globalOptions(self):
return IOptions(self.loopsRoot)
def getOptions(self, key):
for opt in (self.options, self.typeOptions, self.globalOptions):
value = opt[key]
if not isinstance(value, DummyOptions):
return value
def getPredicateOptions(self, relation): def getPredicateOptions(self, relation):
return IOptions(adapted(relation.predicate), None) or DummyOptions() return IOptions(adapted(relation.predicate), None) or DummyOptions()

View file

@ -361,7 +361,8 @@ class ConceptView(BaseView):
options = IOptions(adapted(r.predicate), None) options = IOptions(adapted(r.predicate), None)
if options is not None and options('hide_children'): if options is not None and options('hide_children'):
continue continue
if not fv.check(r.context): filterOptions = self.getOptions('filter')
if not fv.check(r.context, filterOptions):
continue continue
yield r yield r

View file

@ -1,15 +1,16 @@
<html i18n:domain="loops"> <html i18n:domain="loops">
<metal:data define-macro="conceptinfo"> <metal:data define-macro="layout">
<tal:part repeat="part item/parts"> <tal:part repeat="part item/getParts">
<metal:part use-macro="part/renderer" /> <metal:part use-macro="part/macro" />
</tal:part> </tal:part>
</metal:data> </metal:data>
<metal:data define-macro="conceptdata"> <metal:data define-macro="conceptdata">
<div tal:attributes="class string:content-$level;"> <div tal:attributes="class string:content-$level;">
<metal:block use-macro="view/concept_macros/filter_input" />
<metal:block use-macro="view/concept_macros/concepttitle" /> <metal:block use-macro="view/concept_macros/concepttitle" />
<metal:slot define-slot="fields"> <metal:slot define-slot="fields">
<metal:block use-macro="view/concept_macros/conceptfields" /> <metal:block use-macro="view/concept_macros/conceptfields" />
@ -29,6 +30,18 @@
</metal:data> </metal:data>
<metal:selection define-macro="filter_input">
<div tal:define="criteria item/filter"
tal:condition="criteria">
<form method="get" name="filter" id="form-filter">
<span tal:repeat="crit criteria">
<metal:input use-macro="crit/macro" />
</span>
</form>
</div>
</metal:selection>
<metal:title define-macro="concepttitle"> <metal:title define-macro="concepttitle">
<metal:title define-macro="concepttitle_only"> <metal:title define-macro="concepttitle_only">
<tal:actions condition="view/showObjectActions"> <tal:actions condition="view/showObjectActions">

View file

@ -27,6 +27,7 @@ from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from cybertools.browser.configurator import ViewConfigurator, MacroViewProperty from cybertools.browser.configurator import ViewConfigurator, MacroViewProperty
from cybertools.stateful.interfaces import IStateful
from loops.browser.node import NodeView from loops.browser.node import NodeView
from loops.concept import Concept from loops.concept import Concept
from loops.organize.party import getPersonForUser from loops.organize.party import getPersonForUser
@ -107,7 +108,17 @@ class FilterView(NodeView):
result.setdefault(obj.getType(), set([])).add(obj) result.setdefault(obj.getType(), set([])).add(obj)
return result return result
def check(self, obj): def check(self, obj, options=None):
if options:
for std in options.states.keys():
stf = component.getAdapter(obj, IStateful, name=std)
formStates = self.request.form.get('states.' + std)
if formStates:
if stf.state not in formStates.split(','):
return False
else:
if stf.state not in getattr(options.states, std):
return False
fs = self.filterStructure fs = self.filterStructure
if not fs: if not fs:
return True return True

View file

@ -1,3 +1,10 @@
<html i18n:domain="loops">
<metal:input define-macro="filter_allstates">
<input type="checkbox" name="filter.allstates" value="yes"
tal:attributes="checked crit/checked" />
</metal:input>
<metal:query define-macro="query"> <metal:query define-macro="query">
@ -55,3 +62,6 @@
</form> </form>
</div> </div>
</metal:query> </metal:query>
</html>