error checks and feedback

This commit is contained in:
Helmut Merz 2013-03-18 13:20:12 +01:00
parent 74988c1834
commit 12da1c3d0d
7 changed files with 79 additions and 16 deletions

View file

@ -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)

View file

@ -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):

View file

@ -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))]

View file

@ -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)

View file

@ -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">&nbsp;</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 />&nbsp;
</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}" />&nbsp; 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.

View file

@ -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"