first working version of fulltext and title search
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1317 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
		
							parent
							
								
									f8f9ee1fd8
								
							
						
					
					
						commit
						8ee75bbf77
					
				
					 9 changed files with 144 additions and 51 deletions
				
			
		| 
						 | 
					@ -25,12 +25,10 @@ $Id$
 | 
				
			||||||
from zope.app import zapi
 | 
					from zope.app import zapi
 | 
				
			||||||
from zope.app.dublincore.interfaces import IZopeDublinCore
 | 
					from zope.app.dublincore.interfaces import IZopeDublinCore
 | 
				
			||||||
from zope.app.form.browser.interfaces import ITerms
 | 
					from zope.app.form.browser.interfaces import ITerms
 | 
				
			||||||
from zope.app.intid.interfaces import IIntIds
 | 
					 | 
				
			||||||
from zope.cachedescriptors.property import Lazy
 | 
					from zope.cachedescriptors.property import Lazy
 | 
				
			||||||
from zope.dottedname.resolve import resolve
 | 
					from zope.dottedname.resolve import resolve
 | 
				
			||||||
 | 
					from zope.formlib import form
 | 
				
			||||||
from zope.formlib.form import FormFields
 | 
					from zope.formlib.form import FormFields
 | 
				
			||||||
from zope.formlib.form import EditForm as BaseEditForm
 | 
					 | 
				
			||||||
from zope.formlib.form import AddForm as BaseAddForm
 | 
					 | 
				
			||||||
from zope.formlib.namedtemplate import NamedTemplate
 | 
					from zope.formlib.namedtemplate import NamedTemplate
 | 
				
			||||||
from zope.interface import Interface, implements
 | 
					from zope.interface import Interface, implements
 | 
				
			||||||
from zope.app.publisher.browser import applySkin
 | 
					from zope.app.publisher.browser import applySkin
 | 
				
			||||||
| 
						 | 
					@ -44,7 +42,7 @@ from cybertools.browser.view import GenericView
 | 
				
			||||||
from cybertools.relation.interfaces import IRelationRegistry
 | 
					from cybertools.relation.interfaces import IRelationRegistry
 | 
				
			||||||
from cybertools.typology.interfaces import IType
 | 
					from cybertools.typology.interfaces import IType
 | 
				
			||||||
from loops.interfaces import IView
 | 
					from loops.interfaces import IView
 | 
				
			||||||
from loops import util
 | 
					#from loops import util
 | 
				
			||||||
from loops.util import _
 | 
					from loops.util import _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,13 +62,13 @@ class IAddForm(Interface):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AddForm(BaseAddForm):
 | 
					class AddForm(form.AddForm):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    form_fields = FormFields(IAddForm)
 | 
					    form_fields = FormFields(IAddForm)
 | 
				
			||||||
    template = NamedTemplate('loops.pageform')
 | 
					    template = NamedTemplate('loops.pageform')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EditForm(BaseEditForm):
 | 
					class EditForm(form.EditForm):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template = NamedTemplate('loops.pageform')
 | 
					    template = NamedTemplate('loops.pageform')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,10 +179,6 @@ class BaseView(GenericView):
 | 
				
			||||||
        # this may depend on system and user settings...
 | 
					        # this may depend on system and user settings...
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #@Lazy
 | 
					 | 
				
			||||||
    #def inlineEditable(self):
 | 
					 | 
				
			||||||
    #    return self.inlineEditingActive and canWrite(self.context, 'title')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    inlineEditable = False
 | 
					    inlineEditable = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def inlineEdit(self, id):
 | 
					    def inlineEdit(self, id):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,9 @@ from zope.proxy import removeAllProxies
 | 
				
			||||||
from zope.security import canAccess, canWrite
 | 
					from zope.security import canAccess, canWrite
 | 
				
			||||||
from zope.security.proxy import removeSecurityProxy
 | 
					from zope.security.proxy import removeSecurityProxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from zope.app.event.objectevent import ObjectModifiedEvent, Attributes
 | 
				
			||||||
 | 
					from zope.event import notify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from cybertools.ajax import innerHtml
 | 
					from cybertools.ajax import innerHtml
 | 
				
			||||||
from cybertools.browser import configurator
 | 
					from cybertools.browser import configurator
 | 
				
			||||||
from cybertools.browser.view import GenericView
 | 
					from cybertools.browser.view import GenericView
 | 
				
			||||||
| 
						 | 
					@ -299,6 +302,7 @@ class InlineEdit(NodeView):
 | 
				
			||||||
    def save(self):
 | 
					    def save(self):
 | 
				
			||||||
        target = self.virtualTargetObject
 | 
					        target = self.virtualTargetObject
 | 
				
			||||||
        target.data = self.request.form['editorContent']
 | 
					        target.data = self.request.form['editorContent']
 | 
				
			||||||
 | 
					        notify(ObjectModifiedEvent(target, Attributes(IResource, 'data')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# special (named) views for nodes
 | 
					# special (named) views for nodes
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -291,10 +291,12 @@ class IndexAttributes(object):
 | 
				
			||||||
    def __init__(self, context):
 | 
					    def __init__(self, context):
 | 
				
			||||||
        self.context = context
 | 
					        self.context = context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # obsolete, use TextIndexNG (with indexableContent() method) instead
 | 
				
			||||||
    def text(self):
 | 
					    def text(self):
 | 
				
			||||||
        context = self.context
 | 
					        context = self.context
 | 
				
			||||||
        return ' '.join((zapi.getName(context), context.title,))
 | 
					        return ' '.join((zapi.getName(context), context.title,))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def title(self):
 | 
					    def title(self):
 | 
				
			||||||
        return self.text()
 | 
					        context = self.context
 | 
				
			||||||
 | 
					        return ' '.join((zapi.getName(context), context.title,))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,12 +276,22 @@
 | 
				
			||||||
    <require like_class="zope.app.dublincore.annotatableadapter.ZDCAnnotatableAdapter" />
 | 
					    <require like_class="zope.app.dublincore.annotatableadapter.ZDCAnnotatableAdapter" />
 | 
				
			||||||
  </class>
 | 
					  </class>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <adapter factory="loops.concept.IndexAttributes" />
 | 
					  <adapter factory="loops.concept.IndexAttributes" trusted="True" />
 | 
				
			||||||
  <adapter factory="loops.resource.IndexAttributes" />
 | 
					  <class class="loops.concept.IndexAttributes">
 | 
				
			||||||
 | 
					    <allow interface="loops.interfaces.IIndexAttributes" />
 | 
				
			||||||
 | 
					  </class>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <adapter factory="loops.resource.IndexAttributes" trusted="True" />
 | 
				
			||||||
 | 
					  <class class="loops.resource.IndexAttributes">
 | 
				
			||||||
 | 
					    <allow interface="loops.interfaces.IIndexAttributes" />
 | 
				
			||||||
 | 
					  </class>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <adapter factory="loops.resource.IndexableResource" trusted="True" />
 | 
					  <adapter factory="loops.resource.IndexableResource" trusted="True" />
 | 
				
			||||||
  <class class="loops.resource.IndexableResource">
 | 
					  <class class="loops.resource.IndexableResource">
 | 
				
			||||||
    <require permission="zope.View"
 | 
					    <allow interface="textindexng.interfaces.IIndexableContent" />
 | 
				
			||||||
             interface="loops.interfaces.IBaseResourceSchema" />
 | 
					  </class>
 | 
				
			||||||
 | 
					  <class class="textindexng.content.IndexContentCollector">
 | 
				
			||||||
 | 
					    <allow interface="textindexng.interfaces.IIndexContentCollector" />
 | 
				
			||||||
  </class>
 | 
					  </class>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <adapter factory="loops.resource.DocumentReadFileAdapter" />
 | 
					  <adapter factory="loops.resource.DocumentReadFileAdapter" />
 | 
				
			||||||
| 
						 | 
					@ -350,6 +360,21 @@
 | 
				
			||||||
      name="loops.PredicateSource"
 | 
					      name="loops.PredicateSource"
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- textindexng converters -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <utility
 | 
				
			||||||
 | 
					      provides="textindexng.interfaces.IConverter"
 | 
				
			||||||
 | 
					      component="textindexng.converters.null.NullConverter"
 | 
				
			||||||
 | 
					      name="text/structured"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <utility
 | 
				
			||||||
 | 
					      provides="textindexng.interfaces.IConverter"
 | 
				
			||||||
 | 
					      component="textindexng.converters.null.NullConverter"
 | 
				
			||||||
 | 
					      name="text/restructured"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <include package=".knowledge" />
 | 
					  <include package=".knowledge" />
 | 
				
			||||||
  <include package=".organize" />
 | 
					  <include package=".organize" />
 | 
				
			||||||
  <include package=".process" />
 | 
					  <include package=".process" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,9 @@ from zope import schema
 | 
				
			||||||
from persistent import Persistent
 | 
					from persistent import Persistent
 | 
				
			||||||
from cStringIO import StringIO
 | 
					from cStringIO import StringIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from zope.app.event.objectevent import ObjectModifiedEvent, Attributes
 | 
				
			||||||
 | 
					from zope.event import notify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from textindexng.interfaces import IIndexableContent
 | 
					from textindexng.interfaces import IIndexableContent
 | 
				
			||||||
from textindexng.content import IndexContentCollector
 | 
					from textindexng.content import IndexContentCollector
 | 
				
			||||||
from cybertools.relation.registry import getRelations
 | 
					from cybertools.relation.registry import getRelations
 | 
				
			||||||
| 
						 | 
					@ -205,6 +208,7 @@ class DocumentWriteFileAdapter(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def write(self, data):
 | 
					    def write(self, data):
 | 
				
			||||||
        self.context.data = unicode(data.replace('\r', ''), 'UTF-8')
 | 
					        self.context.data = unicode(data.replace('\r', ''), 'UTF-8')
 | 
				
			||||||
 | 
					        notify(ObjectModifiedEvent(self.context, Attributes(IDocument, 'data')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DocumentReadFileAdapter(object):
 | 
					class DocumentReadFileAdapter(object):
 | 
				
			||||||
| 
						 | 
					@ -230,6 +234,7 @@ class IndexAttributes(object):
 | 
				
			||||||
    def __init__(self, context):
 | 
					    def __init__(self, context):
 | 
				
			||||||
        self.context = context
 | 
					        self.context = context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # obsolete, use TextIndexNG (with indexableContent() method) instead
 | 
				
			||||||
    def text(self):
 | 
					    def text(self):
 | 
				
			||||||
        context = self.context
 | 
					        context = self.context
 | 
				
			||||||
        return ' '.join((zapi.getName(context), context.title, context.data)).strip()
 | 
					        return ' '.join((zapi.getName(context), context.title, context.data)).strip()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@ Let's do some basic set up
 | 
				
			||||||
  >>> site = placefulSetUp(True)
 | 
					  >>> site = placefulSetUp(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> from zope import component, interface
 | 
					  >>> from zope import component, interface
 | 
				
			||||||
 | 
					  >>> from zope.interface import implements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
and setup a simple loops site with a concept manager and some concepts
 | 
					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
 | 
					(with all the type machinery, what in real life is done via standard
 | 
				
			||||||
| 
						 | 
					@ -81,3 +82,22 @@ a controller attribute for the search view.
 | 
				
			||||||
  'return submitReplacing("1.results", "1.search.form",
 | 
					  'return submitReplacing("1.results", "1.search.form",
 | 
				
			||||||
       "http://127.0.0.1/loops/views/page/.target19/@@searchresults.html")'
 | 
					       "http://127.0.0.1/loops/views/page/.target19/@@searchresults.html")'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The searchresults.html view, i.e. the SearchResults view class provides the
 | 
				
			||||||
 | 
					result set of the search via its `results` property.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from loops.search.browser import SearchResults
 | 
				
			||||||
 | 
					  >>> form = {'search.2.title': 'yes', 'search.2.text': u'foo' }
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=form)
 | 
				
			||||||
 | 
					  >>> resultsView = SearchResults(page, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Before accessing the `results` property we have to prepare a catalog.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from zope.app.catalog.interfaces import ICatalog
 | 
				
			||||||
 | 
					  >>> class DummyCat(object):
 | 
				
			||||||
 | 
					  ...     implements(ICatalog)
 | 
				
			||||||
 | 
					  ...     def searchResults(self, **criteria):
 | 
				
			||||||
 | 
					  ...         return []
 | 
				
			||||||
 | 
					  >>> component.provideUtility(DummyCat())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> resultsView.results
 | 
				
			||||||
 | 
					  []
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ $Id$
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zope import interface, component
 | 
					from zope import interface, component
 | 
				
			||||||
 | 
					from zope.app.catalog.interfaces import ICatalog
 | 
				
			||||||
from zope.app.pagetemplate import ViewPageTemplateFile
 | 
					from zope.app.pagetemplate import ViewPageTemplateFile
 | 
				
			||||||
from zope.cachedescriptors.property import Lazy
 | 
					from zope.cachedescriptors.property import Lazy
 | 
				
			||||||
from zope.formlib.namedtemplate import NamedTemplate, NamedTemplateImplementation
 | 
					from zope.formlib.namedtemplate import NamedTemplate, NamedTemplateImplementation
 | 
				
			||||||
| 
						 | 
					@ -75,3 +76,22 @@ class SearchResults(BaseView):
 | 
				
			||||||
    def __call__(self):
 | 
					    def __call__(self):
 | 
				
			||||||
        return innerHtml(self)
 | 
					        return innerHtml(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Lazy
 | 
				
			||||||
 | 
					    def results(self):
 | 
				
			||||||
 | 
					        request = self.request
 | 
				
			||||||
 | 
					        text = request.get('search.2.text')
 | 
				
			||||||
 | 
					        if not text:
 | 
				
			||||||
 | 
					            return set()
 | 
				
			||||||
 | 
					        useTitle = request.get('search.2.title')
 | 
				
			||||||
 | 
					        useFull = request.get('search.2.full')
 | 
				
			||||||
 | 
					        r1 = r2 = set()
 | 
				
			||||||
 | 
					        cat = component.getUtility(ICatalog)
 | 
				
			||||||
 | 
					        if useFull:
 | 
				
			||||||
 | 
					            criteria = {'loops_resource_textng': {'query': text},}
 | 
				
			||||||
 | 
					            r1 = set(cat.searchResults(**criteria))
 | 
				
			||||||
 | 
					        if useTitle:
 | 
				
			||||||
 | 
					            criteria = {'loops_title': text,}
 | 
				
			||||||
 | 
					            r2 = set(cat.searchResults(**criteria))
 | 
				
			||||||
 | 
					        result = [BaseView(r, request) for r in r1.union(r2)]
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,23 @@
 | 
				
			||||||
<metal:search define-macro="search">
 | 
					<metal:search define-macro="search">
 | 
				
			||||||
  <div id="search"
 | 
					  <div id="search"
 | 
				
			||||||
       tal:define="macros item/template/macros">
 | 
					       tal:define="macros item/template/macros;
 | 
				
			||||||
 | 
					                   idPrefix string:${view/itemNum}.search;
 | 
				
			||||||
 | 
					                   formId string:$idPrefix.form;
 | 
				
			||||||
 | 
					                   resultsId string:$idPrefix.results">
 | 
				
			||||||
    <h3 tal:attributes="class string:content-$level;
 | 
					    <h3 tal:attributes="class string:content-$level;
 | 
				
			||||||
                        ondblclick item/openEditWindow">
 | 
					                        ondblclick item/openEditWindow">
 | 
				
			||||||
      Search
 | 
					      Search
 | 
				
			||||||
    </h3>
 | 
					    </h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div metal:define-macro="search_form" class="searchForm"
 | 
					    <div metal:define-macro="search_form" class="searchForm">
 | 
				
			||||||
         tal:define="idPrefix string:${view/itemNum}.search;
 | 
					 | 
				
			||||||
                     formId string:$idPrefix.form">
 | 
					 | 
				
			||||||
      <fieldset class="box">
 | 
					      <fieldset class="box">
 | 
				
			||||||
        <form action="." method="post" id="1.search.form"
 | 
					        <form action="." method="post" id="1.search.form"
 | 
				
			||||||
              tal:attributes="id formId">
 | 
					              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">
 | 
					          <table cellpadding="3">
 | 
				
			||||||
            <tal:block repeat="search_selection python: ['type', 'text']">
 | 
					            <tal:block repeat="search_param python: ['type', 'text']">
 | 
				
			||||||
              <metal:row use-macro="macros/search_row" />
 | 
					              <metal:row use-macro="macros/search_row" />
 | 
				
			||||||
            </tal:block>
 | 
					            </tal:block>
 | 
				
			||||||
            <tr>
 | 
					            <tr>
 | 
				
			||||||
| 
						 | 
					@ -24,10 +28,9 @@
 | 
				
			||||||
            </tr>
 | 
					            </tr>
 | 
				
			||||||
            <tr>
 | 
					            <tr>
 | 
				
			||||||
              <td colspan="2">
 | 
					              <td colspan="2">
 | 
				
			||||||
                <input type="submit" name="1.search" value="Search" class="submit"
 | 
					                <input type="submit" name="button.search" value="Search" class="submit"
 | 
				
			||||||
                       tal:attributes="name string:$idPrefix.submit;
 | 
					                       tal:attributes="onclick python:
 | 
				
			||||||
                                       onclick python:
 | 
					                                item.submitReplacing(resultsId, formId, view)" />
 | 
				
			||||||
                                item.submitReplacing('1.results', formId, view)" />
 | 
					 | 
				
			||||||
              </td>
 | 
					              </td>
 | 
				
			||||||
            </tr>
 | 
					            </tr>
 | 
				
			||||||
          </table>
 | 
					          </table>
 | 
				
			||||||
| 
						 | 
					@ -35,11 +38,17 @@
 | 
				
			||||||
      </fieldset>
 | 
					      </fieldset>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div metal:define-macro="search_results"
 | 
					    <div metal:define-macro="search_results" id="1.search.results"
 | 
				
			||||||
         id="1.results">
 | 
					         tal:attributes="id resultsId | request/search.resultsId">
 | 
				
			||||||
      <fieldset class="box">
 | 
					      <fieldset class="box"
 | 
				
			||||||
        Search results
 | 
					                tal:condition="request/search.submitted | nothing">
 | 
				
			||||||
        <p tal:content="python:request.get('2.search.1.text', 'nothing')" />
 | 
					        <legend>Search results</legend>
 | 
				
			||||||
 | 
					        <div tal:repeat="row view/results">
 | 
				
			||||||
 | 
					          <div>
 | 
				
			||||||
 | 
					            <a tal:attributes="href string:${view/url}/.target${row/uniqueId}"
 | 
				
			||||||
 | 
					               tal:content="row/title" />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
      </fieldset>
 | 
					      </fieldset>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,18 +56,22 @@
 | 
				
			||||||
</metal:search>
 | 
					</metal:search>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<tr metal:define-macro="search_row" id="search.row.1.1"
 | 
					<tr metal:define-macro="search_row" id="1.1.row"
 | 
				
			||||||
    tal:define="rowNum item/rowNum;
 | 
					    tal:define="rowNum item/rowNum;
 | 
				
			||||||
                idPrefix string:$idPrefix.$rowNum;
 | 
					                idPrefix string:$idPrefix.$rowNum;
 | 
				
			||||||
                selection search_selection | item/searchSelection"
 | 
					                namePrefix string:search.$rowNum;
 | 
				
			||||||
 | 
					                param search_param | item/searchParam"
 | 
				
			||||||
    tal:attributes="id string:$idPrefix.row">
 | 
					    tal:attributes="id string:$idPrefix.row">
 | 
				
			||||||
  <td style="width: 30px">
 | 
					  <td style="width: 30px">
 | 
				
			||||||
 | 
					    <input type="hidden" name="paramtype" value="type"
 | 
				
			||||||
 | 
					           tal:attributes="name string:$namePrefix.paramtype;
 | 
				
			||||||
 | 
					                           value param" />
 | 
				
			||||||
    <input type="button" value="−"
 | 
					    <input type="button" value="−"
 | 
				
			||||||
           title="Remove search parameter"
 | 
					           title="Remove search parameter"
 | 
				
			||||||
           tal:condition="python: selection not in ['type', 'text']" /> 
 | 
					           tal:condition="python: param not in ['type', 'text']" /> 
 | 
				
			||||||
  </td>
 | 
					  </td>
 | 
				
			||||||
  <td>
 | 
					  <td>
 | 
				
			||||||
    <div metal:use-macro="macros/?selection" />
 | 
					    <div metal:use-macro="macros/?param" />
 | 
				
			||||||
  </td>
 | 
					  </td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,7 +82,7 @@
 | 
				
			||||||
    <label for="text"
 | 
					    <label for="text"
 | 
				
			||||||
           tal:attributes="for string:$idPrefix.text">Type:</label>
 | 
					           tal:attributes="for string:$idPrefix.text">Type:</label>
 | 
				
			||||||
    <select name="text"
 | 
					    <select name="text"
 | 
				
			||||||
            tal:attributes="name string:$idPrefix.text;
 | 
					            tal:attributes="name string:$namePrefix.text;
 | 
				
			||||||
                            id string:$idPrefix.text;">
 | 
					                            id string:$idPrefix.text;">
 | 
				
			||||||
      <option value=".loops/concepts/topic">Topic</option>
 | 
					      <option value=".loops/concepts/topic">Topic</option>
 | 
				
			||||||
      <option value="loops.resource.Document">Document</option>
 | 
					      <option value="loops.resource.Document">Document</option>
 | 
				
			||||||
| 
						 | 
					@ -84,21 +97,21 @@
 | 
				
			||||||
  <div>
 | 
					  <div>
 | 
				
			||||||
    <h3>Search text</h3>
 | 
					    <h3>Search text</h3>
 | 
				
			||||||
    <input type="checkbox" checked
 | 
					    <input type="checkbox" checked
 | 
				
			||||||
           name="title" id="title"
 | 
					           name="title" id="title" value="yes"
 | 
				
			||||||
           tal:attributes="name string:$idPrefix.title;
 | 
					           tal:attributes="name string:$namePrefix.title;
 | 
				
			||||||
                           id string:$idPrefix.title;" />
 | 
					                           id string:$idPrefix.title;" />
 | 
				
			||||||
    <label for="title"
 | 
					    <label for="title"
 | 
				
			||||||
           tal:attributes="for string:$idPrefix.title">Title</label>
 | 
					           tal:attributes="for string:$idPrefix.title">Title</label>
 | 
				
			||||||
    <input type="checkbox"
 | 
					    <input type="checkbox"
 | 
				
			||||||
           name="full" id="full"
 | 
					           name="full" id="full" value="yes"
 | 
				
			||||||
           tal:attributes="name string:$idPrefix.full;
 | 
					           tal:attributes="name string:$namePrefix.full;
 | 
				
			||||||
                           id string:$idPrefix.full;" />
 | 
					                           id string:$idPrefix.full;" />
 | 
				
			||||||
    <label for="full"
 | 
					    <label for="full"
 | 
				
			||||||
           tal:attributes="for string:$idPrefix.full">Full text</label>  
 | 
					           tal:attributes="for string:$idPrefix.full">Full text</label>  
 | 
				
			||||||
    <label for="text"
 | 
					    <label for="text"
 | 
				
			||||||
           tal:attributes="for string:$idPrefix.text">Search words:</label>
 | 
					           tal:attributes="for string:$idPrefix.text">Search words:</label>
 | 
				
			||||||
    <input type="text" name="text"
 | 
					    <input type="text" name="text"
 | 
				
			||||||
           tal:attributes="name string:$idPrefix.text;
 | 
					           tal:attributes="name string:$namePrefix.text;
 | 
				
			||||||
                           id string:$idPrefix.text;" />
 | 
					                           id string:$idPrefix.text;" />
 | 
				
			||||||
    <input type="button" value="+"
 | 
					    <input type="button" value="+"
 | 
				
			||||||
           title="Add search word" /> 
 | 
					           title="Add search word" /> 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								target.py
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								target.py
									
										
									
									
									
								
							| 
						 | 
					@ -31,8 +31,10 @@ from zope.interface import implements
 | 
				
			||||||
from zope import schema
 | 
					from zope import schema
 | 
				
			||||||
from zope.security.proxy import removeSecurityProxy
 | 
					from zope.security.proxy import removeSecurityProxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from loops.interfaces import IResource
 | 
					from zope.app.event.objectevent import ObjectModifiedEvent, Attributes
 | 
				
			||||||
from loops.interfaces import IDocument, IMediaAsset
 | 
					from zope.event import notify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from loops.interfaces import ILoopsObject, IResource, IDocument, IMediaAsset
 | 
				
			||||||
from loops.interfaces import IDocumentView, IMediaAssetView
 | 
					from loops.interfaces import IDocumentView, IMediaAssetView
 | 
				
			||||||
from loops.interfaces import IView
 | 
					from loops.interfaces import IView
 | 
				
			||||||
from loops.interfaces import IConcept, IConceptView
 | 
					from loops.interfaces import IConcept, IConceptView
 | 
				
			||||||
| 
						 | 
					@ -55,7 +57,10 @@ class TargetProxy(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getTitle(self):
 | 
					    def getTitle(self):
 | 
				
			||||||
        return self.target.title
 | 
					        return self.target.title
 | 
				
			||||||
    def setTitle(self, title): self.target.title = title
 | 
					    def setTitle(self, title):
 | 
				
			||||||
 | 
					        self.target.title = title
 | 
				
			||||||
 | 
					        notify(ObjectModifiedEvent(self.target,
 | 
				
			||||||
 | 
					                                   Attributes(ILoopsObject, 'title')))
 | 
				
			||||||
    title = property(getTitle, setTitle)
 | 
					    title = property(getTitle, setTitle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +70,9 @@ class ConceptProxy(TargetProxy):
 | 
				
			||||||
    adapts(IConceptView)
 | 
					    adapts(IConceptView)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getConceptType(self): return self.target.conceptType
 | 
					    def getConceptType(self): return self.target.conceptType
 | 
				
			||||||
    def setConceptType(self, conceptType): self.target.conceptType = conceptType
 | 
					    def setConceptType(self, conceptType):
 | 
				
			||||||
 | 
					        self.target.conceptType = conceptType
 | 
				
			||||||
 | 
					        notify(ObjectModifiedEvent(self.target, Attributes(IConcept, 'conceptType')))
 | 
				
			||||||
    conceptType = property(getConceptType, setConceptType)
 | 
					    conceptType = property(getConceptType, setConceptType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getChildren(self, predicates=None):
 | 
					    def getChildren(self, predicates=None):
 | 
				
			||||||
| 
						 | 
					@ -81,6 +88,7 @@ class ConceptProxy(TargetProxy):
 | 
				
			||||||
class ResourceProxy(TargetProxy):
 | 
					class ResourceProxy(TargetProxy):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setContentType(self, contentType):
 | 
					    def setContentType(self, contentType):
 | 
				
			||||||
 | 
					        notify(ObjectModifiedEvent(self.target, Attributes(IResource, 'contentType')))
 | 
				
			||||||
        self.target.contentType = contentType
 | 
					        self.target.contentType = contentType
 | 
				
			||||||
    def getContentType(self): return self.target.contentType
 | 
					    def getContentType(self): return self.target.contentType
 | 
				
			||||||
    contentType = property(getContentType, setContentType)
 | 
					    contentType = property(getContentType, setContentType)
 | 
				
			||||||
| 
						 | 
					@ -91,7 +99,9 @@ class DocumentProxy(ResourceProxy):
 | 
				
			||||||
    implements(IDocument)
 | 
					    implements(IDocument)
 | 
				
			||||||
    adapts(IDocumentView)
 | 
					    adapts(IDocumentView)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setData(self, data): self.target.data = data
 | 
					    def setData(self, data):
 | 
				
			||||||
 | 
					        self.target.data = data
 | 
				
			||||||
 | 
					        notify(ObjectModifiedEvent(self.target, Attributes(IDocument, 'data')))
 | 
				
			||||||
    def getData(self): return self.target.data
 | 
					    def getData(self): return self.target.data
 | 
				
			||||||
    data = property(getData, setData)
 | 
					    data = property(getData, setData)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue