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.__parent__ = context # to get the permission stuff right
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.context)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
self.checkAttr(attr)
|
||||
return getattr(self.context, '_' + attr, None)
|
||||
|
|
|
@ -62,7 +62,7 @@ class QuestionGroup(AdapterBase, QuestionGroup):
|
|||
|
||||
_contextAttributes = list(IQuestionGroup)
|
||||
_adapterAttributes = AdapterBase._adapterAttributes + (
|
||||
'questionnaire', 'questions', 'feedbackItems',)
|
||||
'questionnaire', 'questions', 'feedbackItems')
|
||||
_noexportAttributes = _adapterAttributes
|
||||
|
||||
@property
|
||||
|
@ -109,9 +109,6 @@ class Question(AdapterBase, Question):
|
|||
def questionnaire(self):
|
||||
return self.questionGroup.questionnaire
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.context)
|
||||
|
||||
|
||||
class FeedbackItem(AdapterBase, FeedbackItem):
|
||||
|
||||
|
|
|
@ -23,11 +23,13 @@ surveys and self-assessments.
|
|||
|
||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope.i18n import translate
|
||||
|
||||
from cybertools.knowledge.survey.questionnaire import Response
|
||||
from loops.browser.concept import ConceptView
|
||||
from loops.common import adapted
|
||||
from loops.organize.party import getPersonForUser
|
||||
from loops.util import _
|
||||
|
||||
|
||||
template = ViewPageTemplateFile('view_macros.pt')
|
||||
|
@ -36,6 +38,7 @@ class SurveyView(ConceptView):
|
|||
|
||||
tabview = 'index.html'
|
||||
data = None
|
||||
errors = None
|
||||
|
||||
@Lazy
|
||||
def macro(self):
|
||||
|
@ -56,20 +59,57 @@ class SurveyView(ConceptView):
|
|||
value = int(value)
|
||||
self.data[uid] = value
|
||||
response.values[question] = value
|
||||
self.errors = self.check(response)
|
||||
if self.errors:
|
||||
return []
|
||||
# TODO: store self.data in track
|
||||
# else:
|
||||
# get response from track
|
||||
if response is not None:
|
||||
result = response.getGroupedResult()
|
||||
return [dict(category=r[0].title, text=r[1].text,
|
||||
score=int(round(r[2] * 100)))
|
||||
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):
|
||||
setting = None
|
||||
# TODO: get response from track
|
||||
if self.data is not None:
|
||||
setting = self.data.get(question.uid)
|
||||
noAnswer = [dict(value='none', checked=(setting == None))]
|
||||
return noAnswer + [dict(value=i, checked=(setting == i))
|
||||
noAnswer = [dict(value='none', checked=(setting == None),
|
||||
radio=(not question.required))]
|
||||
return noAnswer + [dict(value=i, checked=(setting == i), radio=True)
|
||||
for i in reversed(range(question.answerRange))]
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ class IQuestionGroup(IConceptSchema, interfaces.IQuestionGroup):
|
|||
title=_(u'Minimum Number of Answers'),
|
||||
description=_(u'Minumum number of questions that have to be answered. '
|
||||
'Empty means all questions have to be answered.'),
|
||||
default=4,
|
||||
default=None,
|
||||
required=False)
|
||||
|
||||
|
||||
|
|
|
@ -3,8 +3,16 @@
|
|||
|
||||
|
||||
<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" />
|
||||
<div class="error"
|
||||
tal:condition="errors">
|
||||
<div tal:repeat="error errors">
|
||||
<span i18n:translate=""
|
||||
tal:content="error" />
|
||||
</div>
|
||||
</div>
|
||||
<div tal:condition="feedback">
|
||||
<h3 i18n:translate="">Feedback</h3>
|
||||
<table class="listing">
|
||||
|
@ -25,8 +33,15 @@
|
|||
<form method="post">
|
||||
<table class="listing">
|
||||
<tal:qugroup repeat="qugroup item/adapted/questionGroups">
|
||||
<tr><td colspan="6"> </td></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"
|
||||
i18n:translate="">No answer</td>
|
||||
<td colspan="2"
|
||||
|
@ -41,11 +56,16 @@
|
|||
tal:repeat="value python:item.getValues(question)">
|
||||
<input type="radio"
|
||||
i18n:attributes="title"
|
||||
tal:condition="value/radio"
|
||||
tal:attributes="
|
||||
name string:question_${question/uid};
|
||||
value value/value;
|
||||
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>
|
||||
</tr>
|
||||
</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."
|
||||
|
||||
msgid "Required"
|
||||
msgstr "Erforderlich"
|
||||
msgstr "Pflichtfrage"
|
||||
|
||||
msgid "Question must be answered."
|
||||
msgstr "Frage muss unbedingt beantwortet werden."
|
||||
|
@ -241,8 +241,11 @@ msgstr "Bitte beantworten Sie mindestens $minAnswers Fragen."
|
|||
msgid "Please answer all questions."
|
||||
msgstr "Bitte beantworten Sie alle Fragen."
|
||||
|
||||
msgid "Please answer the obligatory questions marked with an asterisk."
|
||||
msgstr "Bitte beantworten Sie die mit einem Stern markierten Pflichtfragen."
|
||||
msgid "Please answer the obligatory questions."
|
||||
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"
|
||||
msgstr "Pflichtfrage, muss beantwortet werden"
|
||||
|
|
Loading…
Add table
Reference in a new issue