From 9f9df6599f36a147567e37c99827b1f36b1d5dec Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Fri, 16 Oct 2015 09:26:49 +0200 Subject: [PATCH] set up basic notification functionality --- organize/personal/README.txt | 39 ++++++++++++++-- organize/personal/favorite.py | 77 +++++++++++++++++++++++++------ organize/personal/notification.py | 57 +++++++++++++++++++++++ 3 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 organize/personal/notification.py diff --git a/organize/personal/README.txt b/organize/personal/README.txt index ed19349..48c453a 100644 --- a/organize/personal/README.txt +++ b/organize/personal/README.txt @@ -2,8 +2,6 @@ loops - Linked Objects for Organization and Processing Services =============================================================== - ($Id$) - Let's do some basic setup >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown @@ -75,7 +73,7 @@ So we are now ready to query the favorites. >>> favs = list(favorites.query(userName=johnCId)) >>> favs - [] + [] >>> list(favAdapted.list(johnC)) ['27'] @@ -117,6 +115,41 @@ Let's now trigger the saving of a favorite. 1 +Notifications +============= + + >>> from loops.organize.personal.notification import Notifications + >>> from loops.common import adapted + + >>> person = adapted(setupData.johnC) + >>> d001 = resources['d001.txt'] + + >>> notifications = Notifications(person) + +We can now add a notification. + + >>> notifications.add(d001, person, 'I send myself a letter.') + + >>> notif = list(notifications.listTracks())[0] + >>> notif + + +When the notification is marked as read the read timestamp will be set. + + >>> notifications.read(notif) + >>> notif + + +It's possible to store more than one notification concerning the same object. + + >>> notifications.add(d001, person, 'I send myself another letter.') + >>> len(list(notifications.listTracks())) + 2 + + Filters - Show only Certain Parts of the Concept Map ==================================================== diff --git a/organize/personal/favorite.py b/organize/personal/favorite.py index 96a8b16..13ba77a 100644 --- a/organize/personal/favorite.py +++ b/organize/personal/favorite.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2010 Helmut Merz helmutm@cy55.de +# Copyright (c) 2015 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 @@ -17,9 +17,7 @@ # """ -Base classes for a notification framework. - -$Id$ +A framework for storing personal favorites and settings. """ from zope.component import adapts @@ -39,39 +37,45 @@ class Favorites(object): def __init__(self, context): self.context = context - def list(self, person, sortKey=None): - for item in self.listTracks(person, sortKey): + def list(self, person, sortKey=None, type='favorite'): + for item in self.listTracks(person, sortKey, type): yield item.taskId - def listTracks(self, person, sortKey=None): + def listTracks(self, person, sortKey=None, type='favorite'): if person is None: return personUid = util.getUidForObject(person) if sortKey is None: sortKey = lambda x: -x.timeStamp for item in sorted(self.context.query(userName=personUid), key=sortKey): + if type is not None: + if item.type != type: + continue yield item - def add(self, obj, person, data=None): + def add(self, obj, person, data=None, nodups=True): if None in (obj, person): return False uid = util.getUidForObject(obj) personUid = util.getUidForObject(person) - if self.context.query(userName=personUid, taskId=uid): - return False if data is None: - data = {} + data = {'type': 'favorite'} + if nodups: + for track in self.context.query(userName=personUid, taskId=uid): + if track.type == data['type']: # already present + return False return self.context.saveUserTrack(uid, 0, personUid, data) - def remove(self, obj, person): + def remove(self, obj, person, type='favorite'): if None in (obj, person): return False uid = util.getUidForObject(obj) personUid = util.getUidForObject(person) changed = False - for t in self.context.query(userName=personUid, taskId=uid): - changed = True - self.context.removeTrack(t) + for track in self.context.query(userName=personUid, taskId=uid): + if track.type == type: + changed = True + self.context.removeTrack(track) return changed @@ -81,3 +85,46 @@ class Favorite(Track): typeName = 'Favorite' + @property + def type(self): + return self.data.get('type') or 'favorite' + + +def updateSortInfo(person, task, data): + if person is not None: + favorites = task.getLoopsRoot().getRecordManager().get('favorites') + if favorites is None: + return data + personUid = util.getUidForObject(person) + taskUid = util.getUidForObject(task) + for fav in favorites.query(userName=personUid, taskId=taskUid): + if fav.data.get('type') == 'sort': + fdata = fav.data['sortInfo'] + if not data: + data = fdata + else: + if data != fdata: + newData = fav.data + newData['sortInfo'] = data + fav.data = newData + break + else: + if data: + Favorites(favorites).add(task, person, + dict(type='sort', sortInfo=data)) + return data + + +def setInstitution(person, inst): + if person is not None: + favorites = inst.getLoopsRoot().getRecordManager().get('favorites') + if favorites is None: + return + personUid = util.getUidForObject(person) + taskUid = util.getUidForObject(inst) + for fav in favorites.query(userName=personUid): + if fav.type == 'institution': + fav.taskId = taskUid + favorites.indexTrack(None, fav, 'taskId') + else: + Favorites(favorites).add(inst, person, dict(type='institution')) diff --git a/organize/personal/notification.py b/organize/personal/notification.py new file mode 100644 index 0000000..59050b7 --- /dev/null +++ b/organize/personal/notification.py @@ -0,0 +1,57 @@ +# +# Copyright (c) 2015 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 +# + +""" +Storing and retrieving notifications. +""" + +from cybertools.util.date import getTimeStamp +from loops.common import baseObject +from loops.organize.personal.favorite import Favorites +from loops import util + + +class Notifications(Favorites): + + def __init__(self, person): + self.person = person + self.context = (baseObject(person). + getLoopsRoot().getRecordManager()['favorites']) + + def listTracks(self): + return super(Notifications, self).listTracks( + self.person, type='notification') + + def add(self, obj, sender, text): + senderUid = util.getUidForObject(baseObject(sender)) + super(Notifications, self).add(obj, self.person, + dict(type='notification', sender=senderUid, text=text), + nodups=False) + + def read(self, track): + data = track.data + data['read_ts'] = getTimeStamp() + track.data = data + + def unread(self, track): + data = track.data + data['read_ts'] = None + track.data = data + + def remove(self, track): + self.context.removeTrack(track)