Remove now obsolete loops.search package.

This commit is contained in:
Helmut Merz 2011-05-20 10:57:23 +02:00
parent ad8c236aa5
commit 0d1bb5a722
6 changed files with 0 additions and 955 deletions

View file

@ -1,239 +0,0 @@
===================================================================
loops.search - Provide search functionality for the loops framework
===================================================================
($Id$)
Let's do some basic set up
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
>>> site = placefulSetUp(True)
>>> from zope import component, interface
>>> from zope.interface import implements
and setup a simple loops site with a concept manager and some concepts
(with all the type machinery, what in real life is done via standard
ZCML setup):
>>> from loops.concept import Concept
>>> from loops.type import ConceptType, TypeConcept
>>> from loops.interfaces import ITypeConcept
>>> from loops.base import Loops
>>> from loops.expert.testsetup import TestSite
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
>>> query = concepts['query']
>>> topic = concepts['topic']
In addition we create a concept that holds the search page and a node
(page) that links to this concept:
>>> search = concepts['search'] = Concept(u'Search')
>>> search.conceptType = query
>>> from loops.view import Node
>>> page = views['page'] = Node('Search Page')
>>> page.target = search
Search views
------------
Now we are ready to create a search view object:
>>> from zope.publisher.browser import TestRequest
>>> from loops.expert.browser.search import Search
>>> searchView = Search(search, TestRequest())
The search view provides values for identifying the search form itself
and the parameter rows; the rowNum is auto-incremented, so it should be
accessed exactly once per row:
>>> searchView.rowNum
1
>>> searchView.rowNum
2
The search view provides vocabularies for types that allow the selection
of types to search for; this needs an ITypeManager adapter registered via
zcml in real life:
>>> from loops.type import LoopsTypeManager
>>> component.provideAdapter(LoopsTypeManager)
>>> t = searchView.typesForSearch()
>>> len(t)
14
>>> t.getTermByToken('loops:resource:*').title
'Any Resource'
>>> t = searchView.conceptTypesForSearch()
>>> len(t)
11
>>> t.getTermByToken('loops:concept:*').title
'Any Concept'
To execute the search in the context of a node we have to set up a node
view for our page. The submitReplacing method returns a JavaScript call
that will replace the results part on the search page; as this registers
the dojo library with the view's controller we also have to supply
a controller attribute for the search view.
>>> from loops.browser.node import NodeView
>>> request = TestRequest()
>>> pageView = NodeView(page, request)
>>> from cybertools.browser.liquid.controller import Controller
>>> searchView.controller = Controller(searchView, request)
>>> searchView.submitReplacing('1.results', '1.search.form', pageView)
'submitReplacing("1.results", "1.search.form",
"http://127.0.0.1/loops/views/page/.target80/@@searchresults.html");...'
Basic (text/title) search
-------------------------
The searchresults.html view, i.e. the SearchResults view class provides the
result set of the search via its `results` property.
Before accessing the `results` property we have to prepare a
resource we can search for and index it in the catalog.
>>> from loops.resource import Resource
>>> rplone = resources['plone'] = Resource()
>>> from zope.app.catalog.interfaces import ICatalog
>>> from loops import util
>>> catalog = component.getUtility(ICatalog)
>>> catalog.index_doc(int(util.getUidForObject(rplone)), rplone)
>>> from loops.expert.browser.search import SearchResults
>>> form = {'search.2.title': True, 'search.2.text': u'plone'}
>>> request = TestRequest(form=form)
>>> resultsView = SearchResults(page, request)
>>> results = list(resultsView.results)
>>> len(results)
1
>>> results[0].context == rplone
True
>>> form = {'search.2.title': True, 'search.2.text': u'foo'}
>>> request = TestRequest(form=form)
>>> resultsView = SearchResults(page, request)
>>> len(list(resultsView.results))
0
Search via related concepts
---------------------------
We first have to prepare some test concepts (topics); we also assign our test
resource (rplone) from above to one of the topics:
>>> czope = concepts['zope'] = Concept(u'Zope')
>>> czope2 = concepts['zope2'] = Concept(u'Zope 2')
>>> czope3 = concepts['zope3'] = Concept(u'Zope 3')
>>> cplone = concepts['plone'] = Concept(u'Plone')
>>> for c in (czope, czope2, czope3, cplone):
... c.conceptType = topic
... catalog.index_doc(int(util.getUidForObject(c)), c)
>>> czope.assignChild(czope2)
>>> czope.assignChild(czope3)
>>> czope2.assignChild(cplone)
>>> rplone.assignConcept(cplone)
Now we can fill our search form and execute the query; note that all concepts
found are listed, plus all their children and all resources associated
with them:
>>> uid = util.getUidForObject(concepts['zope'])
>>> form = {'search.3.type': 'loops:concept:topic', 'search.3.text': uid}
>>> request = TestRequest(form=form)
>>> resultsView = SearchResults(page, request)
>>> results = list(resultsView.results)
>>> len(results)
5
>>> results[0].context.__name__
u'plone'
>>> uid = util.getUidForObject(concepts['zope3'])
>>> form = {'search.3.type': 'loops:concept:topic', 'search.3.text': uid}
>>> request = TestRequest(form=form)
>>> resultsView = SearchResults(page, request)
>>> results = list(resultsView.results)
>>> len(results)
1
>>> results[0].context.__name__
u'zope3'
To support easy entry of concepts to search for we can preselect the available
concepts (optionally restricted to a certain type) by entering text parts
of the concepts' titles:
>>> form = {'searchType': 'loops:concept:topic', 'name': u'zope'}
>>> request = TestRequest(form=form)
>>> view = Search(page, request)
>>> view.listConcepts()
u"{identifier: 'id', items: [{label: 'Zope (Topic)', name: 'Zope', id: '85'}, {label: 'Zope 2 (Topic)', name: 'Zope 2', id: '87'}, {label: 'Zope 3 (Topic)', name: 'Zope 3', id: '89'}]}"
Preset Concept Types on Search Forms
------------------------------------
Often we want to include certain types in our search. We can instruct
the search form to include lines for these types by giving these types
a certain qualifier, via the option attribute of the type interface.
Let's start with a new type, the customer type.
>>> customer = concepts['customer']
>>> custType = ITypeConcept(customer)
>>> custType.options
[]
>>> cust1 = concepts['cust1']
>>> cust2 = concepts['cust2']
>>> for c in (cust1, cust2):
... c.conceptType = customer
... catalog.index_doc(int(util.getUidForObject(c)), c)
>>> from cybertools.typology.interfaces import IType
>>> IType(cust1).qualifiers
('concept',)
>>> searchView = Search(search, TestRequest())
>>> list(searchView.presetSearchTypes)
[]
We can now add a 'search' qualifier to the customer type's options
and thus include the customer type in the preset search types.
>>> custType.options = ('qualifier:search',)
>>> IType(cust1).qualifiers
('concept', 'search')
>>> searchView = Search(search, TestRequest())
>>> list(searchView.presetSearchTypes)
[{'token': 'loops:concept:customer', 'title': u'Customer'}]
>>> searchView.conceptsForType('loops:concept:customer')
[{'token': 'none', 'title': u'not selected'},
{'token': '58', 'title': u'Customer 1'},
{'token': '60', 'title': u'Customer 2'},
{'token': '62', 'title': u'Customer 3'}]
Let's use this new search option for querying:
>>> form = {'search.4.text_selected': u'58'}
>>> resultsView = SearchResults(page, TestRequest(form=form))
>>> results = list(resultsView.results)
>>> results[0].title
u'Customer 1'
Automatic Filtering
-------------------
TODO - more to come...

View file

@ -1,4 +0,0 @@
"""
$Id$
"""

View file

@ -1,295 +0,0 @@
#
# 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
# 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
#
"""
Definition of basic view classes and other browser related stuff for the
loops.search package.
$Id: browser.py 4160 2011-02-07 16:53:08Z helmutm $
"""
from zope import interface, component
from zope import traversing
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from zope.formlib.namedtemplate import NamedTemplate, NamedTemplateImplementation
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.browser.search import searchMacrosTemplate as search_template
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 _
#search_template = ViewPageTemplateFile('search.pt')
class Search(BaseView):
maxRowNum = 0
@Lazy
def search_macros(self):
return self.controller.getTemplateMacros('search', search_template)
@Lazy
def macro(self):
return self.search_macros['search']
@property
def rowNum(self):
""" Return the rowNum to be used for identifying the current search
parameter row.
"""
n = self.request.get('loops.rowNum', 0)
if n: # if given directly we don't use the calculation
return n
n = (self.maxRowNum or self.request.get('loops.maxRowNum', 0)) + 1
self.maxRowNum = n
return n
@Lazy
def presetSearchTypes(self):
""" Return a list of concept type info dictionaries (see BaseView)
that should be displayed on a separate search parameter row.
"""
#return ITypeManager(self.context).listTypes(include=('search',))
return self.listTypesForSearch(include=('search',))
def conceptsForType(self, token):
result = ConceptQuery(self).query(type=token)
fv = FilterView(self.context, self.request)
result = fv.apply(result)
result.sort(key=lambda x: x.title)
noSelection = dict(token='none', title=u'not selected')
return [noSelection] + [dict(title=adapted(o, self.languageInfo).title,
token=util.getUidForObject(o))
for o in result]
def initDojo(self):
self.registerDojo()
cm = self.controller.macros
jsCall = ('dojo.require("dojo.parser");'
'dojo.require("dijit.form.FilteringSelect");'
'dojo.require("dojox.data.QueryReadStore");')
cm.register('js-execute', jsCall, jsCall=jsCall)
def listConcepts(self, filterMethod=None):
""" Used for dijit.FilteringSelect.
"""
request = self.request
request.response.setHeader('Content-Type', 'text/plain; charset=UTF-8')
title = request.get('name')
if title == '*':
title = None
types = request.get('searchType')
data = []
if title or types:
if title is not None:
title = title.replace('(', ' ').replace(')', ' ').replace(' -', ' ')
#title = title.split(' ', 1)[0]
if not types:
types = ['loops:concept:*']
if not isinstance(types, (list, tuple)):
types = [types]
for type in types:
result = self.executeQuery(title=title or None, type=type,
exclude=('hidden',))
fv = FilterView(self.context, self.request)
result = fv.apply(result)
for o in result:
if o.getLoopsRoot() == self.loopsRoot:
adObj = adapted(o, self.languageInfo)
if filterMethod is not None and not filterMethod(adObj):
continue
name = self.getRowName(adObj)
if title and title.endswith('*'):
title = title[:-1]
sort = ((title and name.startswith(title) and '0' or '1')
+ name.lower())
if o.conceptType is None:
raise ValueError('Concept Type missing for %r.' % name)
data.append({'label': self.getRowLabel(adObj, name),
'name': name,
'id': util.getUidForObject(o),
'sort': sort})
data.sort(key=lambda x: x['sort'])
if not title:
data.insert(0, {'label': '', 'name': '', 'id': ''})
json = []
for item in data[:100]:
json.append("{label: '%s', name: '%s', id: '%s'}" %
(item['label'], item['name'], item['id']))
json = "{identifier: 'id', items: [%s]}" % ', '.join(json)
#print '***', json
return json
def executeQuery(self, **kw):
return ConceptQuery(self).query(**kw)
def getRowName(self, obj):
return obj.getLongTitle()
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):
""" Provides results as inner HTML """
@Lazy
def search_macros(self):
return self.controller.getTemplateMacros('search', search_template)
@Lazy
def macro(self):
return self.search_macros['search_results']
def __call__(self):
return innerHtml(self)
@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
fv = FilterView(self.context, self.request)
result = fv.apply(result)
result = sorted(result, key=lambda x: x.title.lower())
return self.viewIterator(result)

View file

@ -1,33 +0,0 @@
<!-- $Id$ -->
<configure
xmlns:zope="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="zope"
>
<!--<zope:adapter
name="search"
for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.search.browser.Search"
permission="zope.View"
/>
<browser:page
name="listConceptsForComboBox.js"
for="loops.interfaces.ILoopsObject"
class="loops.search.browser.Search"
attribute="listConcepts"
permission="zope.View"
/>
<browser:page
name="searchresults.html"
for="loops.interfaces.ILoopsObject"
class="loops.search.browser.SearchResults"
permission="zope.View"
/>-->
</configure>

View file

@ -1,358 +0,0 @@
<metal:search define-macro="search"
i18n:domain="loops">
<div id="search"
tal:define="macros item/search_macros;
idPrefix string:${view/itemNum}.search;
formId string:$idPrefix.form;
resultsId string:$idPrefix.results;
submitted request/search.submitted|nothing">
<h1 tal:attributes="class string:content-$level;
ondblclick item/openEditWindow"
tal:content="item/title">
Search
</h1>
<div metal:define-macro="search_form" class="searchForm">
<fieldset class="box">
<form action="." method="post" id="1.search.form"
tal:attributes="id formId">
<input type="hidden" name="search.submitted" value="yes" />
<input type="hidden" name="search.resultsId" value="1.results"
tal:attributes="value resultsId" />
<table cellpadding="3">
<tal:block repeat="search_param python:
['type', 'text', 'concept', 'state']">
<metal:row use-macro="macros/search_row" />
</tal:block>
<tr tal:condition="nothing">
<td colspan="2">
<input type="button" value="Add concept filter" class="button" />
<input type="button" value="Add attribute filter" class="button" />
</td>
</tr>
<tr>
<td></td>
<td colspan="3"><br />
<input type="submit" name="button.search" value="Search" class="submit"
i18n:attributes="value"
tal:attributes="xx_onclick python:
item.submitReplacing(resultsId, formId, view)" />
</td>
</tr>
</table>
</form>
</fieldset>
</div>
<tal:results condition="request/search.submitted|nothing">
<metal:results use-macro="item/search_macros/results" />
</tal:results>
<div metal:define-macro="search_results" id="1.search.results"
tal:attributes="id resultsId | request/search.resultsId"
i18n:domain="loops"
xtal: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">
<h2 i18n:translate="">Search results</h2>
<table class="listing" summary="Search results"
i18n:attributes="summary">
<thead>
<tr>
<th i18n:translate="">Title</th>
<th i18n:translate="">Type</th>
<th i18n:translate=""
tal:condition="view/useVersioning">V</th>
<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>
<tal:items tal:repeat="row item/results">
<tal:item define="class python: repeat['row'].odd() and 'even' or 'odd';
description row/description">
<tr tal:attributes="class class">
<td>
<a tal:attributes="href
string:${view/url}/.target${row/uniqueId}?version=this;
title description">
<img tal:define="icon row/icon"
tal:condition="icon"
tal:attributes="src icon/src" />
<div tal:content="row/title" /></a>
</td>
<td i18n:translate="" class="center"
tal:content="row/longTypeTitle|row/typeTitle">Type</td>
<tal:version condition="view/useVersioning">
<td class="center"
tal:define="versionId row/versionId|string:">
<a href="#"
tal:content="versionId"
tal:omit-tag="python: versionId and versionId=='1.1'"
tal:attributes="href string:${view/url}/.target${row/uniqueId}?loops.viewName=listversions">1.1</a>
</td>
</tal:version>
<td class="nowrap number">
<span tal:replace="row/context/sizeForDisplay|string:">Size</span>
</td>
<td><span tal:replace="row/modified">modified</span></td>
<td><span tal:replace="row/creators">John</span></td>
<td class="nowrap center"
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>
</tbody>
</table>
</metal:results>
</fieldset>
</div>
</div>
</metal:search>
<div metal:define-macro="search_row" id="1.1.row"
tal:define="rowNum item/rowNum;
basicIdPrefix idPrefix;
idPrefix string:$idPrefix.$rowNum;
namePrefix string:search.$rowNum;
param search_param | item/searchParam"
tal:attributes="id string:$idPrefix.row">
<div metal:use-macro="macros/?param" />
</div>
<metal:text define-macro="type">
<tr>
<td metal:use-macro="macros/minus"/>
<td colspan="3">
<h2 i18n:translate="">Type(s) to search for</h2>
</td>
<tr>
<td></td>
<td>
<label for="text"
tal:attributes="for string:$idPrefix.text">
<span i18n:translate="">Type</span>:</label>
<select name="text"
tal:define="name string:$namePrefix.text;
value request/?name|nothing"
tal:attributes="name name;
id string:$idPrefix.text;">
<tal:types repeat="type item/typesForSearch">
<option value="loops:*"
i18n:translate=""
tal:attributes="value type/token;
selected python: value == type.token"
tal:content="type/title">Topic</option>
</tal:types>
</select>
<input type="button" value="+"
title="Add type"
tal:condition="nothing" />&nbsp;
</td>
<td colspan="2"></td>
</tr>
</metal:text>
<metal:text define-macro="text">
<tr>
<td metal:use-macro="macros/minus"/>
<td colspan="3">
<h2 i18n:translate="">Text-based search</h2>
</td>
<tr>
<td></td>
<td>
<input type="checkbox" value="yes"
tal:define="name string:$namePrefix.title"
tal:attributes="name name;
id string:$idPrefix.title;
checked request/?name|not:submitted|string:yes" />
<label for="title"
i18n:translate=""
tal:attributes="for string:$idPrefix.title">Title</label>
<input type="checkbox" value="yes"
tal:define="name string:$namePrefix.full"
tal:attributes="name name;
id string:$idPrefix.full;
checked request/?name|nothing" />
<label for="full"
i18n:translate=""
tal:attributes="for string:$idPrefix.full">Full text</label>&nbsp;&nbsp;
</td>
<td>
<label for="text"
tal:attributes="for string:$idPrefix.text">
<span i18n:translate="">Search text</span>:</label>
</td>
<td>
<input type="text"
tal:define="name string:$namePrefix.text"
tal:attributes="name name;
id string:$idPrefix.text;
value request/?name|nothing" />
<input type="button" value="+"
title="Add search word"
tal:condition="nothing" />&nbsp;
</td>
</tr>
</metal:text>
<metal:text define-macro="concept">
<tr>
<td metal:use-macro="macros/minus"/>
<td colspan="3">
<h2 i18n:translate="">Search via related concepts</h2>
</td>
<tr tal:repeat="type item/presetSearchTypes">
<tal:preset define="rowNum item/rowNum;
idPrefix string:$basicIdPrefix.$rowNum;
namePrefix string:search.$rowNum;">
<td></td>
<td>
<span i18n:translate="">Type</span>:
<b tal:content="type/title" i18n:translate="" />
<input type="hidden" name="type" value=""
tal:attributes="name string:$namePrefix.type;
value type/token" />
</td>
<td>
<label for="text"
tal:attributes="for string:$idPrefix.text">
<span i18n:translate="">Concept for Search</span>:</label>
</td>
<td>
<select name="text_selected"
tal:define="name string:$namePrefix.text_selected;
value request/?name|nothing"
tal:attributes="name name;
id string:$idPrefix.text;">
<tal:concepts repeat="concept python: item.conceptsForType(type['token'])">
<option tal:attributes="value concept/token;
selected python: value == concept['token']"
i18n:translate=""
tal:content="concept/title">Zope Corp</option>
</tal:concepts>
</select>
</td>
</tal:preset>
</tr>
<tr>
<td></td>
<td>
<label for="type"
tal:attributes="for string:$idPrefix.type">
<span i18n:translate="">Type</span>:</label>
<select name="type"
tal:define="name string:$namePrefix.type;
global conceptTypeValue request/?name|string:"
tal:attributes="name name;
id string:$idPrefix.type;
value conceptTypeValue;
onChange string:setConceptTypeForComboBox('$idPrefix.type', '$idPrefix.text')">
<tal:types repeat="type item/conceptTypesForSearch">
<option value="loops:*"
i18n:translate=""
tal:attributes="value type/token;
selected python: conceptTypeValue == type.token"
tal:content="type/title">Topic</option>
</tal:types>
</select>&nbsp;&nbsp;
</td>
<td>
<label for="text"
tal:attributes="for string:$idPrefix.text">
<span i18n:translate="">Concept for Search</span>:</label>
<input type="text" name="text"
tal:condition="nothing"
tal:attributes="name string:$namePrefix.text;
id string:$idPrefix.text;" />
<input type="button" value="+"
title="Add type"
tal:condition="nothing" />&nbsp;
</td>
<td>
<tal:combo tal:define="dummy item/initDojo;
name string:$namePrefix.text;
value request/?name|nothing;
concept python:
value and view.getObjectForUid(value);
displayValue python:
concept and concept.title or u''">
<div dojoType="dojox.data.QueryReadStore" jsId="conceptSearch"
url="listConceptsForComboBox.js?searchType="
tal:attributes="url
string:listConceptsForComboBox.js?searchType=$conceptTypeValue">
</div>
<input dojoType="dijit.form.FilteringSelect" store="conceptSearch"
autoComplete="False" labelAttr="name" style="height: 16px"
name="concept.search.text" id="concept.search.text"
tal:attributes="name name;
id string:$idPrefix.text;
displayedValue displayValue" />
</tal:combo>
</td>
</tr>
</metal:text>
<metal:text define-macro="state"
tal:define="stateDefs item/statesDefinitions;
deftype string:resource"
tal:condition="stateDefs">
<tr>
<td metal:use-macro="macros/minus"/>
<td colspan="3">
<h2 i18n:translate="">Restrict to objects with certain states</h2>
</td>
<tr>
<td></td>
<th i18n:translate="">Workflow</th>
<th colspan="2"
i18n:translate="">States</th>
</tr>
<tr tal:repeat="def stateDefs">
<td></td>
<td valign="top"
tal:content="def/name"
i18n:translate=""></td>
<td colspan="2">
<tal:states repeat="state def/states">
<tal:state define="name string:state.$deftype.${def/name};
value state/name">
<input type="checkbox"
tal:attributes="name string:$name:list;
value value;
checked python:
value in item.selectedStates.get(name, ());
id string:$name.$value"
/>&nbsp;<label tal:content="state/title"
i18n:translate=""
tal:attributes="for string:$name.$value" />
&nbsp;
</tal:state>
</tal:states>
</td>
</tr>
</metal:text>
<td metal:define-macro="minus">
<input type="button" value="&minus;"
title="Remove search parameter"
tal:condition="python:
param not in ['type', 'text', 'concept', 'state']" />&nbsp;
</td>

View file

@ -1,26 +0,0 @@
# $Id$
import unittest, doctest
from zope.testing.doctestunit import DocFileSuite
from zope.interface.verify import verifyClass
#from loops.search.interfaces import ...
class Test(unittest.TestCase):
"Basic tests for the loops.search package."
def testBase(self):
pass
def test_suite():
flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
return unittest.TestSuite((
unittest.makeSuite(Test),
DocFileSuite('README.txt',
optionflags=flags,),
))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')