add a portlet showing the presence of other users; may be activated by the global option 'organize.showPresence'
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3466 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
c54b0e283c
commit
48701178bd
9 changed files with 149 additions and 2 deletions
|
@ -59,6 +59,7 @@ from loops import util
|
|||
from loops.util import _
|
||||
from loops.browser.common import BaseView
|
||||
from loops.browser.concept import ConceptView
|
||||
from loops.organize.interfaces import IPresence
|
||||
from loops.organize.tracking import access
|
||||
from loops.versioning.util import getVersion
|
||||
|
||||
|
@ -135,9 +136,21 @@ class NodeView(BaseView):
|
|||
icon='cybertools.icons/user.png',
|
||||
url=url,
|
||||
priority=10)
|
||||
if self.globalOptions('organize.showPresence'):
|
||||
cm.register('portlet_right', 'presence', title=_(u'Presence'),
|
||||
subMacro=node_macros.macros['presence'],
|
||||
icon='cybertools.icons/group.png',
|
||||
priority=11)
|
||||
# force early portlet registrations by target by setting up target view
|
||||
self.virtualTarget
|
||||
|
||||
@Lazy
|
||||
def usersPresent(self):
|
||||
presence = component.getUtility(IPresence)
|
||||
presence.update(self.request.principal.id)
|
||||
data = presence.getPresentUsers()
|
||||
return data
|
||||
|
||||
@Lazy
|
||||
def view(self):
|
||||
name = self.request.get('loops.viewName', '') or self.context.viewName
|
||||
|
|
|
@ -236,6 +236,13 @@
|
|||
</metal:actions>
|
||||
|
||||
|
||||
<metal:actions define-macro="presence">
|
||||
<tal:user repeat="user view/usersPresent">
|
||||
<div tal:content="user" />
|
||||
</tal:user>
|
||||
</metal:actions>
|
||||
|
||||
|
||||
<!-- inner HTML macros -->
|
||||
|
||||
<div metal:define-macro="inline_edit"
|
||||
|
|
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-07-13 12:00 CET\n"
|
||||
"PO-Revision-Date: 2009-07-20 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"
|
||||
|
@ -158,6 +158,9 @@ msgstr "Aktuelles Objekt zu Lesezeichen hinzufügen"
|
|||
msgid "Remove from favorites"
|
||||
msgstr "Aus Lesezeichen entfernen"
|
||||
|
||||
msgid "Presence"
|
||||
msgstr "Anwesenheit"
|
||||
|
||||
msgid "Actions"
|
||||
msgstr "Aktionen"
|
||||
|
||||
|
|
|
@ -415,6 +415,13 @@ Send Email to Members
|
|||
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.97\n\n'
|
||||
|
||||
|
||||
Show Presence of Other Users
|
||||
============================
|
||||
|
||||
>>> from loops.organize.presence import Presence
|
||||
>>> component.provideUtility(Presence())
|
||||
|
||||
|
||||
Fin de partie
|
||||
=============
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ from zope.app.security.interfaces import IAuthentication
|
|||
from zope import schema
|
||||
from zope.traversing.api import getParent
|
||||
|
||||
from cybertools.browser.loops.auth import LoopsSessionCredentialsPlugin \
|
||||
as BaseSessionCredentialsPlugin
|
||||
from loops.organize.interfaces import IPresence
|
||||
from loops.util import _
|
||||
|
||||
|
||||
|
@ -98,6 +101,14 @@ class PersonBasedAuthenticator(Persistent, Contained):
|
|||
return InternalPrincipal(self, login)
|
||||
|
||||
|
||||
class LoopsSessionCredentialsPlugin(BaseSessionCredentialsPlugin):
|
||||
|
||||
def logout(self, request):
|
||||
presence = component.getUtility(IPresence)
|
||||
presence.removePresentUser(request.principal.id)
|
||||
super(LoopsSessionCredentialsPlugin, self).logout(request)
|
||||
|
||||
|
||||
class InternalPrincipal(object):
|
||||
|
||||
def __init__(self, auth, login):
|
||||
|
|
|
@ -50,6 +50,11 @@
|
|||
|
||||
<!-- authentication -->
|
||||
|
||||
<zope:utility
|
||||
name="loops Session Credentials"
|
||||
provides="zope.app.authentication.interfaces.ICredentialsPlugin"
|
||||
factory="loops.organize.auth.LoopsSessionCredentialsPlugin" />
|
||||
|
||||
<zope:localUtility class="loops.organize.auth.PersonBasedAuthenticator">
|
||||
<require
|
||||
permission="zope.ManageServices"
|
||||
|
@ -72,6 +77,8 @@
|
|||
<zope:adapter factory="loops.organize.setup.SetupManager"
|
||||
name="organize" />
|
||||
|
||||
<zope:utility factory="loops.organize.presence.Presence" />
|
||||
|
||||
<!-- include -->
|
||||
|
||||
<include package=".browser" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2007 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
|
||||
|
@ -177,3 +177,34 @@ class IAllocated(IConceptSchema):
|
|||
)),
|
||||
default='standard',
|
||||
required=True)
|
||||
|
||||
|
||||
# presence
|
||||
|
||||
class IPresence(Interface):
|
||||
""" Utility for getting information about active principals,
|
||||
mapping principal.id to timestamp of last activity.
|
||||
"""
|
||||
|
||||
def update(self, principalId):
|
||||
""" Update Dictionary of active users, by calling addPresentUser();
|
||||
automaticly check for inactive users by calling
|
||||
removeInactiveUsers().
|
||||
"""
|
||||
|
||||
def addPresentUser(self, principalId):
|
||||
"""Add a user to dictionary of active users.
|
||||
"""
|
||||
|
||||
def removeInactiveUsers(self):
|
||||
""" Remove a user from dictionary of active users if user
|
||||
didn't interact for last min_until_logout minutes.
|
||||
"""
|
||||
|
||||
def getPresentUsers(self):
|
||||
""" Return list of titles of active users.
|
||||
"""
|
||||
|
||||
def removePresentUser(self, principalId):
|
||||
""" Remove user from dictionary of active users, e.g. when user logs out.
|
||||
"""
|
||||
|
|
68
organize/presence.py
Normal file
68
organize/presence.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
#
|
||||
# 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
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
"""
|
||||
Utility for collecting information about logged-in/active users.
|
||||
|
||||
Author: Hannes Plattner.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope.interface import implements
|
||||
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 import util
|
||||
|
||||
|
||||
class Presence(object):
|
||||
|
||||
implements(IPresence)
|
||||
|
||||
def __init__(self, min_until_logout=10, presentUsers=None):
|
||||
self.min_until_logout = min_until_logout
|
||||
self.presentUsers = presentUsers or {}
|
||||
|
||||
def update(self, principalId):
|
||||
self.addPresentUser(principalId)
|
||||
self.removeInactiveUsers()
|
||||
|
||||
def addPresentUser(self, principalId):
|
||||
self.presentUsers[principalId] = getTimeStamp()
|
||||
|
||||
def removeInactiveUsers(self):
|
||||
toDelete = []
|
||||
for id, timeStamp in self.presentUsers.iteritems():
|
||||
if (getTimeStamp() - timeStamp) > (self.min_until_logout*60):
|
||||
toDelete.append(id)
|
||||
for id in toDelete:
|
||||
if id in self.presentUsers:
|
||||
del self.presentUsers[id]
|
||||
|
||||
def getPresentUsers(self):
|
||||
ret = []
|
||||
for id, timeStamp in self.presentUsers.iteritems():
|
||||
ret.append(util.getPrincipalForUserId(id).title)
|
||||
return ret
|
||||
|
||||
def removePresentUser(self, principalId):
|
||||
if principalId in self.presentUsers:
|
||||
del self.presentUsers[principalId]
|
Loading…
Add table
Reference in a new issue