error checks and feedback
This commit is contained in:
parent
74988c1834
commit
12da1c3d0d
7 changed files with 79 additions and 16 deletions
|
@ -113,6 +113,9 @@ class AdapterBase(object):
|
||||||
self.context = context
|
self.context = context
|
||||||
self.__parent__ = context # to get the permission stuff right
|
self.__parent__ = context # to get the permission stuff right
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self.context)
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
self.checkAttr(attr)
|
self.checkAttr(attr)
|
||||||
return getattr(self.context, '_' + attr, None)
|
return getattr(self.context, '_' + attr, None)
|
||||||
|
|
|
@ -62,7 +62,7 @@ class QuestionGroup(AdapterBase, QuestionGroup):
|
||||||
|
|
||||||
_contextAttributes = list(IQuestionGroup)
|
_contextAttributes = list(IQuestionGroup)
|
||||||
_adapterAttributes = AdapterBase._adapterAttributes + (
|
_adapterAttributes = AdapterBase._adapterAttributes + (
|
||||||
'questionnaire', 'questions', 'feedbackItems',)
|
'questionnaire', 'questions', 'feedbackItems')
|
||||||
_noexportAttributes = _adapterAttributes
|
_noexportAttributes = _adapterAttributes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -109,9 +109,6 @@ class Question(AdapterBase, Question):
|
||||||
def questionnaire(self):
|
def questionnaire(self):
|
||||||
return self.questionGroup.questionnaire
|
return self.questionGroup.questionnaire
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(self.context)
|
|
||||||
|
|
||||||
|
|
||||||
class FeedbackItem(AdapterBase, FeedbackItem):
|
class FeedbackItem(AdapterBase, FeedbackItem):
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,13 @@ surveys and self-assessments.
|
||||||
|
|
||||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
from zope.i18n import translate
|
||||||
|
|
||||||
from cybertools.knowledge.survey.questionnaire import Response
|
from cybertools.knowledge.survey.questionnaire import Response
|
||||||
from loops.browser.concept import ConceptView
|
from loops.browser.concept import ConceptView
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
from loops.organize.party import getPersonForUser
|
from loops.organize.party import getPersonForUser
|
||||||
|
from loops.util import _
|
||||||
|
|
||||||
|
|
||||||
template = ViewPageTemplateFile('view_macros.pt')
|
template = ViewPageTemplateFile('view_macros.pt')
|
||||||
|
@ -36,6 +38,7 @@ class SurveyView(ConceptView):
|
||||||
|
|
||||||
tabview = 'index.html'
|
tabview = 'index.html'
|
||||||
data = None
|
data = None
|
||||||
|
errors = None
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def macro(self):
|
def macro(self):
|
||||||
|
@ -56,20 +59,57 @@ class SurveyView(ConceptView):
|
||||||
value = int(value)
|
value = int(value)
|
||||||
self.data[uid] = value
|
self.data[uid] = value
|
||||||
response.values[question] = value
|
response.values[question] = value
|
||||||
|
self.errors = self.check(response)
|
||||||
|
if self.errors:
|
||||||
|
return []
|
||||||
# TODO: store self.data in track
|
# TODO: store self.data in track
|
||||||
# else:
|
|
||||||
# get response from track
|
|
||||||
if response is not None:
|
if response is not None:
|
||||||
result = response.getGroupedResult()
|
result = response.getGroupedResult()
|
||||||
return [dict(category=r[0].title, text=r[1].text,
|
return [dict(category=r[0].title, text=r[1].text,
|
||||||
score=int(round(r[2] * 100)))
|
score=int(round(r[2] * 100)))
|
||||||
for r in result]
|
for r in result]
|
||||||
|
|
||||||
|
def check(self, response):
|
||||||
|
errors = []
|
||||||
|
values = response.values
|
||||||
|
for qu in self.adapted.questions:
|
||||||
|
if qu.required and qu not in values:
|
||||||
|
errors.append('Please answer the obligatory questions.')
|
||||||
|
break
|
||||||
|
qugroups = {}
|
||||||
|
for qugroup in self.adapted.questionGroups:
|
||||||
|
qugroups[qugroup] = 0
|
||||||
|
for qu in values:
|
||||||
|
qugroups[qu.questionGroup] += 1
|
||||||
|
for qugroup, count in qugroups.items():
|
||||||
|
minAnswers = qugroup.minAnswers
|
||||||
|
if minAnswers in (u'', None):
|
||||||
|
minAnswers = len(qugroup.questions)
|
||||||
|
if count < minAnswers:
|
||||||
|
errors.append('Please answer the minimum number of questions.')
|
||||||
|
return errors
|
||||||
|
|
||||||
|
def getInfoText(self, qugroup):
|
||||||
|
lang = self.languageInfo.language
|
||||||
|
text = qugroup.description
|
||||||
|
info = None
|
||||||
|
if qugroup.minAnswers in (u'', None):
|
||||||
|
info = translate(_(u'Please answer all questions.'), target_language=lang)
|
||||||
|
elif qugroup.minAnswers > 0:
|
||||||
|
info = translate(_(u'Please answer at least $minAnswers questions.',
|
||||||
|
mapping=dict(minAnswers=qugroup.minAnswers)),
|
||||||
|
target_language=lang)
|
||||||
|
if info:
|
||||||
|
text = u'%s<br />(%s)' % (text, info)
|
||||||
|
return text
|
||||||
|
|
||||||
def getValues(self, question):
|
def getValues(self, question):
|
||||||
setting = None
|
setting = None
|
||||||
|
# TODO: get response from track
|
||||||
if self.data is not None:
|
if self.data is not None:
|
||||||
setting = self.data.get(question.uid)
|
setting = self.data.get(question.uid)
|
||||||
noAnswer = [dict(value='none', checked=(setting == None))]
|
noAnswer = [dict(value='none', checked=(setting == None),
|
||||||
return noAnswer + [dict(value=i, checked=(setting == i))
|
radio=(not question.required))]
|
||||||
|
return noAnswer + [dict(value=i, checked=(setting == i), radio=True)
|
||||||
for i in reversed(range(question.answerRange))]
|
for i in reversed(range(question.answerRange))]
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ class IQuestionGroup(IConceptSchema, interfaces.IQuestionGroup):
|
||||||
title=_(u'Minimum Number of Answers'),
|
title=_(u'Minimum Number of Answers'),
|
||||||
description=_(u'Minumum number of questions that have to be answered. '
|
description=_(u'Minumum number of questions that have to be answered. '
|
||||||
'Empty means all questions have to be answered.'),
|
'Empty means all questions have to be answered.'),
|
||||||
default=4,
|
default=None,
|
||||||
required=False)
|
required=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,16 @@
|
||||||
|
|
||||||
|
|
||||||
<metal:block define-macro="survey"
|
<metal:block define-macro="survey"
|
||||||
tal:define="feedback item/results">
|
tal:define="feedback item/results;
|
||||||
|
errors item/errors">
|
||||||
<metal:title use-macro="item/conceptMacros/concepttitle" />
|
<metal:title use-macro="item/conceptMacros/concepttitle" />
|
||||||
|
<div class="error"
|
||||||
|
tal:condition="errors">
|
||||||
|
<div tal:repeat="error errors">
|
||||||
|
<span i18n:translate=""
|
||||||
|
tal:content="error" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div tal:condition="feedback">
|
<div tal:condition="feedback">
|
||||||
<h3 i18n:translate="">Feedback</h3>
|
<h3 i18n:translate="">Feedback</h3>
|
||||||
<table class="listing">
|
<table class="listing">
|
||||||
|
@ -25,8 +33,15 @@
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<table class="listing">
|
<table class="listing">
|
||||||
<tal:qugroup repeat="qugroup item/adapted/questionGroups">
|
<tal:qugroup repeat="qugroup item/adapted/questionGroups">
|
||||||
|
<tr><td colspan="6"> </td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b tal:content="qugroup/title" /></td>
|
<td tal:define="infoText python:item.getInfoText(qugroup)">
|
||||||
|
<b tal:content="qugroup/title" />
|
||||||
|
<div tal:condition="infoText">
|
||||||
|
<span tal:content="structure infoText" />
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td style="text-align: center"
|
<td style="text-align: center"
|
||||||
i18n:translate="">No answer</td>
|
i18n:translate="">No answer</td>
|
||||||
<td colspan="2"
|
<td colspan="2"
|
||||||
|
@ -41,11 +56,16 @@
|
||||||
tal:repeat="value python:item.getValues(question)">
|
tal:repeat="value python:item.getValues(question)">
|
||||||
<input type="radio"
|
<input type="radio"
|
||||||
i18n:attributes="title"
|
i18n:attributes="title"
|
||||||
|
tal:condition="value/radio"
|
||||||
tal:attributes="
|
tal:attributes="
|
||||||
name string:question_${question/uid};
|
name string:question_${question/uid};
|
||||||
value value/value;
|
value value/value;
|
||||||
checked value/checked;
|
checked value/checked;
|
||||||
title string:survey_value_${value/value}" />
|
title string:survey_value_${value/value}" />
|
||||||
|
<span tal:condition="not:value/radio"
|
||||||
|
title="Obligatory question, must be answered"
|
||||||
|
i18n:attributes="title">***
|
||||||
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tal:qugroup>
|
</tal:qugroup>
|
||||||
|
|
Binary file not shown.
|
@ -185,7 +185,7 @@ msgid "Minumum number of questions that have to be answered. Empty means all que
|
||||||
msgstr "Anzahl der Fragen, die mindestens beantwortet werden müssen. Keine Angabe: Es müssen alle Fragen beantwortet werden."
|
msgstr "Anzahl der Fragen, die mindestens beantwortet werden müssen. Keine Angabe: Es müssen alle Fragen beantwortet werden."
|
||||||
|
|
||||||
msgid "Required"
|
msgid "Required"
|
||||||
msgstr "Erforderlich"
|
msgstr "Pflichtfrage"
|
||||||
|
|
||||||
msgid "Question must be answered."
|
msgid "Question must be answered."
|
||||||
msgstr "Frage muss unbedingt beantwortet werden."
|
msgstr "Frage muss unbedingt beantwortet werden."
|
||||||
|
@ -241,8 +241,11 @@ msgstr "Bitte beantworten Sie mindestens $minAnswers Fragen."
|
||||||
msgid "Please answer all questions."
|
msgid "Please answer all questions."
|
||||||
msgstr "Bitte beantworten Sie alle Fragen."
|
msgstr "Bitte beantworten Sie alle Fragen."
|
||||||
|
|
||||||
msgid "Please answer the obligatory questions marked with an asterisk."
|
msgid "Please answer the obligatory questions."
|
||||||
msgstr "Bitte beantworten Sie die mit einem Stern markierten Pflichtfragen."
|
msgstr "Bitte beantworten Sie die Pflichtfragen."
|
||||||
|
|
||||||
|
msgid "Please answer the minimum number of questions."
|
||||||
|
msgstr "Bitte beantworten Sie die angegebene Mindestanzahl an Fragen je Fragengruppe."
|
||||||
|
|
||||||
msgid "Obligatory question, must be answered"
|
msgid "Obligatory question, must be answered"
|
||||||
msgstr "Pflichtfrage, muss beantwortet werden"
|
msgstr "Pflichtfrage, muss beantwortet werden"
|
||||||
|
|
Loading…
Add table
Reference in a new issue