Yellow Pages: view task_candidates for listing persons with knowledge required for task.
This commit is contained in:
parent
5f072547b1
commit
d21c4a28ea
8 changed files with 114 additions and 28 deletions
|
@ -6,6 +6,8 @@ $Id$
|
|||
1.1
|
||||
---
|
||||
|
||||
- yellow pages: view task_candidates for selecting persons with required
|
||||
knowledge for task
|
||||
- improve 'move' and 'delegate' actions: create new run, store source and
|
||||
target work items, keep state when moving
|
||||
- keep access trail (history) in session
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
|
||||
# Copyright (c) 2011 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
|
||||
|
@ -58,14 +58,13 @@ actions.register('editTopic', 'portlet', DialogAction,
|
|||
)
|
||||
|
||||
|
||||
class MyKnowledge(BaseView):
|
||||
class MyKnowledge(ConceptView):
|
||||
|
||||
#template = NamedTemplate('loops.knowledge_macros')
|
||||
template = ViewPageTemplateFile('knowledge_macros.pt')
|
||||
|
||||
@Lazy
|
||||
def macro(self):
|
||||
return self.template.macros['requirements']
|
||||
return self.template.macros['requirement_providers']
|
||||
|
||||
@Lazy
|
||||
def person(self):
|
||||
|
@ -91,3 +90,12 @@ class MyKnowledge(BaseView):
|
|||
'providers': (BaseView(p.context, request) for p in prov)}
|
||||
for req, prov in providers)
|
||||
|
||||
|
||||
class Candidates(ConceptView):
|
||||
|
||||
template = ViewPageTemplateFile('knowledge_macros.pt')
|
||||
|
||||
@Lazy
|
||||
def macro(self):
|
||||
return self.template.macros['requirement_candidates']
|
||||
|
||||
|
|
|
@ -74,8 +74,15 @@
|
|||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
provides="zope.interface.Interface"
|
||||
factory="loops.knowledge.browser.MyKnowledge"
|
||||
permission="zope.View"
|
||||
/>
|
||||
permission="zope.View" />
|
||||
|
||||
<zope:adapter
|
||||
name="task_candidates"
|
||||
for="loops.interfaces.IConcept
|
||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
provides="zope.interface.Interface"
|
||||
factory="loops.knowledge.browser.Candidates"
|
||||
permission="zope.View" />
|
||||
|
||||
<!-- other adapters -->
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@ from loops.schema.base import Relation, RelationSet
|
|||
|
||||
_ = MessageFactory('loops')
|
||||
|
||||
# TODO: separate interfaces for viewing and changing methods!
|
||||
|
||||
|
||||
class IPerson(IBasePerson, IKnowing, ILoopsAdapter):
|
||||
""" A person, including knowledge/learning management features.
|
||||
|
@ -54,6 +52,12 @@ class ITask(IBaseTask, IRequirementProfile, ILoopsAdapter):
|
|||
""" A task, also acting as a knowledge requirement profile.
|
||||
"""
|
||||
|
||||
requirements = RelationSet(
|
||||
title=_(u'Requirements'),
|
||||
description=_(u'The knowledge required for this task.'),
|
||||
#target_types=('topic',), # set via global option knowledge.element
|
||||
required=False)
|
||||
|
||||
|
||||
class ITopic(IConceptSchema, IKnowledgeElement, ILoopsAdapter):
|
||||
""" Just a topic, some general classification concept.
|
||||
|
|
|
@ -150,6 +150,11 @@ class Task(BaseTask, KnowledgeAdapterMixin):
|
|||
|
||||
implements(ITask)
|
||||
|
||||
_adapterAttributes = BasePerson._adapterAttributes + ('requirements',)
|
||||
_noexportAttributes = ('requirements',)
|
||||
|
||||
requirements = ParentRelationSetProperty('requires')
|
||||
|
||||
def getRequirements(self):
|
||||
return (IKnowledgeElement(c)
|
||||
for c in self.context.getParents((self.requiresPred,)))
|
||||
|
@ -160,6 +165,26 @@ class Task(BaseTask, KnowledgeAdapterMixin):
|
|||
def removeRequirement(self, obj):
|
||||
self.context.deassignParent(obj.context, (self.requiresPred,))
|
||||
|
||||
def getCandidates(self):
|
||||
result = []
|
||||
candidates = []
|
||||
reqs = list(self.requirements)
|
||||
for req in reqs:
|
||||
for p in req.getKnowers():
|
||||
if p not in candidates:
|
||||
candidates.append(p)
|
||||
item = dict(person=p, required=[], other=[], fit=0.0)
|
||||
for k in p.knowledge:
|
||||
if k in reqs:
|
||||
item['required'].append(k)
|
||||
item['fit'] += 1.0
|
||||
else:
|
||||
item['other'].append(k)
|
||||
result.append(item)
|
||||
for item in result:
|
||||
item['fit'] /= len(reqs)
|
||||
return sorted(result, key=lambda x: (-x['fit'], x['person'].title))
|
||||
|
||||
|
||||
class ConceptKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
|
||||
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
<metal:listing define-macro="requirements">
|
||||
<html i18n:domain="loops">
|
||||
|
||||
|
||||
<metal:providers define-macro="requirement_providers">
|
||||
<metal:block use-macro="view/concept_macros/conceptdata" />
|
||||
<div>
|
||||
<h3 tal:attributes="class string:content-$level;
|
||||
ondblclick item/openEditWindow">
|
||||
<span i18n:translate="">Concept</span>:
|
||||
<span tal:content="item/title">Title</span>
|
||||
</h3>
|
||||
<metal:listing define-macro="requirementslisting2">
|
||||
<div tal:attributes="class string:content-$level;
|
||||
ondblclick python: item.openEditWindow('configure.html')">
|
||||
<h4>Requirements</h4>
|
||||
<h3>Requirements</h3>
|
||||
<table class="listing">
|
||||
<tr>
|
||||
<th i18n:translate="">Requirement</th>
|
||||
|
@ -16,20 +13,48 @@
|
|||
</tr>
|
||||
<tr tal:repeat="related item/myKnowledgeProvidersForTask">
|
||||
<td>
|
||||
<a href="#"
|
||||
tal:attributes="href string:${view/url}/.target${related/required/uniqueId}"
|
||||
<a tal:attributes="href
|
||||
string:${view/url}/.target${related/required/uniqueId}"
|
||||
tal:content="related/required/title">Concept Title</a>
|
||||
</td>
|
||||
<td>
|
||||
<tal:provider repeat="prov related/providers">
|
||||
<a href="#"
|
||||
tal:attributes="href string:${view/url}/.target${prov/uniqueId}"
|
||||
<a tal:attributes="href string:${view/url}/.target${prov/uniqueId}"
|
||||
tal:content="prov/title">Provider Title</a>
|
||||
</tal:provider>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</metal:listing>
|
||||
</div>
|
||||
</metal:listing>
|
||||
</metal:providers>
|
||||
|
||||
|
||||
<metal:candidates define-macro="requirement_candidates">
|
||||
<metal:block use-macro="view/concept_macros/conceptdata" />
|
||||
<h3 i18n:translate="">Candidates for Task</h3>
|
||||
<table class="listing">
|
||||
<tr>
|
||||
<th i18n:translate="">Candidate</th>
|
||||
<th i18n:translate=""
|
||||
title="coverage"
|
||||
i18n:attributes="title description_fit">Fit</th>
|
||||
<th i18n:translate="">Knowledge</th>
|
||||
</tr>
|
||||
<tr tal:repeat="candidate item/adapted/getCandidates">
|
||||
<td tal:define="person candidate/person">
|
||||
<b tal:omit-tag="python:candidate['fit'] < 1.0">
|
||||
<a tal:attributes="href python:view.getUrlForTarget(person.context)"
|
||||
tal:content="person/title" /></b></td>
|
||||
<td tal:content="candidate/fit" />
|
||||
<td>
|
||||
<tal:knowledge tal:repeat="ke candidate/required">
|
||||
<a tal:attributes="href python:view.getUrlForTarget(ke.context)"
|
||||
tal:content="ke/title" /><tal:sep condition="not:repeat/ke/end">, </tal:sep>
|
||||
</tal:knowledge></td>
|
||||
</tr>
|
||||
</table>
|
||||
</metal:candidates>
|
||||
|
||||
|
||||
</html>
|
||||
|
|
Binary file not shown.
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
|
||||
"Project-Id-Version: $Id$\n"
|
||||
"POT-Creation-Date: 2007-05-22 12:00 CET\n"
|
||||
"PO-Revision-Date: 2011-03-07 12:00 CET\n"
|
||||
"PO-Revision-Date: 2011-04-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"
|
||||
|
@ -498,10 +498,25 @@ msgid "End date"
|
|||
msgstr "Ende"
|
||||
|
||||
msgid "Knowledge"
|
||||
msgstr "Wissen"
|
||||
msgstr "Kompetenzen"
|
||||
|
||||
msgid "Requirements"
|
||||
msgstr "Anforderungen"
|
||||
|
||||
msgid "The knowledge elements for this person."
|
||||
msgstr "Die Wissenselemente für diese Person."
|
||||
msgstr "Die Kompetenzen dieser Person."
|
||||
|
||||
msgid "Candidates for Task"
|
||||
msgstr "Kandidaten für Aufgabe"
|
||||
|
||||
msgid "Candidate"
|
||||
msgstr "Kandidat"
|
||||
|
||||
msgid "Fit"
|
||||
msgstr "DG"
|
||||
|
||||
msgid "description_fit"
|
||||
msgstr "Deckungsgrad"
|
||||
|
||||
msgid "Create loops Note"
|
||||
msgstr "loops-Notiz anlegen"
|
||||
|
|
Loading…
Add table
Reference in a new issue