diff --git a/common.py b/common.py index 985f27d..3e566af 100644 --- a/common.py +++ b/common.py @@ -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) diff --git a/knowledge/survey/base.py b/knowledge/survey/base.py index a4a5d57..7dc0a19 100644 --- a/knowledge/survey/base.py +++ b/knowledge/survey/base.py @@ -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): diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 30c7cdd..7177c15 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -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(%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))] diff --git a/knowledge/survey/interfaces.py b/knowledge/survey/interfaces.py index 1e23003..7b634b5 100644 --- a/knowledge/survey/interfaces.py +++ b/knowledge/survey/interfaces.py @@ -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) diff --git a/knowledge/survey/view_macros.pt b/knowledge/survey/view_macros.pt index d225219..42757a2 100644 --- a/knowledge/survey/view_macros.pt +++ b/knowledge/survey/view_macros.pt @@ -3,8 +3,16 @@ + tal:define="feedback item/results; + errors item/errors"> + + + + + Feedback @@ -25,8 +33,15 @@ + - + + + + + + + No answer + title string:survey_value_${value/value}" /> + *** + diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index e8c66bb..39dbbd7 100644 Binary files a/locales/de/LC_MESSAGES/loops.mo and b/locales/de/LC_MESSAGES/loops.mo differ diff --git a/locales/de/LC_MESSAGES/loops.po b/locales/de/LC_MESSAGES/loops.po index 518d611..383441a 100644 --- a/locales/de/LC_MESSAGES/loops.po +++ b/locales/de/LC_MESSAGES/loops.po @@ -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"