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:
parent
6ff94ad004
commit
12061a6aa3
8 changed files with 184 additions and 40 deletions
|
@ -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):
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
=============
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue