work in progress: job positions and competences

This commit is contained in:
Helmut Merz 2014-07-31 18:45:07 +02:00
parent 11a7546506
commit f0248b2ec8
13 changed files with 154 additions and 27 deletions

View file

@ -27,7 +27,7 @@ configuration):
>>> concepts, resources, views = t.setup()
>>> len(concepts) + len(resources)
38
41
>>> loopsRoot = site['loops']
@ -47,11 +47,11 @@ Type- and text-based queries
>>> from loops.expert import query
>>> qu = query.Title('ty*')
>>> list(qu.apply())
[0, 2, 69]
[0, 2, 79]
>>> qu = query.Type('loops:*')
>>> len(list(qu.apply()))
38
41
>>> qu = query.Type('loops:concept:predicate')
>>> len(list(qu.apply()))

View file

@ -66,13 +66,13 @@ zcml in real life:
>>> t = searchView.typesForSearch()
>>> len(t)
16
19
>>> t.getTermByToken('loops:resource:*').title
'Any Resource'
>>> t = searchView.conceptTypesForSearch()
>>> len(t)
13
16
>>> 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/.target100/@@searchresults.html");...'
"http://127.0.0.1/loops/views/page/.target110/@@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 (Thema)', name: 'Zope', id: '105'}, {label: 'Zope 2 (Thema)', name: 'Zope 2', id: '107'}, {label: 'Zope 3 (Thema)', name: 'Zope 3', id: '109'}]}"
u"{identifier: 'id', items: [{label: 'Zope (Thema)', name: 'Zope', id: '115'}, {label: 'Zope 2 (Thema)', name: 'Zope 2', id: '117'}, {label: 'Zope 3 (Thema)', name: 'Zope 3', id: '119'}]}"
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': '78', 'title': u'Customer 1'},
{'token': '80', 'title': u'Customer 2'},
{'token': '82', 'title': u'Customer 3'}]
{'token': '88', 'title': u'Customer 1'},
{'token': '90', 'title': u'Customer 2'},
{'token': '92', 'title': u'Customer 3'}]
Let's use this new search option for querying:
>>> form = {'search.4.text_selected': u'74'}
>>> form = {'search.4.text_selected': u'84'}
>>> resultsView = SearchResults(page, TestRequest(form=form))
>>> results = list(resultsView.results)
>>> results[0].title

6
external/README.txt vendored
View file

@ -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)
(35, 3, 1)
(38, 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)
(36, 3, 1)
(39, 3, 1)
>>> from loops.common import adapted
>>> adMyquery = adapted(concepts['myquery'])
@ -118,7 +118,7 @@ Extracting elements
>>> extractor = Extractor(loopsRoot, os.path.join(dataDirectory, 'export'))
>>> elements = list(extractor.extract())
>>> len(elements)
67
74
Writing object information to the external storage
--------------------------------------------------

View file

@ -1,6 +1,12 @@
type(u'competence', u'Kompetenz', viewName=u'',
type(u'competence', u'Qualifikation', viewName=u'',
typeInterface=u'loops.knowledge.qualification.interfaces.ICompetence',
options=u'action.portlet:create_subtype,edit_concept')
type(u'ipskill', u'Kompetenz', viewName=u'',
options=u'action.portlet:edit_concept')
type(u'ipskillsrequired', u'Soll-Profil', viewName=u'',
options=u'action.portlet:edit_concept')
type(u'jobposition', u'Stelle', viewName=u'',
options=u'action.portlet:edit_concept')
type(u'person', u'Person', viewName=u'',
typeInterface=u'loops.knowledge.interfaces.IPerson',
options=u'action.portlet:createQualification,editPerson')
@ -35,6 +41,9 @@ concept(u'qualification_overview', u'Qualification Overview', u'report',
# structure
child(u'general', u'competence', u'standard')
child(u'general', u'depends', u'standard')
child(u'general', u'ipskill', u'standard')
child(u'general', u'ipskillsrequired', u'standard')
child(u'general', u'jobposition', u'standard')
child(u'general', u'knows', u'standard')
child(u'general', u'person', u'standard')
child(u'general', u'provides', u'standard')
@ -44,6 +53,7 @@ child(u'general', u'topic', u'standard')
#child(u'general', u'training', u'standard')
child(u'system', u'issubtype', u'standard')
child(u'system', u'report', u'standard')
child(u'competence', u'competence', u'issubtype')
#child(u'competence', u'training', u'issubtype', usePredicate=u'provides')

View file

@ -1,6 +1,14 @@
type(u'competence', u'Kompetenz', viewName=u'',
type(u'competence', u'Qualifikation', viewName=u'',
typeInterface=u'loops.knowledge.qualification.interfaces.ICompetence',
options=u'action.portlet:create_subtype,edit_concept')
type(u'ipskill', u'Kompetenz', viewName=u'',
options=u'action.portlet:edit_concept')
type(u'ipskillsrequired', u'Soll-Profil', viewName=u'',
options=u'action.portlet:edit_concept')
type(u'jobposition', u'Stelle', viewName=u'',
options=u'action.portlet:edit_concept')
type(u'report', u'Report', viewName=u'',
typeInterface='loops.expert.report.IReport')
# type(u'person', u'Person', viewName=u'',
# typeInterface=u'loops.knowledge.interfaces.IPerson',
# options=u'action.portlet:editPerson')
@ -33,6 +41,9 @@ concept(u'qualification_overview', u'Qualification Overview', u'report',
# structure
child(u'general', u'competence', u'standard')
child(u'general', u'depends', u'standard')
child(u'general', u'ipskill', u'standard')
child(u'general', u'ipskillsrequired', u'standard')
child(u'general', u'jobposition', u'standard')
child(u'general', u'knows', u'standard')
#child(u'general', u'person', u'standard')
child(u'general', u'provides', u'standard')
@ -42,6 +53,7 @@ child(u'general', u'requires', u'standard')
#child(u'general', u'training', u'standard')
child(u'system', u'issubtype', u'standard')
child(u'system', u'report', u'standard')
child(u'competence', u'competence', u'issubtype')
#child(u'competence', u'training', u'issubtype', usePredicate=u'provides')

View file

@ -25,11 +25,71 @@ from zope import interface, component
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from cybertools.browser.action import actions
from loops.browser.action import DialogAction
from loops.browser.concept import ConceptView
from loops.expert.browser.report import ResultsConceptView
from loops.knowledge.browser import template, knowledge_macros
from loops.organize.party import getPersonForUser
from loops.util import _
template = ViewPageTemplateFile('qualification_macros.pt')
actions.register('createJobPosition', 'portlet', DialogAction,
title=_(u'Create Job...'),
description=_(u'Create a new job / position.'),
viewName='create_concept.html',
dialogName='createPosition',
typeToken='.loops/concepts/jobposition',
fixedType=True,
innerForm='inner_concept_form.html',
permission='loops.AssignAsParent',
)
class Qualifications(ResultsConceptView):
reportName = 'qualification_overview'
class QualificationBaseView(object):
template = template
templateName = 'knowledge.qualification'
@Lazy
def institutionType(self):
return self.conceptManager['institution']
@Lazy
def jobPositionType(self):
return self.conceptManager['jobposition']
@Lazy
def isMemberPredicate(self):
return self.conceptManager['ismember']
class JobPositionsOverview(QualificationBaseView, ConceptView):
macroName = 'jobpositions'
@Lazy
def positions(self):
result = []
p = getPersonForUser(self.context, self.request)
if p is not None:
for parent in p.getParents([self.isMemberPredicate]):
if parent.conceptType == self.institutionType:
for child in parent.getChildren([self.defaultPredicate]):
if child.conceptType == self.jobPositionType:
result.append(child)
return result
class IPSkillsForm(QualificationBaseView, ConceptView):
""" Form for entering interpersonal skills required for a certain position.
"""
macroName = 'ipskillsform'

View file

@ -23,6 +23,22 @@
factory="loops.knowledge.qualification.browser.Qualifications"
permission="zope.View" />
<zope:adapter
name="jobpositions.html"
for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.knowledge.qualification.browser.JobPositionsOverview"
permission="zope.View" />
<zope:adapter
name="ipskillsform.html"
for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.knowledge.qualification.browser.IPSkillsForm"
permission="zope.View" />
<!-- reports -->
<zope:adapter

View file

@ -0,0 +1,17 @@
<html i18n:domain="loops">
<metal:jobpositions define-macro="jobpositions">
<metal:block use-macro="view/concept_macros/concepttitle" />
<h2 i18n:translate="">Jobs / Positions</h2>
<metal:block use-macro="view/concept_macros/conceptchildren" />
<table>
<tr><th></th></tr>
<tr tal:repeat="pos item/positions">
<td tal:content="pos/title"></td>
</tr>
</table>
</metal:jobpositions>
</html>

Binary file not shown.

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: 0.13.0\n"
"POT-Creation-Date: 2007-05-22 12:00 CET\n"
"PO-Revision-Date: 2014-07-11 12:00 CET\n"
"PO-Revision-Date: 2014-07-30 12:00 CET\n"
"Last-Translator: Helmut Merz <helmutm@cy55.de>\n"
"Language-Team: loops developers <helmutm@cy55.de>\n"
"MIME-Version: 1.0\n"
@ -298,7 +298,16 @@ msgstr "Rang Team"
msgid "Team Size"
msgstr "Anzahl der vom Team ausgefüllten Fragebögen"
# competence (qualification)
# compentence and qualification management
msgid "Jobs / Positions"
msgstr "Stellen"
msgid "Create Job..."
msgstr "Stelle anlegen..."
msgid "Create a new job / position"
msgstr "Eine neue Stelle anlegen..."
msgid "Validity Period (Months)"
msgstr "Gültigkeitszeitraum (Monate)"

View file

@ -427,7 +427,7 @@ Send Email to Members
>>> form.subject
u"loops Notification from '$site'"
>>> form.mailBody
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.117\n\n'
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.127\n\n'
Show Presence of Other Users

View file

@ -18,7 +18,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)
(35, 3, 1)
(38, 3, 1)
>>> from cybertools.tracking.btree import TrackingStorage
>>> from loops.system.job import JobRecord

View file

@ -35,7 +35,7 @@ ZCML setup):
Let's look what setup has provided us with:
>>> len(concepts)
24
27
Now let's add a few more concepts:
@ -72,7 +72,8 @@ note that the 'hasType' predicate is not shown as it should not be
applied in an explicit assignment.
>>> sorted(t['name'] for t in xrf.getConceptTypes())
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
[u'competence', u'customer', u'domain', u'file', u'ipskill',
u'ipskillsrequired', u'jobposition', u'note', u'person',
u'predicate', u'report', u'task', u'textdocument', u'topic', u'type']
>>> sorted(t['name'] for t in xrf.getPredicates())
[u'depends', u'issubtype', u'knows', u'ownedby', u'provides', u'requires',
@ -95,7 +96,8 @@ All methods that retrieve one object also returns its children and parents:
>>> ch[0]['name']
u'hasType'
>>> sorted(c['name'] for c in ch[0]['objects'])
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
[u'competence', u'customer', u'domain', u'file', u'ipskill',
u'ipskillsrequired', u'jobposition', u'note', u'person',
u'predicate', u'report', u'task', u'textdocument', u'topic', u'type']
>>> pa = defaultPred['parents']
@ -114,7 +116,8 @@ We can also retrieve children and parents explicitely:
>>> ch[0]['name']
u'hasType'
>>> sorted(c['name'] for c in ch[0]['objects'])
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
[u'competence', u'customer', u'domain', u'file', u'ipskill',
u'ipskillsrequired', u'jobposition', u'note', u'person',
u'predicate', u'report', u'task', u'textdocument', u'topic', u'type']
>>> pa = xrf.getParents('5')
@ -174,14 +177,14 @@ Updating the concept map
>>> topicId = xrf.getObjectByName('topic')['id']
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
{'description': u'', 'title': u'Zope 2', 'type': '38', 'id': '76',
{'description': u'', 'title': u'Zope 2', 'type': '44', 'id': '86',
'name': u'zope2'}
The name of the concept is checked by a name chooser; if the corresponding
parameter is empty, the name will be generated from the title.
>>> xrf.createConcept(topicId, u'', u'Python')
{'description': u'', 'title': u'Python', 'type': '38', 'id': '78',
{'description': u'', 'title': u'Python', 'type': '44', 'id': '88',
'name': u'python'}
If we try to deassign a ``hasType`` relation nothing will happen; a