diff --git a/classifier/README.txt b/classifier/README.txt
index f35014d..e5b7a1b 100644
--- a/classifier/README.txt
+++ b/classifier/README.txt
@@ -27,7 +27,7 @@ configuration):
>>> concepts, resources, views = t.setup()
>>> len(concepts), len(resources)
- (20, 0)
+ (15, 0)
Let's now add an external collection that reads in a set of resources
from external files so we have something to work with.
diff --git a/classifier/testsetup.py b/classifier/testsetup.py
index a529bce..b3414e7 100644
--- a/classifier/testsetup.py
+++ b/classifier/testsetup.py
@@ -24,7 +24,7 @@ from loops.integrator.collection import DirectoryCollectionProvider
from loops.integrator.collection import ExternalCollectionAdapter
from loops.integrator.interfaces import IExternalCollection, IExternalCollectionProvider
from loops.organize.setup import SetupManager as OrganizeSetupManager
-from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
+#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
from loops.knowledge.knowledge import Person
from loops.knowledge.interfaces import IPerson
from loops.setup import SetupManager, addAndConfigureObject
@@ -39,7 +39,7 @@ class TestSite(BaseTestSite):
self.site = site
def setup(self):
- component.provideAdapter(KnowledgeSetupManager, name='knowledge')
+ #component.provideAdapter(KnowledgeSetupManager, name='knowledge')
component.provideAdapter(OrganizeSetupManager, name='organize')
concepts, resources, views = self.baseSetup()
diff --git a/expert/README.txt b/expert/README.txt
index 0404b89..9f9d949 100644
--- a/expert/README.txt
+++ b/expert/README.txt
@@ -27,7 +27,7 @@ configuration):
>>> concepts, resources, views = t.setup()
>>> len(concepts) + len(resources)
- 33
+ 37
>>> loopsRoot = site['loops']
@@ -47,19 +47,19 @@ Type- and text-based queries
>>> from loops.expert import query
>>> qu = query.Title('ty*')
>>> list(qu.apply())
- [0, 1, 47]
+ [0, 1, 68]
>>> qu = query.Type('loops:*')
>>> len(list(qu.apply()))
- 33
+ 37
>>> qu = query.Type('loops:concept:predicate')
>>> len(list(qu.apply()))
- 7
+ 8
>>> qu = query.Type('loops:concept:predicate') & query.Title('t*')
>>> list(qu.apply())
- [1, 43]
+ [1, 29]
State-based queries
-------------------
diff --git a/expert/search.txt b/expert/search.txt
index fa33f30..d752ac1 100755
--- a/expert/search.txt
+++ b/expert/search.txt
@@ -66,13 +66,13 @@ zcml in real life:
>>> t = searchView.typesForSearch()
>>> len(t)
- 14
+ 16
>>> t.getTermByToken('loops:resource:*').title
'Any Resource'
>>> t = searchView.conceptTypesForSearch()
>>> len(t)
- 11
+ 13
>>> t.getTermByToken('loops:concept:*').title
'Any Concept'
@@ -91,7 +91,7 @@ a controller attribute for the search view.
>>> 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");...'
+ "http://127.0.0.1/loops/views/page/.target99/@@searchresults.html");...'
Basic (text/title) search
-------------------------
@@ -177,7 +177,7 @@ of the concepts' titles:
>>> 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'}]}"
+ u"{identifier: 'id', items: [{label: 'Zope (Thema)', name: 'Zope', id: '104'}, {label: 'Zope 2 (Thema)', name: 'Zope 2', id: '106'}, {label: 'Zope 3 (Thema)', name: 'Zope 3', id: '108'}]}"
Preset Concept Types on Search Forms
------------------------------------
@@ -219,13 +219,13 @@ and thus include the customer type in the preset search types.
>>> 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'}]
+ {'token': '77', 'title': u'Customer 1'},
+ {'token': '79', 'title': u'Customer 2'},
+ {'token': '81', 'title': u'Customer 3'}]
Let's use this new search option for querying:
- >>> form = {'search.4.text_selected': u'58'}
+ >>> form = {'search.4.text_selected': u'77'}
>>> resultsView = SearchResults(page, TestRequest(form=form))
>>> results = list(resultsView.results)
>>> results[0].title
diff --git a/expert/testsetup.py b/expert/testsetup.py
index 90b5075..05d8b5e 100644
--- a/expert/testsetup.py
+++ b/expert/testsetup.py
@@ -14,7 +14,8 @@ from loops.expert.setup import SetupManager as ExpertSetupManager
from loops.resource import Resource
from loops.knowledge.interfaces import IPerson
from loops.knowledge.knowledge import Person
-from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
+#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
+from loops.knowledge.tests import importData
from loops.setup import SetupManager, addObject
from loops.tests.setup import TestSite as BaseTestSite
from loops.type import ConceptType, ResourceType, TypeConcept
@@ -32,10 +33,11 @@ class TestSite(BaseTestSite):
component.provideAdapter(Person, provides=IPerson)
- component.provideAdapter(KnowledgeSetupManager, name='knowledge')
+ #component.provideAdapter(KnowledgeSetupManager, name='knowledge')
component.provideAdapter(ExpertSetupManager, name='expert')
setup = SetupManager(loopsRoot)
concepts, resources, views = setup.setup()
+ importData(loopsRoot)
tType = concepts.getTypeConcept()
tDomain = concepts['domain']
diff --git a/external/README.txt b/external/README.txt
index 5005e0f..cfbdcb8 100644
--- a/external/README.txt
+++ b/external/README.txt
@@ -17,7 +17,7 @@ Let's set up a loops site with basic and example concepts and resources.
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
>>> len(concepts), len(resources), len(views)
- (30, 3, 1)
+ (34, 3, 1)
Importing loops Objects
@@ -44,7 +44,7 @@ Creating the corresponding objects
>>> loader = Loader(loopsRoot)
>>> loader.load(elements)
>>> len(concepts), len(resources), len(views)
- (31, 3, 1)
+ (35, 3, 1)
>>> from loops.common import adapted
>>> adMyquery = adapted(concepts['myquery'])
@@ -131,7 +131,7 @@ Extracting elements
>>> extractor = Extractor(loopsRoot, os.path.join(dataDirectory, 'export'))
>>> elements = list(extractor.extract())
>>> len(elements)
- 53
+ 68
Writing object information to the external storage
--------------------------------------------------
@@ -143,6 +143,7 @@ Writing object information to the external storage
>>> writer = PyWriter()
>>> writer.write(elements, output)
>>> print output.getvalue()
+ type(u'task', ...)...
type(u'country', u'Country', viewName=u'', typeInterface=u''..., options=u''...)...
type(u'query', u'Query', viewName=u'', typeInterface='loops.expert.concept.IQueryConcept'..., options=u''...)...
concept(u'myquery', u'My Query', u'query', options=u'option1\noption2',
@@ -184,6 +185,7 @@ corresponding extractor adapter.
>>> PyWriter().write(extractor.extract(), output)
>>> print output.getvalue()
+ type(u'task', ...)...
type(u'country', u'Country', viewName=u'', typeInterface=u''..., options=u''...)...
concept(u'myquery', u'My Query', u'query', options=u'option1\noption2',
viewName=u'mystuff.html')[
diff --git a/external/element.py b/external/element.py
index 1490dd2..672aaa2 100644
--- a/external/element.py
+++ b/external/element.py
@@ -30,10 +30,11 @@ from zope.traversing.api import getName, traverse
from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.interfaces import ISchemaFactory
+from cybertools.tracking.btree import TrackingStorage
from cybertools.typology.interfaces import IType
from loops.common import adapted
-from loops.interfaces import IConceptSchema
from loops.external.interfaces import IElement
+from loops.interfaces import IConceptSchema
from loops.i18n.common import I18NValue
from loops.layout.base import LayoutNode
from loops.predicate import adaptedRelation
@@ -132,6 +133,33 @@ class TypeElement(ConceptElement):
adapted(self.object).typeInterface = kw['typeInterface']
+class RecordManagerElement(Element):
+
+ elementType = 'records'
+ posArgs = ('name', 'trackFactory')
+
+ def __init__(self, name, trackFactory, **kw):
+ self['name'] = name
+ tf = self['trackFactory'] = trackFactory
+ if not isinstance(tf, basestring):
+ self['trackFactory'] = '.'.join((tf.__module__, tf.__name__))
+ for k, v in kw.items():
+ self[k] = v
+
+ def execute(self, loader):
+ name = self['name']
+ tf = resolve(self['trackFactory'])
+ records = loader.context.getRecordManager()
+ obj = records.get(name)
+ if obj is None:
+ obj = records[name] = TrackingStorage(trackFactory=tf)
+ else:
+ obj.trackFactory = tf
+ obj.indexAttributes = tf.index_attributes
+ obj.setupIndexes()
+ self.object = obj
+
+
class ChildElement(Element):
elementType = 'child'
@@ -261,6 +289,7 @@ class LayoutNodeElement(NodeElement):
elementTypes = dict(
type=TypeElement,
concept=ConceptElement,
+ records=RecordManagerElement,
child=ChildElement,
resource=ResourceElement,
resourceRelation=ResourceRelationElement,
@@ -270,5 +299,5 @@ elementTypes = dict(
I18NValue=I18NValue,
)
-toplevelElements = ('type', 'concept', 'resource',
+toplevelElements = ('type', 'concept', 'resource', 'records',
'child', 'resourceRelation', 'node', 'deassign')
diff --git a/i18n/README.txt b/i18n/README.txt
index 534ec0b..7aedcd3 100644
--- a/i18n/README.txt
+++ b/i18n/README.txt
@@ -18,15 +18,15 @@ ZCML setup):
>>> from loops.interfaces import ILoops, IConcept
>>> from loops.concept import Concept
>>> from loops.setup import ISetupManager
- >>> from loops.knowledge.setup import SetupManager
- >>> component.provideAdapter(SetupManager, (ILoops,), ISetupManager,
- ... name='knowledge')
>>> from loops.tests.setup import TestSite
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
+ >>> from loops.knowledge.tests import importData
+ >>> importData(loopsRoot)
+
>>> from loops.knowledge.knowledge import Topic
>>> component.provideAdapter(Topic)
diff --git a/integrator/README.txt b/integrator/README.txt
index 4d84425..cba0381 100644
--- a/integrator/README.txt
+++ b/integrator/README.txt
@@ -27,7 +27,7 @@ configuration):
>>> concepts, resources, views = t.setup()
>>> len(concepts) + len(resources)
- 18
+ 11
>>> loopsRoot = site['loops']
>>> #loopsRoot.options = ['useVersioning:rev']
diff --git a/integrator/testsetup.py b/integrator/testsetup.py
index cd4108c..f672a0e 100644
--- a/integrator/testsetup.py
+++ b/integrator/testsetup.py
@@ -18,7 +18,7 @@ from loops.resource import Resource, FileAdapter, ExternalFileAdapter
from loops.integrator.interfaces import IExternalSourceInfo, IExternalCollection
from loops.integrator.interfaces import IOfficeFile
from loops.integrator.office.base import OfficeFile
-from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
+#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
from loops.setup import SetupManager, addAndConfigureObject
from loops.tests.setup import TestSite as BaseTestSite
from loops.versioning.versionable import VersionableResource
@@ -32,7 +32,7 @@ class TestSite(BaseTestSite):
self.site = site
def setup(self):
- component.provideAdapter(KnowledgeSetupManager, name='knowledge')
+ #component.provideAdapter(KnowledgeSetupManager, name='knowledge')
concepts, resources, views = self.baseSetup()
component.provideAdapter(FileAdapter, provides=IFile)
diff --git a/knowledge/README.txt b/knowledge/README.txt
index ed77023..994b7ae 100644
--- a/knowledge/README.txt
+++ b/knowledge/README.txt
@@ -2,33 +2,32 @@
loops - Linked Objects for Organization and Processing Services
===============================================================
- ($Id$)
-
-Note: This package depends on cybertools.knowledge and cybertools.organize.
+Note: This package depends on cybertools.knowledge and loops.organize.
Let's do some basic set up
+ >>> from zope import component, interface
+
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
>>> site = placefulSetUp(True)
- >>> from zope import component, interface
-
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.interfaces import ILoops, IConcept
- >>> from loops.setup import ISetupManager
- >>> from loops.knowledge.setup import SetupManager
- >>> component.provideAdapter(SetupManager, (ILoops,), ISetupManager,
- ... name='knowledge')
-
>>> from loops.tests.setup import TestSite
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
+ >>> loopsRoot = site['loops']
+
+We then import a loops .dmp file containing all necessary types and
+predicates.
+
+ >>> from loops.knowledge.tests import importData
+ >>> importData(loopsRoot)
We need some type concepts for controlling the meaning of the concepts objects,
-these have already been created during setup:
+these have already been created during setup and .dmp import:
>>> topic = concepts['topic']
>>> person = concepts['person']
@@ -40,6 +39,7 @@ Manage knowledge and knowledge requirements
The classes used in this package are just adapters to IConcept.
+ >>> from loops.interfaces import IConcept
>>> from loops.knowledge.knowledge import Person, Topic, Task
>>> from loops.knowledge.interfaces import IPerson
>>> from cybertools.knowledge.interfaces import IKnowledgeElement
@@ -166,6 +166,34 @@ For testing, we first have to provide the needed utilities and settings
>>> view = MyKnowledge(task01C, request)
>>> prov = view.myKnowledgeProvidersForTask()
+
+Competence and Certification Management
+=======================================
+
+ >>> from cybertools.stateful.interfaces import IStatesDefinition
+ >>> from loops.knowledge.qualification import qualificationStates
+ >>> from loops.knowledge.interfaces import IQualificationRecords
+ >>> from loops.knowledge.qualification import QualificationRecords
+ >>> component.provideUtility(qualificationStates,
+ ... provides=IStatesDefinition,
+ ... name='knowledge.qualification')
+ >>> component.provideAdapter(QualificationRecords,
+ ... provides=IQualificationRecords)
+
+ >>> qurecs = loopsRoot.getRecordManager()['qualification']
+
+We first create a training that provides knowledge in Python specials.
+
+ >>> trainingPySpecC = concepts['trpyspec'] = Concept(
+ ... u'Python Specials Training')
+ >>> trainingPySpecC.assignParent(pySpecialsC)
+
+Then we record the need for John to acquire this knowledge.
+
+ >>> from loops.knowledge.browser import CreateQualificationRecordForm
+ >>> from loops.knowledge.browser import CreateQualificationRecord
+
+
Glossaries
==========
diff --git a/knowledge/browser.py b/knowledge/browser.py
index 53b7634..ff9781e 100644
--- a/knowledge/browser.py
+++ b/knowledge/browser.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
+# Copyright (c) 2012 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
@@ -19,8 +19,6 @@
"""
Definition of view classes and other browser related stuff for the
loops.knowledge package.
-
-$Id$
"""
from zope import interface, component
@@ -32,11 +30,17 @@ from cybertools.typology.interfaces import IType
from loops.browser.action import DialogAction
from loops.browser.common import BaseView
from loops.browser.concept import ConceptView
+from loops.expert.browser.report import ResultsConceptView
from loops.knowledge.interfaces import IPerson, ITask
+from loops.organize.work.browser import CreateWorkItemForm, CreateWorkItem
from loops.organize.party import getPersonForUser
from loops.util import _
+template = ViewPageTemplateFile('knowledge_macros.pt')
+knowledge_macros = template.macros
+
+
actions.register('createTopic', 'portlet', DialogAction,
title=_(u'Create Topic...'),
description=_(u'Create a new topic.'),
@@ -54,10 +58,19 @@ actions.register('editTopic', 'portlet', DialogAction,
dialogName='editTopic',
)
+actions.register('createQualification', 'portlet', DialogAction,
+ title=_(u'Create Qualification Record...'),
+ description=_(u'Create a work item for this person.'),
+ viewName='create_qualification.html',
+ dialogName='createQualification',
+ prerequisites=['registerDojoDateWidget', 'registerDojoNumberWidget',
+ 'registerDojoTextarea'],
+)
+
class MyKnowledge(ConceptView):
- template = ViewPageTemplateFile('knowledge_macros.pt')
+ template = template
@Lazy
def macro(self):
@@ -90,9 +103,30 @@ class MyKnowledge(ConceptView):
class Candidates(ConceptView):
- template = ViewPageTemplateFile('knowledge_macros.pt')
+ template = template
@Lazy
def macro(self):
return self.template.macros['requirement_candidates']
+
+# qualification stuff
+
+class PersonQualificationView(ResultsConceptView):
+
+ pass
+
+
+class CreateQualificationRecordForm(CreateWorkItemForm):
+
+ macros = knowledge_macros
+
+ @Lazy
+ def macro(self):
+ return self.macros['create_qualification']
+
+
+class CreateQualificationRecord(CreateWorkItem):
+
+ pass
+
diff --git a/knowledge/configure.zcml b/knowledge/configure.zcml
index 5b3a3c4..2552184 100644
--- a/knowledge/configure.zcml
+++ b/knowledge/configure.zcml
@@ -66,6 +66,22 @@
interface="cybertools.knowledge.interfaces.IKnowledgeProvider" />
+
+
+
+
+
+
+
+
+
+
+
-
-
diff --git a/knowledge/data/loops_knowledge_de.dmp b/knowledge/data/loops_knowledge_de.dmp
new file mode 100644
index 0000000..2ca69b4
--- /dev/null
+++ b/knowledge/data/loops_knowledge_de.dmp
@@ -0,0 +1,44 @@
+type(u'competence', u'Competence', viewName=u'',
+ typeInterface=u'', options=u'action.portlet:edit_concept')
+type(u'person', u'Person', viewName=u'',
+ typeInterface=u'loops.knowledge.interfaces.IPerson',
+ options=u'action.portlet:editPerson')
+type(u'task', u'Aufgabe', viewName=u'',
+ typeInterface=u'loops.knowledge.interfaces.ITask',
+ options=u'action.portlet:createTopic,editTopic')
+type(u'topic', u'Thema', viewName=u'',
+ typeInterface=u'loops.knowledge.interfaces.ITopic',
+ options=u'action.portlet:createTopic,editTopic')
+type(u'training', u'Schulung', viewName=u'',
+ typeInterface=u'loops.organize.interfaces.ITask',
+ options=u'action.portlet:create_subtype,edit_concept')
+
+concept(u'general', u'Allgemein', u'domain')
+concept(u'system', u'System', u'domain')
+
+# predicates
+concept(u'depends', u'depends', u'predicate')
+concept(u'knows', u'knows', u'predicate')
+concept(u'provides', u'provides', u'predicate')
+concept(u'requires', u'requires', u'predicate')
+
+concept(u'issubtype', u'is Subtype', u'predicate', options=u'hide_children',
+ predicateInterface='loops.interfaces.IIsSubtype')
+
+# structure
+child(u'competence', u'general', u'standard')
+child(u'depends', u'general', u'standard')
+child(u'knows', u'general', u'standard')
+child(u'person', u'general', u'standard')
+child(u'provides', u'general', u'standard')
+child(u'requires', u'general', u'standard')
+child(u'task', u'general', u'standard')
+child(u'topic', u'general', u'standard')
+child(u'training', u'general', u'standard')
+
+child(u'issubtype', u'system', u'standard')
+
+child(u'training', u'competence', u'issubtype', usePredicate=u'provides')
+
+# records
+records(u'qualification', u'loops.knowledge.qualification.QualificationRecord')
diff --git a/knowledge/interfaces.py b/knowledge/interfaces.py
index 7176ab5..f1aef6b 100644
--- a/knowledge/interfaces.py
+++ b/knowledge/interfaces.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
+# Copyright (c) 2012 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
@@ -18,8 +18,6 @@
"""
Interfaces for knowledge management and elearning with loops.
-
-$Id$
"""
from zope.interface import Interface, Attribute
@@ -29,6 +27,7 @@ from zope.security.proxy import removeSecurityProxy
from cybertools.knowledge.interfaces import IKnowing, IRequirementProfile
from cybertools.knowledge.interfaces import IKnowledgeElement
+from cybertools.organize.interfaces import IWorkItem, IWorkItems
from loops.interfaces import IConceptSchema, ILoopsAdapter
from loops.organize.interfaces import IPerson as IBasePerson
from loops.organize.interfaces import ITask as IBaseTask
@@ -63,3 +62,13 @@ class ITopic(IConceptSchema, IKnowledgeElement, ILoopsAdapter):
""" Just a topic, some general classification concept.
"""
+
+class IQualificationRecord(IWorkItem):
+ """ Records needs for qualification (acqusition of competence)
+ and corresponding participations in training events etc.
+ """
+
+
+class IQualificationRecords(IWorkItems):
+ """ Container for qualification records.
+ """
diff --git a/knowledge/knowledge.py b/knowledge/knowledge.py
index 80b42ba..e65cb9b 100644
--- a/knowledge/knowledge.py
+++ b/knowledge/knowledge.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
+# Copyright (c) 2012 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
@@ -19,8 +19,6 @@
"""
Adapters for IConcept providing interfaces from the
cybertools.knowledge package.
-
-$Id$
"""
from zope import interface, component
diff --git a/knowledge/knowledge_macros.pt b/knowledge/knowledge_macros.pt
index 1a8f660..5d12f77 100644
--- a/knowledge/knowledge_macros.pt
+++ b/knowledge/knowledge_macros.pt
@@ -57,4 +57,19 @@
+
+
+
+
+
+
+