work in progress: personal filters

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@4034 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2010-10-10 20:13:19 +00:00
parent 0bbea0f45b
commit 64db0029e6
11 changed files with 298 additions and 11 deletions

View file

@ -12,9 +12,9 @@
<h1><a tal:omit-tag="python: level > 1"
tal:attributes="href request/URL"
tal:content="item/title">Title</a></h1>
<p tal:define="description description|item/description"
<p tal:define="description description|item/renderedDescription"
tal:condition="description">
<i tal:content="description">Description</i></p>
<i tal:content="structure description">Description</i></p>
<metal:fields define-slot="fields" />
<div class="content-1" id="1.body"
tal:attributes="id id;"

View file

@ -74,7 +74,8 @@ textarea {
table.listing {
margin: 1px;
margin-top: 6px;
/*margin-top: 0.5em; */
margin-bottom: 1em;
}
table.listing th {

View file

@ -19,6 +19,9 @@
<ul>
<li><a href="change_password.html"
i18n:translate="">Change Password</a></li>
<li><a href="change_password.html"
tal:condition="python:item.globalOptions('organize.useFilters')"
i18n:translate="">Edit Filters</a></li>
</ul>
</metal:block>
</metal:block>

View file

@ -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]

View file

@ -20,4 +20,13 @@
<page name="removeFavorite.html" attribute="remove" />
</browser:pages>
<browser:pages
class="loops.organize.personal.browser.filter.FilterView"
for="loops.interfaces.INode"
permission="zope.View">
<page name="filters_view" />
<page name="addFilter.html" attribute="add" />
<page name="deactivateFilter.html" attribute="deactivate" />
</browser:pages>
</configure>

View file

@ -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)

View file

@ -22,3 +22,29 @@
i18n:attributes="title">Add to Favorites</a>
</div>
</metal:actions>
<metal:actions define-macro="filters_portlet"
tal:define="view nocall:context/@@filters_view;
targetUid view/targetUid">
<div tal:repeat="item view/listFilters">
<span style="float:right" class="delete-item">&nbsp;<a href="removeFilter.html"
tal:attributes="href
string:${view/url}/deactivateFilter.html?id=${item/uid};
title string:Deactivate filter"
i18n:attributes="title">X</a>&nbsp;</span>
<a href=""
tal:attributes="href item/url;
title item/description"
tal:content="item/title">Some object</a>
</div>
<div id="addFilter" class="action"
tal:condition="targetUid">
<a href="addFilter.html"
i18n:translate=""
tal:attributes="href
string:${view/virtualTargetUrl}/addFilter.html?id=$targetUid;
title string:Use current object as filter"
i18n:attributes="title">Add Filter</a>
</div>
</metal:actions>

View file

@ -17,6 +17,19 @@
interface="loops.organize.personal.interfaces.IFavorites" />
</class>
<class class="loops.organize.personal.filter.Filter">
<require permission="zope.View"
interface="loops.organize.personal.interfaces.IFilter" />
<require permission="zope.ManageContent"
set_schema="loops.organize.personal.interfaces.IFilter" />
</class>
<adapter factory="loops.organize.personal.filter.Filters" trusted="True" />
<class class="loops.organize.personal.filter.Filters">
<require permission="zope.View"
interface="loops.organize.personal.interfaces.IFilters" />
</class>
<adapter factory="loops.organize.personal.setup.SetupManager"
name="organize.personal" />

View file

@ -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'

View file

@ -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.
"""

View file

@ -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)