web/box.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 18 Jan 2010 19:05:08 +0100
changeset 4251 3c6569be1f86
parent 4161 4273f5094651
child 4252 6c4f109c2b03
permissions -rw-r--r--
fix pb with bytes field processing: currently when an existing file is edited and no new file is specified, it finds no value in req.form and so try to detach the current file, which is wrong. In that case, nothing should be done. So introduce a new UnmodifiedField exception that may be raised in field's process_form_value method (catched in field.process_posted).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""abstract box classes for CubicWeb web client
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1885
diff changeset
     4
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1885
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     7
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
2159
0ca23d0eace2 move up
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
     9
_ = unicode
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    10
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2159
diff changeset
    11
from logilab.mtconverter import xml_escape
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    12
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 838
diff changeset
    13
from cubicweb import Unauthorized, role as get_role, target as get_target
2710
40789c3044f3 [web.box] remove deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2381
diff changeset
    14
from cubicweb.schema import display_name
652
603c782dc092 various SyntaxErrors / missing import fixes + reorganization of the `registered` classmethod
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 640
diff changeset
    15
from cubicweb.selectors import (one_line_rset,  primary_view,
2819
b864288fd316 remove more 3.2 deprecated code, reintroduce checkbox used by formrenderers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2799
diff changeset
    16
                                match_context_prop, partial_has_related_entities)
816
9cd49a910fce kill Template class and 'templates' registry
sylvain.thenault@logilab.fr
parents: 809
diff changeset
    17
from cubicweb.view import View, ReloadableMixIn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
from cubicweb.web.htmlwidgets import (BoxLink, BoxWidget, SideBoxWidget,
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
    20
                                      RawBoxItem, BoxSeparator)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
from cubicweb.web.action import UnregisteredAction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    22
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    23
816
9cd49a910fce kill Template class and 'templates' registry
sylvain.thenault@logilab.fr
parents: 809
diff changeset
    24
class BoxTemplate(View):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
    """base template for boxes, usually a (contextual) list of possible
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    26
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
    actions. Various classes attributes may be used to control the box
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    28
    rendering.
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    29
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
    You may override on of the formatting callbacks is this is not necessary
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
    for your custom box.
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    32
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
    Classes inheriting from this class usually only have to override call
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
    to fetch desired actions, and then to do something like  ::
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
        box.render(self.w)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
    __registry__ = 'boxes'
809
31962f99770b fix box selectors
sylvain.thenault@logilab.fr
parents: 782
diff changeset
    39
    __select__ = match_context_prop()
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    40
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
    categories_in_order = ()
2799
b703639614e7 refactor property handling to avoid name conflicts
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2789
diff changeset
    42
    cw_property_defs = {
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    43
        _('visible'): dict(type='Boolean', default=True,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
                           help=_('display the box or not')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
        _('order'):   dict(type='Int', default=99,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
                           help=_('display order of the box')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
        # XXX 'incontext' boxes are handled by the default primary view
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
        _('context'): dict(type='String', default='left',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
                           vocabulary=(_('left'), _('incontext'), _('right')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
                           help=_('context where this box should be displayed')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
        }
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
    context = 'left'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    53
    htmlitemclass = 'boxItem'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
    def sort_actions(self, actions):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
        """return a list of (category, actions_sorted_by_title)"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
        result = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
        actions_by_cat = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
        for action in actions:
3220
11b6016e3970 cleanup, futur warning fixes :)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2757
diff changeset
    60
            actions_by_cat.setdefault(action.category, []).append(
11b6016e3970 cleanup, futur warning fixes :)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2757
diff changeset
    61
                (action.title, action) )
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
        for key, values in actions_by_cat.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
            actions_by_cat[key] = [act for title, act in sorted(values)]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
        for cat in self.categories_in_order:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
            if cat in actions_by_cat:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
                result.append( (cat, actions_by_cat[cat]) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
        for item in sorted(actions_by_cat.items()):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
            result.append(item)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
        return result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    71
    def mk_action(self, title, path, escape=True, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    72
        """factory function to create dummy actions compatible with the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    73
        .format_actions method
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
        if escape:
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2159
diff changeset
    76
            title = xml_escape(title)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
        return self.box_action(self._action(title, path, **kwargs))
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    78
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
    def _action(self, title, path, **kwargs):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
    80
        return UnregisteredAction(self._cw, self.cw_rset, title, path, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
    # formating callbacks
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
    def boxitem_link_tooltip(self, action):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
    85
        if action.__regid__:
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
    86
            return u'keyword: %s' % action.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
        return u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    88
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    89
    def box_action(self, action):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    90
        cls = getattr(action, 'html_class', lambda: None)() or self.htmlitemclass
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
    91
        return BoxLink(action.url(), self._cw._(action.title),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
                       cls, self.boxitem_link_tooltip(action))
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    93
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
class RQLBoxTemplate(BoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    96
    """abstract box for boxes displaying the content of a rql query not
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
    related to the current result set.
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    98
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
    It rely on etype, rtype (both optional, usable to control registration
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
    according to application schema and display according to connected
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
    user's rights) and rql attributes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
    """
640
8e64f12be69c drop EntityAction usage in cw, upgrade rql_condition and friends
sylvain.thenault@logilab.fr
parents: 526
diff changeset
   103
#XXX    __selectors__ = BoxTemplate.__selectors__ + (etype_rtype_selector,)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   105
    rql  = None
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   106
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
    def to_display_rql(self):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   108
        assert self.rql is not None, self.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
        return (self.rql,)
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   110
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
    def call(self, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
        try:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   113
            rset = self._cw.execute(*self.to_display_rql())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
        except Unauthorized:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
            # can't access to something in the query, forget this box
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
        if len(rset) == 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
            return
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   119
        box = BoxWidget(self._cw._(self.title), self.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
        for i, (teid, tname) in enumerate(rset):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
            entity = rset.get_entity(i, 0)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
            box.append(self.mk_action(tname, entity.absolute_url()))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
        box.render(w=self.w)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   125
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   126
class UserRQLBoxTemplate(RQLBoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
    """same as rql box template but the rql is build using the eid of the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
    request's user
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
    def to_display_rql(self):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   132
        assert self.rql is not None, self.__regid__
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   133
        return (self.rql, {'x': self._cw.user.eid}, 'x')
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   134
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
class EntityBoxTemplate(BoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
    """base class for boxes related to a single entity"""
809
31962f99770b fix box selectors
sylvain.thenault@logilab.fr
parents: 782
diff changeset
   138
    __select__ = BoxTemplate.__select__ & one_line_rset() & primary_view()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
    context = 'incontext'
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   140
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
    def call(self, row=0, col=0, **kwargs):
526
sylvain.thenault@logilab.fr
parents: 455
diff changeset
   142
        """classes inheriting from EntityBoxTemplate should define cell_call"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
        self.cell_call(row, col, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   146
class RelatedEntityBoxTemplate(EntityBoxTemplate):
838
f2c56312b03a rename abstract_* selectors into partial_* + add docstrings
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 816
diff changeset
   147
    __select__ = EntityBoxTemplate.__select__ & partial_has_related_entities()
742
99115e029dca replaced most of __selectors__ assignments with __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 670
diff changeset
   148
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   149
    def cell_call(self, row, col, **kwargs):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   150
        entity = self.cw_rset.get_entity(row, col)
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   151
        limit = self._cw.property_value('navigation.related-limit') + 1
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   152
        role = get_role(self)
1885
c2011d238e98 replace sideRelated with sideBox
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1696
diff changeset
   153
        self.w(u'<div class="sideBox">')
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   154
        self.wview('sidebox', entity.related(self.rtype, role, limit=limit),
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   155
                   title=display_name(self._cw, self.rtype, role))
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   156
        self.w(u'</div>')
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   157
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
class EditRelationBoxTemplate(ReloadableMixIn, EntityBoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
    """base class for boxes which let add or remove entities linked
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
    by a given relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
    subclasses should define at least id, rtype and target
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
    class attributes.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
    """
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   166
1624
baf484a182cd should take arbitrary arguments
sylvain.thenault@logilab.fr
parents: 1493
diff changeset
   167
    def cell_call(self, row, col, view=None, **kwargs):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   168
        self._cw.add_js('cubicweb.ajax.js')
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   169
        entity = self.cw_rset.get_entity(row, col)
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   170
        box = SideBoxWidget(display_name(self._cw, self.rtype), self.__regid__)
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   171
        related = self.related_boxitems(entity)
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   172
        unrelated = self.unrelated_boxitems(entity)
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   173
        box.extend(related)
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   174
        if related and unrelated:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
            box.append(BoxSeparator())
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   176
        box.extend(unrelated)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
        box.render(self.w)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
    def div_id(self):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   180
        return self.__regid__
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   181
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
    def box_item(self, entity, etarget, rql, label):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
        """builds HTML link to edit relation between `entity` and `etarget`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
        """
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 838
diff changeset
   185
        role, target = get_role(self), get_target(self)
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 838
diff changeset
   186
        args = {role[0] : entity.eid, target[0] : etarget.eid}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
        url = self.user_rql_callback((rql, args))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
        # for each target, provide a link to edit the relation
4094
8b0c6c272ad9 fix non-xml_escaped url in box
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 3451
diff changeset
   189
        label = u'[<a href="%s">%s</a>] %s' % (xml_escape(url), label,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
                                               etarget.view('incontext'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
        return RawBoxItem(label, liclass=u'invisible')
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   192
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   193
    def related_boxitems(self, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
        rql = 'DELETE S %s O WHERE S eid %%(s)s, O eid %%(o)s' % self.rtype
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   195
        related = []
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   196
        for etarget in self.related_entities(entity):
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   197
            related.append(self.box_item(entity, etarget, rql, u'-'))
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   198
        return related
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   199
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   200
    def unrelated_boxitems(self, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
        rql = 'SET S %s O WHERE S eid %%(s)s, O eid %%(o)s' % self.rtype
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   202
        unrelated = []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
        for etarget in self.unrelated_entities(entity):
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   204
            unrelated.append(self.box_item(entity, etarget, rql, u'+'))
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   205
        return unrelated
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   206
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   207
    def related_entities(self, entity):
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   208
        return entity.related(self.rtype, get_role(self), entities=True)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
    def unrelated_entities(self, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
        """returns the list of unrelated entities
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        if etype is not defined on the Box's class, the default
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
        behaviour is to use the entity's appropraite vocabulary function
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        # use entity.unrelated if we've been asked for a particular etype
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
        if hasattr(self, 'etype'):
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 838
diff changeset
   218
            return entity.unrelated(self.rtype, self.etype, get_role(self)).entities()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
        # in other cases, use vocabulary functions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
        entities = []
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   221
        form = self.vreg['forms'].select('edition', self._cw, rset=self.cw_rset,
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   222
                                         row=self.cw_row or 0)
1695
9a9822f3cb6c update implementation to get vocab from form instead of entity
sylvain.thenault@logilab.fr
parents: 1624
diff changeset
   223
        field = form.field_by_name(self.rtype, get_role(self), entity.e_schema)
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4094
diff changeset
   224
        for _, eid in field.choices(form):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
            if eid is not None:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   226
                rset = self._cw.eid_rset(eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
                entities.append(rset.get_entity(0, 0))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
        return entities
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   229