From 74988c1834f7e4c2aac0a446ba86a3c8b9092d82 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 18 Mar 2013 10:54:08 +0100 Subject: [PATCH 01/51] rearrange answer options; allow for unanswered questions; intermediate question group headings --- knowledge/survey/browser.py | 16 ++++++---- knowledge/survey/interfaces.py | 13 ++++++++ knowledge/survey/view_macros.pt | 55 ++++++++++++++++---------------- locales/de/LC_MESSAGES/loops.mo | Bin 22194 -> 23228 bytes locales/de/LC_MESSAGES/loops.po | 44 +++++++++++++++++++++---- 5 files changed, 86 insertions(+), 42 deletions(-) diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 657c3e9..30c7cdd 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -52,9 +52,10 @@ class SurveyView(ConceptView): if key.startswith('question_'): uid = key[len('question_'):] question = adapted(self.getObjectForUid(uid)) - value = int(value) - self.data[uid] = value - response.values[question] = value + if value != 'none': + value = int(value) + self.data[uid] = value + response.values[question] = value # TODO: store self.data in track # else: # get response from track @@ -65,9 +66,10 @@ class SurveyView(ConceptView): for r in result] def getValues(self, question): - setting = 0 + setting = None if self.data is not None: - setting = self.data.get(question.uid) or 0 - return [dict(value=i, checked=(i == setting)) - for i in range(question.answerRange)] + setting = self.data.get(question.uid) + noAnswer = [dict(value='none', checked=(setting == None))] + return noAnswer + [dict(value=i, checked=(setting == i)) + for i in reversed(range(question.answerRange))] diff --git a/knowledge/survey/interfaces.py b/knowledge/survey/interfaces.py index ea15928..1e23003 100644 --- a/knowledge/survey/interfaces.py +++ b/knowledge/survey/interfaces.py @@ -43,11 +43,24 @@ class IQuestionGroup(IConceptSchema, interfaces.IQuestionGroup): """ A group of questions within a questionnaire. """ + minAnswers = schema.Int( + 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, + required=False) + class IQuestion(IConceptSchema, interfaces.IQuestion): """ A single question within a questionnaire. """ + required = schema.Bool( + title=_(u'Required'), + description=_(u'Question must be answered.'), + default=False, + required=False) + revertAnswerOptions = schema.Bool( title=_(u'Negative'), description=_(u'Value inversion: High selection means low value.'), diff --git a/knowledge/survey/view_macros.pt b/knowledge/survey/view_macros.pt index 3956120..d225219 100644 --- a/knowledge/survey/view_macros.pt +++ b/knowledge/survey/view_macros.pt @@ -7,7 +7,7 @@

Feedback

- +
@@ -23,33 +23,32 @@

Questionnaire

-
Category Response
- - - - - - - +
- - - - - -
Does not applyFully applies
-
- -   -   - -
+ + + + + + + + + + +
No answerFully appliesDoes not apply
+ +   +

BrgW;Fgw|jTuCx3m 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 PSUMD1kUc<+0!k6K6v)XKY} z>IX!uARRUEc+>zvE1!c}*+SG^cm%a$#pW8+4m^pP$To8~YA0XAlD{RWfsdj3IfJnn zIY&Y>yMgN9Tgy9{-h`r21Jp5FpeB@p+ObrujTxu`bF4g!b;;jn`PHcY|A2abvsWH* zULv8b*pHggJE#FaM14NjFaaA+@Xod)>L~i7Ix0YQya4sya@0gtqjqvVYUMAW4^I-` z5IM@|``7C834cj}3ccraX#($}?xy8qtX)f!JLU8x`dD7g?j=%)I%UdQkj^CbQT`S2 zGVzYS|AWN;68thcJ8%l|DJSHVg;e+IFVkG;{T(;hSsi&IShYKxppGa%Kk`t zKhd82Y%A0FCI2yCt`#WXw@g}j9m5%77!gHX2fW?d%qi1$0_oY*eL-9$bZqO0m4qIB z;#oum+9eZTYyay}P(K--(C@sSTK2-d*p0kCO+7Wq_qMtzQnM6Axj#xRaVydN;FC=adJt$j@wTSHmPsCYDVHM(4a#Sa!Xr%uo9#9AU~`Re#6`P=XimOj5F(TAw2^PfcJ8Zt>lHqoE>8&UcU zB%vP~{h0J1QfR*ldlOF(rO(pR1YRP}5%WFX%BJIF^0(pNi9Zq73H^7aTy#;-AdjE^Sxx6( z`uv4N1EQQ>A|50Cf>p+o&mx)`rSiN@>dKVq5G;{2%F_#8e`W z{7n6-jUqmxU^&r-D191HuIE9bAL)F{FCgEA7)(r~tRI#>V@eZdlz9a2q3wxZ)JI|{ z*hDm;@+cl4-X;9Rp9wwR5f2mNY15b}Pr87pOgv7UB05tZCVoS@^yxre&l2LPk`(_% z6-N@Cl=pG|b!jxk8mjDdBAt9R-lGDZS;Q7%I5Cd8AYLQ%JVQ(*>JXKwOCt2#iq-Kj zv5>f%{H-{j`1vV*wPD2>aa8?}m3@wviCCgGkxJ-!gm|$e#UatY7wMOX3B+f_UBnP# z2cf4cZOT5&$Pe`G=;hX}5($Qac}02d@S?mafdV&wn%g&2I5$vG=%fcjMXKSSRx`UO zP#6y8hYH$(j>z!};!%fSXnFP9WRw4$PYsp6BKTC~>oLbKRfc`A^NA^c~|` zH}};KIKu;T7495{W(a3^zI9ssQ1Y(CDY?PvS>gPGc|Y}+?B*2}hRcp!+^5ayh&Pdc zAKC9@+iuVqP$0tNp3p!e6!y=LFpRUyont=4BPk3}m}=gW(*e>e6AL zpnR}!roTAWKQZoC)AJW+``7xicYN)St`u8XR4^wnZ_=Es+@ipwP<|*-e6!0#QSDQ9 ztVkJJJ;Kgsv(s6j`B^!+>bq|!JU71}90)mmy|QeMDzzYMdLWeSW(NZ<3(*?^Hhl_P z@3juQoMUz%^1DL=!BBwSre{qFbaMx?2Cqi@6|fH7DRIB*!N21~>I7fw zfSZw@n^h1Dzp*~dVHGI??pQmq(#}f;-;tK)^EJQUnvX6BPMgN4IUHO_d*aS7a>^DeOKX3%f7{05qOm>y1-7Z6O#lD@ delta 8480 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\n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -178,8 +178,20 @@ msgstr "Abstufung Bewertungen" msgid "Number of items (answer options) to select from." msgstr "Anzahl der Abstufungen, aus denen bei der Antwort gewählt werden kann." -msgid "Negativ" -msgstr "Negativbewertung" +msgid "Minimum Number of Answers" +msgstr "Mindestanzahl an Antworten" + +msgid "Minumum number of questions that have to be answered. Empty means all questions have to be answered." +msgstr "Anzahl der Fragen, die mindestens beantwortet werden müssen. Keine Angabe: Es müssen alle Fragen beantwortet werden." + +msgid "Required" +msgstr "Erforderlich" + +msgid "Question must be answered." +msgstr "Frage muss unbedingt beantwortet werden." + +msgid "Negative" +msgstr "Negative Polarität" msgid "Value inversion: High selection means low value." msgstr "Invertierung der Bewertung: Hohe gewählte Stufe bedeutet niedriger Wert." @@ -196,27 +208,45 @@ msgstr "Kategorie" msgid "Response" msgstr "Beurteilung" +msgid "No answer" +msgstr "Keine Antwort" + msgid "Does not apply" msgstr "Trifft nicht zu" msgid "Fully applies" msgstr "Trifft voll zu" +msgid "survey_value_none" +msgstr "Keine Antwort" + msgid "survey_value_0" -msgstr "trifft für unser Unternehmen überhaupt nicht zu" +msgstr "Trifft für unser Unternehmen überhaupt nicht zu" msgid "survey_value_1" -msgstr "trifft eher nicht zu" +msgstr "Trifft eher nicht zu" msgid "survey_value_2" -msgstr "trifft eher zu" +msgstr "Trifft eher zu" msgid "survey_value_3" -msgstr "trifft für unser Unternehmen voll und ganz zu" +msgstr "Trifft für unser Unternehmen voll und ganz zu" msgid "Evaluate Questionnaire" msgstr "Fragebogen auswerten" +msgid "Please answer at least $minAnswers questions." +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 "Obligatory question, must be answered" +msgstr "Pflichtfrage, muss beantwortet werden" + # competence (qualification) msgid "Validity Period (Months)" From 12da1c3d0dc0c9a0dc2a15e95f77d6fdfb2eee46 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 18 Mar 2013 13:20:12 +0100 Subject: [PATCH 02/51] error checks and feedback --- common.py | 3 ++ knowledge/survey/base.py | 5 +--- knowledge/survey/browser.py | 48 +++++++++++++++++++++++++++++--- knowledge/survey/interfaces.py | 2 +- knowledge/survey/view_macros.pt | 28 ++++++++++++++++--- locales/de/LC_MESSAGES/loops.mo | Bin 23228 -> 23318 bytes locales/de/LC_MESSAGES/loops.po | 9 ++++-- 7 files changed, 79 insertions(+), 16 deletions(-) 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 @@
+ - + diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index e8c66bb176f6eb92cd6c9e1e96f1c9e401cdeff0..39dbbd7b78c9f2902fb16249adcdb9abb4e40d65 100644 GIT binary patch delta 8179 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 delta 8138 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 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" From 5e8d0a89783fd2e11ec5a9f71e15ec523c3218fc Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 18 Mar 2013 13:24:43 +0100 Subject: [PATCH 03/51] only show first error of a certain type --- knowledge/survey/browser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 7177c15..829b340 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -87,6 +87,7 @@ class SurveyView(ConceptView): minAnswers = len(qugroup.questions) if count < minAnswers: errors.append('Please answer the minimum number of questions.') + break return errors def getInfoText(self, qugroup): From 96103b28c44e8e506ee3642bfdf64cc42e3ad348 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 18 Mar 2013 17:14:19 +0100 Subject: [PATCH 04/51] do not show questionnaire together with result; store data entered as track --- knowledge/survey/base.py | 1 - knowledge/survey/browser.py | 8 ++- knowledge/survey/configure.zcml | 9 +++ knowledge/survey/response.py | 37 ++++++++---- knowledge/survey/view_macros.pt | 99 +++++++++++++++++--------------- locales/de/LC_MESSAGES/loops.mo | Bin 23318 -> 23379 bytes locales/de/LC_MESSAGES/loops.po | 3 + organize/tracking/base.py | 8 ++- 8 files changed, 101 insertions(+), 64 deletions(-) diff --git a/knowledge/survey/base.py b/knowledge/survey/base.py index 7dc0a19..cacdcc7 100644 --- a/knowledge/survey/base.py +++ b/knowledge/survey/base.py @@ -122,4 +122,3 @@ class FeedbackItem(AdapterBase, FeedbackItem): @property def text(self): return self.context.description - diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 829b340..7fb5631 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -28,6 +28,7 @@ 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.knowledge.survey.response import Responses from loops.organize.party import getPersonForUser from loops.util import _ @@ -62,7 +63,7 @@ class SurveyView(ConceptView): self.errors = self.check(response) if self.errors: return [] - # TODO: store self.data in track + Responses(self.context).save(self.data) if response is not None: result = response.getGroupedResult() return [dict(category=r[0].title, text=r[1].text, @@ -106,8 +107,9 @@ class SurveyView(ConceptView): def getValues(self, question): setting = None - # TODO: get response from track - if self.data is not None: + if self.data is None: + self.data = Responses(self.context).load() + if self.data: setting = self.data.get(question.uid) noAnswer = [dict(value='none', checked=(setting == None), radio=(not question.required))] diff --git a/knowledge/survey/configure.zcml b/knowledge/survey/configure.zcml index 81c33d3..7475adc 100644 --- a/knowledge/survey/configure.zcml +++ b/knowledge/survey/configure.zcml @@ -21,6 +21,15 @@ factory="loops.knowledge.survey.base.FeedbackItem" provides="loops.knowledge.survey.interfaces.IFeedbackItem" /> + + + + + + +
 
+ +
+ +
  +
+
No answer   + title string:survey_value_${value/value}" /> + *** +
-
+ +
+
+

Questionnaire

+ + + + + + + + + + + + + + +
 
+ +
+ +
  +
+
No answerFully appliesDoes not apply
+ + + *** + +
+ +
-

Questionnaire

-
- - - - - - - - - - - - - -
 
- -
- -
  -
-
No answerFully appliesDoes not apply
- - - *** - -
-
- -
diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index 39dbbd7b78c9f2902fb16249adcdb9abb4e40d65..84d9df9db4bc64c2e78c6b38714a8caf7af56b16 100644 GIT binary patch delta 8624 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 n8{$^t24V~0 Date: Mon, 18 Mar 2013 17:30:39 +0100 Subject: [PATCH 05/51] save answers even if not valid --- knowledge/survey/browser.py | 2 +- knowledge/survey/response.py | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 7fb5631..a614d7f 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -60,10 +60,10 @@ class SurveyView(ConceptView): value = int(value) self.data[uid] = value response.values[question] = value + Responses(self.context).save(self.data) self.errors = self.check(response) if self.errors: return [] - Responses(self.context).save(self.data) if response is not None: result = response.getGroupedResult() return [dict(category=r[0].title, text=r[1].text, diff --git a/knowledge/survey/response.py b/knowledge/survey/response.py index 38b6fef..647af14 100644 --- a/knowledge/survey/response.py +++ b/knowledge/survey/response.py @@ -41,11 +41,8 @@ class Responses(BaseRecordManager): def save(self, data): if not self.personId: return - tracks = self.storage.getUserTracks(self.uid, 0, self.personId) - if tracks: - self.storage.updateTrack(tracks[0], data) - else: - self.storage.saveUserTrack(self.uid, 0, self.personId, data) + self.storage.saveUserTrack(self.uid, 0, self.personId, data, + update=True, overwrite=True) def load(self): if self.personId: From cd2eeaeed24ee5eb2504f82751ab4d2c3b1e969c Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 21 Mar 2013 10:25:19 +0100 Subject: [PATCH 06/51] do not show description on feedback page, show feedback footer instead; use trusted=True in configure to make fields editable in management interface --- browser/concept_macros.pt | 5 +++-- knowledge/survey/configure.zcml | 36 ++++++++++++++++++++++++++++---- knowledge/survey/interfaces.py | 9 +++++++- knowledge/survey/view_macros.pt | 22 ++++++++++++------- locales/de/LC_MESSAGES/loops.mo | Bin 23379 -> 23558 bytes locales/de/LC_MESSAGES/loops.po | 6 ++++++ 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/browser/concept_macros.pt b/browser/concept_macros.pt index 78ca2b3..b10081d 100644 --- a/browser/concept_macros.pt +++ b/browser/concept_macros.pt @@ -62,9 +62,10 @@ string:$resourceBase/cybertools.icons/table.png" /> - + -

Description

diff --git a/knowledge/survey/configure.zcml b/knowledge/survey/configure.zcml index 7475adc..dd27bff 100644 --- a/knowledge/survey/configure.zcml +++ b/knowledge/survey/configure.zcml @@ -7,19 +7,47 @@ + provides="loops.knowledge.survey.interfaces.IQuestionnaire" + trusted="True" /> + + + + + provides="loops.knowledge.survey.interfaces.IQuestionGroup" + trusted="True" /> + + + + + provides="loops.knowledge.survey.interfaces.IQuestion" + trusted="True" /> + + + + + provides="loops.knowledge.survey.interfaces.IFeedbackItem" + trusted="True" /> + + + + diff --git a/knowledge/survey/interfaces.py b/knowledge/survey/interfaces.py index 7b634b5..7ce5849 100644 --- a/knowledge/survey/interfaces.py +++ b/knowledge/survey/interfaces.py @@ -24,7 +24,7 @@ from zope.interface import Interface, Attribute from zope import interface, component, schema from cybertools.knowledge.survey import interfaces -from loops.interfaces import IConceptSchema +from loops.interfaces import IConceptSchema, ILoopsAdapter from loops.util import _ @@ -38,6 +38,13 @@ class IQuestionnaire(IConceptSchema, interfaces.IQuestionnaire): default=4, required=True) + feedbackFooter = schema.Text( + title=_(u'Feedback Footer'), + description=_(u'Text that will appear at the end of the feedback page.'), + default=u'', + missing_value=u'', + required=False) + class IQuestionGroup(IConceptSchema, interfaces.IQuestionGroup): """ A group of questions within a questionnaire. diff --git a/knowledge/survey/view_macros.pt b/knowledge/survey/view_macros.pt index 481b82e..49731dc 100644 --- a/knowledge/survey/view_macros.pt +++ b/knowledge/survey/view_macros.pt @@ -5,14 +5,10 @@ - -
-
- -
-
+ + + +

Feedback

@@ -33,10 +29,20 @@ Back to Questionnaire
+

Questionnaire

+
+
+ +
+
diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index 84d9df9db4bc64c2e78c6b38714a8caf7af56b16..4b3d58f48cda03e924f2cae731cf6cafab0dad90 100644 GIT binary patch delta 8587 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 diff --git a/locales/de/LC_MESSAGES/loops.po b/locales/de/LC_MESSAGES/loops.po index 71a8362..4b39018 100644 --- a/locales/de/LC_MESSAGES/loops.po +++ b/locales/de/LC_MESSAGES/loops.po @@ -175,6 +175,12 @@ msgstr "Glossareintrag anlegen." msgid "Answer Range" msgstr "Abstufung Bewertungen" +msgid "Feedback Footer" +msgstr "Auswertungs-Hinweis" + +msgid "Text that will appear at the end of the feedback page." +msgstr "Text, der am Ende der Auswertungsseite erscheinen soll." + msgid "Number of items (answer options) to select from." msgstr "Anzahl der Abstufungen, aus denen bei der Antwort gewählt werden kann." From 55354b780ee6d1f7dd65b33fc3d5084a235ab496 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 21 Mar 2013 17:36:54 +0100 Subject: [PATCH 07/51] provide survey data export --- knowledge/survey/browser.py | 56 ++++++++++++++++++++++++++++++++ knowledge/survey/configure.zcml | 5 +++ knowledge/survey/response.py | 3 ++ locales/de/LC_MESSAGES/loops.mo | Bin 23558 -> 23558 bytes locales/de/LC_MESSAGES/loops.po | 2 +- 5 files changed, 65 insertions(+), 1 deletion(-) diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index a614d7f..6b6c767 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -21,15 +21,20 @@ Definition of view classes and other browser related stuff for surveys and self-assessments. """ +import csv +from cStringIO import StringIO 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 cybertools.util.date import formatTimeStamp from loops.browser.concept import ConceptView +from loops.browser.node import NodeView from loops.common import adapted from loops.knowledge.survey.response import Responses from loops.organize.party import getPersonForUser +from loops.util import getObjectForUid from loops.util import _ @@ -116,3 +121,54 @@ class SurveyView(ConceptView): return noAnswer + [dict(value=i, checked=(setting == i), radio=True) for i in reversed(range(question.answerRange))] + +class SurveyCsvExport(NodeView): + + encoding = 'ISO8859-15' + + def encode(self, text): + text.encode(self.encoding) + + @Lazy + def questions(self): + result = [] + for idx1, qug in enumerate(adapted(self.virtualTargetObject).questionGroups): + for idx2, qu in enumerate(qug.questions): + result.append((idx1, idx2, qug, qu)) + return result + + @Lazy + def columns(self): + infoCols = ['Name', 'Timestamp'] + dataCols = ['%02i-%02i' % (item[0], item[1]) for item in self.questions] + return infoCols + dataCols + + def getRows(self): + for tr in Responses(self.virtualTargetObject).getAllTracks(): + p = adapted(getObjectForUid(tr.userName)) + name = p and p.title or u'???' + ts = formatTimeStamp(tr.timeStamp) + cells = [tr.data.get(qu.uid, -1) + for (idx1, idx2, qug, qu) in self.questions] + yield [name, ts] + cells + + def __call__(self): + f = StringIO() + writer = csv.writer(f, delimiter=',') + writer.writerow(self.columns) + for row in self.getRows(): + writer.writerow(row) + text = f.getvalue() + self.setDownloadHeader(text) + return text + + def setDownloadHeader(self, text): + response = self.request.response + filename = 'survey_data.csv' + response.setHeader('Content-Disposition', + 'attachment; filename=%s' % filename) + response.setHeader('Cache-Control', '') + response.setHeader('Pragma', '') + response.setHeader('Content-Length', len(text)) + response.setHeader('Content-Type', 'text/csv') + diff --git a/knowledge/survey/configure.zcml b/knowledge/survey/configure.zcml index dd27bff..423889d 100644 --- a/knowledge/survey/configure.zcml +++ b/knowledge/survey/configure.zcml @@ -68,4 +68,9 @@ factory="loops.knowledge.survey.browser.SurveyView" permission="zope.View" /> + + diff --git a/knowledge/survey/response.py b/knowledge/survey/response.py index 647af14..b27979e 100644 --- a/knowledge/survey/response.py +++ b/knowledge/survey/response.py @@ -51,6 +51,9 @@ class Responses(BaseRecordManager): return tracks[0].data return {} + def getAllTracks(self): + return self.storage.query(taskId=self.uid) + class Response(Track): diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index 4b3d58f48cda03e924f2cae731cf6cafab0dad90..fca2a64fb4145914853b06e1784078da52c00049 100644 GIT binary patch delta 17 YcmZqM!PvHgal>3|CL_bm^R3er06#GXfB*mh delta 17 YcmZqM!PvHgal>3|CPRzO^R3er06$a)h5!Hn diff --git a/locales/de/LC_MESSAGES/loops.po b/locales/de/LC_MESSAGES/loops.po index 4b39018..a73d55a 100644 --- a/locales/de/LC_MESSAGES/loops.po +++ b/locales/de/LC_MESSAGES/loops.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: 0.13.0\n" "POT-Creation-Date: 2007-05-22 12:00 CET\n" -"PO-Revision-Date: 2013-03-18 12:00 CET\n" +"PO-Revision-Date: 2013-03-21 12:00 CET\n" "Last-Translator: Helmut Merz \n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" From 233ece8dfdced37bd61cee593dcfbcb78da490c3 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sun, 31 Mar 2013 11:08:12 +0200 Subject: [PATCH 08/51] section view: show children with title and description --- compound/book/view_macros.pt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compound/book/view_macros.pt b/compound/book/view_macros.pt index 0431662..576c224 100644 --- a/compound/book/view_macros.pt +++ b/compound/book/view_macros.pt @@ -1,14 +1,18 @@ - - + +
- +
@@ -242,11 +239,8 @@ tal:attributes="dojoType python: item.editable and 'dojo.dnd.Source' or ''"> - + From 8300cbf59beb4a30ec5adedd2bb6a2742419dfd9 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 1 Apr 2013 10:39:30 +0200 Subject: [PATCH 10/51] provide a special topic view for books that shows informative lists of children and text resources --- browser/resource.py | 7 ++ compound/README.txt | 2 +- compound/book/base.py | 52 -------------- compound/book/browser.py | 107 +++++++-------------------- compound/book/configure.zcml | 76 +------------------- compound/book/interfaces.py | 32 --------- compound/book/loops_book_de.dmp | 7 +- compound/book/view_macros.pt | 124 +++++++++++++++++--------------- locales/de/LC_MESSAGES/loops.mo | Bin 23558 -> 23626 bytes locales/de/LC_MESSAGES/loops.po | 8 ++- 10 files changed, 115 insertions(+), 300 deletions(-) delete mode 100644 compound/book/base.py delete mode 100644 compound/book/interfaces.py diff --git a/browser/resource.py b/browser/resource.py index 015c57b..8ec1e95 100644 --- a/browser/resource.py +++ b/browser/resource.py @@ -40,6 +40,7 @@ from zope.traversing.browser import absoluteURL from cybertools.browser.action import actions from cybertools.meta.interfaces import IOptions from cybertools.typology.interfaces import IType +from cybertools.util.html import extractFirstPart from cybertools.xedit.browser import ExternalEditorView, fromUnicode from loops.browser.action import DialogAction, TargetAction from loops.browser.common import EditForm, BaseView @@ -252,6 +253,12 @@ class ResourceView(BaseView): #return util.toUnicode(wp.render(self.request)) return super(ResourceView, self).renderText(text, contentType) + def renderShortText(self): + return self.renderDescription() or self.createShortText(self.render()) + + def createShortText(self, text=None): + return extractFirstPart(text or self.render()) + def download(self): """ Force download, e.g. of a PDF file """ return self.show(True) diff --git a/compound/README.txt b/compound/README.txt index 976111f..2f1d441 100644 --- a/compound/README.txt +++ b/compound/README.txt @@ -355,7 +355,7 @@ Books, Sections, and Pages >>> importPath = os.path.join(os.path.dirname(__file__), 'book') >>> importData(loopsRoot, importPath, 'loops_book_de.dmp') - >>> from loops.compound.book.browser import PageLayout + >>> from loops.compound.book.browser import BookView, SectionView, TopicView Fin de partie diff --git a/compound/book/base.py b/compound/book/base.py deleted file mode 100644 index 80579fe..0000000 --- a/compound/book/base.py +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (c) 2012 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 -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -""" -Implementation of book and book components -""" - -from zope.cachedescriptors.property import Lazy -from zope.interface import implements -from zope.traversing.api import getName - -from loops.compound.base import Compound -from loops.compound.book.interfaces import IPage -from loops.type import TypeInterfaceSourceList - - -TypeInterfaceSourceList.typeInterfaces += (IPage,) - - -class Page(Compound): - - implements(IPage) - - compoundPredicateNames = ['ispartof', 'standard'] - - @Lazy - def documentType(self): - return self.context.getConceptManager()['documenttype'] - - def getParts(self): - result = {} - for r in super(Page, self).getParts(): - for parent in r.getParents(): - if parent.conceptType == self.documentType: - item = result.setdefault(getName(parent), []) - item.append(r) - return result diff --git a/compound/book/browser.py b/compound/book/browser.py index d71a89a..98009c7 100644 --- a/compound/book/browser.py +++ b/compound/book/browser.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2012 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 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 @@ -45,10 +45,22 @@ class Base(object): def book_macros(self): return book_template.macros + @Lazy + def documentTypeType(self): + return self.conceptManager['documenttype'] + + @Lazy + def sectionType(self): + return self.conceptManager['section'] + @Lazy def isPartOfPredicate(self): return self.conceptManager['ispartof'] + @Lazy + def showNavigation(self): + return self.typeOptions.show_navigation + @Lazy def breadcrumbsParent(self): for p in self.context.getParents([self.isPartOfPredicate]): @@ -82,34 +94,8 @@ class Base(object): if self.editable: return 'index.html' - -class BookOverview(Base, ConceptView): - - @Lazy - def macro(self): - return book_template.macros['book'] - - -class SectionView(Base, ConceptView): - - @Lazy - def macro(self): - return book_template.macros['section'] - - @Lazy - def documentTypeType(self): - return self.conceptManager['documenttype'] - - @Lazy - def showNavigation(self): - return self.typeOptions.show_navigation - - @Lazy - def sectionType(self): - return self.conceptManager['section'] - def getResources(self): - relViews = super(SectionView, self).getResources() + relViews = super(Base, self).getResources() return relViews @Lazy @@ -144,64 +130,23 @@ class SectionView(Base, ConceptView): yield c -# layout parts - probably obsolete: +class BookView(Base, ConceptView): -class PageLayout(Base, standard.Layout): - - def getParts(self): - parts = ['headline', 'keyquestions', 'quote', 'maintext', - 'story', 'tip', 'usecase'] - return self.getPartViews(parts) + @Lazy + def macro(self): + return book_template.macros['book'] -class PagePart(object): +class SectionView(Base, ConceptView): - template = book_template - templateName = 'compound.book' - macroName = 'text' - partName = None # define in subclass - gridPattern = ['span-4'] - - def getResources(self): - result = [] - res = self.adapted.getParts().get(self.partName) or [] - for idx, r in enumerate(res): - result.append(standard.ResourceView( - r, self.request, parent=self, idx=idx)) - return result + @Lazy + def macro(self): + return book_template.macros['section'] -class Headline(PagePart, standard.Header2): +class TopicView(Base, ConceptView): - macroName = 'headline' + @Lazy + def macro(self): + return book_template.macros['topic'] - -class MainText(PagePart, standard.BasePart): - - partName = 'maintext' - - -class KeyQuestions(PagePart, standard.BasePart): - - partName = 'keyquestions' - - -class Story(PagePart, standard.BasePart): - - partName = 'story' - - -class Tip(PagePart, standard.BasePart): - - partName = 'tip' - - -class UseCase(PagePart, standard.BasePart): - - partName = 'usecase' - - -class Quote(PagePart, standard.BasePart): - - partName = 'quote' - gridPattern = ['span-2 last'] diff --git a/compound/book/configure.zcml b/compound/book/configure.zcml index 4ff408f..09a374a 100644 --- a/compound/book/configure.zcml +++ b/compound/book/configure.zcml @@ -3,18 +3,6 @@ xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="loops"> - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/compound/book/interfaces.py b/compound/book/interfaces.py deleted file mode 100644 index 3dd1e43..0000000 --- a/compound/book/interfaces.py +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2012 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 -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -""" -Books, sections, pages... -""" - -from zope.interface import Interface, Attribute -from zope import interface, component, schema - -from loops.compound.interfaces import ICompound -from loops.util import _ - - -class IPage(ICompound): - - pass diff --git a/compound/book/loops_book_de.dmp b/compound/book/loops_book_de.dmp index 5185bb2..a7d846f 100644 --- a/compound/book/loops_book_de.dmp +++ b/compound/book/loops_book_de.dmp @@ -4,11 +4,11 @@ type(u'documenttype', u'Dokumentenart', options=u'qualifier:assign', # book types type(u'book', u'Buch', viewName=u'book_overview', typeInterface=u'', options=u'action.portlet:create_subtype,edit_concept') -#type(u'page', u'Seite', viewName=u'page_layout', -# typeInterface=u'loops.compound.book.interfaces.IPage', -# options=u'action.portlet:edit_concept') type(u'section', u'Kapitel', viewName=u'section_view', typeInterface=u'', options=u'action.portlet:create_subtype,edit_concept') +#type(u'topic', u'Thema', viewName=u'book_topic_view', +# typeInterface=u'loops.knowledge.interfaces.ITopic', +# options=u'action.portlet:create_topic,edit_topic') concept(u'system', u'System', u'domain') @@ -30,4 +30,3 @@ concept(u'usecase', u'Fallbeispiel', u'documenttype') # book structure child(u'book', u'section', u'issubtype', usePredicate=u'ispartof') child(u'section', u'section', u'issubtype', usePredicate=u'ispartof') -#child(u'section', u'page', u'issubtype', usePredicate=u'ispartof') diff --git a/compound/book/view_macros.pt b/compound/book/view_macros.pt index 576c224..298f67d 100644 --- a/compound/book/view_macros.pt +++ b/compound/book/view_macros.pt @@ -2,7 +2,9 @@ -
+

@@ -37,71 +39,81 @@ -
-
-
-
-
-
- - - - + +
+ +

- - - -
- -
-
- - - -
-

- + + +

Children

+ +

Text Elements

+
+
+

+ +

+ + diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index fca2a64fb4145914853b06e1784078da52c00049..c2a1970b3b85bb688dcd8ffcd2de2df37f39fd3c 100644 GIT binary patch delta 8356 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\n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -537,6 +537,9 @@ msgstr "Unterbegriffe" msgid "Resources" msgstr "Ressourcen" +msgid "Text Elements" +msgstr "Texte" + msgid "Title" msgstr "Titel" @@ -702,6 +705,9 @@ msgstr "Zugeordnete Begriffe" msgid "more..." msgstr "Mehr..." +msgid "More..." +msgstr "Mehr..." + msgid "Versioning" msgstr "Versionierung" From fbd036a7d0da1d0884d8d470a3fdff5dc176a505 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sat, 6 Apr 2013 16:13:06 +0200 Subject: [PATCH 11/51] provide button for resetting responses entered --- browser/loops.js | 8 +++++++- knowledge/survey/view_macros.pt | 3 +++ locales/de/LC_MESSAGES/loops.mo | Bin 23626 -> 23689 bytes locales/de/LC_MESSAGES/loops.po | 5 ++++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/browser/loops.js b/browser/loops.js index 4be35a5..bb24e2c 100644 --- a/browser/loops.js +++ b/browser/loops.js @@ -1,4 +1,4 @@ -/* $Id$ */ +/* loops.js */ function openEditWindow(url) { zmi = window.open(url, 'zmi'); @@ -19,6 +19,12 @@ function toggleCheckBoxes(toggle, fieldName) { for (i in w) w[i].checked=toggle.checked; } +function setRadioButtons(value) { + dojo.forEach(dojo.query('input[type="radio"][value="' + value + '"]'), + function(n) { + n.checked = true;}) +} + function validate(nodeName, required) { // (work in progress) - may be used for onBlur event handler var w = dojo.byId(nodeName); diff --git a/knowledge/survey/view_macros.pt b/knowledge/survey/view_macros.pt index 49731dc..51c2c6a 100644 --- a/knowledge/survey/view_macros.pt +++ b/knowledge/survey/view_macros.pt @@ -85,6 +85,9 @@

+ title related/relationInfo"> Resource Title
+ title related/relationInfo">
Resource Title
+
diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index c2a1970b3b85bb688dcd8ffcd2de2df37f39fd3c..9ebc458fe70403c8fea5c10820767a09f829c035 100644 GIT binary patch delta 8158 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 s#Bid3*hc7SPo2A;=gAjrS)Mc@WJ~>~Cj\n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -241,6 +241,9 @@ msgstr "Trifft für unser Unternehmen voll und ganz zu" msgid "Evaluate Questionnaire" msgstr "Fragebogen auswerten" +msgid "Reset Responses Entered" +msgstr "Eingaben zurücksetzen" + msgid "Back to Questionnaire" msgstr "Zurück zum Fragebogen" From a78ce4f8800a6b64a3ee5c20c9e357068a68b301 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Tue, 9 Apr 2013 08:38:02 +0200 Subject: [PATCH 12/51] work in progress: states portlet --- browser/node.py | 6 +++++- organize/stateful/browser.py | 10 ++++++++++ organize/stateful/view_macros.pt | 28 ++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/browser/node.py b/browser/node.py index 2763ada..270f459 100644 --- a/browser/node.py +++ b/browser/node.py @@ -195,7 +195,11 @@ class NodeView(BaseView): subMacro=calendar_macros.macros['main'], priority=90) # force early portlet registrations by target by setting up target view - self.virtualTarget + if self.virtualTarget is not None: + std = self.virtualTarget.typeOptions('portlet_states') + if std: + from loops.organize.stateful.browser import registerStatesPortlet + registerStatesPortlet(self.controller, self.virtualTarget, std) @Lazy def usersPresent(self): diff --git a/organize/stateful/browser.py b/organize/stateful/browser.py index ae57c87..42e04a2 100644 --- a/organize/stateful/browser.py +++ b/organize/stateful/browser.py @@ -43,6 +43,16 @@ statefulActions = ('classification_quality', 'publishable_task',) +def registerStatesPortlet(controller, view, statesDefs, + region='portlet_right', priority=98): + cm = controller.macros + stfs = [component.getAdapter(view.context, IStateful, name=std) + for std in statesDefs] + cm.register(region, 'states', title=_(u'States'), + subMacro=template.macros['portlet_states'], + priority=priority, info=view, stfs=stfs) + + class StateAction(Action): url = None diff --git a/organize/stateful/view_macros.pt b/organize/stateful/view_macros.pt index 6dfad17..d1be431 100644 --- a/organize/stateful/view_macros.pt +++ b/organize/stateful/view_macros.pt @@ -68,4 +68,32 @@ + + + +
+
+ Workflow + +
+
+ State: + +
+
+
Available Transitions:
+ +
+
+
+ + From cad21c5dc3218840a9b128d6220815dea4292b2b Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 11 Apr 2013 08:28:19 +0200 Subject: [PATCH 13/51] unauthenticated user should not provide a person ID --- knowledge/survey/browser.py | 1 + knowledge/survey/response.py | 7 +++---- organize/tracking/base.py | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 6b6c767..55935ad 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -48,6 +48,7 @@ class SurveyView(ConceptView): @Lazy def macro(self): + self.registerDojo() return template.macros['survey'] def results(self): diff --git a/knowledge/survey/response.py b/knowledge/survey/response.py index b27979e..3841c4f 100644 --- a/knowledge/survey/response.py +++ b/knowledge/survey/response.py @@ -39,10 +39,9 @@ class Responses(BaseRecordManager): self.context = context def save(self, data): - if not self.personId: - return - self.storage.saveUserTrack(self.uid, 0, self.personId, data, - update=True, overwrite=True) + if self.personId: + self.storage.saveUserTrack(self.uid, 0, self.personId, data, + update=True, overwrite=True) def load(self): if self.personId: diff --git a/organize/tracking/base.py b/organize/tracking/base.py index f8a1323..645e091 100644 --- a/organize/tracking/base.py +++ b/organize/tracking/base.py @@ -20,6 +20,7 @@ Base class(es) for track/record managers. """ +from zope.app.security.interfaces import IUnauthenticatedPrincipal from zope.cachedescriptors.property import Lazy from cybertools.meta.interfaces import IOptions @@ -65,6 +66,8 @@ class BaseRecordManager(object): else: principal = getPrincipalForUserId(userId, context=self.context) if principal is not None: + if IUnauthenticatedPrincipal.providedBy(principal): + return None person = getPersonForUser(self.context, principal=principal) if person is None: return principal.id From feb6ea1a060c3189ca0baddd0ef73606709cfd8e Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 15 Apr 2013 07:50:17 +0200 Subject: [PATCH 14/51] work in progress: self registration with email notiification/confirmation --- organize/browser/configure.zcml | 12 +++++++++++ organize/browser/member.py | 35 +++++++++++++++++++++++++++------ organize/browser/view_macros.pt | 4 ++++ 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/organize/browser/configure.zcml b/organize/browser/configure.zcml index 91d40f1..e351efa 100644 --- a/organize/browser/configure.zcml +++ b/organize/browser/configure.zcml @@ -27,6 +27,18 @@ class="loops.organize.browser.member.MemberRegistration" permission="zope.View" /> + + + + + + + + From 4a6d5abefcfb27e2749a43eeb8643eff8741e2e3 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Tue, 23 Apr 2013 08:27:52 +0200 Subject: [PATCH 15/51] don't show lightbox if image is large --- browser/lobo/standard.pt | 1 + layout/base.py | 1 + 2 files changed, 2 insertions(+) diff --git a/browser/lobo/standard.pt b/browser/lobo/standard.pt index 9148b61..34a015e 100644 --- a/browser/lobo/standard.pt +++ b/browser/lobo/standard.pt @@ -117,6 +117,7 @@ Date: Fri, 26 Apr 2013 09:23:25 +0200 Subject: [PATCH 16/51] fix check for showing tabview icon --- knowledge/survey/browser.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 55935ad..99eac6d 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -42,7 +42,6 @@ template = ViewPageTemplateFile('view_macros.pt') class SurveyView(ConceptView): - tabview = 'index.html' data = None errors = None @@ -51,6 +50,11 @@ class SurveyView(ConceptView): self.registerDojo() return template.macros['survey'] + @Lazy + def tabview(self): + if self.editable: + return 'index.html' + def results(self): result = [] response = None From 320e83c602c5b9a630a4926bc3d64cf20cb03733 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sat, 27 Apr 2013 15:07:11 +0200 Subject: [PATCH 17/51] provide tabbed page concept type for showing sub-queries as tabs --- browser/concept.py | 30 +++++++++++++++++++++++++++++- browser/configure.zcml | 8 ++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/browser/concept.py b/browser/concept.py index c94dce3..b550830 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2012 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 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 @@ -50,6 +50,7 @@ from cybertools.meta.interfaces import IOptions from cybertools.typology.interfaces import IType, ITypeManager from cybertools.util.jeep import Jeep from loops.browser.common import EditForm, BaseView, LoopsTerms, concept_macros +from loops.browser.common import ViewMode from loops.common import adapted from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList from loops.i18n.browser import I18NView @@ -746,3 +747,30 @@ class ListTypeInstances(ListChildren): noDuplicates, useFilter, [self.typePredicate]): yield c + +class TabbedPage(ConceptView): + + @Lazy + def subpagePredicates(self): + pred = self.conceptManager.get('issubpage') + if pred is None: + pred = self.isPartOfPredicate + return [pred] + + def viewModes(self): + modes = Jeep() + for s in self.getSiblings(self.subpagePredicates): + url = self.nodeView.getUrlForTarget(s) + modes.append(ViewMode(getName(s), s.title, url)) + if not modes: + return modes + modes[getName(self.context)].active = True + return modes + + def getSiblings(self, preds): + for p in self.context.getParents(preds): + parent = p + break + else: + return [] + return p.getChildren(preds) diff --git a/browser/configure.zcml b/browser/configure.zcml index f6f3695..70f3b2c 100644 --- a/browser/configure.zcml +++ b/browser/configure.zcml @@ -553,6 +553,14 @@ factory="loops.browser.concept.ListTypeInstances" permission="zope.View" /> + + Date: Mon, 29 Apr 2013 08:39:14 +0200 Subject: [PATCH 18/51] improve questionnaire layout --- browser/skin/lobo/lobo.css | 8 ++++++++ knowledge/survey/browser.py | 2 +- knowledge/survey/view_macros.pt | 9 +++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/browser/skin/lobo/lobo.css b/browser/skin/lobo/lobo.css index ec06252..3e15e5c 100644 --- a/browser/skin/lobo/lobo.css +++ b/browser/skin/lobo/lobo.css @@ -120,6 +120,10 @@ thead th { margin-bottom: 0.3em; } +.infotext { + font-size: 90%; +} + .fields td { vertical-align: top; } @@ -163,6 +167,10 @@ table.listing td { border-bottom: 1px dotted #dddddd; } +table.listing tr.vpad td { + padding: 7px 2px 7px 2px; +} + fieldset.box table.listing td { padding: 0 1px 0 1px; } diff --git a/knowledge/survey/browser.py b/knowledge/survey/browser.py index 99eac6d..d9075d6 100644 --- a/knowledge/survey/browser.py +++ b/knowledge/survey/browser.py @@ -112,7 +112,7 @@ class SurveyView(ConceptView): mapping=dict(minAnswers=qugroup.minAnswers)), target_language=lang) if info: - text = u'%s
(%s)' % (text, info) + text = u'%s
(%s)' % (text, info) return text def getValues(self, question): diff --git a/knowledge/survey/view_macros.pt b/knowledge/survey/view_macros.pt index 51c2c6a..bdb6ded 100644 --- a/knowledge/survey/view_macros.pt +++ b/knowledge/survey/view_macros.pt @@ -47,12 +47,12 @@ - + - + + + - @@ -119,6 +121,8 @@ tal:attributes="value typeToken" /> + + - diff --git a/browser/skin/lobo/body.pt b/browser/skin/lobo/body.pt index f1f08c6..2a3ea56 100644 --- a/browser/skin/lobo/body.pt +++ b/browser/skin/lobo/body.pt @@ -30,7 +30,13 @@
-
+ +
+
-
+ +
+
0: + # show form again + return True + login = form.get('loginName') + regMan = IMemberRegistrationManager(self.context.getLoopsRoot()) + pw = generateName() + email = form.get('email') + result = regMan.register(login, pw, + form.get('lastName'), form.get('firstName'), + email=email,) + if isinstance(result, dict): + fi = formState.fieldInstances[result['fieldName']] + fi.setError(result['error'], self.formErrors) + formState.severity = max(formState.severity, fi.severity) + return True + self.object = result + person = result.context + pa = self.getPrincipalAnnotation( + getPrincipalForUserId(adapted(person).getUserId())) + pa['id'] = generateName() + pa['timestamp'] = datetime.utcnow() + self.notifyEmail(login, email, pa['id']) + msg = self.message + self.request.response.redirect('%s?loops.message=%s' % (self.url, msg)) + return False - # TODO: control form via interface? + def notifyEmail(self, userid, recipient, id): + baseUrl = absoluteURL(self.context.getMenu(), self.request) + url = u'%s/selfservice_confirmation.html?login=%s&id=%s' % ( + baseUrl, userid, id,) + recipients = [recipient] + message = u'Um die Anmeldung abzuschliessen muessen Sie folgenden Link betaetigen:\n\n' + message = (message + url).encode('UTF-8') + sender = 'webmaster@zeitraum-bayern.de' + msg = MIMEText(message, 'plain', 'utf-8') + msg['Subject'] = 'Benutzer-Registrierung' + msg['From'] = sender + msg['To'] = ', '.join(recipients) + mailhost = component.getUtility(IMailDelivery, 'Mail') + mailhost.send(sender, recipients, msg.as_string()) + + +class ConfirmMemberRegistration(BaseMemberRegistration, Form): + + permissions_key = u'secure_registration.permissions' + roles_key = u'secure_registration.roles' + + template = form_macros + isInnerHtml = False + showAssignments = False + form_action = 'confirm_registration' + + def closeAction(self, submit=True): + return u'' @Lazy def macro(self): return organize_macros.macros['confirm'] + @Lazy + def data(self): + form = self.request.form + return dict(loginName=form.get('login'), id=form.get('id')) + + @Lazy + def schema(self): + schema = super(ConfirmMemberRegistration, self).schema + schema.fields.remove('birthDate') + schema.fields.remove('phoneNumbers') + schema.fields.loginName.readonly = True + schema.fields.reorder(-2, 'loginName') + schema.fields.firstName.readonly = True + schema.fields.lastName.readonly = True + schema.fields.firstName.readonly = True + schema.fields.email.readonly = True + return schema + + def update(self): + form = self.request.form + if form.get('form.action') != 'confirm_registration': + return True + if not form.get('login'): + return True + regMan = IMemberRegistrationManager(self.context.getLoopsRoot()) + prefix = regMan.getPrincipalFolderFromOption().prefix + userId = prefix + form['login'] + principal = getPrincipalForUserId(userId) + pa = self.getPrincipalAnnotation(principal) + id = form.get('id') + if not id or id != pa.get('id'): + return True + pw = form.get('password') + pwConfirm = form.get('passwordConfirm') + if pw != pwConfirm: + msg = self.errorMessages['confirm_nomatch'] + self.request.form['message'] = msg + return True + del pa['id'] + del pa['timestamp'] + ip = getInternalPrincipal(userId) + ip.setPassword(pw) + url = '%s?loops.message=%s' % (self.url, self.message) + self.request.response.redirect(url) + return False + class PasswordChange(NodeView, Form): diff --git a/organize/browser/view_macros.pt b/organize/browser/view_macros.pt index af8ea2b..ecc21ad 100644 --- a/organize/browser/view_macros.pt +++ b/organize/browser/view_macros.pt @@ -1,7 +1,22 @@ - - + + + + +
+ + + diff --git a/organize/member.py b/organize/member.py index 9753bd6..09e5326 100644 --- a/organize/member.py +++ b/organize/member.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2012 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 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 @@ -62,11 +62,20 @@ class MemberRegistrationManager(object): def __init__(self, context): self.context = context + @Lazy + def personType(self): + concepts = self.context.getConceptManager() + return adapted(concepts[self.person_typeName]) + + def getPrincipalFolderFromOption(self): + options = IOptions(self.personType) + pfName = options(self.principalfolder_key, + (self.default_principalfolder,))[0] + return getPrincipalFolder(self.context, pfName) + def register(self, userId, password, lastName, firstName=u'', groups=[], useExisting=False, pfName=None, **kw): - concepts = self.context.getConceptManager() - personType = adapted(concepts[self.person_typeName]) - options = IOptions(personType) + options = IOptions(self.personType) if pfName is None: pfName = options(self.principalfolder_key, (self.default_principalfolder,))[0] @@ -74,7 +83,7 @@ class MemberRegistrationManager(object): if len(groups)==0: groups = options(self.groups_key, ()) self.setGroupsForPrincipal(pfName, userId, groups=groups) - self.createPersonForPrincipal(pfName, userId, lastName, firstName, + return self.createPersonForPrincipal(pfName, userId, lastName, firstName, useExisting, **kw) def createPrincipal(self, pfName, userId, password, lastName, From 9427b8ccbd74d561b451b41f6fca596cd1d4bea0 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 6 May 2013 08:00:09 +0200 Subject: [PATCH 23/51] self registration with confirmation working (needs still improvements: sender email, info messages) --- locales/de/LC_MESSAGES/loops.mo | Bin 23689 -> 23981 bytes locales/de/LC_MESSAGES/loops.po | 11 +++++++- organize/browser/member.py | 45 ++++++++++++++++++++------------ organize/member.py | 3 ++- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index 9ebc458fe70403c8fea5c10820767a09f829c035..b0317196556620a3f9a8c56118766a5291aa3c4c 100644 GIT binary patch delta 8698 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 ACjbBd delta 8443 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\n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -86,6 +86,9 @@ msgstr "Thema bearbeiten..." msgid "Modify topic." msgstr "Thema ändern" +msgid "Please correct the indicated errors." +msgstr "Bitte berichtigen Sie die angezeigten Fehler." + # blog msgid "Edit Blog Post..." @@ -759,12 +762,18 @@ msgstr "Teilnehmerregistrierung" msgid "Register" msgstr "Benutzer registrieren" +msgid "Login name already taken." +msgstr "Die von Ihnen eingegebene Benutzerkennung ist schon vergeben." + msgid "Your old password was not entered correctly." msgstr "Sie haben Ihr altes Passwort nicht korrekt eingegeben." msgid "Password and password confirmation do not match." msgstr "Die Passwort-Wiederholung stimmt nicht mit dem eingegebenen Passwort überein." +msgid "The user account has been created." +msgstr "Ihr Benutzerkonto wurde eingerichtet." + msgid "Your password has been changed." msgstr "Ihr Passwort wurde geändert." diff --git a/organize/browser/member.py b/organize/browser/member.py index 8abe37b..502c71f 100644 --- a/organize/browser/member.py +++ b/organize/browser/member.py @@ -111,6 +111,10 @@ class BaseMemberRegistration(NodeView): def item(self): return self + @Lazy + def data(self): + return self.request.form + def getPrincipalAnnotation(self, principal): return annotations(principal).get(ANNOTATION_KEY, None) @@ -201,12 +205,13 @@ class SecureMemberRegistration(BaseMemberRegistration, CreateForm): regMan = IMemberRegistrationManager(self.context.getLoopsRoot()) pw = generateName() email = form.get('email') - result = regMan.register(login, pw, - form.get('lastName'), form.get('firstName'), - email=email,) - if isinstance(result, dict): - fi = formState.fieldInstances[result['fieldName']] - fi.setError(result['error'], self.formErrors) + try: + result = regMan.register(login, pw, + form.get('lastName'), form.get('firstName'), + email=email,) + except ValueError, e: + fi = formState.fieldInstances['loginName'] + fi.setError('duplicate_loginname', self.formErrors) formState.severity = max(formState.severity, fi.severity) return True self.object = result @@ -225,11 +230,11 @@ class SecureMemberRegistration(BaseMemberRegistration, CreateForm): url = u'%s/selfservice_confirmation.html?login=%s&id=%s' % ( baseUrl, userid, id,) recipients = [recipient] - message = u'Um die Anmeldung abzuschliessen muessen Sie folgenden Link betaetigen:\n\n' + message = _(u'confirmation_mail_text') + u':\n\n' message = (message + url).encode('UTF-8') - sender = 'webmaster@zeitraum-bayern.de' + sender = 'helmutm@cy55.de' msg = MIMEText(message, 'plain', 'utf-8') - msg['Subject'] = 'Benutzer-Registrierung' + msg['Subject'] = _(u'confirmation_mail_subject') msg['From'] = sender msg['To'] = ', '.join(recipients) mailhost = component.getUtility(IMailDelivery, 'Mail') @@ -263,12 +268,10 @@ class ConfirmMemberRegistration(BaseMemberRegistration, Form): schema = super(ConfirmMemberRegistration, self).schema schema.fields.remove('birthDate') schema.fields.remove('phoneNumbers') - schema.fields.loginName.readonly = True - schema.fields.reorder(-2, 'loginName') - schema.fields.firstName.readonly = True - schema.fields.lastName.readonly = True - schema.fields.firstName.readonly = True - schema.fields.email.readonly = True + schema.fields.remove('loginName') + schema.fields.remove('firstName') + schema.fields.remove('lastName') + schema.fields.remove('email') return schema def update(self): @@ -285,11 +288,19 @@ class ConfirmMemberRegistration(BaseMemberRegistration, Form): id = form.get('id') if not id or id != pa.get('id'): return True + instance = component.getAdapter(self.object, IInstance, name='editor') + instance.template = self.schema + self.formState = formState = instance.applyTemplate(data=form, + fieldHandlers=self.fieldHandlers) + #formState = self.formState = self.validate(form) + if formState.severity > 0: + return True pw = form.get('password') pwConfirm = form.get('passwordConfirm') if pw != pwConfirm: - msg = self.errorMessages['confirm_nomatch'] - self.request.form['message'] = msg + fi = formState.fieldInstances['password'] + fi.setError('confirm_nomatch', self.formErrors) + formState.severity = max(formState.severity, fi.severity) return True del pa['id'] del pa['timestamp'] diff --git a/organize/member.py b/organize/member.py index 09e5326..88428aa 100644 --- a/organize/member.py +++ b/organize/member.py @@ -79,7 +79,8 @@ class MemberRegistrationManager(object): if pfName is None: pfName = options(self.principalfolder_key, (self.default_principalfolder,))[0] - self.createPrincipal(pfName, userId, password, lastName, firstName, useExisting=useExisting) + self.createPrincipal(pfName, userId, password, lastName, firstName, + useExisting=useExisting) if len(groups)==0: groups = options(self.groups_key, ()) self.setGroupsForPrincipal(pfName, userId, groups=groups) From d84e8de9a09cf761a0eeb89d55ec47753ff46f0a Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Mon, 6 May 2013 12:21:50 +0200 Subject: [PATCH 24/51] handle missing properties in Office file correctly --- integrator/office/base.py | 18 +++++++++--------- locales/de/LC_MESSAGES/loops.po | 6 ++++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/integrator/office/base.py b/integrator/office/base.py index bed343b..542aa0a 100644 --- a/integrator/office/base.py +++ b/integrator/office/base.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2012 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 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 @@ -78,28 +78,28 @@ class OfficeFile(ExternalFileAdapter): @Lazy def docPropertyDom(self): fn = self.docFilename - dummy = dict(core=[], custom=[]) + result = dict(core=[], custom=[]) root, ext = os.path.splitext(fn) if not ext.lower() in self.fileExtensions: - return dummy + return result try: zf = ZipFile(fn, 'r') except IOError, e: from logging import getLogger self.logger.warn(e) - return dummy + return result if self.corePropFileName not in zf.namelist(): self.logger.warn('Core properties not found in file %s.' % self.externalAddress) + else: + result['core'] = etree.fromstring(zf.read(self.corePropFileName)) if self.propFileName not in zf.namelist(): self.logger.warn('Custom properties not found in file %s.' % self.externalAddress) - propsXml = zf.read(self.propFileName) - corePropsXml = zf.read(self.corePropFileName) - # TODO: read core.xml, return both trees in dictionary + else: + result['custom'] = etree.fromstring(zf.read(self.propFileName)) zf.close() - return {'custom': etree.fromstring(propsXml), - 'core': etree.fromstring(corePropsXml)} + return result def getDocProperty(self, pname): for p in self.docPropertyDom['custom']: diff --git a/locales/de/LC_MESSAGES/loops.po b/locales/de/LC_MESSAGES/loops.po index 2e143ef..3d0a6bb 100644 --- a/locales/de/LC_MESSAGES/loops.po +++ b/locales/de/LC_MESSAGES/loops.po @@ -771,6 +771,12 @@ msgstr "Sie haben Ihr altes Passwort nicht korrekt eingegeben." msgid "Password and password confirmation do not match." msgstr "Die Passwort-Wiederholung stimmt nicht mit dem eingegebenen Passwort überein." +msgid "confirmation_mail_subject" +msgstr "Benutzer-Registrierung" + +msgid "confirmation_mail_text." +msgstr "Bitte clicken Sie auf den folgenden Link, um die Anmeldung abzschließen." + msgid "The user account has been created." msgstr "Ihr Benutzerkonto wurde eingerichtet." From 3f1ffdb8f4f44c71541c5368e6866981ae490195 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Fri, 17 May 2013 11:30:10 +0200 Subject: [PATCH 25/51] work in progress: info texts and feedback pages for self-service registration --- browser/common.py | 2 +- locales/de/LC_MESSAGES/loops.mo | Bin 23981 -> 24159 bytes locales/de/LC_MESSAGES/loops.po | 2 +- organize/README.txt | 2 +- organize/browser/member.py | 72 +++++++++++++++++++++++++------- organize/browser/view_macros.pt | 7 ++++ 6 files changed, 66 insertions(+), 19 deletions(-) diff --git a/browser/common.py b/browser/common.py index 8639958..d8886e3 100644 --- a/browser/common.py +++ b/browser/common.py @@ -481,7 +481,7 @@ class BaseView(GenericView, I18NView): return absoluteURL(provider, self.request) return None - def renderText(self, text, contentType): + def renderText(self, text, contentType='text/restructured'): text = util.toUnicode(text) typeKey = util.renderingFactories.get(contentType, None) if typeKey is None: diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index b0317196556620a3f9a8c56118766a5291aa3c4c..ad3d32055612f5c99ce41d9468b0b9cced058617 100644 GIT binary patch delta 7346 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 UTTtlt?ceAtYP~ID%=()D1F?2ma{vGU delta 7169 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 + + + + + + + + + + + - - + + + + From bc24407d343da3b40d216722f693dc63c28d3a44 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Fri, 7 Jun 2013 09:17:27 +0200 Subject: [PATCH 27/51] add header field for feedback page --- knowledge/survey/interfaces.py | 7 +++++++ knowledge/survey/view_macros.pt | 3 +++ 2 files changed, 10 insertions(+) diff --git a/knowledge/survey/interfaces.py b/knowledge/survey/interfaces.py index 7ce5849..e2adffc 100644 --- a/knowledge/survey/interfaces.py +++ b/knowledge/survey/interfaces.py @@ -38,6 +38,13 @@ class IQuestionnaire(IConceptSchema, interfaces.IQuestionnaire): default=4, required=True) + feedbackHeader = schema.Text( + title=_(u'Feedback Header'), + description=_(u'Text that will appear at the top of the feedback page.'), + default=u'', + missing_value=u'', + required=False) + feedbackFooter = schema.Text( title=_(u'Feedback Footer'), description=_(u'Text that will appear at the end of the feedback page.'), diff --git a/knowledge/survey/view_macros.pt b/knowledge/survey/view_macros.pt index bdb6ded..9e7593c 100644 --- a/knowledge/survey/view_macros.pt +++ b/knowledge/survey/view_macros.pt @@ -11,6 +11,9 @@

Feedback

+
 
-
+
-
 
Does not apply
From d0243d056423b3dceca82d7d24c3dbad44f998e6 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Wed, 1 May 2013 10:44:43 +0200 Subject: [PATCH 19/51] no underline for elements of any kind --- browser/skin/lobo/lobo.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/browser/skin/lobo/lobo.css b/browser/skin/lobo/lobo.css index 3e15e5c..13665e8 100644 --- a/browser/skin/lobo/lobo.css +++ b/browser/skin/lobo/lobo.css @@ -62,6 +62,10 @@ h1, h2, h3, h4, h5, h6 { margin-bottom: 0.4em; } +a { + text-decoration: none; +} + a[href]:hover { text-decoration: none; color: #6060c0; From 135aa74d9c2934d05a7ddd89643b2bf252a76ce9 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 2 May 2013 15:24:05 +0200 Subject: [PATCH 20/51] reverse parts of header title if specified by global option reverseHeadTitle --- browser/node.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/browser/node.py b/browser/node.py index 270f459..a49a350 100644 --- a/browser/node.py +++ b/browser/node.py @@ -385,6 +385,8 @@ class NodeView(BaseView): ht = super(NodeView, self).headTitle if ht not in parts: parts.append(ht) + if self.globalOptions('reverseHeadTitle'): + parts.reverse() return ' - ' .join(parts) @Lazy From 90b4da1a9ba02ffb9652269c80d7cdaf999bd121 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sat, 4 May 2013 08:55:25 +0200 Subject: [PATCH 21/51] improve position of top and page actions --- browser/skin/lobo/lobo.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/browser/skin/lobo/lobo.css b/browser/skin/lobo/lobo.css index 13665e8..4fbcbd3 100644 --- a/browser/skin/lobo/lobo.css +++ b/browser/skin/lobo/lobo.css @@ -279,7 +279,8 @@ fieldset.box td { .top-actions { position: absolute; - top: 30px; + top: 40px; + margin-left: 10px; } .quicksearch input { @@ -293,7 +294,7 @@ fieldset.box td { .page-actions { position: absolute; - top: 55px; + top: 75px; margin-left: 210px; } From 7b9a85a586f0e4a5f2addcaf89b3279831129be7 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Sun, 5 May 2013 16:55:11 +0200 Subject: [PATCH 22/51] self registration with confirmation: basically working; missing: translations, sender email, improved error handling --- browser/form_macros.pt | 8 +- browser/skin/lobo/body.pt | 8 +- compound/book/browser.py | 3 + compound/book/view_macros.pt | 8 +- organize/browser/member.py | 136 ++++++++++++++++++++++++++++++-- organize/browser/view_macros.pt | 19 ++++- organize/member.py | 19 +++-- 7 files changed, 180 insertions(+), 21 deletions(-) diff --git a/browser/form_macros.pt b/browser/form_macros.pt index 63543d3..47e846b 100644 --- a/browser/form_macros.pt +++ b/browser/form_macros.pt @@ -51,6 +51,8 @@
@@ -59,7 +61,7 @@
@@ -127,7 +131,7 @@
+ + + + +
Login Name +
+
From 45eeac9a4113f37623486c23d7867c97e6ef8805 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Wed, 5 Jun 2013 09:15:50 +0200 Subject: [PATCH 26/51] member registration: use info and feedback pages; configurable sender email; login/register portlet --- browser/node_macros.pt | 7 +++++- locales/de/LC_MESSAGES/loops.mo | Bin 24159 -> 24237 bytes locales/de/LC_MESSAGES/loops.po | 7 ++++-- organize/browser/member.py | 20 +++++++++++------ organize/browser/view_macros.pt | 37 +++++++++++++++++++++----------- 5 files changed, 49 insertions(+), 22 deletions(-) diff --git a/browser/node_macros.pt b/browser/node_macros.pt index b67f1fb..640f9a1 100644 --- a/browser/node_macros.pt +++ b/browser/node_macros.pt @@ -314,8 +314,13 @@ - + diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index ad3d32055612f5c99ce41d9468b0b9cced058617..89e7e8c8dd3ffa2fd069020eeb9f787eaca30e35 100644 GIT binary patch delta 8836 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 diff --git a/locales/de/LC_MESSAGES/loops.po b/locales/de/LC_MESSAGES/loops.po index 1a93a8d..1885c16 100644 --- a/locales/de/LC_MESSAGES/loops.po +++ b/locales/de/LC_MESSAGES/loops.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: 0.13.0\n" "POT-Creation-Date: 2007-05-22 12:00 CET\n" -"PO-Revision-Date: 2013-05-05 12:00 CET\n" +"PO-Revision-Date: 2013-06-05 12:00 CET\n" "Last-Translator: Helmut Merz \n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -762,6 +762,9 @@ msgstr "Teilnehmerregistrierung" msgid "Register" msgstr "Benutzer registrieren" +msgid "Register new member" +msgstr "Neu registrieren" + msgid "Login name already taken." msgstr "Die von Ihnen eingegebene Benutzerkennung ist schon vergeben." @@ -775,7 +778,7 @@ msgid "confirmation_mail_subject" msgstr "Benutzer-Registrierung" msgid "confirmation_mail_text" -msgstr "Bitte clicken Sie auf den folgenden Link, um die Anmeldung abzschließen." +msgstr "Bitte clicken Sie auf den folgenden Link, um die Anmeldung abzuschließen." msgid "The user account has been created." msgstr "Ihr Benutzerkonto wurde eingerichtet." diff --git a/organize/browser/member.py b/organize/browser/member.py index 28e13f0..5916929 100644 --- a/organize/browser/member.py +++ b/organize/browser/member.py @@ -92,6 +92,7 @@ class BaseMemberRegistration(NodeView): label = _(u'Member Registration') label_submit = _(u'Register') + title = _('Member Registration') permissions_key = u'registration.permissions' roles_key = u'registration.roles' @@ -104,6 +105,7 @@ class BaseMemberRegistration(NodeView): isInnerHtml = False showAssignments = False form_action = 'register' + versionInfo = None def closeAction(self, submit=True): return u'' @@ -202,6 +204,7 @@ class SecureMemberRegistration(BaseMemberRegistration, CreateForm): permissions_key = u'secure_registration.permissions' roles_key = u'secure_registration.roles' + email_key = 'reg_email' @Lazy def schema(self): @@ -265,17 +268,19 @@ class SecureMemberRegistration(BaseMemberRegistration, CreateForm): baseUrl, userid, id,) recipients = [recipient] subject = _(u'confirmation_mail_subject') - name = '.'.join((self.text_names_prefix, self.feedback_key)) + name = '.'.join((self.text_names_prefix, self.email_key)) text = self.resourceManager.get(name) if text: - message = text.data % url + message = (text.data % url).encode('UTF-8') subject = text.description or subject else: message = _(u'confirmation_mail_text') + u':\n\n' message = (message + url).encode('UTF-8') - sender = 'helmutm@cy55.de' + senderInfo = self.globalOptions('email.sender') + sender = senderInfo and senderInfo[0] or 'info@loops.cy55.de' + sender = sender.encode('UTF-8') msg = MIMEText(message, 'plain', 'utf-8') - msg['Subject'] = subject + msg['Subject'] = subject.encode('UTF-8') msg['From'] = sender msg['To'] = ', '.join(recipients) mailhost = component.getUtility(IMailDelivery, 'Mail') @@ -286,8 +291,9 @@ class ConfirmMemberRegistration(BaseMemberRegistration, Form): permissions_key = u'secure_registration.permissions' roles_key = u'secure_registration.roles' - info_key = 'conf_info' - feedback_key = 'conf_feedback' + info_key = 'confirm_info' + feedback_key = 'confirm_feedback' + email_key = 'confirm_email' form_action = 'confirm_registration' @@ -303,6 +309,8 @@ class ConfirmMemberRegistration(BaseMemberRegistration, Form): @Lazy def schema(self): schema = super(ConfirmMemberRegistration, self).schema + schema.fields.remove('salutation') + schema.fields.remove('academicTitle') schema.fields.remove('birthDate') schema.fields.remove('phoneNumbers') schema.fields.remove('loginName') diff --git a/organize/browser/view_macros.pt b/organize/browser/view_macros.pt index bff4b91..93ef80e 100644 --- a/organize/browser/view_macros.pt +++ b/organize/browser/view_macros.pt @@ -2,25 +2,36 @@ - - + + +
+ +
- - - - -
Login Name -
-
+ +
+ + + + +
Login Name +
+
From 9d3f6a2fb3b4d7593d59faf9f2669786f59659be Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Wed, 19 Jun 2013 20:46:25 +0200 Subject: [PATCH 28/51] work in progress: state change dialog --- organize/stateful/browser.py | 59 ++++++++++++++++++++++++++++++-- organize/stateful/configure.zcml | 15 +++++++- organize/stateful/view_macros.pt | 42 +++++++++++++++++++++-- 3 files changed, 109 insertions(+), 7 deletions(-) diff --git a/organize/stateful/browser.py b/organize/stateful/browser.py index 42e04a2..98dc3a9 100644 --- a/organize/stateful/browser.py +++ b/organize/stateful/browser.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2012 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 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 @@ -26,9 +26,13 @@ from zope.cachedescriptors.property import Lazy from zope.i18n import translate from cybertools.browser.action import Action, actions +from cybertools.composer.schema.field import Field +from cybertools.composer.schema.interfaces import ISchemaFactory +from cybertools.composer.schema.schema import Schema from cybertools.stateful.interfaces import IStateful, IStatesDefinition from loops.browser.common import BaseView from loops.browser.concept import ConceptView +from loops.browser.form import ObjectForm, EditObject from loops.expert.query import And, Or, State, Type, getObjects from loops.expert.browser.search import search_template from loops.security.common import checkPermission @@ -83,16 +87,65 @@ class StateAction(Action): for std in statefulActions: actions.register('state.' + std, 'object', StateAction, - definition = std, + definition=std, cssClass='icon-action', ) +class ChangeStateBase(object): + + @Lazy + def stateful(self): + return component.getAdapter(self.view.context, IStateful, + name=self.definition) + + @Lazy + def definition(self): + return self.request.form.get('stdef') or u'' + + @Lazy + def action(self): + return self.request.form.get('action') or u'' + + @Lazy + def stateObject(self): + return self.stateful.getStateObject() + + +class ChangeStateForm(ObjectForm, ChangeStateBase): + + form_action = 'change_state_action' + data = {} + + @Lazy + def macro(self): + return template.macros['change_state'] + + @Lazy + def schema(self): + # TODO: create schema directly, use field information specified + # in transition + commentsField = Field('comments', u'Comments', 'textarea', + description=u'Enter comments.') + fields = [commentsField] + return Schema(name='change_state', request=self.request, + manager=self, *fields) + #schemaFactory = ISchemaFactory(self.adapted) + #return schemaFactory(self.typeInterface, manager=self, + # request=self.request) + + +class ChangeState(EditObject, ChangeStateBase): + + def update(self): + print '***', self.request.form + return True + + #class StateQuery(ConceptView): class StateQuery(BaseView): template = template - form_action = 'execute_search_action' @Lazy diff --git a/organize/stateful/configure.zcml b/organize/stateful/configure.zcml index 7833208..30ad487 100644 --- a/organize/stateful/configure.zcml +++ b/organize/stateful/configure.zcml @@ -77,7 +77,7 @@ set_schema="cybertools.stateful.interfaces.IStateful" /> - + + + + + diff --git a/organize/stateful/view_macros.pt b/organize/stateful/view_macros.pt index d1be431..e6ce00b 100644 --- a/organize/stateful/view_macros.pt +++ b/organize/stateful/view_macros.pt @@ -68,8 +68,6 @@ - -
Category
+ +
+
+ +
+
+
+
+ + + + +
+ + + + + From 18f794bfe7978771ca64af0250bc9021d42993e9 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Thu, 20 Jun 2013 13:32:48 +0200 Subject: [PATCH 29/51] work in progress: form and processing for state transitions --- locales/de/LC_MESSAGES/loops.mo | Bin 24237 -> 24577 bytes locales/de/LC_MESSAGES/loops.po | 22 ++++++++++++++++++++-- organize/stateful/browser.py | 26 +++++++++++++++++--------- organize/stateful/task.py | 1 + organize/stateful/view_macros.pt | 24 ++++++++++++++++++------ 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/locales/de/LC_MESSAGES/loops.mo b/locales/de/LC_MESSAGES/loops.mo index 89e7e8c8dd3ffa2fd069020eeb9f787eaca30e35..454e658170da1b4c2b00c65e24c62f9b9deacdba 100644 GIT binary patch delta 9216 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�$Bc zzg951ueNCqj4LkvB<80Ip zEJf|$OL^?SwrnRA8hAfy=0`CIk7I2-jhbjBYJeN4uO#FScf~Qt`{*R%T{so>u6%;p z>Ppl&;r-l+H^vs^Ej<*pf}yA_oq`&;7;E7ov&8O~A$>WUP#yk?+R|%S7whM{D{O}C z$$KMnb>?Cs9>!$+4P((0+uuFo9MnVxqPAutYU`$<23m;fU^!}HyKp3yqmC+SfO~{l z7)(A0_54_?FGekF1=hwgWIT_voq}Gfa#Y8MFc42*D?E*wK=44fT?5o-8iSf>I;wp( z*1=rVP7X)48-wb17OLGs48;=6WPIm&3i?6$4)u~<#Wol^$UVdEs2PvLwpfIk&{ot0 zUa|YTEq~Yi81(~n3^i~i>g%|M`i%Vsll#7Z3hJ;H*27TCo0+XpE9zi*Hmai>Ov60X ziWZ?dUW@Iq4E49=C}vbxs`&p=o8dHU!n#$joOKGsI85>)2&ZL zwQq$X*b#kOkD9=6R6hl%uW20WbDW5JNf)Dze9fKgzZ!0^8{1JY(_ZY2Cs8{SJ=FaP zO+p<-7OI23sQW`u1K*A6Zxr%DI1{lO?n5o;FVsW>hPgjbc#hjt`=a?gP|We{G&ay(7P(CVbWEs|K7khLc}JtvrCAH%%Z2wX#@Lhs{yiIIO-;UY|FKR;jQ3D=9eN7b@hQW7p)cXG8 zDd;TPqdFRc>UbLJ!C9z@EJ1DMYShX%q95K*@P#^aNsi&;_#do_ebnHV>pJBJZ^<>j z^EW|X&KY7pkw&EOAV==|E0s_ADat*pvusoEg|6mA1~Hg=y}UQC67sRuHkZn8iABWN zn+_PI}ol>M7(!it97No_ zI#L%*=nBISBFjykg_OUsvbdN0H5Kqt;t@Z0e5VnKu9oKOlpiAAA^KAHFzUMB?oY!1 zlK<(eJ`Xi!i zvOTno@>yaX(aq`}!vo~q3H|NR|BBv__=@rdVhvH1&{ayLbMG-sC3X{SbpBnaY(ZpG zj=*sI~$-!CZ*r~Ykxz-m`xed0mtCt^$DIC1Oc`Gsr@4fOvS zyPfDm-W1ysT`33PRAL-)5Al~h{WIo~>-q<=pZJ>SOx+Z`3!{kklyAN6BH2L%a<8?1 ze>RewCmIqB2wjV~xz8;+_u$J!DRn2XE@B8FCi zh$X~l#O=g%+BL$VsB69cVSMKlF^9@as<7)m>`C2J%OkO`mGg1Fb)u?&6WvtcT4DA6 zZt7HGI+0-YC$0VsY(?F$M<`q%zPB46O7r-nK*X u{k=_jp0F|Nj8yoQJ*u diff --git a/locales/de/LC_MESSAGES/loops.po b/locales/de/LC_MESSAGES/loops.po index 1885c16..32535c4 100644 --- a/locales/de/LC_MESSAGES/loops.po +++ b/locales/de/LC_MESSAGES/loops.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: 0.13.0\n" "POT-Creation-Date: 2007-05-22 12:00 CET\n" -"PO-Revision-Date: 2013-06-05 12:00 CET\n" +"PO-Revision-Date: 2013-06-20 12:00 CET\n" "Last-Translator: Helmut Merz \n" "Language-Team: loops developers \n" "MIME-Version: 1.0\n" @@ -1025,14 +1025,26 @@ msgid "Restrict to objects with certain states" msgstr "Auf Objekte mit bestimmtem Status beschränken" msgid "Workflow" -msgstr "Statusdefinition/Workflow" +msgstr "Workflow" msgid "States" msgstr "Statuswerte" +msgid "States Definition" +msgstr "Workflowdefinition" + +msgid "State Transition" +msgstr "Workflow-Statusänderung" + +msgid "Transition" +msgstr "Aktion" + msgid "State information for $definition: $title" msgstr "Status ($definition): $title" +msgid "Available Transitions" +msgstr "Übergänge" + msgid "classification_quality" msgstr "Klassifizierung" @@ -1045,6 +1057,12 @@ msgstr "Aufgabe" msgid "publishable_task" msgstr "Aufgabe/Zugriff" +msgid "label_transition_comments" +msgstr "Bemerkung" + +msgid "desc_transition_comments" +msgstr "Notizen zum Statusübergang." + # state names msgid "accepted" diff --git a/organize/stateful/browser.py b/organize/stateful/browser.py index 98dc3a9..130daf4 100644 --- a/organize/stateful/browser.py +++ b/organize/stateful/browser.py @@ -52,7 +52,7 @@ def registerStatesPortlet(controller, view, statesDefs, cm = controller.macros stfs = [component.getAdapter(view.context, IStateful, name=std) for std in statesDefs] - cm.register(region, 'states', title=_(u'States'), + cm.register(region, 'states', title=_(u'Workflow'), subMacro=template.macros['portlet_states'], priority=priority, info=view, stfs=stfs) @@ -81,8 +81,9 @@ class StateAction(Action): @Lazy def icon(self): - icon = self.stateObject.icon or 'led%s.png' % self.stateObject.color - return 'cybertools.icons/' + icon + return self.stateObject.stateIcon + #icon = self.stateObject.icon or 'led%s.png' % self.stateObject.color + #return 'cybertools.icons/' + icon for std in statefulActions: @@ -96,7 +97,7 @@ class ChangeStateBase(object): @Lazy def stateful(self): - return component.getAdapter(self.view.context, IStateful, + return component.getAdapter(self.view.virtualTargetObject, IStateful, name=self.definition) @Lazy @@ -107,6 +108,10 @@ class ChangeStateBase(object): def action(self): return self.request.form.get('action') or u'' + @Lazy + def transition(self): + return self.stateful.getStatesDefinition().transitions[self.action] + @Lazy def stateObject(self): return self.stateful.getStateObject() @@ -121,24 +126,27 @@ class ChangeStateForm(ObjectForm, ChangeStateBase): def macro(self): return template.macros['change_state'] + @Lazy + def title(self): + return self.virtualTargetObject.title + @Lazy def schema(self): # TODO: create schema directly, use field information specified # in transition - commentsField = Field('comments', u'Comments', 'textarea', - description=u'Enter comments.') + commentsField = Field('comments', _(u'label_transition_comments'), + 'textarea', + description=_(u'desc_transition_comments')) fields = [commentsField] return Schema(name='change_state', request=self.request, manager=self, *fields) - #schemaFactory = ISchemaFactory(self.adapted) - #return schemaFactory(self.typeInterface, manager=self, - # request=self.request) class ChangeState(EditObject, ChangeStateBase): def update(self): print '***', self.request.form + self.stateful.doTransition(self.action) return True diff --git a/organize/stateful/task.py b/organize/stateful/task.py index 0721bc4..5e60ee5 100644 --- a/organize/stateful/task.py +++ b/organize/stateful/task.py @@ -59,6 +59,7 @@ def taskStates(): Transition('finish', 'finish', 'finished'), Transition('cancel', 'cancel', 'cancelled'), Transition('reopen', 're-open', 'draft'), + Transition('archive', 'archive', 'archived'), initialState='draft') diff --git a/organize/stateful/view_macros.pt b/organize/stateful/view_macros.pt index e6ce00b..1d30d3d 100644 --- a/organize/stateful/view_macros.pt +++ b/organize/stateful/view_macros.pt @@ -71,7 +71,7 @@
- Workflow + States Definition
@@ -79,9 +79,10 @@ State: +
-
-
Available Transitions:
+
Available Transitions: