merge branch master

This commit is contained in:
Helmut Merz 2013-04-27 15:15:35 +02:00
commit 3c43a14af9
17 changed files with 154 additions and 17 deletions

View file

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

View file

@ -553,6 +553,14 @@
factory="loops.browser.concept.ListTypeInstances"
permission="zope.View" />
<zope:adapter
name="tabbed_page.html"
for="loops.interfaces.IConcept
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.browser.concept.TabbedPage"
permission="zope.View" />
<!-- dialogs/forms (end-user views) -->
<page

View file

@ -117,6 +117,7 @@
<tal:img condition="cell/img">
<a dojoType="dojox.image.Lightbox" group="mediasset"
i18n:attributes="title"
tal:omit-tag="python:part.imageSize in ('large',)"
tal:attributes="href cell/img/fullImageUrl;
title python: cell.img['description'] or cell.img['title']">
<img tal:condition="showImageLink|python:False"

View file

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

View file

@ -195,9 +195,12 @@ class NodeView(BaseView):
cm.register('portlet_left', 'calendar', title=_(u'Calendar'),
subMacro=calendar_macros.macros['main'],
priority=90)
if self.setupTarget:
# force early portlet registrations by target
self.virtualTarget
# force early portlet registrations by target by setting up target view
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):

View file

@ -42,14 +42,19 @@ template = ViewPageTemplateFile('view_macros.pt')
class SurveyView(ConceptView):
tabview = 'index.html'
data = None
errors = None
@Lazy
def macro(self):
self.registerDojo()
return template.macros['survey']
@Lazy
def tabview(self):
if self.editable:
return 'index.html'
def results(self):
result = []
response = None

View file

@ -39,8 +39,7 @@ class Responses(BaseRecordManager):
self.context = context
def save(self, data):
if not self.personId:
return
if self.personId:
self.storage.saveUserTrack(self.uid, 0, self.personId, data,
update=True, overwrite=True)

View file

@ -85,6 +85,9 @@
</table>
<input type="submit" name="submit" value="Evaluate Questionnaire"
i18n:attributes="value" />
<input type="button" name="reset_responses" value="Reset Responses Entered"
i18n:attributes="value"
onclick="setRadioButtons('none'); return false" />
</form>
</div>
</metal:block>

View file

@ -158,4 +158,5 @@ class TargetLayoutInstance(NodeLayoutInstance):
target = self.viewAnnotations.get('target')
if target is None:
target = adapted(self.context.target)
#self.viewAnnotations['target'] = target # TODO: has to be tested!
return target

Binary file not shown.

View file

@ -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-04-01 12:00 CET\n"
"PO-Revision-Date: 2013-04-06 12:00 CET\n"
"Last-Translator: Helmut Merz <helmutm@cy55.de>\n"
"Language-Team: loops developers <helmutm@cy55.de>\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"

View file

@ -27,6 +27,18 @@
class="loops.organize.browser.member.MemberRegistration"
permission="zope.View" />
<browser:page
for="loops.interfaces.INode"
name="selfservice_registration.html"
class="loops.organize.browser.member.SecureMemberRegistration"
permission="zope.View" />
<browser:page
for="loops.interfaces.INode"
name="selfservice_confirmation.html"
class="loops.organize.browser.member.ConfirmMemberRegistration"
permission="zope.View" />
<browser:page
for="loops.interfaces.INode"
name="change_password.html"

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2008 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
@ -19,8 +19,6 @@
"""
Definition of view classes and other browser related stuff for
members (persons).
$Id$
"""
from zope import interface, component
@ -78,7 +76,7 @@ class PersonalInfo(ConceptView):
class MemberRegistration(NodeView, CreateForm):
interface = IMemberRegistration
interface = IMemberRegistration # TODO: add company, create institution
message = _(u'The user account has been created.')
formErrors = dict(
@ -99,7 +97,7 @@ class MemberRegistration(NodeView, CreateForm):
def checkPermissions(self):
personType = adapted(self.conceptManager['person'])
perms = IOptions(personType)('registration.permission')
perms = IOptions(personType)(self.permissions_key)
if perms:
return checkPermission(perms[0], self.context)
return checkPermission('loops.ManageSite', self.context)
@ -114,7 +112,7 @@ class MemberRegistration(NodeView, CreateForm):
schema.fields.remove('birthDate')
schema.fields.reorder(-2, 'loginName')
return schema
# TODO: add company, create institution
@Lazy
def object(self):
return Person(Concept())
@ -157,6 +155,31 @@ class MemberRegistration(NodeView, CreateForm):
return False
class SecureMemberRegistration(MemberRegistration):
permissions_key = u'secure_registration.permissions'
roles_key = u'secure_registration.roles'
@Lazy
def schema(self):
schema = super(MemberRegistration, self).schema
schema.fields.remove('birthDate')
schema.fields.remove('password')
schema.fields.remove('passwordConfirm')
schema.fields.remove('phoneNumbers')
schema.fields.reorder(-2, 'loginName')
return schema
class ConfirmMemberRegistration(NodeView):
# TODO: control form via interface?
@Lazy
def macro(self):
return organize_macros.macros['confirm']
class PasswordChange(NodeView, Form):
interface = IPasswordChange

View file

@ -1,5 +1,9 @@
<html i18n:domain="loops">
<metal:registration define-macro="confirm">
</metal:registration>
<metal:task define-macro="task">
<metal:data use-macro="view/concept_macros/conceptdata">
</metal:data>

View file

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

View file

@ -68,4 +68,32 @@
</metal:query>
<!-- portlets -->
<metal:actions define-macro="portlet_states">
<div tal:repeat="stf macro/stfs">
<div tal:condition="python:len(macro.stfs) > 1">
<span i18n:translate="">Workflow</span>
<span i18n:translate=""
tal:content="stf/statesDefinition" />
</div>
<div>
<b i18n:translate="">State</b>:
<span i18n:translate=""
tal:content="stf/state" />
</div>
<div>
<div><b i18n:translate="">Available Transitions</b>:</div>
<ul>
<li tal:repeat="action stf/getAvailableTransitionsForUser">
<a i18n:translate=""
tal:attributes="href string:change_state.html"
tal:content="action/title" />
</li>
</ul>
</div>
</div>
</metal:actions>
</html>

View file

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