From 64db0029e683913ef8a90df2ec4c1ae6eeecc249 Mon Sep 17 00:00:00 2001 From: helmutm Date: Sun, 10 Oct 2010 20:13:19 +0000 Subject: [PATCH] work in progress: personal filters git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@4034 fd906abe-77d9-0310-91a1-e0d9ade77398 --- browser/resource_macros.pt | 4 +- browser/skin/lobo/lobo.css | 3 +- organize/browser/view_macros.pt | 3 + organize/personal/browser/configurator.py | 46 +++++++++-- organize/personal/browser/configure.zcml | 9 ++ organize/personal/browser/filter.py | 87 ++++++++++++++++++++ organize/personal/browser/personal_macros.pt | 26 ++++++ organize/personal/configure.zcml | 13 +++ organize/personal/filter.py | 79 ++++++++++++++++++ organize/personal/interfaces.py | 36 ++++++++ organize/personal/setup.py | 3 + 11 files changed, 298 insertions(+), 11 deletions(-) create mode 100644 organize/personal/browser/filter.py create mode 100644 organize/personal/filter.py diff --git a/browser/resource_macros.pt b/browser/resource_macros.pt index 523e492..6b47802 100644 --- a/browser/resource_macros.pt +++ b/browser/resource_macros.pt @@ -12,9 +12,9 @@

Title

-

- Description

+ Description

  • Change Password
  • +
  • Edit Filters
  • diff --git a/organize/personal/browser/configurator.py b/organize/personal/browser/configurator.py index d791f3a..4951432 100644 --- a/organize/personal/browser/configurator.py +++ b/organize/personal/browser/configurator.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2008 Helmut Merz helmutm@cy55.de +# Copyright (c) 2010 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 @@ -29,6 +29,7 @@ from zope.cachedescriptors.property import Lazy from zope.traversing.browser.absoluteurl import absoluteURL from cybertools.browser.configurator import ViewConfigurator, MacroViewProperty +from cybertools.meta.interfaces import IOptions from loops.organize.party import getPersonForUser from loops.util import _ @@ -44,17 +45,32 @@ class PortletConfigurator(ViewConfigurator): self.context = context self.request = request + @property + def viewProperties(self): + return self.favorites + self.filters + + @Lazy + def records(self): + return self.context.getLoopsRoot().getRecordManager() + + @Lazy + def person(self): + return getPersonForUser(self.context, self.request) + def hasFavorites(self): - records = self.context.getLoopsRoot().getRecordManager() - if records is not None: - return 'favorites' in records + if self.records is not None: + return 'favorites' in self.records + return False + + def hasFilters(self): + if (IOptions(self.context.getLoopsRoot()).organize.useFilters and + self.records is not None): + return 'filters' in self.records return False @property - def viewProperties(self): - if (not self.hasFavorites() - or getPersonForUser(self.context, self.request) is None): - #if IUnauthenticatedPrincipal.providedBy(self.request.principal): + def favorites(self): + if (not self.hasFavorites() or self.person is None): return [] favorites = MacroViewProperty(self.context, self.request) favorites.setParams(dict( @@ -67,3 +83,17 @@ class PortletConfigurator(ViewConfigurator): )) return [favorites] + @property + def filters(self): + if (not self.hasFilters() or self.person is None): + return [] + filters = MacroViewProperty(self.context, self.request) + filters.setParams(dict( + slot='portlet_right', + identifier='loops.organize.filters', + title=_(u'Filters'), + subMacro=personal_macros.macros['filters_portlet'], + priority=195, + url=absoluteURL(self.context, self.request) + '/@@filters.html', + )) + return [filters] diff --git a/organize/personal/browser/configure.zcml b/organize/personal/browser/configure.zcml index 3f38e27..e91aa60 100644 --- a/organize/personal/browser/configure.zcml +++ b/organize/personal/browser/configure.zcml @@ -20,4 +20,13 @@ + + + + + + diff --git a/organize/personal/browser/filter.py b/organize/personal/browser/filter.py new file mode 100644 index 0000000..8bcabf3 --- /dev/null +++ b/organize/personal/browser/filter.py @@ -0,0 +1,87 @@ +# +# Copyright (c) 2010 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 +# + +""" +A view (to be used by listings, portlets, ...) for filters. + +$Id$ +""" + +from zope import component +from zope.app.pagetemplate import ViewPageTemplateFile +from zope.cachedescriptors.property import Lazy + +from cybertools.browser.configurator import ViewConfigurator, MacroViewProperty +from loops.browser.node import NodeView +from loops.organize.party import getPersonForUser +from loops.organize.personal.interfaces import IFilters +from loops import util + + +personal_macros = ViewPageTemplateFile('personal_macros.pt') + + +class FilterView(NodeView): + + @Lazy + def item(self): + return self + + @Lazy + def person(self): + return getPersonForUser(self.context, self.request) + + @Lazy + def filters(self): + records = self.loopsRoot.getRecordManager() + if records is not None: + storage = records.get('filters') + if storage is not None: + return IFilters(storage) + return None + + def listFilters(self): + if self.filters is None: + return + for uid in self.filters.list(self.person): + obj = util.getObjectForUid(uid) + if obj is not None: + yield dict(url=self.getUrlForTarget(obj), + uid=uid, + title=obj.title, + description=obj.description, + object=obj) + + def add(self): + if self.filters is None: + return + uid = self.request.get('id') + if not uid: + return + obj = util.getObjectForUid(uid) + self.filters.add(obj, self.person) + self.request.response.redirect(self.virtualTargetUrl) + + def deactivate(self): + if self.filters is None: + return + id = self.request.get('id') + if not id: + return + self.filters.deactivate(id) + self.request.response.redirect(self.virtualTargetUrl) diff --git a/organize/personal/browser/personal_macros.pt b/organize/personal/browser/personal_macros.pt index ec5186e..4ed1250 100644 --- a/organize/personal/browser/personal_macros.pt +++ b/organize/personal/browser/personal_macros.pt @@ -22,3 +22,29 @@ i18n:attributes="title">Add to Favorites
    + + + +
    +  X  + Some object +
    + +
    diff --git a/organize/personal/configure.zcml b/organize/personal/configure.zcml index 935d454..9da25a0 100644 --- a/organize/personal/configure.zcml +++ b/organize/personal/configure.zcml @@ -17,6 +17,19 @@ interface="loops.organize.personal.interfaces.IFavorites" /> + + + + + + + + + + diff --git a/organize/personal/filter.py b/organize/personal/filter.py new file mode 100644 index 0000000..a382c1b --- /dev/null +++ b/organize/personal/filter.py @@ -0,0 +1,79 @@ +# +# Copyright (c) 2010 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 +# + +""" +Base classes for filters. + +$Id$ +""" + +from zope.component import adapts +from zope.interface import implements + +from cybertools.tracking.btree import Track +from cybertools.tracking.interfaces import ITrackingStorage +from loops.organize.personal.interfaces import IFilters, IFilter +from loops import util + + +class Filters(object): + + implements(IFilters) + adapts(ITrackingStorage) + + def __init__(self, context): + self.context = context + + def list(self, person, activeOnly=True, sortKey=None): + for item in self.listTracks(person, sortKey): + yield item.taskId + + def listTracks(self, person, sortKey=None): + 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): + yield item + + def add(self, obj, person, data=None): + 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 = {} + return self.context.saveUserTrack(uid, 0, personUid, data) + + def remove(self, id): + changed = False + for t in self.context.query(userName=personUid, taskId=uid): + changed = True + self.context.removeTrack(t) + return changed + + +class Filter(Track): + + implements(IFilter) + + typeName = 'Filter' + diff --git a/organize/personal/interfaces.py b/organize/personal/interfaces.py index 2c03983..19b30a9 100644 --- a/organize/personal/interfaces.py +++ b/organize/personal/interfaces.py @@ -51,3 +51,39 @@ class IFavorite(ITrack): the user/person for which the favorite is to be stored. The tracking storage's run management is not used. """ + + +class IFilters(Interface): + """ A collection of filters. + """ + + def add(title, filter, person): + """ Add a filter specification (a mapping) to the person's + filters collection using the title given. + """ + + def activate(id): + """ Activate the filter specified by its ID. + """ + + def deactivate(id): + """ Deactivate the filter specified by its ID. + """ + + def remove(id): + """ Remove the filter specified by its ID from the person's + favorites collection. + """ + + def list(person, activeOnly=True, sortKey=None): + """ Return a list of filters for the person given. + """ + + +class IFilter(ITrack): + """ A filter is a stored query that will be used for restricting the result + set of child and resource listings as well as explicit searches. + It usually references a parent concept via the task id attribute. + The user/person for which the filter is to be stored. + The tracking storage's run management is not used. + """ diff --git a/organize/personal/setup.py b/organize/personal/setup.py index 75be581..e1636e6 100644 --- a/organize/personal/setup.py +++ b/organize/personal/setup.py @@ -27,6 +27,7 @@ from zope.interface import implements, Interface from cybertools.tracking.btree import TrackingStorage from loops.organize.personal.favorite import Favorite +from loops.organize.personal.filter import Filter from loops.setup import SetupManager as BaseSetupManager @@ -36,3 +37,5 @@ class SetupManager(BaseSetupManager): records = self.context.getRecordManager() favorites = self.addObject(records, TrackingStorage, 'favorites', trackFactory=Favorite) + filters = self.addObject(records, TrackingStorage, 'filters', + trackFactory=Filter)