web/action.py
author Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
Tue, 17 Feb 2009 13:48:58 +0100
branchtls-sprint
changeset 657 fd019f41aa2f
parent 653 189877d9547d
child 661 4f61eb8a96b7
permissions -rw-r--r--
work in progress - fix deprecation of EntityAction - fix various selectors bugs

"""abstract action classes for CubicWeb web client

:organization: Logilab
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"

from logilab.common.deprecation import class_moved

from cubicweb import role, target
from cubicweb.selectors import (relation_possible, match_search_state,
                                one_line_rset, may_add_relation, yes,
                                accepts_compat, condition_compat, deprecate)
from cubicweb.common.appobject import AppRsetObject
from cubicweb.common.registerers import action_registerer

_ = unicode


class Action(AppRsetObject):
    """abstract action. Handle the .search_states attribute to match
    request search state. 
    """
    __registry__ = 'actions'
    __registerer__ = action_registerer
    __selectors__ = (yes,) 
    
    property_defs = {
        'visible':  dict(type='Boolean', default=True,
                         help=_('display the action or not')),
        'order':    dict(type='Int', default=99,
                         help=_('display order of the action')),
        'category': dict(type='String', default='moreactions',
                         vocabulary=('mainactions', 'moreactions', 'addrelated',
                                     'useractions', 'siteactions', 'hidden'),
                         help=_('context where this component should be displayed')),
    }
    site_wide = True # don't want user to configuration actions eproperties
    category = 'moreactions'
    
    def url(self):
        """return the url associated with this action"""
        raise NotImplementedError
    
    def html_class(self):
        if self.req.selected(self.url()):
            return 'selected'
        if self.category:
            return 'box' + self.category.capitalize()


class UnregisteredAction(Action):
    """non registered action used to build boxes. Unless you set them
    explicitly, .vreg and .schema attributes at least are None.
    """
    category = None
    id = None
    
    def __init__(self, req, rset, title, path, **kwargs):
        Action.__init__(self, req, rset)
        self.title = req._(title)
        self._path = path
        self.__dict__.update(kwargs)
        
    def url(self):
        return self._path


class LinkToEntityAction(Action):
    """base class for actions consisting to create a new object
    with an initial relation set to an entity.
    Additionaly to EntityAction behaviour, this class is parametrized
    using .etype, .rtype and .target attributes to check if the
    action apply and if the logged user has access to it
    """
    def my_selector(cls, req, rset, row=None, col=0, **kwargs):
        selector = (match_search_state('normal') & one_line_rset
                    & relation_possible(cls.rtype, role(cls), cls.etype,
                                        action='add')
                    & may_add_relation(cls.rtype, role(cls)))
        return selector(cls, req, rset, row, col, **kwargs)

    __selectors__ = (my_selector,)
    registered = accepts_compat(Action.registered.im_func)
    
    category = 'addrelated'
                
    def url(self):
        current_entity = self.rset.get_entity(self.row or 0, self.col or 0)
        linkto = '%s:%s:%s' % (self.rtype, current_entity.eid, target(self))
        return self.build_url(vid='creation', etype=self.etype,
                              __linkto=linkto,
                              __redirectpath=current_entity.rest_path(), # should not be url quoted!
                              __redirectvid=self.req.form.get('__redirectvid', ''))

class EntityAction(Action):
    """DEPRECATED / BACKWARD COMPAT
    """
    registered = deprecate(accepts_compat(condition_compat(Action.registered)),
                           msg='EntityAction is deprecated, use Action with '
                           'appropriate selectors')