Included chages after moving from intids to simpler implementation

This commit is contained in:
David Convent 2013-03-05 09:53:53 +01:00
parent 2104bc4c20
commit 7416350c25
20 changed files with 326 additions and 310 deletions

View File

@ -0,0 +1,19 @@
PFWBGED - Notes réunion avec service doc
=========================================
- Définition des termes de l'interface
Equivalences entre crochet = pas suffisant
au moins un intitulé ("employé pour")
BT = termes génériques
RT = voir aussi (termes associés)
NT = termes spécifiques
Employé pour (équivalences) (nobreak, semicolon)
NA = Note d'application
NH = Note historique
nothing = /néant/

View File

@ -17,7 +17,7 @@ long_description = (
setup(name='collective.dms.thesaurus',
version=version,
description="Mail content type for document management system",
description="Thesaurus based keywords for Plone",
long_description=long_description,
classifiers=[
"Environment :: Web Environment",
@ -42,8 +42,9 @@ setup(name='collective.dms.thesaurus',
install_requires=[
'setuptools',
'plone.app.dexterity',
'plone.directives.form',
'collective.contact.core',
#'plone.directives.form',
#'collective.contact.core',
'collective.dms.thesauruswidget',
'five.grok',
],
extras_require={

View File

@ -1,40 +0,0 @@
from zope.interface import implements, implementer
from zope.component import adapter, getUtility
from zope.app.intid.interfaces import IIntIds
from zc.relation.interfaces import ICatalog
from z3c.form.interfaces import IFormLayer, IFieldWidget
from z3c.form.widget import FieldWidget
from z3c.relationfield.interfaces import IRelationList
from z3c.relationfield.schema import RelationChoice, RelationList
from plone.formwidget.contenttree.widget import MultiContentTreeWidget
from plone.formwidget.contenttree.utils import closest_content
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from .relatedkeywords import RelatedThesaurusKeywords
from .relatedkeywords import RelatedThesaurusKeywordsWidget
from .relatedkeywords import ThesaurusPathSourceBinder
class IBroaderThesaurusKeywords(IRelationList):
""""""
@adapter(IBroaderThesaurusKeywords, IFormLayer)
@implementer(IFieldWidget)
def BroaderThesaurusKeywordsFieldWidget(field, request):
return FieldWidget(field, RelatedThesaurusKeywordsWidget(
request, from_attribute='broader'))
class BroaderThesaurusKeywords(RelatedThesaurusKeywords):
implements(IBroaderThesaurusKeywords)
def __init__(self, **kwargs):
RelationList.__init__(self,
value_type=RelationChoice(
title=u'',
source=ThesaurusPathSourceBinder()),
**kwargs)

View File

@ -20,8 +20,9 @@
/>
<browser:page
for="collective.dms.thesaurus.dmskeyword.IDmsKeyword"
name="dmskeyword.view"
for="collective.dms.thesaurus.dmskeyword.IDmsKeyword"
layer="plone.app.z3cform.interfaces.IPloneFormLayer"
class="collective.dms.thesaurus.browser.view.DmsKeywordView"
template="dmskeyword_view.pt"
permission="zope2.View"

View File

@ -9,12 +9,14 @@
<metal:main fill-slot="main">
<h1 class="documentFirstHeading" tal:content="context/Title" />
<div tal:replace="structure provider:plone.belowcontenttitle" />
<div id="dmskeywords-navigation">
<tal:broader define="widget python:view.widgets.get('broader')">
<div id="dmskeywords-navigation-broader"
class="field"
tal:condition="python:widget.__name__ not in ('IBasic.title', 'IBasic.description', 'title', 'description',)">
<div id="dmskeywords-navigation-broader-field"
class="field">
<label tal:content="widget/label" />
<br />
<div tal:content="structure widget/render" />
@ -23,6 +25,18 @@
<div id="dmskeywords-navigation-middle">
<h1 class="documentFirstHeading" tal:content="context/Title" />
<p class="documentDescription">
<tal:equivs define="widget python:view.widgets.get('equivs')"
condition="python:widget.__name__ not in ('IBasic.title', 'IBasic.description', 'title', 'description',) and widget.terms()"
>[
<tal:equiv-terms repeat="value widget/terms"
><span tal:content="value"
/><span tal:condition="not:repeat/value/end"
tal:replace="python:', '"
/></tal:equiv-terms>
]</tal:equivs></p>
<dl class="portalMessage warning"
tal:define="widget python:view.widgets.get('scope_note')"
tal:condition="widget/value"
@ -37,32 +51,19 @@
<span tal:replace="structure widget/render" />
</dd></dl>
<h1 class="documentFirstHeading" tal:content="context/Title" />
<p class="documentDescription">
<tal:equivs define="widget python:view.widgets.get('equivs')"
condition="python:widget.__name__ not in ('IBasic.title', 'IBasic.description', 'title', 'description',) and widget.terms()"
>[
<tal:equiv-terms repeat="value widget/terms"
><span tal:content="value"
/><span tal:condition="not:repeat/value/end"
tal:replace="python:', '"
/></tal:equiv-terms>
]</tal:equivs></p>
<div tal:replace="structure provider:plone.belowcontenttitle" />
<tal:related define="widget python:view.widgets.get('related')">
<div id="dmskeywords-navigation-related"
class="field"
tal:condition="python:widget.__name__ not in ('IBasic.title', 'IBasic.description', 'title', 'description',)">
<label tal:content="widget/label" />
<br />
<div tal:content="structure widget/render" />
</div>
<div id="dmskeywords-navigation-related-field"
class="field">
<label tal:content="widget/label" />
<br />
<div tal:content="structure widget/render" />
</div>
</tal:related>
</div>
<div class="field" id="dmskeywords-navigation-narrower">
<div class="field" id="dmskeywords-navigation-narrower-field">
<label tal:content="string:NT (Narrower Terms)" />
<br />
<tal:list condition="view/children">

View File

@ -16,6 +16,8 @@ class DmsKeywordView(DefaultView):
@property
def children(self):
return []
"""
intids = getUtility(IIntIds)
catalog = getUtility(ICatalog)
value = []
@ -36,3 +38,4 @@ class DmsKeywordView(DefaultView):
value.append(tp)
return value
"""

View File

@ -19,12 +19,9 @@
<include package="." />
<include package=".browser" />
<include file="widgets.zcml" />
<interface interface=".vocabulary.IMainThesaurus" />
<adapter factory=".relatedkeywords.RelatedThesaurusKeywordsFieldWidget" />
<adapter factory=".broaderkeywords.BroaderThesaurusKeywordsFieldWidget" />
<adapter factory=".equivalences.ThesaurusKeywordEquivalencesFieldWidget" />
<adapter factory=".field.ThesaurusKeywordsFieldWidget" />
<include file="widgets.zcml" />
<adapter
name="SearchableText"

View File

@ -9,30 +9,31 @@ from plone.dexterity.content import Item
from plone.supermodel import model
from . import _
from .relatedkeywords import RelatedThesaurusKeywords
from .broaderkeywords import BroaderThesaurusKeywords
from .equivalences import ThesaurusKeywordEquivalences
from .keywordsfield import ThesaurusKeywords
from .equivalencesfield import ThesaurusKeywordEquivalences
class IDmsKeyword(model.Schema):
""" """
# EQ: equivalences
equivs = ThesaurusKeywordEquivalences(
title=u'EQ (Equivalences)',
title=_(u'EQ (Equivalences)'),
required=False,
)
# BT: broader term
broader = BroaderThesaurusKeywords(
broader = ThesaurusKeywords(
title=_(u"BT (Broader Terms)"),
required=False,
vocabulary=u'dms.thesaurus.samesource'
)
# RT: related term
related = RelatedThesaurusKeywords(
related = ThesaurusKeywords(
title=_(u"RT (Related Terms)"),
required=False,
display_backrefs=True
display_backrefs=True,
vocabulary=u'dms.thesaurus.samesource'
)
# HN: historical note

View File

@ -1,24 +1,35 @@
from zope.interface import implements, implementer
from zope.component import adapter, getUtility
from zope.component import adapter
#, getUtility
from zope import schema
from zope.schema.interfaces import IList
from zope.app.intid.interfaces import IIntIds
#from zope.app.intid.interfaces import IIntIds
from zc.relation.interfaces import ICatalog
#from zc.relation.interfaces import ICatalog
from z3c.form.interfaces import IFormLayer, IFieldWidget
from z3c.form.widget import FieldWidget
from z3c.form.browser.multi import MultiWidget
# #from z3c.relationfield.interfaces import IRelationList
#from z3c.relationfield.interfaces import IRelationList
#from z3c.relationfield.schema import RelationChoice, RelationList
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
#from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class IThesaurusKeywordEquivalences(IList):
""""""
class ThesaurusKeywordEquivalences(schema.List):
implements(IThesaurusKeywordEquivalences)
def __init__(self, **kwargs):
super(ThesaurusKeywordEquivalences, self).__init__(
value_type=schema.TextLine(
title=u'', required=False),
**kwargs)
class ThesaurusKeywordEquivalencesWidget(MultiWidget):
def __init__(self, request):
@ -33,12 +44,3 @@ class ThesaurusKeywordEquivalencesWidget(MultiWidget):
def ThesaurusKeywordEquivalencesFieldWidget(field, request):
return FieldWidget(field, ThesaurusKeywordEquivalencesWidget(request))
class ThesaurusKeywordEquivalences(schema.List):
implements(IThesaurusKeywordEquivalences)
def __init__(self, **kwargs):
super(ThesaurusKeywordEquivalences, self).__init__(
value_type=schema.TextLine(
title=u'', required=False),
**kwargs)

View File

@ -1,55 +0,0 @@
from zope.interface import implements, implementer
from zope.component import adapter
from z3c.form.interfaces import IFormLayer, IFieldWidget
from z3c.form.widget import FieldWidget
from z3c.relationfield.interfaces import IRelationList
from z3c.relationfield.schema import RelationChoice, RelationList
from plone.formwidget.contenttree.widget import MultiContentTreeWidget
from plone.formwidget.contenttree.utils import closest_content
from plone.formwidget.contenttree import ObjPathSourceBinder
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class IThesaurusKeywords(IRelationList):
""""""
class ThesaurusKeywordsWidget(MultiContentTreeWidget):
display_template = ViewPageTemplateFile('thesaurus-keywords-display.pt')
def __init__(self, request):
super(ThesaurusKeywordsWidget, self).__init__(request)
def terms(self):
return [ x for x in self.value ]
@adapter(IThesaurusKeywords, IFormLayer)
@implementer(IFieldWidget)
def ThesaurusKeywordsFieldWidget(field, request):
return FieldWidget(field, ThesaurusKeywordsWidget(request))
class ThesaurusPathSourceBinder(ObjPathSourceBinder):
def __call__(self, context):
selectable_filter = self.selectable_filter
selectable_filter.criteria['portal_type'] = ('dmskeyword',)
#thesaurus_path = {'query': '/'.join(context.getPhysicalPath()[:-1])}
#selectable_filter.criteria['path'] = thesaurus_path
return self.path_source(
closest_content(context),
selectable_filter=selectable_filter,
navigation_tree_query=self.navigation_tree_query)
class ThesaurusKeywords(RelationList):
implements(IThesaurusKeywords)
def __init__(self, **kwargs):
RelationList.__init__(self,
value_type=RelationChoice(
title=u'',
source=ThesaurusPathSourceBinder()),
**kwargs)

View File

@ -0,0 +1,86 @@
from Acquisition import aq_parent
from zope import schema
from zope.interface import implements, implementer
from zope.component import adapter
#from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.schema.interfaces import ISet
from zope.schema.interfaces import IFromUnicode
from z3c.form.interfaces import IFormLayer, IFieldWidget, ISequenceWidget
#from z3c.form.interfaces import IWidget
from z3c.form.widget import FieldWidget, SequenceWidget
#from z3c.form.widget import Widget
#from z3c.form.browser.select import SelectWidget
from . import _
class IThesaurusKeywords(ISet):
pass
class ThesaurusKeywords(schema.Set):
implements(IThesaurusKeywords, IFromUnicode)
def __init__(self, display_backrefs=False, **kw):
self.display_backrefs = display_backrefs
vocabulary = kw.pop('vocabulary', u'dms.thesaurus.global')
super(ThesaurusKeywords, self).__init__(
value_type=schema.Choice(vocabulary=vocabulary),
**kw)
class IThesaurusKeywordsWidget(ISequenceWidget):
pass
class NoThesaurusFound(Exception):
"""No thesaurus found"""
class ThesaurusKeywordsWidget(SequenceWidget):
implements(IThesaurusKeywordsWidget)
def __init__(self, request, display_backrefs=False):
self.display_backrefs = display_backrefs
super(ThesaurusKeywordsWidget, self).__init__(request)
def items(self):
value = []
for token in self.value:
# Ignore no value entries. They are in the request only.
if token == self.noValueToken:
continue
term = self.terms.getTermByToken(token)
value.append({'id': token, 'value': term.value,
'content': term.title, 'selected': True
})
return value
def displayItems(self):
thesaurus = self.context
# XXX attention on remonte a partir d'un document ou d'un kw
value = []
for token in self.value:
# Ignore no value entries. They are in the request only.
if token == self.noValueToken:
continue
term = self.terms.getTermByToken(token)
value.append(
{'title': term.title,
'href': '#dummy',
})
return value
@adapter(IThesaurusKeywords, IFormLayer)
@implementer(IFieldWidget)
def ThesaurusKeywordsFieldWidget(field, request):
return FieldWidget(field, ThesaurusKeywordsWidget(
request, display_backrefs=field.display_backrefs))

View File

@ -2,6 +2,7 @@
<metadata>
<version>0001</version>
<dependencies>
<dependency>profile-plone.app.z3cform:default</dependency>
<dependency>profile-plone.app.dexterity:default</dependency>
<dependency>profile-plone.app.intid:default</dependency>
<dependency>profile-collective.dms.thesaurus:default</dependency>

View File

@ -1,25 +0,0 @@
<ul id="" class=""
tal:condition="view/dictvalues"
tal:attributes="id view/id;
class view/klass;
style view/style;
title view/title;
lang view/lang;
onclick view/onclick;
ondblclick view/ondblclick;
onmousedown view/onmousedown;
onmouseup view/onmouseup;
onmouseover view/onmouseover;
onmousemove view/onmousemove;
onmouseout view/onmouseout;
onkeypress view/onkeypress;
onkeydown view/onkeydown;
onkeyup view/onkeyup
"><li tal:repeat="value view/dictvalues"
><a class="selected-option"
href="#"
tal:content="value/label"
tal:attributes="href value/url"
/></li
></ul>
<em tal:condition="not:view/dictvalues">(nothing)</em>

View File

@ -1,102 +0,0 @@
from zope.interface import implements, implementer
from zope.component import adapter, getUtility
from zope.app.intid.interfaces import IIntIds
from zc.relation.interfaces import ICatalog
from z3c.form.interfaces import IFormLayer, IFieldWidget
from z3c.form.widget import FieldWidget
from z3c.relationfield.interfaces import IRelationList
from z3c.relationfield.schema import RelationChoice, RelationList
from plone.formwidget.contenttree.widget import MultiContentTreeWidget
from plone.formwidget.contenttree.utils import closest_content
from plone.formwidget.contenttree import ObjPathSourceBinder
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class IRelatedThesaurusKeywords(IRelationList):
""""""
class RelatedThesaurusKeywordsWidget(MultiContentTreeWidget):
display_template = ViewPageTemplateFile('related-thesaurus-keywords-display.pt')
def __init__(self, request, from_attribute='related', display_backrefs=False):
self.from_attribute = from_attribute
self.display_backrefs = display_backrefs
super(RelatedThesaurusKeywordsWidget, self).__init__(request)
def get_url(self, v):
return v
def get_term(self, v):
return self.terms.getTermByToken(v)
def get_label(self, v):
return self.get_term(v).title
def get_hn(self, v):
return self.get_term(v).value.historical_note
def get_sn(self, v):
return self.get_term(v).value.scope_note
def dictvalues(self):
refs = [dict(
url=self.get_url(x),
label=self.get_label(x),
hn=self.get_hn(x),
sn=self.get_sn(x),
) for x in self.value]
if self.display_backrefs:
intids = getUtility(IIntIds)
catalog = getUtility(ICatalog)
try:
doc_intid = intids.getId(self.context)
except KeyError:
pass
else:
for ref in catalog.findRelations(
{'to_id': doc_intid,
'from_attribute': self.from_attribute}):
tp = dict(
url=ref.from_path,
label=ref.from_object.Title(),
hn=ref.from_object.historical_note,
sn=ref.from_object.scope_note
)
if tp not in refs:
refs.append(tp)
return refs
@adapter(IRelatedThesaurusKeywords, IFormLayer)
@implementer(IFieldWidget)
def RelatedThesaurusKeywordsFieldWidget(field, request):
return FieldWidget(field, RelatedThesaurusKeywordsWidget(
request, display_backrefs=field.display_backrefs))
class ThesaurusPathSourceBinder(ObjPathSourceBinder):
def __call__(self, context):
selectable_filter = self.selectable_filter
selectable_filter.criteria['portal_type'] = ('dmskeyword',)
thesaurus_path = {'query': '/'.join(context.getPhysicalPath()[:-1])}
selectable_filter.criteria['path'] = thesaurus_path
return self.path_source(
closest_content(context),
selectable_filter=selectable_filter,
navigation_tree_query=self.navigation_tree_query)
class RelatedThesaurusKeywords(RelationList):
implements(IRelatedThesaurusKeywords)
def __init__(self, display_backrefs=False, **kwargs):
self.display_backrefs = display_backrefs
RelationList.__init__(self,
value_type=RelationChoice(
title=u'',
source=ThesaurusPathSourceBinder()),
**kwargs)

View File

@ -1,20 +0,0 @@
<ul id="" class=""
tal:condition="view/terms"
tal:attributes="id view/id;
class view/klass;
style view/style;
title view/title;
lang view/lang;
onclick view/onclick;
ondblclick view/ondblclick;
onmousedown view/onmousedown;
onmouseup view/onmouseup;
onmouseover view/onmouseover;
onmousemove view/onmousemove;
onmouseout view/onmouseout;
onkeypress view/onkeypress;
onkeydown view/onkeydown;
onkeyup view/onkeyup"><li
tal:repeat="item view/terms"
><span tal:replace="item/title" /></li></ul
><em tal:condition="not:view/value">(nothing)</em>

View File

@ -0,0 +1,11 @@
<ul id="" class=""
tal:condition="view/displayItems"
tal:define="th_url python:'/'.join(view.context.absolute_url().split('/')[:-1]);"
tal:attributes="id view/id"
><li tal:repeat="value view/displayItems"><a href=""
tal:content="value/title"
tal:attributes="href value/href"
/></li
></ul>
<em tal:condition="not:view/displayItems"
i18n:translate="">none</em>

View File

@ -0,0 +1,52 @@
<div xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
tal:omit-tag="">
<select id="" name="" class="" tabindex="" disabled="" multiple="multiple" size="5"
style="display: none;"
tal:attributes="id view/id;
name string:${view/name}:list">
<tal:block repeat="item view/items"
><option id="" value="" selected="selected"
tal:condition="item/selected"
tal:attributes="id item/id;
value item/value"
tal:content="item/content">label</option
><option id="" value=""
tal:condition="not:item/selected"
tal:attributes="id item/id;
value item/value"
tal:content="item/content">label</option
></tal:block>
</select>
<input name="field-empty-marker" type="hidden" value="1"
tal:attributes="name string:${view/name}-empty-marker" />
<span id="" class=""><tal:block
tal:repeat="item view/items"
><span class="selected-option"
tal:attributes="data-term-id item/value">
<span tal:content="item/content"
/> <span class="remove">×</span></span><tal:block condition="not:repeat/item/end">, </tal:block
></tal:block
></span>
<!--script type="text/javascript" tal:content="structure view/js"></script-->
<style type="text/css">
span.selected-option {
border: 1px solid gray;
border-radius: 3px;
background: #eef;
padding: 0.5ex 1ex;
}
span.remove {
margin-left: 1ex;
background: black;
color: white;
border-radius: 3px;
}
</style>
<button onclick="return false;">Add</button>
</div>

View File

@ -5,20 +5,21 @@ from zope.app.intid.interfaces import IIntIds
from z3c.relationfield import RelationValue
from Products.Five.browser import BrowserView
from zope.component import getUtility
from zope.schema.interfaces import IVocabularyFactory
from zope.event import notify
from zope.lifecycleevent import ObjectAddedEvent, ObjectModifiedEvent
class ImportJson(BrowserView):
def __call__(self):
self.intids = component.getUtility(IIntIds)
path = '/tmp/thesaurus.json'
# XXX: replace with a path given in the query string, or load json
# from POST data
terms = json.load(file(path))
term_intids = {}
# 1st step; create object for terms
for term_id, term in terms.items():
@ -29,21 +30,20 @@ class ImportJson(BrowserView):
title=term.get('title'))
object = getattr(self.context, term_id)
notify(ObjectAddedEvent(object))
try:
term_intids[term_id] = self.intids.getId(object)
except KeyError:
self.intids.register(object)
#try:
# term_intids[term_id] = self.intids.getId(object)
#except KeyError:
# self.intids.register(object)
object.title = term.get('title')
object.historical_note = term.get('historical_note')
object.scope_note = term.get('scope_note')
object.equivs = term.get('equivalents')
term_intids[term_id] = self.intids.getId(object)
# 2nd step; add relations
for term_id, term in terms.items():
object = getattr(self.context, term_id)
object.related = [RelationValue(term_intids[x]) for x in term.get('related', [])]
object.broader = [RelationValue(term_intids[x]) for x in term.get('parents', [])]
object.related = [x for x in term.get('related', [])]
object.broader = [x for x in term.get('parents', [])]
notify(ObjectModifiedEvent(object))
return 'OK'

View File

@ -0,0 +1,64 @@
from zope.interface import Interface
#from zope.interface import implements
from five import grok
#from zope.component import queryUtility
from zope.schema.interfaces import IVocabularyFactory
#from zope.schema.interfaces import ISource, IContextSourceBinder
from zope.schema.vocabulary import SimpleVocabulary
#from zope.schema.vocabulary import SimpleTerm
from Products.CMFCore.utils import getToolByName
class IMainThesaurus(Interface):
""" Marker interface for main thesaurus container
"""
class GlobalThesaurusSource(object):
grok.implements(IVocabularyFactory)
def __call__(self, context):
catalog = getToolByName(context, 'portal_catalog')
results = catalog(portal_type='dmskeyword')
keywords = [x.getObject() for x in results]
def cmp_keyword(x, y):
return cmp(x.title, y.title)
keywords.sort(cmp_keyword)
keyword_ids = [x.id for x in keywords]
keyword_terms = [SimpleVocabulary.createTerm(
x.id, x.id, x.title) for x in keywords]
return SimpleVocabulary(keyword_terms)
def __iter__(self):
# hack to let schema editor handle the field
yield u'DO NOT TOUCH'
grok.global_utility(GlobalThesaurusSource,
name=u'dms.thesaurus.global')
class KeywordFromSameThesaurusSource(object):
grok.implements(IVocabularyFactory)
def __call__(self, context):
#XXX: need to add url filter
catalog = getToolByName(context, 'portal_catalog')
results = catalog(portal_type='dmskeyword')
keywords = [x.getObject() for x in results]
def cmp_keyword(x, y):
return cmp(x.title, y.title)
keywords.sort(cmp_keyword)
keyword_ids = [x.id for x in keywords]
keyword_terms = [SimpleVocabulary.createTerm(
x.id, x.id, x.title) for x in keywords]
return SimpleVocabulary(keyword_terms)
def __iter__(self):
# hack to let schema editor handle the field
yield u'DO NOT TOUCH'
grok.global_utility(KeywordFromSameThesaurusSource,
name=u'dms.thesaurus.samesource')

View File

@ -3,11 +3,30 @@
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:z3c="http://namespaces.zope.org/z3c">
<z3c:widgetTemplate
mode="display"
widget=".equivalences.ThesaurusKeywordEquivalencesWidget"
layer="z3c.form.interfaces.IFormLayer"
template="thesaurus-keyword-equivs-display.pt"
/>
<!-- thesaurus keywords widget, used in other types schema -->
<adapter factory=".keywordsfield.ThesaurusKeywordsFieldWidget"/>
<z3c:widgetTemplate
mode="display"
widget=".keywordsfield.IThesaurusKeywordsWidget"
layer="z3c.form.interfaces.IFormLayer"
template="thesauruskeywords_display.pt"/>
<z3c:widgetTemplate
mode="input"
widget=".keywordsfield.IThesaurusKeywordsWidget"
layer="z3c.form.interfaces.IFormLayer"
template="thesauruskeywords_input.pt"/>
<!-- keyword equivalences widget, used in keyword schema -->
<adapter factory=".equivalencesfield.ThesaurusKeywordEquivalencesFieldWidget" />
<z3c:widgetTemplate
mode="display"
widget=".equivalencesfield.ThesaurusKeywordEquivalencesWidget"
layer="z3c.form.interfaces.IFormLayer"
template="thesaurus-keyword-equivs-display.pt"
/>
</configure>