web/box.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 20 May 2010 10:41:36 +0200
branchstable
changeset 5551 e41cd3bf5080
parent 5426 0d4853a6e5ee
child 5927 654a34e4eb2e
permissions -rw-r--r--
[migration] fix storage_change migraction to avoid exhausting the server's memory
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     1
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
"""abstract box classes for CubicWeb web client
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
__docformat__ = "restructuredtext en"
2159
0ca23d0eace2 move up
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    22
_ = unicode
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    23
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2159
diff changeset
    24
from logilab.mtconverter import xml_escape
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 838
diff changeset
    26
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
    27
from cubicweb.schema import display_name
5223
6abd6e3599f4 #773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    28
from cubicweb.selectors import (no_cnx, 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
    29
                                match_context_prop, partial_has_related_entities)
816
9cd49a910fce kill Template class and 'templates' registry
sylvain.thenault@logilab.fr
parents: 809
diff changeset
    30
from cubicweb.view import View, ReloadableMixIn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
4345
06a34ff6b49a skil internal field value, else we get an error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    32
from cubicweb.web import INTERNAL_FIELD_VALUE
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
from cubicweb.web.htmlwidgets import (BoxLink, BoxWidget, SideBoxWidget,
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
    34
                                      RawBoxItem, BoxSeparator)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
from cubicweb.web.action import UnregisteredAction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
816
9cd49a910fce kill Template class and 'templates' registry
sylvain.thenault@logilab.fr
parents: 809
diff changeset
    38
class BoxTemplate(View):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
    """base template for boxes, usually a (contextual) list of possible
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
    actions. Various classes attributes may be used to control the box
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    42
    rendering.
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    43
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
    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
    45
    for your custom box.
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    46
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
    Classes inheriting from this class usually only have to override call
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
    to fetch desired actions, and then to do something like  ::
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
        box.render(self.w)
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
    __registry__ = 'boxes'
5223
6abd6e3599f4 #773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4490
diff changeset
    53
    __select__ = ~no_cnx() & match_context_prop()
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    54
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
    categories_in_order = ()
2799
b703639614e7 refactor property handling to avoid name conflicts
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2789
diff changeset
    56
    cw_property_defs = {
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
        _('visible'): dict(type='Boolean', default=True,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
                           help=_('display the box or not')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
        _('order'):   dict(type='Int', default=99,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
                           help=_('display order of the box')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
        # XXX 'incontext' boxes are handled by the default primary view
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
        _('context'): dict(type='String', default='left',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
                           vocabulary=(_('left'), _('incontext'), _('right')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
                           help=_('context where this box should be displayed')),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
        }
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
    context = 'left'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
    htmlitemclass = 'boxItem'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
    def sort_actions(self, actions):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
        """return a list of (category, actions_sorted_by_title)"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    71
        result = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    72
        actions_by_cat = {}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    73
        for action in actions:
3220
11b6016e3970 cleanup, futur warning fixes :)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2757
diff changeset
    74
            actions_by_cat.setdefault(action.category, []).append(
11b6016e3970 cleanup, futur warning fixes :)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2757
diff changeset
    75
                (action.title, action) )
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
        for key, values in actions_by_cat.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
            actions_by_cat[key] = [act for title, act in sorted(values)]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
        for cat in self.categories_in_order:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
            if cat in actions_by_cat:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
                result.append( (cat, actions_by_cat[cat]) )
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
        for item in sorted(actions_by_cat.items()):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
            result.append(item)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
        return result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
    def mk_action(self, title, path, escape=True, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    86
        """factory function to create dummy actions compatible with the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
        .format_actions method
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
        if escape:
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2159
diff changeset
    90
            title = xml_escape(title)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
        return self.box_action(self._action(title, path, **kwargs))
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
    92
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    93
    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
    94
        return UnregisteredAction(self._cw, self.cw_rset, title, path, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    96
    # formating callbacks
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
    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
    99
        if action.__regid__:
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   100
            return u'keyword: %s' % action.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
        return u''
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   103
    def box_action(self, action):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
        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
   105
        return BoxLink(action.url(), self._cw._(action.title),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
                       cls, self.boxitem_link_tooltip(action))
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   107
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
class RQLBoxTemplate(BoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
    """abstract box for boxes displaying the content of a rql query not
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
    related to the current result set.
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   112
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   113
    It rely on etype, rtype (both optional, usable to control registration
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
    according to application schema and display according to connected
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
    user's rights) and rql attributes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
    rql  = None
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   119
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
    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
   121
        assert self.rql is not None, self.__regid__
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
        return (self.rql,)
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   123
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
    def call(self, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   125
        try:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   126
            rset = self._cw.execute(*self.to_display_rql())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
        except Unauthorized:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
            # can't access to something in the query, forget this box
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
        if len(rset) == 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
            return
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3230
diff changeset
   132
        box = BoxWidget(self._cw._(self.title), self.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
        for i, (teid, tname) in enumerate(rset):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
            entity = rset.get_entity(i, 0)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
            box.append(self.mk_action(tname, entity.absolute_url()))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
        box.render(w=self.w)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   138
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
class UserRQLBoxTemplate(RQLBoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
    """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
   141
    request's user
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
    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
   145
        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
   146
        return (self.rql, {'x': self._cw.user.eid}, 'x')
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   147
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   149
class EntityBoxTemplate(BoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
    """base class for boxes related to a single entity"""
809
31962f99770b fix box selectors
sylvain.thenault@logilab.fr
parents: 782
diff changeset
   151
    __select__ = BoxTemplate.__select__ & one_line_rset() & primary_view()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
    context = 'incontext'
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   153
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    def call(self, row=0, col=0, **kwargs):
526
sylvain.thenault@logilab.fr
parents: 455
diff changeset
   155
        """classes inheriting from EntityBoxTemplate should define cell_call"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
        self.cell_call(row, col, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   159
class RelatedEntityBoxTemplate(EntityBoxTemplate):
838
f2c56312b03a rename abstract_* selectors into partial_* + add docstrings
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 816
diff changeset
   160
    __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
   161
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   162
    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
   163
        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
   164
        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
   165
        role = get_role(self)
1885
c2011d238e98 replace sideRelated with sideBox
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1696
diff changeset
   166
        self.w(u'<div class="sideBox">')
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   167
        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
   168
                   title=display_name(self._cw, self.rtype, role))
250
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   169
        self.w(u'</div>')
7fd7a0d387d7 new RelatedEntityBoxTemplate base class
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 237
diff changeset
   170
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
class EditRelationBoxTemplate(ReloadableMixIn, EntityBoxTemplate):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
    """base class for boxes which let add or remove entities linked
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
    by a given relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
    subclasses should define at least id, rtype and target
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
    class attributes.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
    """
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   179
1624
baf484a182cd should take arbitrary arguments
sylvain.thenault@logilab.fr
parents: 1493
diff changeset
   180
    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
   181
        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
   182
        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
   183
        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
   184
        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
   185
        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
   186
        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
   187
        if related and unrelated:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
            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
   189
        box.extend(unrelated)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
        box.render(self.w)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
    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
   193
        return self.__regid__
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   194
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
    def box_item(self, entity, etarget, rql, label):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
        """builds HTML link to edit relation between `entity` and `etarget`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
        """
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 838
diff changeset
   198
        role, target = get_role(self), get_target(self)
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 838
diff changeset
   199
        args = {role[0] : entity.eid, target[0] : etarget.eid}
4382
6fb02edd05da 3.6 api update, cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4345
diff changeset
   200
        url = self._cw.user_rql_callback((rql, args))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
        # for each target, provide a link to edit the relation
4205
4458c7cc193b must escape user_rql_callback
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3220
diff changeset
   202
        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
   203
                                               etarget.view('incontext'))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
        return RawBoxItem(label, liclass=u'invisible')
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   205
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   206
    def related_boxitems(self, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
        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
   208
        related = []
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   209
        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
   210
            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
   211
        return related
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   212
2757
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   213
    def unrelated_boxitems(self, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
        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
   215
        unrelated = []
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        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
   217
            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
   218
        return unrelated
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   219
c8e28e1754f0 B [web.box] fix EditRelationBoxTemplate in case neither related nor unrelated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2710
diff changeset
   220
    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
   221
        return entity.related(self.rtype, get_role(self), entities=True)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
    def unrelated_entities(self, entity):
4385
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   224
        """returns the list of unrelated entities, using the entity's
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   225
        appropriate vocabulary function
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
        """
4385
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   227
        skip = set(e.eid for e in entity.related(self.rtype, get_role(self),
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   228
                                                 entities=True))
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   229
        skip.add(None)
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   230
        skip.add(INTERNAL_FIELD_VALUE)
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   231
        filteretype = getattr(self, 'etype', None)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
        entities = []
4385
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   233
        form = self._cw.vreg['forms'].select('edition', self._cw,
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   234
                                             rset=self.cw_rset,
4382
6fb02edd05da 3.6 api update, cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4345
diff changeset
   235
                                             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
   236
        field = form.field_by_name(self.rtype, get_role(self), entity.e_schema)
4385
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   237
        for _, eid in field.vocabulary(form):
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   238
            if eid not in skip:
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   239
                entity = self._cw.entity_from_eid(eid)
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   240
                if filteretype is None or entity.__regid__ == filteretype:
820aa03f71ad use field.vocabulary instead of field.choices, skip already related eids. Also consider vocabulary when no etype specified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   241
                    entities.append(entity)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
        return entities
1493
8270580b65a0 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1422
diff changeset
   243