work in progress: 'send link by email' feature

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3154 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2009-01-17 16:51:51 +00:00
parent 6ff94ad004
commit 12061a6aa3
8 changed files with 184 additions and 40 deletions

View file

@ -101,8 +101,8 @@ class ConceptEditForm(EditForm, I18NView):
desc.height = 2
class ConceptRelationView(BaseView):
""" For displaying children and resources lists, used by ConceptView.
class BaseRelationView(BaseView):
""" For displaying children and resources lists.
"""
def __init__(self, relation, request, contextIsSecond=False):
@ -123,6 +123,9 @@ class ConceptRelationView(BaseView):
@Lazy
def data(self):
return self.getData()
def getData(self):
return self.instance.applyTemplate()
@Lazy
@ -176,19 +179,13 @@ class ConceptRelationView(BaseView):
def order(self):
return self.relation.order
def getActions(self, category='object', page=None, target=None):
t = IType(self.context)
actInfo = t.optionsDict.get('action.' + category, '')
actNames = [n.strip() for n in actInfo.split(',')]
if actNames:
return actions.get(category, actNames, view=self, page=page, target=target)
return []
class ConceptView(BaseView):
template = concept_macros
childViewFactory = ConceptRelationView
def childViewFactory(self, *args, **kw):
return ConceptRelationView(*args, **kw)
@Lazy
def macro(self):
@ -354,12 +351,32 @@ class ConceptView(BaseView):
yield NodeView(node, self.request)
def getActions(self, category='object', page=None, target=None):
acts = []
t = IType(self.context)
actInfo = t.optionsDict.get('action.' + category, '')
actNames = [n.strip() for n in actInfo.split(',')]
if actNames:
return actions.get(category, actNames, view=self, page=page, target=target)
return []
acts = list(actions.get(category, actNames,
view=self, page=page, target=target))
if category in self.actions:
acts.extend(self.actions[category](self, page, target))
return acts
def getObjectActions(self, page=None, target=None):
acts = ['info']
acts.extend('state.' + st.statesDefinition for st in self.states)
if self.globalOptions('organize.allowSendEmail'):
acts.append('send_email')
return actions.get('object', acts, view=self, page=page, target=target)
actions = dict(object=getObjectActions)
class ConceptRelationView(ConceptView, BaseRelationView):
__init__ = BaseRelationView.__init__
getData = BaseRelationView.getData
class ConceptConfigureView(ConceptView):

View file

@ -3,7 +3,7 @@
<metal:info define-macro="object_info"
tal:define="item nocall:view/item">
<table class="object_info">
<table class="object_info" width="400">
<tr>
<td colspan="2"><h2 i18n:translate="">Object Information</h2><br /></td>
</tr>
@ -23,9 +23,10 @@
<td><span i18n:translate="">Type</span>:</td>
<td tal:content="item/longTypeTitle"></td>
</tr>
<tr>
<tr tal:define="size item/context/sizeForDisplay|nothing"
tal:condition="size">
<td><span i18n:translate="">Size</span>:</td>
<td tal:content="item/context/sizeForDisplay"></td>
<td tal:content="size"></td>
</tr>
<tr>
<td><span i18n:translate="">modified</span>:</td>

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
# Copyright (c) 2009 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
@ -38,7 +38,6 @@ from zope.event import notify
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope.lifecycleevent import Attributes
from zope.formlib.form import Form, FormFields
from zope.formlib.namedtemplate import NamedTemplate
from zope.proxy import removeAllProxies
from zope.security import canAccess, canWrite, checkPermission
from zope.security.proxy import removeSecurityProxy
@ -50,7 +49,7 @@ from cybertools.browser.view import GenericView
from cybertools.stateful.interfaces import IStateful
from cybertools.typology.interfaces import IType, ITypeManager
from cybertools.xedit.browser import ExternalEditorView
from loops.browser.action import DialogAction
from loops.browser.action import actions, DialogAction
from loops.common import adapted, AdapterBase
from loops.i18n.browser import i18n_macros
from loops.interfaces import IConcept, IResource, IDocument, IMediaAsset, INode
@ -438,6 +437,12 @@ class NodeView(BaseView):
page=self, target=target))
return actions
def xx_getObjectActions(self, target=None):
acts = []
if self.globalOptions('organize.allowSendEmail'):
acts.append('send_email')
return actions.get('object', acts, view=self, page=self, target=target)
actions = dict(portlet=getPortletActions)
@Lazy
@ -704,7 +709,9 @@ class ConfigureView(NodeView):
class NodeAdding(Adding):
def addingInfo(self):
pass
def xx_addingInfo(self):
info = super(NodeAdding, self).addingInfo()
#info.append({'title': 'Document',
# 'action': 'AddLoopsNodeDocument.html',

View file

@ -44,7 +44,8 @@ from cybertools.typology.interfaces import IType
from cybertools.xedit.browser import ExternalEditorView, fromUnicode
from loops.browser.action import DialogAction, TargetAction
from loops.browser.common import EditForm, BaseView
from loops.browser.concept import ConceptRelationView, ConceptConfigureView
from loops.browser.concept import BaseRelationView, ConceptRelationView
from loops.browser.concept import ConceptConfigureView
from loops.browser.node import NodeView, node_macros
from loops.common import adapted, NameChooser
from loops.interfaces import IBaseResource, IDocument, IMediaAsset, ITextDocument
@ -190,8 +191,9 @@ class ResourceView(BaseView):
def getObjectActions(self, page=None, target=None):
acts = ['info']
#acts.extend('state.' + st for st in statefulActions)
acts.extend('state.' + st.statesDefinition for st in self.states)
if self.globalOptions('organize.allowSendEmail'):
acts.append('send_email')
if self.xeditable:
acts.append('external_edit')
return actions.get('object', acts, view=self, page=page, target=target)
@ -214,10 +216,9 @@ class ResourceView(BaseView):
yield NodeView(node, self.request)
class ResourceRelationView(ResourceView, ConceptRelationView):
class ResourceRelationView(ResourceView, BaseRelationView):
def __init__(self, relation, request, contextIsSecond=False):
ConceptRelationView.__init__(self, relation, request, contextIsSecond)
__init__ = BaseRelationView.__init__
getActions = ResourceView.getActions

View file

@ -132,6 +132,7 @@ concept assigned we should get an error:
>>> johnC.conceptType = person
>>> john = IPerson(johnC)
>>> john.userId = 'users.john'
>>> john.email = 'john@loopz.org'
>>> marthaC = concepts['martha'] = Concept(u'Martha')
>>> marthaC.conceptType = person
@ -377,6 +378,20 @@ Allocation of persons to tasks
... conceptType=predicate, predicateInterface=IAllocated)
Send Email to Members
=====================
>>> menu.target = event01
>>> from loops.organize.browser.party import SendEmailForm
>>> form = SendEmailForm(menu, TestRequest())
>>> form.members
[{'email': 'john@loopz.org', 'title': u'John'}]
>>> form.subject
u"loops Notification from '$site'"
>>> form.mailBody
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.target95\n\n'
Fin de partie
=============

View file

@ -11,8 +11,7 @@
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.organize.browser.member.PersonalInfo"
permission="zope.View"
/>
permission="zope.View" />
<zope:view
type="zope.publisher.interfaces.browser.IBrowserRequest"
@ -20,22 +19,19 @@
zope.schema.interfaces.ITextLine"
provides="zope.app.form.interfaces.IDisplayWidget"
factory="cybertools.browser.widget.SimpleListDisplayWidget"
permission="zope.Public"
/>
permission="zope.Public" />
<browser:page
for="loops.interfaces.INode"
name="register_user.html"
class="loops.organize.browser.member.MemberRegistration"
permission="zope.Public"
/>
permission="zope.Public" />
<browser:page
for="loops.interfaces.INode"
name="change_password.html"
class="loops.organize.browser.member.PasswordChange"
permission="zope.Public"
/>
permission="zope.Public" />
<zope:adapter
name="task.html"
@ -43,8 +39,7 @@
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.organize.browser.task.TaskView"
permission="zope.View"
/>
permission="zope.View" />
<zope:adapter
name="list_events.html"
@ -52,15 +47,19 @@
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.organize.browser.event.Events"
permission="zope.View"
/>
permission="zope.View" />
<zope:adapter
for="cybertools.tracking.interfaces.ITrack
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="cybertools.tracking.browser.TrackView"
permission="zope.View"
/>
permission="zope.View" />
<browser:page
name="object_send_email.html"
for="loops.interfaces.INode"
class="loops.organize.browser.party.SendEmailForm"
permission="zope.View" />
</configure>

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
# Copyright (c) 2009 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
@ -24,12 +24,19 @@ $Id$
"""
from zope import interface, component
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy
from zope.dublincore.interfaces import IZopeDublinCore
from cybertools.ajax import innerHtml
from cybertools.browser.action import actions
from loops.browser.action import DialogAction
from loops.browser.node import NodeView
from loops.common import adapted
from loops.util import _
organize_macros = ViewPageTemplateFile('view_macros.pt')
actions.register('createPerson', 'portlet', DialogAction,
title=_(u'Create Person...'),
@ -66,3 +73,53 @@ actions.register('editAddress', 'portlet', DialogAction,
viewName='edit_concept.html',
dialogName='editAddress',
)
actions.register('send_email', 'object', DialogAction,
description=_(u'Send a link to this object by email.'),
viewName='object_send_email.html',
dialogName='',
icon='cybertools.icons/email.png',
cssClass='icon-action',
prerequisites=['registerDojoTextWidget', 'registerDojoTextarea'],
addParams=dict(version='this'),
)
class SendEmailForm(NodeView):
__call__ = innerHtml
@property
def macro(self):
return organize_macros.macros['send_email']
@Lazy
def dialog_name(self):
return self.request.get('dialog', 'object_send_email')
@Lazy
def title(self):
return self.target.title
@Lazy
def targetUrl(self):
return self.getUrlForTarget(self.virtualTargetObject)
@Lazy
def members(self):
persons = self.conceptManager['person'].getChildren([self.typePredicate])
persons = [adapted(p) for p in persons]
return [dict(title=p.title, email=p.email) for p in persons if p.email]
@Lazy
def mailBody(self):
return '\n\n%s\n%s\n\n' % (self.title, self.targetUrl)
@Lazy
def subject(self):
menu = self.context.getMenu()
zdc = IZopeDublinCore(menu)
zdc.languageInfo = self.languageInfo
site = zdc.title or menu.title
return _(u"loops Notification from '$site'",
mapping=dict(site=site))

View file

@ -43,3 +43,50 @@
</tal:child>
</div>
</metal:block>
<metal:block define-macro="send_email">
<form method="post" id="sendEmail_form" class="dialog"
dojoType="dijit.form.Form">
<input type="hidden" name="form.action" value="create_workitem" />
<div class="heading">
<span i18n:translate="">Send Link by Email</span> -
<span tal:content="view/target/title"></span></div>
<div>
<label i18n:translate="" for="subject">Subject</label>
<div>
<input name="subject" id="subject" style="width: 60em"
dojoType="dijit.form.ValidationTextBox" required
tal:attributes="value view/subject" /></div>
</div>
<div>
<label i18n:translate="" for="mailbody">Mail Body</label>
<div>
<textarea name="mailbody" cols="80" rows="4" id="mailbody"
dojoType="dijit.form.SimpleTextarea" style="width: 60em"
tal:content="view/mailBody"></textarea></div>
</div>
<div>
<label i18n:translate="">Recipients</label>
<div tal:repeat="member view/members">
<input type="checkbox" checked name="recipients:list"
tal:attributes="value member/email" />
<span tal:content="member/title">Johnny</span>
(<span tal:content="member/email">Johnny</span>)
</div>
<div>
<label i18n:translate="" for="addrecipients">Additional recipients</label>
<div>
<textarea name="addrecipients" cols="80" rows="4" id="addrecipients"
dojoType="dijit.form.SimpleTextarea"
style="width: 60em"></textarea></div>
</div>
<div class="buttons">
<input value="Send email" type="submit"
onClick="return closeDialog(true)"
i18n:attributes="value">
<input type="button" value="Cancel"
onClick="return closeDialog(false)"
i18n:attributes="value"></div>
</form>
</metal:block>