provide create and edit dialogs for concepts - starting with glossary items
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2209 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
3a3755f466
commit
309f5f1e21
13 changed files with 228 additions and 73 deletions
|
@ -239,10 +239,13 @@ class BaseView(GenericView):
|
|||
def listTypes(self, include=None, exclude=None, sortOn='title'):
|
||||
types = [dict(token=t.token, title=t.title)
|
||||
for t in ITypeManager(self.context).listTypes(include, exclude)]
|
||||
if sortOn:
|
||||
types.sort(key=lambda x: x[sortOn])
|
||||
#if sortOn:
|
||||
# types.sort(key=lambda x: x[sortOn])
|
||||
return types
|
||||
|
||||
def getTypesVocabulary(self, include=None):
|
||||
return util.KeywordVocabulary(self.listTypes(include, ('hidden',)))
|
||||
|
||||
def resourceTypes(self):
|
||||
return util.KeywordVocabulary(self.listTypes(('resource',), ('hidden',)))
|
||||
#if t.factory == Resource]) # ? if necessary -> type.qualifiers
|
||||
|
@ -377,16 +380,6 @@ class BaseView(GenericView):
|
|||
cm.register('js', 'dojo.js', resourceName='ajax.dojo/dojo.js')
|
||||
|
||||
|
||||
# actions - obsolete, see loops.browser.action
|
||||
|
||||
#class Action(object):
|
||||
|
||||
# def __init__(self, renderer, url, **kw):
|
||||
# self.renderer = renderer
|
||||
# self.url = url
|
||||
# self.__dict__.update(kw)
|
||||
|
||||
|
||||
# vocabulary stuff
|
||||
|
||||
class LoopsTerms(object):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2004 Helmut Merz helmutm@cy55.de
|
||||
# Copyright (c) 2007 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
|
||||
|
@ -60,10 +60,13 @@ class ConceptEditForm(EditForm):
|
|||
|
||||
@property
|
||||
def form_fields(self):
|
||||
fields = FormFields(IConcept)
|
||||
typeInterface = self.typeInterface
|
||||
if typeInterface is not None:
|
||||
fields = FormFields(fields, typeInterface)
|
||||
if typeInterface is None:
|
||||
fields = FormFields(IConcept)
|
||||
elif 'title' in typeInterface: # new "complete" type interface
|
||||
fields = FormFields(typeInterface)
|
||||
else:
|
||||
fields = FormFields(IConcept, typeInterface)
|
||||
return fields
|
||||
|
||||
def setUpWidgets(self, ignore_request=False):
|
||||
|
@ -96,9 +99,12 @@ class ConceptView(BaseView):
|
|||
|
||||
def fieldData(self):
|
||||
ti = IType(self.context).typeInterface
|
||||
if not ti: return
|
||||
if not ti:
|
||||
return
|
||||
adapter = ti(self.context)
|
||||
for n, f in schema.getFieldsInOrder(ti):
|
||||
if n in ('title', 'description',): # already shown in header
|
||||
continue
|
||||
value = getattr(adapter, n, '')
|
||||
if not value:
|
||||
continue
|
||||
|
|
|
@ -557,6 +557,13 @@
|
|||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<page
|
||||
name="create_concept.html"
|
||||
for="loops.interfaces.INode"
|
||||
class="loops.browser.form.CreateConceptForm"
|
||||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<page
|
||||
name="edit_concept.html"
|
||||
for="loops.interfaces.INode"
|
||||
|
@ -571,6 +578,13 @@
|
|||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<page
|
||||
name="inner_concept_form.html"
|
||||
for="loops.interfaces.INode"
|
||||
class="loops.browser.form.InnerConceptForm"
|
||||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<zope:adapter
|
||||
name="create_resource"
|
||||
for="loops.browser.node.NodeView
|
||||
|
@ -587,6 +601,22 @@
|
|||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<zope:adapter
|
||||
name="create_concept"
|
||||
for="loops.browser.node.NodeView
|
||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
factory="loops.browser.form.CreateConcept"
|
||||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<zope:adapter
|
||||
name="edit_concept"
|
||||
for="loops.browser.node.NodeView
|
||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
factory="loops.browser.form.EditConcept"
|
||||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<!-- inner HTML views -->
|
||||
|
||||
<page
|
||||
|
|
156
browser/form.py
156
browser/form.py
|
@ -25,6 +25,7 @@ $Id$
|
|||
from zope import component, interface, schema
|
||||
from zope.component import adapts
|
||||
from zope.event import notify
|
||||
from zope.interface import Interface
|
||||
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
|
||||
|
||||
from zope.app.container.interfaces import INameChooser
|
||||
|
@ -46,8 +47,8 @@ from cybertools.composer.schema.browser.common import schema_macros, schema_edit
|
|||
from cybertools.composer.schema.schema import FormState
|
||||
from cybertools.typology.interfaces import IType, ITypeManager
|
||||
from loops.common import adapted
|
||||
from loops.concept import Concept, ResourceRelation
|
||||
from loops.interfaces import IConcept, IResourceManager, IDocument
|
||||
from loops.concept import Concept, ConceptRelation, ResourceRelation
|
||||
from loops.interfaces import IConcept, IConceptSchema, IResourceManager, IDocument
|
||||
from loops.interfaces import IFile, IExternalFile, INote, ITextDocument
|
||||
from loops.browser.node import NodeView
|
||||
from loops.browser.concept import ConceptRelationView
|
||||
|
@ -98,9 +99,10 @@ class ObjectForm(NodeView):
|
|||
|
||||
@Lazy
|
||||
def schema(self):
|
||||
#ti = self.typeInterface or Interface #IConcept
|
||||
ti = self.typeInterface or IConceptSchema
|
||||
schemaFactory = component.getAdapter(self.adapted, ISchemaFactory)
|
||||
return schemaFactory(self.typeInterface, manager=self,
|
||||
request=self.request)
|
||||
return schemaFactory(ti, manager=self, request=self.request)
|
||||
|
||||
@Lazy
|
||||
def fields(self):
|
||||
|
@ -186,11 +188,10 @@ class EditConceptForm(EditObjectForm):
|
|||
|
||||
title = _(u'Edit Concept')
|
||||
form_action = 'edit_concept'
|
||||
isInnerHtml = False
|
||||
|
||||
@Lazy
|
||||
def typeInterface(self):
|
||||
return IType(self.target).typeInterface or IConcept
|
||||
return IType(self.target).typeInterface or IConceptSchema
|
||||
|
||||
@property
|
||||
def assignments(self):
|
||||
|
@ -224,13 +225,11 @@ class CreateObjectForm(ObjectForm):
|
|||
t = self.loopsRoot.loopsTraverse(typeToken)
|
||||
return removeSecurityProxy(ITypeConcept(t).typeInterface)
|
||||
else:
|
||||
#return INote
|
||||
return ITextDocument
|
||||
|
||||
@property
|
||||
def assignments(self):
|
||||
target = self.virtualTargetObject
|
||||
#target = self.target
|
||||
if (IConcept.providedBy(target) and
|
||||
target.conceptType !=
|
||||
self.loopsRoot.getConceptManager().getTypeConcept()):
|
||||
|
@ -239,10 +238,58 @@ class CreateObjectForm(ObjectForm):
|
|||
return ()
|
||||
|
||||
|
||||
class CreateConceptForm(CreateObjectForm):
|
||||
|
||||
title = _(u'Create Concept, Type = ')
|
||||
form_action = 'create_concept'
|
||||
|
||||
@Lazy
|
||||
def dialog_name(self):
|
||||
return self.request.get('dialog', 'createConcept')
|
||||
|
||||
@Lazy
|
||||
def adapted(self):
|
||||
ti = self.typeInterface
|
||||
if ti is None:
|
||||
return Concept()
|
||||
return ti(Concept())
|
||||
|
||||
@Lazy
|
||||
def instance(self):
|
||||
return IInstance(Concept())
|
||||
|
||||
@Lazy
|
||||
def typeInterface(self):
|
||||
typeToken = self.request.get('form.type')
|
||||
if typeToken:
|
||||
t = self.loopsRoot.loopsTraverse(typeToken)
|
||||
return removeSecurityProxy(ITypeConcept(t).typeInterface)
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def assignments(self):
|
||||
target = self.virtualTargetObject
|
||||
if (IConcept.providedBy(target) and
|
||||
target.conceptType !=
|
||||
self.loopsRoot.getConceptManager().getTypeConcept()):
|
||||
rv = ConceptRelationView(ConceptRelation(target, None), self.request)
|
||||
return (rv,)
|
||||
return ()
|
||||
|
||||
|
||||
class InnerForm(CreateObjectForm):
|
||||
|
||||
@property
|
||||
def macro(self): return self.fieldRenderers['fields']
|
||||
def macro(self):
|
||||
return self.fieldRenderers['fields']
|
||||
|
||||
|
||||
class InnerConceptForm(CreateConceptForm):
|
||||
|
||||
@property
|
||||
def macro(self):
|
||||
return self.fieldRenderers['fields']
|
||||
|
||||
|
||||
# processing form input
|
||||
|
@ -296,12 +343,6 @@ class EditObject(FormController):
|
|||
self.object = obj
|
||||
formState = self.updateFields()
|
||||
# TODO: error handling
|
||||
#errors = self.updateFields()
|
||||
#if errors:
|
||||
# self.view.setUp()
|
||||
# for fieldName, message in errors.items():
|
||||
# self.view.widgets[fieldName].error = message
|
||||
# return True
|
||||
self.request.response.redirect(self.view.virtualTargetUrl + '?version=this')
|
||||
return False
|
||||
|
||||
|
@ -342,8 +383,10 @@ class EditObject(FormController):
|
|||
return dict(fileupload=self.handleFileUpload)
|
||||
|
||||
def collectConcepts(self, fieldName, value):
|
||||
if self.old is None: self.old = []
|
||||
if self.selected is None: self.selected = []
|
||||
if self.old is None:
|
||||
self.old = []
|
||||
if self.selected is None:
|
||||
self.selected = []
|
||||
for v in value:
|
||||
if fieldName == 'old':
|
||||
self.old.append(v)
|
||||
|
@ -356,16 +399,25 @@ class EditObject(FormController):
|
|||
c, p = v.split(':')
|
||||
concept = util.getObjectForUid(c)
|
||||
predicate = util.getObjectForUid(p)
|
||||
obj.deassignConcept(concept, [predicate])
|
||||
self.deassignConcept(obj, concept, [predicate])
|
||||
for v in self.selected:
|
||||
if v != 'none' and v not in self.old:
|
||||
c, p = v.split(':')
|
||||
concept = util.getObjectForUid(c)
|
||||
predicate = util.getObjectForUid(p)
|
||||
exists = obj.getConceptRelations(predicates=[p], concept=concept)
|
||||
exists = self.getConceptRelations(obj, [p], concept)
|
||||
if not exists:
|
||||
self.assignConcept(obj, concept, predicate)
|
||||
|
||||
def getConceptRelations(self, obj, predicates, concept):
|
||||
return obj.getConceptRelations(predicates=predicates, concept=concept)
|
||||
|
||||
def assignConcept(self, obj, concept, predicate):
|
||||
obj.assignConcept(concept, predicate)
|
||||
|
||||
def deassignConcept(self, obj, concept, predicates):
|
||||
obj.deassignConcept(concept, predicates)
|
||||
|
||||
def checkCreateVersion(self, obj):
|
||||
form = self.request.form
|
||||
if form.get('version.create'):
|
||||
|
@ -379,14 +431,15 @@ class EditObject(FormController):
|
|||
|
||||
class CreateObject(EditObject):
|
||||
|
||||
def update(self):
|
||||
form = self.request.form
|
||||
container = self.loopsRoot.getResourceManager()
|
||||
title = form.get('title')
|
||||
if not title:
|
||||
raise BadRequest('Title field is empty')
|
||||
obj = Resource(title)
|
||||
data = form.get('data')
|
||||
factory = Resource
|
||||
defaultTypeToken = '.loops/concepts/textdocument'
|
||||
|
||||
@Lazy
|
||||
def container(self):
|
||||
return self.loopsRoot.getResourceManager()
|
||||
|
||||
def getNameFromData(self):
|
||||
data = self.request.form.get('data')
|
||||
if data and isinstance(data, FileUpload):
|
||||
name = getattr(data, 'filename', None)
|
||||
# strip path from IE uploads:
|
||||
|
@ -394,11 +447,21 @@ class CreateObject(EditObject):
|
|||
name = name.rsplit('\\', 1)[-1]
|
||||
else:
|
||||
name = None
|
||||
return name
|
||||
|
||||
def update(self):
|
||||
form = self.request.form
|
||||
container = self.container
|
||||
title = form.get('title')
|
||||
if not title:
|
||||
raise BadRequest('Title field is empty')
|
||||
obj = self.factory(title)
|
||||
name = self.getNameFromData()
|
||||
# TODO: validate fields
|
||||
name = INameChooser(container).chooseName(name, obj)
|
||||
container[name] = obj
|
||||
tc = form.get('form.type') or '.loops/concepts/note'
|
||||
obj.resourceType = self.loopsRoot.loopsTraverse(tc)
|
||||
tc = form.get('form.type') or self.defaultTypeToken
|
||||
obj.setType(self.loopsRoot.loopsTraverse(tc))
|
||||
notify(ObjectCreatedEvent(obj))
|
||||
self.object = obj
|
||||
self.updateFields() # TODO: suppress validation
|
||||
|
@ -406,3 +469,38 @@ class CreateObject(EditObject):
|
|||
self.request.response.redirect(self.view.request.URL)
|
||||
return False
|
||||
|
||||
|
||||
class EditConcept(EditObject):
|
||||
|
||||
def getConceptRelations(self, obj, predicates, concept):
|
||||
return obj.getParentRelations(predicates=predicates, parent=concept)
|
||||
|
||||
def assignConcept(self, obj, concept, predicate):
|
||||
obj.assignParent(concept, predicate)
|
||||
|
||||
def deassignConcept(self, obj, concept, predicates):
|
||||
obj.deassignParent(concept, predicates)
|
||||
|
||||
def update(self):
|
||||
self.object = self.view.virtualTargetObject
|
||||
formState = self.updateFields()
|
||||
# TODO: error handling
|
||||
self.request.response.redirect(self.view.virtualTargetUrl)
|
||||
return False
|
||||
|
||||
|
||||
class CreateConcept(EditConcept, CreateObject):
|
||||
|
||||
factory = Concept
|
||||
defaultTypeToken = '.loops/concepts/topic'
|
||||
|
||||
@Lazy
|
||||
def container(self):
|
||||
return self.loopsRoot.getConceptManager()
|
||||
|
||||
def getNameFromData(self):
|
||||
return None
|
||||
|
||||
def update(self):
|
||||
return CreateObject.update(self)
|
||||
|
||||
|
|
|
@ -36,7 +36,9 @@
|
|||
|
||||
|
||||
<metal:block define-macro="create" i18n:domain="loops">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<form method="post" enctype="multipart/form-data"
|
||||
tal:define="qualifier request/qualifier | string:resource;
|
||||
innerForm request/inner_form | string:inner_form.html">
|
||||
<input type="hidden" name="form.action" value="create"
|
||||
tal:attributes="value view/form_action" />
|
||||
<table cellpadding="3" class="form">
|
||||
|
@ -47,10 +49,12 @@
|
|||
tal:attributes="onChange
|
||||
string:return replaceFieldsNode(
|
||||
'form.fields', 'form.type',
|
||||
'${view/url}/inner_form.html')">
|
||||
'${view/url}/$innerForm')">
|
||||
<option value=".loops/concepts/note"
|
||||
i18n:translate=""
|
||||
tal:repeat="type view/resourceTypes"
|
||||
xtal:repeat="type view/resourceTypes"
|
||||
tal:repeat="type python:
|
||||
view.getTypesVocabulary((qualifier,))"
|
||||
tal:content="type/title"
|
||||
tal:attributes="value type/token;
|
||||
selected python:
|
||||
|
|
|
@ -23,7 +23,6 @@ $Id$
|
|||
"""
|
||||
|
||||
from zope import component, schema
|
||||
#from zope.app import zapi
|
||||
from zope.app.container.btree import BTreeContainer
|
||||
from zope.app.container.contained import Contained
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
|
@ -130,6 +129,9 @@ class Concept(Contained, Persistent):
|
|||
def getType(self):
|
||||
return self.conceptType
|
||||
|
||||
def setType(self, value):
|
||||
self.conceptType = value
|
||||
|
||||
def getLoopsRoot(self):
|
||||
return getParent(self).getLoopsRoot()
|
||||
|
||||
|
@ -252,7 +254,6 @@ class ConceptManager(BTreeContainer):
|
|||
|
||||
def getTypeConcept(self):
|
||||
if self.typeConcept is None:
|
||||
#self.typeConcept = self['type']
|
||||
self.typeConcept = self.get('type')
|
||||
return self.typeConcept
|
||||
|
||||
|
@ -311,7 +312,6 @@ class PredicateSourceList(object):
|
|||
typePred = cm.getTypePredicate()
|
||||
if defPred is not None and typePred is not None:
|
||||
result.append(defPred)
|
||||
#result.append(typePred)
|
||||
predType = defPred.conceptType
|
||||
if predType is not None and predType != cm.getTypeConcept():
|
||||
result.extend(p for p in predType.getChildren([typePred])
|
||||
|
|
|
@ -69,11 +69,8 @@ class IPotentialTarget(Interface):
|
|||
|
||||
# concept interfaces
|
||||
|
||||
class IConcept(ILoopsObject, IPotentialTarget):
|
||||
""" The concept is the central element of the loops framework.
|
||||
|
||||
A concept is related to other concepts, may have resources
|
||||
associated with it and may be referenced by views.
|
||||
class IConceptSchema(Interface):
|
||||
""" The primary fields of a concept object.
|
||||
"""
|
||||
|
||||
title = schema.TextLine(
|
||||
|
@ -90,6 +87,14 @@ class IConcept(ILoopsObject, IPotentialTarget):
|
|||
missing_value=u'',
|
||||
required=False)
|
||||
|
||||
|
||||
class IConcept(IConceptSchema, ILoopsObject, IPotentialTarget):
|
||||
""" The concept is the central element of the loops framework.
|
||||
|
||||
A concept is related to other concepts, may have resources
|
||||
associated with it and may be referenced by views.
|
||||
"""
|
||||
|
||||
conceptType = schema.Choice(
|
||||
title=_(u'Concept Type'),
|
||||
description=_(u"The type of the concept, specified by a relation to "
|
||||
|
@ -575,7 +580,8 @@ class IIndexAttributes(Interface):
|
|||
|
||||
# types stuff
|
||||
|
||||
class ITypeConcept(Interface):
|
||||
#class ITypeConcept(Interface):
|
||||
class ITypeConcept(IConceptSchema):
|
||||
""" Concepts of type 'type' should be adaptable to this interface.
|
||||
"""
|
||||
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
</zope:class>
|
||||
|
||||
<zope:adapter factory="loops.knowledge.knowledge.Topic"
|
||||
provides="cybertools.knowledge.interfaces.IKnowledgeElement"
|
||||
provides="loops.knowledge.interfaces.ITopic"
|
||||
trusted="True" />
|
||||
|
||||
<zope:class class="loops.knowledge.knowledge.Topic">
|
||||
<require permission="zope.View"
|
||||
interface="cybertools.knowledge.interfaces.IKnowledgeElement" />
|
||||
interface="loops.knowledge.interfaces.ITopic" />
|
||||
</zope:class>
|
||||
|
||||
<zope:adapter factory="loops.knowledge.knowledge.Task"
|
||||
|
|
|
@ -46,10 +46,14 @@ class GlossaryView(ConceptView):
|
|||
if category == 'portlet':
|
||||
actions.append(Action(self, title='Create Glossary Item...',
|
||||
description='Create a new glossary item.',
|
||||
url='create_glossaryitem.html',
|
||||
onClick="objectDialog('create', '%s/create_object.html'); "
|
||||
"return false;" % self.virtualTargetUrl,
|
||||
innerHtmlId='dialog.create'))
|
||||
url='create_concept.html',
|
||||
onClick="objectDialog('createGlossaryItem', "
|
||||
" '%s/create_concept.html?qualifier=concept"
|
||||
"&form.type=.loops/concepts/topic"
|
||||
"&inner_form=inner_concept_form.html"
|
||||
"&dialog=createGlossaryItem'); "
|
||||
"return false;" % page.virtualTargetUrl,
|
||||
innerHtmlId='dialog.createGlossaryItem'))
|
||||
return actions
|
||||
|
||||
|
||||
|
@ -62,11 +66,13 @@ class GlossaryItemView(ConceptView):
|
|||
def getActions(self, category='object', page=None):
|
||||
actions = []
|
||||
if category == 'portlet':
|
||||
actions.append(Action(self, title='Create Glossary Item...',
|
||||
description='Create a new glossary item.',
|
||||
url='create_glossaryitem.html'))
|
||||
actions.append(Action(self, title='Edit Glossary Item...',
|
||||
description='Modify glossary item.',
|
||||
url='edit_glossaryitem.html'))
|
||||
url='edit_concept.html',
|
||||
onClick="objectDialog('editGlossaryItem', "
|
||||
" '%s/edit_concept.html"
|
||||
"?dialog=editGlossaryItem'); "
|
||||
"return false;" % page.virtualTargetUrl,
|
||||
innerHtmlId='dialog.editGlossaryItem'))
|
||||
return actions
|
||||
|
||||
|
|
|
@ -26,4 +26,5 @@
|
|||
</a><tal:comma condition="not:repeat/related/end">,</tal:comma>
|
||||
</span>
|
||||
</p>
|
||||
<metal:resources use-macro="item/conceptMacros/conceptresources" />
|
||||
</metal:block>
|
||||
|
|
|
@ -29,8 +29,10 @@ from zope.i18nmessageid import MessageFactory
|
|||
from zope.security.proxy import removeSecurityProxy
|
||||
|
||||
from cybertools.knowledge.interfaces import IKnowing, IRequirementProfile
|
||||
from loops.organize.interfaces import IPerson as IBasePerson
|
||||
from cybertools.knowledge.interfaces import IKnowledgeElement
|
||||
from cybertools.organize.interfaces import ITask as IBaseTask
|
||||
from loops.interfaces import IConceptSchema
|
||||
from loops.organize.interfaces import IPerson as IBasePerson
|
||||
|
||||
_ = MessageFactory('zope')
|
||||
|
||||
|
@ -45,3 +47,9 @@ class IPerson(IBasePerson, IKnowing):
|
|||
class ITask(IBaseTask, IRequirementProfile):
|
||||
""" A task, also acting as a knowledge requirement profile.
|
||||
"""
|
||||
|
||||
|
||||
class ITopic(IConceptSchema, IKnowledgeElement):
|
||||
""" Just a topic, some general classification concept.
|
||||
"""
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ from cybertools.typology.interfaces import IType
|
|||
from cybertools.knowledge.interfaces import IKnowledgeElement, IKnowledgeProvider
|
||||
from cybertools.knowledge.knowing import Knowing
|
||||
from loops.interfaces import IConcept, IResource
|
||||
from loops.knowledge.interfaces import IPerson, ITask
|
||||
from loops.knowledge.interfaces import IPerson, ITask, ITopic
|
||||
from loops.organize.party import Person as BasePerson
|
||||
from loops.organize.task import Task as BaseTask
|
||||
from loops.common import AdapterBase
|
||||
|
@ -42,7 +42,7 @@ from loops.type import TypeInterfaceSourceList
|
|||
|
||||
# register type interfaces - (TODO: use a function for this)
|
||||
|
||||
TypeInterfaceSourceList.typeInterfaces += (IPerson, IKnowledgeElement,
|
||||
TypeInterfaceSourceList.typeInterfaces += (IPerson, ITopic, IKnowledgeElement,
|
||||
ITask, IKnowledgeProvider)
|
||||
|
||||
|
||||
|
@ -99,7 +99,7 @@ class Topic(AdapterBase, KnowledgeAdapterMixin):
|
|||
may act as a knowledge element.
|
||||
"""
|
||||
|
||||
implements(IKnowledgeElement)
|
||||
implements(ITopic)
|
||||
_adapterAttributes = ('context', '__parent__', 'parent')
|
||||
|
||||
def getParent(self):
|
||||
|
|
|
@ -140,6 +140,9 @@ class Resource(Image, Contained):
|
|||
def getType(self):
|
||||
return self.resourceType
|
||||
|
||||
def setType(self, value):
|
||||
self.resourceType = value
|
||||
|
||||
def _setData(self, data):
|
||||
#if not data:
|
||||
# return
|
||||
|
|
Loading…
Add table
Reference in a new issue