merge branch master
This commit is contained in:
commit
3c43a14af9
17 changed files with 154 additions and 17 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue