new view list_children.html; action options for queries; send mail feature basically working; presence with link to person
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3575 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
21036dae20
commit
a6dbafcce8
14 changed files with 104 additions and 15 deletions
|
@ -8,6 +8,9 @@ $Id$
|
|||
|
||||
New features
|
||||
|
||||
- new view: ``list_children.html``
|
||||
- evaluate action settings also on queries
|
||||
- "send email" feature, controlled by global option ``organize.allowSendEmail``
|
||||
- presence: portlet showing other users logged-in and working within the
|
||||
same loops site, controlled by global option ``organize.showPresence`,
|
||||
using new LoopsSessionCredentialsPlugin;
|
||||
|
|
|
@ -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
|
||||
|
@ -352,9 +352,8 @@ class ConceptView(BaseView):
|
|||
|
||||
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(',')]
|
||||
optKey = 'action.' + category
|
||||
actNames = (self.options(optKey) or []) + (self.typeOptions(optKey) or [])
|
||||
if actNames:
|
||||
acts = list(actions.get(category, actNames,
|
||||
view=self, page=page, target=target))
|
||||
|
@ -508,3 +507,11 @@ class ConceptConfigureView(ConceptView):
|
|||
yield terms.getTerm(pred)
|
||||
|
||||
|
||||
# query views
|
||||
|
||||
class ListChildren(ConceptView):
|
||||
|
||||
@Lazy
|
||||
def macro(self):
|
||||
return concept_macros.macros['list_children']
|
||||
|
||||
|
|
|
@ -93,7 +93,8 @@
|
|||
ondblclick python: item.openEditWindow('configure.html')"
|
||||
tal:define="children python: list(item.children())"
|
||||
tal:condition="children">
|
||||
<h2 i18n:translate="">Children</h2>
|
||||
<h2 i18n:translate=""
|
||||
tal:condition="show_headline|python:True">Children</h2>
|
||||
<table class="listing">
|
||||
<tr>
|
||||
<th i18n:translate="">Title</th>
|
||||
|
@ -218,6 +219,14 @@
|
|||
</metal:listing>
|
||||
|
||||
|
||||
<metal:listing define-macro="list_children">
|
||||
<div tal:define="show_headline nothing">
|
||||
<metal:fields use-macro="item/template/macros/concepttitle" /><br />
|
||||
<metal:fields use-macro="item/template/macros/conceptchildren" />
|
||||
</div>
|
||||
</metal:listing>
|
||||
|
||||
|
||||
<!-- portlets -->
|
||||
|
||||
<metal:actions define-macro="parents">
|
||||
|
|
|
@ -531,6 +531,16 @@
|
|||
|
||||
</pages>
|
||||
|
||||
<!-- query views -->
|
||||
|
||||
<zope:adapter
|
||||
name="list_children.html"
|
||||
for="loops.interfaces.IConcept
|
||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
provides="zope.interface.Interface"
|
||||
factory="loops.browser.concept.ListChildren"
|
||||
permission="zope.View" />
|
||||
|
||||
<!-- dialogs/forms (end-user views) -->
|
||||
|
||||
<page
|
||||
|
|
|
@ -150,8 +150,13 @@ class NodeView(BaseView):
|
|||
def usersPresent(self):
|
||||
presence = component.getUtility(IPresence)
|
||||
presence.update(self.request.principal.id)
|
||||
data = presence.getPresentUsers()
|
||||
return data
|
||||
data = presence.getPresentUsers(self.context)
|
||||
for u in data:
|
||||
if IConcept.providedBy(u):
|
||||
url = self.getUrlForTarget(u)
|
||||
else:
|
||||
url = None
|
||||
yield dict(title=u.title, url=url)
|
||||
|
||||
@Lazy
|
||||
def view(self):
|
||||
|
|
|
@ -238,7 +238,10 @@
|
|||
|
||||
<metal:actions define-macro="presence">
|
||||
<tal:user repeat="user view/usersPresent">
|
||||
<div tal:content="user" />
|
||||
<div>
|
||||
<a tal:omit-tag="not:user/url"
|
||||
tal:attributes="href user/url"
|
||||
tal:content="user/title" /></div>
|
||||
</tal:user>
|
||||
</metal:actions>
|
||||
|
||||
|
|
|
@ -600,7 +600,8 @@ class IConceptRelation(IDyadicRelation):
|
|||
"""
|
||||
|
||||
predicate = Attribute("A concept of type 'predicate' that defines the "
|
||||
"type of the relation-")
|
||||
"type of the relation.")
|
||||
relevance = Attribute("A float between 0 and 1.")
|
||||
|
||||
|
||||
# interfaces for catalog indexes
|
||||
|
|
Binary file not shown.
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
|
||||
"Project-Id-Version: $Id$\n"
|
||||
"POT-Creation-Date: 2007-05-22 12:00 CET\n"
|
||||
"PO-Revision-Date: 2009-09-17 12:00 CET\n"
|
||||
"PO-Revision-Date: 2009-10-11 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"
|
||||
|
@ -98,6 +98,18 @@ msgstr "Glossareintrag anlegen..."
|
|||
msgid "Create Glossary Item"
|
||||
msgstr "Glossareintrag anlegen"
|
||||
|
||||
msgid "Create Person..."
|
||||
msgstr "Person anlegen..."
|
||||
|
||||
msgid "Create a new person."
|
||||
msgstr "Eine neue Person anlegen"
|
||||
|
||||
msgid "Edit Person..."
|
||||
msgstr "Person bearbeiten..."
|
||||
|
||||
msgid "Modify person."
|
||||
msgstr "Person bearbeiten"
|
||||
|
||||
msgid "Create Resource, Type = "
|
||||
msgstr "Ressource anlegen, Typ = "
|
||||
|
||||
|
|
|
@ -364,6 +364,7 @@ OK, the action is not provided automatically any more by the TaskView
|
|||
but has to be entered as a type option.
|
||||
|
||||
>>> adapted(task).options = ['action.portlet:editTask']
|
||||
>>> view = TaskView(task01, TestRequest())
|
||||
>>> list(view.getActions('portlet'))
|
||||
[<loops.browser.action.DialogAction ...>]
|
||||
|
||||
|
|
|
@ -62,6 +62,13 @@
|
|||
class="loops.organize.browser.party.SendEmailForm"
|
||||
permission="zope.View" />
|
||||
|
||||
<zope:adapter
|
||||
name="send_email"
|
||||
for="loops.browser.node.NodeView
|
||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||
factory="loops.organize.browser.party.SendEmail"
|
||||
permission="zope.View" />
|
||||
|
||||
<!-- authentication -->
|
||||
|
||||
<browser:addform
|
||||
|
|
|
@ -23,16 +23,20 @@ loops.organize.party.
|
|||
$Id$
|
||||
"""
|
||||
|
||||
from email.MIMEText import MIMEText
|
||||
from zope import interface, component
|
||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope.dublincore.interfaces import IZopeDublinCore
|
||||
from zope.sendmail.interfaces import IMailDelivery
|
||||
|
||||
from cybertools.ajax import innerHtml
|
||||
from cybertools.browser.action import actions
|
||||
from cybertools.browser.form import FormController
|
||||
from loops.browser.action import DialogAction
|
||||
from loops.browser.node import NodeView
|
||||
from loops.common import adapted
|
||||
from loops.organize.party import getPersonForUser
|
||||
from loops.util import _
|
||||
|
||||
organize_macros = ViewPageTemplateFile('view_macros.pt')
|
||||
|
@ -123,3 +127,22 @@ class SendEmailForm(NodeView):
|
|||
site = zdc.title or menu.title
|
||||
return _(u"loops Notification from '$site'",
|
||||
mapping=dict(site=site))
|
||||
|
||||
|
||||
class SendEmail(FormController):
|
||||
|
||||
def update(self):
|
||||
form = self.request.form
|
||||
subject = form.get('subject') or u''
|
||||
message = form.get('mailbody') or u''
|
||||
recipients = form.get('recipients') or []
|
||||
recipients += (form.get('addrRecipients') or u'').split('\n')
|
||||
person = getPersonForUser(self.context, self.request)
|
||||
sender = person and adapted(person).email or 'loops@unknown.com'
|
||||
msg = MIMEText(message, 'plain', 'utf-8')
|
||||
msg['Subject'] = subject
|
||||
msg['From'] = sender
|
||||
msg['To'] = ', '.join(r.strip() for r in recipients if r.strip())
|
||||
mailhost = component.getUtility(IMailDelivery, 'Mail')
|
||||
mailhost.send(sender, recipients, msg.as_string())
|
||||
return True
|
||||
|
|
|
@ -55,9 +55,9 @@
|
|||
|
||||
|
||||
<metal:block define-macro="send_email">
|
||||
<form method="post" id="sendEmail_form" class="dialog"
|
||||
<form method="post" id="sendEmail_form" name="sendEmail" class="dialog"
|
||||
dojoType="dijit.form.Form">
|
||||
<input type="hidden" name="form.action" value="create_workitem" />
|
||||
<input type="hidden" name="form.action" value="send_email" />
|
||||
<div class="heading">
|
||||
<span i18n:translate="">Send Link by Email</span> -
|
||||
<span tal:content="view/target/title"></span></div>
|
||||
|
@ -78,11 +78,16 @@
|
|||
<div>
|
||||
<label i18n:translate="">Recipients</label>
|
||||
<div tal:repeat="member view/members">
|
||||
<input type="checkbox" checked name="recipients:list"
|
||||
<input type="checkbox" name="recipients:list"
|
||||
tal:attributes="value member/email" />
|
||||
<span tal:content="member/title">Johnny</span>
|
||||
(<span tal:content="member/email">Johnny</span>)
|
||||
</div>
|
||||
<div style="color: grey">
|
||||
<input type="checkbox"
|
||||
onClick="p = document.forms.sendEmail['recipients:list'];
|
||||
for (i in p) p[i].checked=this.checked;" />
|
||||
<span i18n:translate="">Toggle all</span></div>
|
||||
<div>
|
||||
<label i18n:translate="" for="addrecipients">Additional recipients</label>
|
||||
<div>
|
||||
|
|
|
@ -30,6 +30,7 @@ from zope.cachedescriptors.property import Lazy
|
|||
from cybertools.meta.interfaces import IOptions
|
||||
from cybertools.util.date import getTimeStamp
|
||||
from loops.organize.interfaces import IPresence
|
||||
from loops.organize.party import getPersonForUser
|
||||
from loops.organize import util
|
||||
|
||||
|
||||
|
@ -57,10 +58,12 @@ class Presence(object):
|
|||
if id in self.presentUsers:
|
||||
del self.presentUsers[id]
|
||||
|
||||
def getPresentUsers(self):
|
||||
def getPresentUsers(self, context=None):
|
||||
ret = []
|
||||
for id, timeStamp in self.presentUsers.iteritems():
|
||||
ret.append(util.getPrincipalForUserId(id).title)
|
||||
principal = util.getPrincipalForUserId(id)
|
||||
person = getPersonForUser(context, principal=principal)
|
||||
ret.append(person or principal)
|
||||
return ret
|
||||
|
||||
def removePresentUser(self, principalId):
|
||||
|
|
Loading…
Add table
Reference in a new issue