From 603c5dfdea6e2b3fe34a4e53bdf6a16ba7e6f0b3 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Tue, 26 Apr 2011 10:38:05 +0200 Subject: [PATCH 1/3] New and extende search page. - Reload page on search execution instead of replacing result list via AJAX. - Add state selection as search criteria. --- search/browser.py | 81 ++++++++++++++++++++++++++++-- search/search.pt | 123 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 173 insertions(+), 31 deletions(-) diff --git a/search/browser.py b/search/browser.py index 826c5cd..a4f077a 100644 --- a/search/browser.py +++ b/search/browser.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2010 Helmut Merz helmutm@cy55.de +# Copyright (c) 2011 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 @@ -20,7 +20,7 @@ Definition of basic view classes and other browser related stuff for the loops.search package. -$Id$ +$Id: browser.py 4160 2011-02-07 16:53:08Z helmutm $ """ from zope import interface, component @@ -32,11 +32,13 @@ from zope.i18nmessageid import MessageFactory from cybertools.ajax import innerHtml from cybertools.relation.interfaces import IRelationRegistry +from cybertools.stateful.interfaces import IStateful, IStatesDefinition from cybertools.typology.interfaces import ITypeManager from loops.browser.common import BaseView from loops.browser.node import NodeView from loops.common import adapted, AdapterBase from loops.expert.concept import ConceptQuery, FullQuery +from loops.interfaces import IResource from loops.organize.personal.browser.filter import FilterView from loops import util from loops.util import _ @@ -151,17 +153,90 @@ class Search(BaseView): def getRowName(self, obj): return obj.getLongTitle() - def getRowLabel(self, obj, name): + def getRowLabel(self, obj, name=None): if isinstance(obj, AdapterBase): obj = obj.context + if name is None: + name = obj.title return '%s (%s)' % (name, obj.conceptType.title) + @Lazy + def statesDefinitions(self): + return [component.getUtility(IStatesDefinition, name=n) + for n in self.globalOptions('organize.stateful.resource', ())] + + @Lazy + def selectedStates(self): + result = {} + for k, v in self.request.form.items(): + if k.startswith('state.') and v: + result[k] = v + return result + def submitReplacing(self, targetId, formId, view): self.registerDojo() return 'submitReplacing("%s", "%s", "%s"); return false;' % ( targetId, formId, '%s/.target%s/@@searchresults.html' % (view.url, self.uniqueId)) + @Lazy + def results(self): + form = self.request.form + type = form.get('search.1.text', 'loops:*') + text = form.get('search.2.text') + if text is not None: + text = util.toUnicode(text, encoding='ISO8859-15') # IE hack!!! + useTitle = form.get('search.2.title') + useFull = form.get('search.2.full') + conceptType = form.get('search.3.type', 'loops:concept:*') + #conceptTitle = form.get('search.3.text') + #if conceptTitle is not None: + # conceptTitle = util.toUnicode(conceptTitle, encoding='ISO8859-15') + conceptUid = form.get('search.3.text') + result = FullQuery(self).query(text=text, type=type, + useTitle=useTitle, useFull=useFull, + #conceptTitle=conceptTitle, + conceptUid=conceptUid, + conceptType=conceptType) + rowNum = 4 + while rowNum < 10: + addCriteria = form.get('search.%i.text_selected' % rowNum) + rowNum += 1 + if not addCriteria: + break + if addCriteria == 'none': + continue + addSelection = FullQuery(self).query(text=text, type=type, + useTitle=useTitle, useFull=useFull, + conceptUid=addCriteria) + if result: + result = [r for r in result if r in addSelection] + else: + result = addSelection + result = [r for r in result if self.checkStates(r)] + fv = FilterView(self.context, self.request) + result = fv.apply(result) + result = sorted(result, key=lambda x: x.title.lower()) + return self.viewIterator(result) + + def checkStates(self, obj): + if not IResource.providedBy(obj): + return True + for std, states in self.selectedStates.items(): + if std.startswith('state.resource.'): + std = std[len('state.resource.'):] + else: + continue + stf = component.queryAdapter(obj, IStateful, name=std) + if stf is None: + continue + for state in states: + if stf.state == state: + break + else: + return False + return True + #class SearchResults(BaseView): class SearchResults(NodeView): diff --git a/search/search.pt b/search/search.pt index 07d4926..3b2bf8d 100644 --- a/search/search.pt +++ b/search/search.pt @@ -4,7 +4,8 @@ tal:define="macros item/search_macros; idPrefix string:${view/itemNum}.search; formId string:$idPrefix.form; - resultsId string:$idPrefix.results"> + resultsId string:$idPrefix.results; + submitted request/search.submitted|nothing">

@@ -19,7 +20,8 @@ - + @@ -30,10 +32,10 @@ - @@ -45,7 +47,7 @@
Type: @@ -167,17 +172,19 @@
+ + + + + + + + + + + + + + + + From c4376c8a30623dcb11c3d77c27bed07dc9800ff3 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 28 Apr 2011 12:12:02 +0200 Subject: [PATCH 2/3] Test file as updated after test run. --- integrator/testdata/office/example.docx | Bin 17409 -> 17409 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/integrator/testdata/office/example.docx b/integrator/testdata/office/example.docx index 37b5a5be8cdad7de6012a2792257785b6913377d..ca24a0ad3ae0623a276bf1307ec1c1ece769fe5e 100644 GIT binary patch delta 26 fcmZqdU~KGQ+z?~I9GN(0bG$`3H;6HLr?UqDe@F?A delta 26 fcmZqdU~KGQ+z?~I{5N3M=6H*6ZV+SgPG=7QjCl&M From a69bda06d743a6df5166e74264cbe28235db4e1c Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 28 Apr 2011 12:15:13 +0200 Subject: [PATCH 3/3] Provide 'request' attribute for adapted objects. Put the current request (if available) into concept or resource adapters in order to be able to access the session an follow the navigation history, e.g. getting the current parent object. The request is stored in the adapted object automatically when using the 'adapted' view property. --- browser/common.py | 2 +- common.py | 8 +++++--- interfaces.py | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/browser/common.py b/browser/common.py index a0c78c1..bb88283 100644 --- a/browser/common.py +++ b/browser/common.py @@ -312,7 +312,7 @@ class BaseView(GenericView, I18NView): @Lazy def adapted(self): - return adapted(self.context, self.languageInfo) + return adapted(self.context, self.languageInfo, self.request) @Lazy def baseObject(self): diff --git a/common.py b/common.py index 0857ce8..6de6fb3 100644 --- a/common.py +++ b/common.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2008 Helmut Merz helmutm@cy55.de +# Copyright (c) 2011 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 @@ -43,10 +43,11 @@ from loops import util # convenience functions -def adapted(obj, langInfo=None): +def adapted(obj, langInfo=None, request=None): """ Return adapter based on the object type's type interface. """ if isinstance(obj, AdapterBase): + obj.request = request return obj t = IType(obj, None) if t is not None: @@ -57,6 +58,7 @@ def adapted(obj, langInfo=None): if isinstance(adapted, I18NAdapterBase): adapted.languageInfo = langInfo if adapted is not None: + adapted.request = request return adapted return obj @@ -98,7 +100,7 @@ class AdapterBase(object): adapts(IConcept) - _adapterAttributes = ('context', '__parent__',) + _adapterAttributes = ('context', '__parent__', 'request') _contextAttributes = list(IConcept) _noexportAttributes = () _textIndexAttributes = () diff --git a/interfaces.py b/interfaces.py index 85bdefc..c9b05a4 100644 --- a/interfaces.py +++ b/interfaces.py @@ -200,6 +200,7 @@ class ILoopsAdapter(IConceptSchema): context = Attribute('The underlying persistent object.') uid = Attribute('Unique id of the context object.') + request = Attribute('A a mapping with current settings, optional.') def getChildren(): """ Return a collection of child objects provided by the context
+
- + - +    @@ -188,9 +195,11 @@ Search text: - +   @@ -224,10 +233,13 @@    @@ -266,23 +282,74 @@ tal:condition="nothing" />  - +
+ url="listConceptsForComboBox.js?searchType=" + tal:attributes="url + string:listConceptsForComboBox.js?searchType=$conceptTypeValue">
+ tal:attributes="name name; + id string:$idPrefix.text; + displayedValue displayValue" />
+ +

Restrict to objects with certain states

+
WorkflowStates
+ + +   + +
  + tal:condition="python: + param not in ['type', 'text', 'concept', 'state']" />