web/facet.py
author Aurelien Campeas <aurelien.campeas@logilab.fr>
Wed, 08 Jan 2014 14:00:31 +0100
changeset 9377 4e0d8f06efbc
parent 9373 d5d9acadb975
child 9492 c7fc56eecd1a
permissions -rw-r--r--
[js/widgets] fix the InOut widget with modern jQuery versions Several things are done there: * reduction in size and complexity of the code * the unused defaultsettings are removed * the initial `unlinked` list is now correctly populated from python-side * the unit test is adjusted because it tested an irrelevant implementation detail which is no longer true (but the widget of course still handles correctly the linkto information) Tested with ie7, ie9, chromium, firefox. Tested with jQuery 1.6 (cw 3.17.x) and 1.10. Closes #3154531.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8165
diff changeset
     1
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
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: 5225
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    18
"""
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    19
The :mod:`cubicweb.web.facet` module contains a set of abstract classes to use
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    20
as bases to build your own facets
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    21
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    22
All facet classes inherits from the :class:`AbstractFacet` class, though you'll
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    23
usually find some more handy class that do what you want.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    24
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    25
Let's see available classes.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    26
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    27
Classes you'll want to use
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    28
--------------------------
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    29
.. autoclass:: cubicweb.web.facet.RelationFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    30
.. autoclass:: cubicweb.web.facet.RelationAttributeFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    31
.. autoclass:: cubicweb.web.facet.HasRelationFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    32
.. autoclass:: cubicweb.web.facet.AttributeFacet
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
    33
.. autoclass:: cubicweb.web.facet.RQLPathFacet
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    34
.. autoclass:: cubicweb.web.facet.RangeFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    35
.. autoclass:: cubicweb.web.facet.DateRangeFacet
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
    36
.. autoclass:: cubicweb.web.facet.BitFieldFacet
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    37
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    38
Classes for facets implementor
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    39
------------------------------
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    40
Unless you didn't find the class that does the job you want above, you may want
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    41
to skip those classes...
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    42
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    43
.. autoclass:: cubicweb.web.facet.AbstractFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    44
.. autoclass:: cubicweb.web.facet.VocabularyFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    45
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    46
.. comment: XXX widgets
5768
1e73a466aa69 [fti] support for fti ranking: has_text query results sorted by relevance, and provides a way to control weight per entity / entity's attribute
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5618
diff changeset
    47
"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
__docformat__ = "restructuredtext en"
6582
8eb7883b4223 [pylint] fix a bug of pylint detected errors and i18n pb (calling builtins._ instead of req._)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6380
diff changeset
    50
_ = unicode
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
8719
539ed3fb27cb [towards py3k] import reduce() from functools (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8696
diff changeset
    52
from functools import reduce
7678
ab3d1a77be55 [facets] fix missing 'warnings' import and missing self reference on 'filtered_variable'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7632
diff changeset
    53
from warnings import warn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
from copy import deepcopy
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
    55
from datetime import datetime, timedelta
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
    57
from logilab.mtconverter import xml_escape
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
from logilab.common.graph import has_path
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
    59
from logilab.common.decorators import cached, cachedproperty
7117
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
    60
from logilab.common.date import datetime2ticks, ustrftime, ticks2datetime
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
from logilab.common.compat import all
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    62
from logilab.common.deprecation import deprecated
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8165
diff changeset
    63
from logilab.common.registry import yes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
    65
from rql import nodes, utils
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8719
diff changeset
    67
from cubicweb import Unauthorized
2305
8f6dbe884700 import display_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2152
diff changeset
    68
from cubicweb.schema import display_name
8859
6ed22ac7257c [facet] ensure a facet DOM id is a valid jQuery identifier. Closes #2789089
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8598
diff changeset
    69
from cubicweb.uilib import css_em_num_value, domid
4466
8b0ca7904820 moved generic datetime manipulation function to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4333
diff changeset
    70
from cubicweb.utils import make_uid
8190
2a3c1b787688 [vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8165
diff changeset
    71
from cubicweb.predicates import match_context_prop, partial_relation_possible
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
    72
from cubicweb.appobject import AppObject
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
    73
from cubicweb.web import RequestError, htmlwidgets
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    75
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    76
def rtype_facet_title(facet):
9135
d42540bacff4 [facet] don't crash if no title specified on a facet and filtered rset is empty. Closes #2587883
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 8867
diff changeset
    77
    if facet.cw_rset:
d42540bacff4 [facet] don't crash if no title specified on a facet and filtered rset is empty. Closes #2587883
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 8867
diff changeset
    78
        ptypes = facet.cw_rset.column_types(0)
d42540bacff4 [facet] don't crash if no title specified on a facet and filtered rset is empty. Closes #2587883
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 8867
diff changeset
    79
        if len(ptypes) == 1:
d42540bacff4 [facet] don't crash if no title specified on a facet and filtered rset is empty. Closes #2587883
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 8867
diff changeset
    80
            return display_name(facet._cw, facet.rtype, form=facet.role,
d42540bacff4 [facet] don't crash if no title specified on a facet and filtered rset is empty. Closes #2587883
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 8867
diff changeset
    81
                                context=iter(ptypes).next())
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    82
    return display_name(facet._cw, facet.rtype, form=facet.role)
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    83
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
    84
def get_facet(req, facetid, select, filtered_variable):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
    85
    return req.vreg['facets'].object_by_id(facetid, req, select=select,
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
    86
                                           filtered_variable=filtered_variable)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    87
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    88
@deprecated('[3.13] filter_hiddens moved to cubicweb.web.views.facets with '
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    89
            'slightly modified prototype')
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7874
diff changeset
    90
def filter_hiddens(w, baserql, **kwargs):
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    91
    from cubicweb.web.views.facets import filter_hiddens
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7874
diff changeset
    92
    return filter_hiddens(w, baserql, wdgs=kwargs.pop('facets'), **kwargs)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    93
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    94
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
## rqlst manipulation functions used by facets ################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    96
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
    97
def init_facets(rset, select, mainvar=None):
7944
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
    98
    """Alters in place the <select> for filtering and returns related data.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
    99
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   100
    Calls :func:`prepare_select` to prepare the syntaxtree for selection and
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   101
    :func:`get_filtered_variable` that selects the variable to be filtered and
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   102
    drops several parts of the select tree. See each function docstring for
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   103
    details.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   104
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   105
    :param rset: ResultSet we init facet for.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   106
    :type rset: :class:`~cubicweb.rset.ResultSet`
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   107
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   108
    :param select: Select statement to be *altered* to support filtering.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   109
    :type select:   :class:`~rql.stmts.Select` from the ``rset`` parameters.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   110
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   111
    :param mainvar: Name of the variable we want to filter with facets.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   112
    :type mainvar:  string
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   113
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   114
    :rtype: (filtered_variable, baserql) tuple.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   115
    :return filtered_variable:  A rql class:`~rql.node.VariableRef`
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   116
                                instance as returned by
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   117
                                :func:`get_filtered_variable`.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   118
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   119
    :return baserql: A string containing the rql before
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   120
                     :func:`prepare_select` but after
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   121
                     :func:`get_filtered_variable`.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   122
    """
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   123
    rset.req.vreg.rqlhelper.annotate(select)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   124
    filtered_variable = get_filtered_variable(select, mainvar)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   125
    baserql = select.as_string(kwargs=rset.args) # before call to prepare_select
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   126
    prepare_select(select, filtered_variable)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   127
    return filtered_variable, baserql
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   128
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   129
def get_filtered_variable(select, mainvar=None):
9373
d5d9acadb975 [web/facet] do NOT drop offset/limit of the base rql (closes #3344579)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9139
diff changeset
   130
    """ Return the variable whose name is `mainvar`
d5d9acadb975 [web/facet] do NOT drop offset/limit of the base rql (closes #3344579)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9139
diff changeset
   131
    or the first variable selected in column 0
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   132
    """
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   133
    if mainvar is None:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   134
        vref = select.selection[0].iget_nodes(nodes.VariableRef).next()
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   135
        return vref.variable
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   136
    return select.defined_vars[mainvar]
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   137
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   138
def prepare_select(select, filtered_variable):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
    """prepare a syntax tree to generate facet filters
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   140
7601
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   141
    * remove ORDERBY/GROUPBY clauses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
    * cleanup selection (remove everything)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
    * undefine unnecessary variables
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
    * set DISTINCT
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   145
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   146
    Notice unset of LIMIT/OFFSET us expected to be done by a previous call to
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   147
    :func:`get_filtered_variable`.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
    """
7601
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   149
    # cleanup sort terms / group by
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
    select.remove_sort_terms()
7601
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   151
    select.remove_groups()
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   152
    # XXX remove aggregat from having
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    # selection: only vocabulary entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    for term in select.selection[:]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
        select.remove_selected(term)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    # remove unbound variables which only have some type restriction
8696
0bb18407c053 [toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8598
diff changeset
   157
    for dvar in list(select.defined_vars.itervalues()):
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   158
        if not (dvar is filtered_variable or dvar.stinfo['relations']):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
            select.undefine_variable(dvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
    # global tree config: DISTINCT, LIMIT, OFFSET
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   161
    select.set_distinct(True)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   163
@deprecated('[3.13] use init_facets instead')
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   164
def prepare_facets_rqlst(rqlst, args=None):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   165
    assert len(rqlst.children) == 1, 'FIXME: union not yet supported'
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   166
    select = rqlst.children[0]
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   167
    filtered_variable = get_filtered_variable(select)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   168
    baserql = select.as_string(args)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   169
    prepare_select(select, filtered_variable)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   170
    return filtered_variable, baserql
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   171
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   172
def prepare_vocabulary_select(select, filtered_variable, rtype, role,
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   173
                              select_target_entity=True):
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   174
    """prepare a syntax tree to generate a filter vocabulary rql using the given
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   175
    relation:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   176
    * create a variable to filter on this relation
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   177
    * add the relation
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   178
    * add the new variable to GROUPBY clause if necessary
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   179
    * add the new variable to the selection
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   180
    """
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   181
    newvar = _add_rtype_relation(select, filtered_variable, rtype, role)[0]
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   182
    if select_target_entity:
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   183
        # if select.groupby: XXX we remove groupby now
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   184
        #     select.add_group_var(newvar)
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   185
        select.add_selected(newvar)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   186
    # add is restriction if necessary
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   187
    if filtered_variable.stinfo['typerel'] is None:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   188
        etypes = frozenset(sol[filtered_variable.name] for sol in select.solutions)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   189
        select.add_type_restriction(filtered_variable, etypes)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   190
    return newvar
0
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
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   193
def insert_attr_select_relation(select, filtered_variable, rtype, role, attrname,
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   194
                                sortfuncname=None, sortasc=True,
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   195
                                select_target_entity=True):
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   196
    """modify a syntax tree to :
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   197
    * link a new variable to `filtered_variable` through `rtype` (where filtered_variable has `role`)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   198
    * retrieve only the newly inserted variable and its `attrname`
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   199
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   200
    Sorting:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   201
    * on `attrname` ascendant (`sortasc`=True) or descendant (`sortasc`=False)
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   202
    * on `sortfuncname`(`attrname`) if `sortfuncname` is specified
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   203
    * no sort if `sortasc` is None
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   204
    """
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   205
    cleanup_select(select, filtered_variable)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   206
    var = prepare_vocabulary_select(select, filtered_variable, rtype, role,
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   207
                                   select_target_entity)
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   208
    attrvar = select.make_variable()
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   209
    select.add_relation(var, attrname, attrvar)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   210
    # if query is grouped, we have to add the attribute variable
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   211
    #if select.groupby: XXX may not occur anymore
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   212
    #    if not attrvar in select.groupby:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   213
    #        select.add_group_var(attrvar)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   214
    if sortasc is not None:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   215
        _set_orderby(select, attrvar, sortasc, sortfuncname)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   216
    # add attribute variable to selection
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   217
    select.add_selected(attrvar)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   218
    return var
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   219
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   221
def cleanup_select(select, filtered_variable):
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   222
    """cleanup tree from unnecessary restrictions:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   223
    * attribute selection
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   224
    * optional relations linked to the main variable
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   225
    * mandatory relations linked to the main variable
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   226
    """
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   227
    if select.where is None:
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   228
        return
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   229
    schema = select.root.schema
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   230
    toremove = set()
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   231
    vargraph = deepcopy(select.vargraph) # graph representing links between variable
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   232
    for rel in select.where.get_nodes(nodes.Relation):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   233
        ovar = _may_be_removed(rel, schema, filtered_variable)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   234
        if ovar is not None:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   235
            toremove.add(ovar)
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   236
    removed = set()
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   237
    while toremove:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   238
        trvar = toremove.pop()
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   239
        trvarname = trvar.name
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   240
        # remove paths using this variable from the graph
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   241
        linkedvars = vargraph.pop(trvarname)
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   242
        for ovarname in linkedvars:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   243
            vargraph[ovarname].remove(trvarname)
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   244
        # remove relation using this variable
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   245
        for rel in trvar.stinfo['relations']:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   246
            if rel in removed:
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   247
                # already removed
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   248
                continue
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   249
            select.remove_node(rel)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   250
            removed.add(rel)
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   251
        rel = trvar.stinfo['typerel']
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   252
        if rel is not None and not rel in removed:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   253
            select.remove_node(rel)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   254
            removed.add(rel)
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   255
        # cleanup groupby clause
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   256
        if select.groupby:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   257
            for vref in select.groupby[:]:
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   258
                if vref.name == trvarname:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   259
                    select.remove_group_var(vref)
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   260
        # we can also remove all variables which are linked to this variable
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   261
        # and have no path to the main variable
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   262
        for ovarname in linkedvars:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   263
            if ovarname == filtered_variable.name:
7600
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
   264
                continue
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   265
            if not has_path(vargraph, ovarname, filtered_variable.name):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   266
                toremove.add(select.defined_vars[ovarname])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   267
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   268
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   269
def _may_be_removed(rel, schema, variable):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
    """if the given relation may be removed from the tree, return the variable
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   271
    on the other side of `variable`, else return None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
    Conditions:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
    * the relation is an attribute selection of the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
    * the relation is optional relation linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
    * the relation is a mandatory relation linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
      without any restriction on the other variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   277
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   278
    lhs, rhs = rel.get_variable_parts()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
    rschema = schema.rschema(rel.r_type)
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   280
    if lhs.variable is variable:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
            ovar = rhs.variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   283
        except AttributeError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
            # constant restriction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   285
            # XXX: X title LOWER(T) if it makes sense?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
            return None
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3333
diff changeset
   287
        if rschema.final:
7624
ce020f90fb8e [facet] closes #1806932: test and fix facet bug w/ having query (need rql update)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7618
diff changeset
   288
            if len(ovar.stinfo['relations']) == 1 \
ce020f90fb8e [facet] closes #1806932: test and fix facet bug w/ having query (need rql update)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7618
diff changeset
   289
                   and not ovar.stinfo.get('having'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
                # attribute selection
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
                return ovar
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   292
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
        opt = 'right'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
        cardidx = 0
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   295
    elif getattr(rhs, 'variable', None) is variable:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
        ovar = lhs.variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
        opt = 'left'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
        cardidx = 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
        # not directly linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   301
        return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
    if rel.optional in (opt, 'both'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
        # optional relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
        return ovar
4073
03681ba6da0b cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3720
diff changeset
   305
    if all(rdef.cardinality[cardidx] in '1+'
8696
0bb18407c053 [toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8598
diff changeset
   306
           for rdef in rschema.rdefs.itervalues()):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
        # mandatory relation without any restriction on the other variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
        for orel in ovar.stinfo['relations']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
            if rel is orel:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
            if _may_be_removed(orel, schema, ovar) is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
        return ovar
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
    return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   316
def _make_relation(select, variable, rtype, role):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   317
    newvar = select.make_variable()
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   318
    if role == 'object':
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   319
        rel = nodes.make_relation(newvar, rtype, (variable,), nodes.VariableRef)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   320
    else:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   321
        rel = nodes.make_relation(variable, rtype, (newvar,), nodes.VariableRef)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   322
    return newvar, rel
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   323
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   324
def _add_rtype_relation(select, variable, rtype, role):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   325
    """add a relation relying `variable` to entities linked by the `rtype`
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   326
    relation (where `variable` has `role`)
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   327
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   328
    return the inserted variable for linked entities.
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   329
    """
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   330
    newvar, newrel = _make_relation(select, variable, rtype, role)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   331
    select.add_restriction(newrel)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   332
    return newvar, newrel
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   333
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   334
def _remove_relation(select, rel, var):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
    """remove a constraint relation from the syntax tree"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
    # remove the relation
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   337
    select.remove_node(rel)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
    # remove relations where the filtered variable appears on the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
    # lhs and rhs is a constant restriction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
    extra = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
    for vrel in var.stinfo['relations']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
        if vrel is rel:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
            continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
        if vrel.children[0].variable is var:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
            if not vrel.children[1].get_nodes(nodes.Constant):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
                extra.append(vrel)
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   347
            select.remove_node(vrel)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
    return extra
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   350
def _set_orderby(select, newvar, sortasc, sortfuncname):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
    if sortfuncname is None:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   352
        select.add_sort_var(newvar, sortasc)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
        vref = nodes.variable_ref(newvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
        vref.register_reference()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
        sortfunc = nodes.Function(sortfuncname)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
        sortfunc.append(vref)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
        term = nodes.SortTerm(sortfunc, sortasc)
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   359
        select.add_sort_term(term)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   361
def _get_var(select, varname, varmap):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   362
    try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   363
        return varmap[varname]
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   364
    except KeyError:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   365
        varmap[varname] = var = select.make_variable()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   366
        return var
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   367
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
   368
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   369
_prepare_vocabulary_rqlst = deprecated('[3.13] renamed prepare_vocabulary_select')(
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   370
    prepare_vocabulary_select)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   371
_cleanup_rqlst = deprecated('[3.13] renamed to cleanup_select')(cleanup_select)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   373
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   374
## base facet classes ##########################################################
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   375
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   376
class AbstractFacet(AppObject):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   377
    """Abstract base class for all facets. Facets are stored in their own
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   378
    'facets' registry. They are similar to contextual components since the use
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   379
    the following configurable properties:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   380
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   381
    * `visible`, boolean flag telling if a facet should be displayed or not
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   382
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   383
    * `order`, integer to control facets display order
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   384
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   385
    * `context`, telling if a facet should be displayed in the table form filter
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   386
      (context = 'tablefilter') or in the facet box (context = 'facetbox') or in
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   387
      both (context = '')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   388
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   389
    The following methods define the facet API:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   390
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   391
    .. automethod:: cubicweb.web.facet.AbstractFacet.get_widget
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   392
    .. automethod:: cubicweb.web.facet.AbstractFacet.add_rql_restrictions
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   393
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   394
    Facets will have the following attributes set (beside the standard
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   395
    :class:`~cubicweb.appobject.AppObject` ones):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   396
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   397
    * `select`, the :class:`rql.stmts.Select` node of the rql syntax tree being
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   398
      filtered
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   399
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   400
    * `filtered_variable`, the variable node in this rql syntax tree that we're
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   401
      interested in filtering
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   402
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   403
    Facets implementors may also be interested in the following properties /
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   404
    methods:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   405
7632
3c9dfc6e820b [book] fix some rest/sphinx errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7629
diff changeset
   406
    .. autoattribute:: cubicweb.web.facet.AbstractFacet.operator
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   407
    .. automethod:: cubicweb.web.facet.AbstractFacet.rqlexec
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   408
    """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
    __abstract__ = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   410
    __registry__ = 'facets'
2799
b703639614e7 refactor property handling to avoid name conflicts
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2770
diff changeset
   411
    cw_property_defs = {
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   412
        _('visible'): dict(type='Boolean', default=True,
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   413
                           help=_('display the facet or not')),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   414
        _('order'):   dict(type='Int', default=99,
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   415
                           help=_('display order of the facet')),
496
e25a3c2f5393 set default to empty string, not None
sylvain.thenault@logilab.fr
parents: 467
diff changeset
   416
        _('context'): dict(type='String', default='',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
                           # None <-> both
446
3a3ab6bbccc5 use empty string instead of None as possible context value to avoid getting an <optgroup> tag in associated widget
sylvain.thenault@logilab.fr
parents: 408
diff changeset
   418
                           vocabulary=(_('tablefilter'), _('facetbox'), ''),
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   419
                           help=_('context where this facet should be displayed, '
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   420
                                  'leave empty for both')),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   421
        }
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   422
    visible = True
446
3a3ab6bbccc5 use empty string instead of None as possible context value to avoid getting an <optgroup> tag in associated widget
sylvain.thenault@logilab.fr
parents: 408
diff changeset
   423
    context = ''
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   424
    needs_update = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   425
    start_unfolded = True
8165
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
   426
    allow_hide = True
4701
3acd198a66c9 [facet] before 3.6 we were sure to have a cw_rset attribute. Restore this for facets
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4615
diff changeset
   427
    cw_rset = None # ensure facets have a cw_rset attribute
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   428
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   429
    def __init__(self, req, select=None, filtered_variable=None,
2658
5535857eeaa5 [appobject selection process] drop the need for the .selected method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
   430
                 **kwargs):
4614
95ccd84c892b fix the bad rqlst syntax tree usage during facets initialization by copying it
Charles Hébert <charles.hebert@logilab.fr>
parents: 4546
diff changeset
   431
        super(AbstractFacet, self).__init__(req, **kwargs)
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   432
        assert select is not None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   433
        assert filtered_variable
4614
95ccd84c892b fix the bad rqlst syntax tree usage during facets initialization by copying it
Charles Hébert <charles.hebert@logilab.fr>
parents: 4546
diff changeset
   434
        # take care: facet may be retreived using `object_by_id` from an ajax call
95ccd84c892b fix the bad rqlst syntax tree usage during facets initialization by copying it
Charles Hébert <charles.hebert@logilab.fr>
parents: 4546
diff changeset
   435
        # or from `select` using the result set to filter
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   436
        self.select = select
2658
5535857eeaa5 [appobject selection process] drop the need for the .selected method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2656
diff changeset
   437
        self.filtered_variable = filtered_variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   439
    def __repr__(self):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   440
        return '<%s>' % self.__class__.__name__
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   441
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   442
    def get_widget(self):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   443
        """Return the widget instance to use to display this facet, or None if
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   444
        the facet can't do anything valuable (only one value in the vocabulary
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   445
        for instance).
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   446
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   447
        raise NotImplementedError
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   448
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   449
    def add_rql_restrictions(self):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   450
        """When some facet criteria has been updated, this method is called to
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   451
        add restriction for this facet into the rql syntax tree. It should get
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   452
        back its value in form parameters, and modify the syntax tree
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   453
        (`self.select`) accordingly.
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   454
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   455
        raise NotImplementedError
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   456
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   457
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   458
    def operator(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   459
        """Return the operator (AND or OR) to use for this facet when multiple
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   460
        values are selected.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   461
        """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   462
        # OR between selected values by default
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   463
        return self._cw.form.get(xml_escape(self.__regid__) + '_andor', 'OR')
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   464
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   465
    def rqlexec(self, rql, args=None):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   466
        """Utility method to execute some rql queries, and simply returning an
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   467
        empty list if :exc:`Unauthorized` is raised.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   468
        """
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   469
        try:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   470
            return self._cw.execute(rql, args)
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   471
        except Unauthorized:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   472
            return []
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   473
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   474
    @property
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   475
    def wdgclass(self):
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   476
        raise NotImplementedError
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   477
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   478
    @property
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   479
    @deprecated('[3.13] renamed .select')
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   480
    def rqlst(self):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   481
        return self.select
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   482
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   483
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   484
class VocabularyFacet(AbstractFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   485
    """This abstract class extend :class:`AbstractFacet` to use the
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   486
    :class:`FacetVocabularyWidget` as widget, suitable for facets that may
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   487
    restrict values according to a (usually computed) vocabulary.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   488
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   489
    A class which inherits from VocabularyFacet must define at least these methods:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   490
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   491
    .. automethod:: cubicweb.web.facet.VocabularyFacet.vocabulary
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   492
    .. automethod:: cubicweb.web.facet.VocabularyFacet.possible_values
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   493
    """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   494
    needs_update = True
7608
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   495
    support_and = False
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   496
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   497
    @property
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   498
    def wdgclass(self):
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   499
        return FacetVocabularyWidget
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   500
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
   501
    def get_selected(self):
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8719
diff changeset
   502
        return frozenset(int(eid) for eid in self._cw.list_form_param(self.__regid__))
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
   503
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   504
    def get_widget(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   505
        """Return the widget instance to use to display this facet.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   506
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   507
        This implementation expects a .vocabulary method on the facet and
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   508
        return a combobox displaying this vocabulary.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
        vocab = self.vocabulary()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
        if len(vocab) <= 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
            return None
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
   513
        wdg = self.wdgclass(self)
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
   514
        selected = self.get_selected()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
        for label, value in vocab:
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
   516
            wdg.items.append((value, label, value in selected))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   517
        return wdg
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   518
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   519
    def vocabulary(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   520
        """Return vocabulary for this facet, eg a list of 2-uple (label, value).
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   521
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   522
        raise NotImplementedError
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   523
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
    def possible_values(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   525
        """Return a list of possible values (as string since it's used to
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   526
        compare to a form value in javascript) for this facet.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   527
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   528
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   529
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   530
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   531
class RelationFacet(VocabularyFacet):
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   532
    """Base facet to filter some entities according to other entities to which
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7874
diff changeset
   533
    they are related. Create concrete facet by inheriting from this class an then
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   534
    configuring it by setting class attribute described below.
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   535
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   536
    The relation is defined by the `rtype` and `role` attributes.
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   537
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   538
    The `no_relation` boolean flag tells if a special 'no relation' value should be
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   539
    added (allowing to filter on entities which *do not* have the relation set).
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   540
    Default is computed according the relation's cardinality.
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   541
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   542
    The values displayed for related entities will be:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   543
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   544
    * result of calling their `label_vid` view if specified
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   545
    * else their `target_attr` attribute value if specified
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   546
    * else their eid (you usually want something nicer...)
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   547
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   548
    When no `label_vid` is set, you will get translated value if `i18nable` is
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   549
    set. By default, `i18nable` will be set according to the schema, but you can
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   550
    force its value by setting it has a class attribute.
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   551
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   552
    You can filter out target entity types by specifying `target_type`.
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   553
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   554
    By default, vocabulary will be displayed sorted on `target_attr` value in an
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   555
    ascending way. You can control sorting with:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   556
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   557
    * `sortfunc`: set this to a stored procedure name if you want to sort on the
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   558
      result of this function's result instead of direct value
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   559
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   560
    * `sortasc`: boolean flag to control ascendant/descendant sorting
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   561
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   562
    To illustrate this facet, let's take for example an *excerpt* of the schema
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   563
    of an office location search application:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   564
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   565
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   566
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   567
      class Office(WorkflowableEntityType):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   568
          price = Int(description='euros / m2 / HC / HT')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   569
          surface = Int(description='m2')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   570
          has_address = SubjectRelation('PostalAddress',
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   571
                                        cardinality='1?',
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   572
                                        composite='subject')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   573
          proposed_by = SubjectRelation('Agency')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   574
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   575
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   576
    We can simply define a facet to filter offices according to the agency
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   577
    proposing it:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   578
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   579
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   580
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   581
      class AgencyFacet(RelationFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   582
          __regid__ = 'agency'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   583
          # this facet should only be selected when visualizing offices
6152
6824f8b61098 use is_instance in a number of places (esp. documentation) rather than the deprecated implements
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6120
diff changeset
   584
          __select__ = RelationFacet.__select__ & is_instance('Office')
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   585
          # this facet is a filter on the 'Agency' entities linked to the office
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   586
          # through the 'proposed_by' relation, where the office is the subject
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   587
          # of the relation
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   588
          rtype = 'has_address'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   589
          # 'subject' is the default but setting it explicitly doesn't hurt...
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   590
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   591
          # we want to display the agency's name
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   592
          target_attr = 'name'
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   593
    """
838
f2c56312b03a rename abstract_* selectors into partial_* + add docstrings
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 782
diff changeset
   594
    __select__ = partial_relation_possible() & match_context_prop()
5006
871269e5e020 [facet] allow to specify a target type on relation facets for case such as Keyword/CodeKeyword where we only targets Keyword
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   595
    # class attributes to configure the relation facet
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
    rtype = None
1433
091ac3ba5d51 remove trailing white spaces
sylvain.thenault@logilab.fr
parents: 1432
diff changeset
   597
    role = 'subject'
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   598
    target_type = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
    target_attr = 'eid'
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   600
    # for subclasses parametrization, should not change if you want a
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   601
    # RelationFacet
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   602
    target_attr_type = 'Int'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   603
    restr_attr = 'eid'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   604
    restr_attr_type = 'Int'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   605
    comparator = '=' # could be '<', '<=', '>', '>='
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   606
    # set this to a stored procedure name if you want to sort on the result of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   607
    # this function's result instead of direct value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   608
    sortfunc = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   609
    # ascendant/descendant sorting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   610
    sortasc = True
3328
76888cd23d83 facets enhancement: can now set label_vid to use a view instead of a simple attribute as label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   611
    # if you want to call a view on the entity instead of using `target_attr`
76888cd23d83 facets enhancement: can now set label_vid to use a view instead of a simple attribute as label
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   612
    label_vid = None
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   613
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   614
    # internal purpose
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   615
    _select_target_entity = True
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   616
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
   617
    title = property(rtype_facet_title)
7851
54e6abed520a [i18n, facet] missing registration of <no relation> msgid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7849
diff changeset
   618
    no_relation_label = _('<no relation>')
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   619
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   620
    def __repr__(self):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   621
        return '<%s on (%s-%s)>' % (self.__class__.__name__, self.rtype, self.role)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   622
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   623
    # facet public API #########################################################
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   624
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   625
    def vocabulary(self):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   626
        """return vocabulary for this facet, eg a list of 2-uple (label, value)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   627
        """
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   628
        select = self.select
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   629
        select.save_state()
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   630
        if self.rql_sort:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   631
            sort = self.sortasc
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   632
        else:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   633
            sort = None # will be sorted on label
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   634
        try:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   635
            var = insert_attr_select_relation(
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   636
                select, self.filtered_variable, self.rtype, self.role,
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   637
                self.target_attr, self.sortfunc, sort,
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   638
                self._select_target_entity)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   639
            if self.target_type is not None:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   640
                select.add_type_restriction(var, self.target_type)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   641
            try:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   642
                rset = self.rqlexec(select.as_string(), self.cw_rset.args)
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   643
            except Exception:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   644
                self.exception('error while getting vocabulary for %s, rql: %s',
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   645
                               self, select.as_string())
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   646
                return ()
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   647
        finally:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   648
            select.recover()
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   649
        # don't call rset_vocabulary on empty result set, it may be an empty
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   650
        # *list* (see rqlexec implementation)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   651
        values = rset and self.rset_vocabulary(rset) or []
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   652
        if self._include_no_relation():
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   653
            values.insert(0, (self._cw._(self.no_relation_label), ''))
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   654
        return values
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   655
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   656
    def possible_values(self):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   657
        """return a list of possible values (as string since it's used to
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   658
        compare to a form value in javascript) for this facet
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   659
        """
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   660
        select = self.select
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   661
        select.save_state()
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   662
        try:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   663
            cleanup_select(select, self.filtered_variable)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   664
            if self._select_target_entity:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   665
                prepare_vocabulary_select(select, self.filtered_variable, self.rtype,
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   666
                                         self.role, select_target_entity=True)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   667
            else:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   668
                insert_attr_select_relation(
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   669
                    select, self.filtered_variable, self.rtype, self.role,
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   670
                    self.target_attr, select_target_entity=False)
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   671
            values = [unicode(x) for x, in self.rqlexec(select.as_string())]
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   672
        except Exception:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   673
            self.exception('while computing values for %s', self)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   674
            return []
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   675
        finally:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   676
            select.recover()
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   677
        if self._include_no_relation():
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   678
            values.append('')
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   679
        return values
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   680
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   681
    def add_rql_restrictions(self):
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   682
        """add restriction for this facet into the rql syntax tree"""
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   683
        value = self._cw.form.get(self.__regid__)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   684
        if value is None:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   685
            return
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   686
        filtered_variable = self.filtered_variable
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   687
        restrvar, rel = _add_rtype_relation(self.select, filtered_variable,
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   688
                                            self.rtype, self.role)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   689
        self.value_restriction(restrvar, rel, value)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   690
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   691
    # internal control API #####################################################
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   692
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   693
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   694
    def i18nable(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   695
        """should label be internationalized"""
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   696
        if self.target_type:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   697
            eschema = self._cw.vreg.schema.eschema(self.target_type)
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   698
        elif self.role == 'subject':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   699
            eschema = self._cw.vreg.schema.rschema(self.rtype).objects()[0]
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   700
        else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   701
            eschema = self._cw.vreg.schema.rschema(self.rtype).subjects()[0]
6662
8862bf4a6dd4 [facet] only String attributes have internationalizable property
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6623
diff changeset
   702
        return getattr(eschema.rdef(self.target_attr), 'internationalizable', False)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   703
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   704
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   705
    def no_relation(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   706
        return (not self._cw.vreg.schema.rschema(self.rtype).final
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   707
                and self._search_card('?*'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   708
6251
afc757568492 [facet] add missing @property making subsequent access always true
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6152
diff changeset
   709
    @property
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   710
    def rql_sort(self):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   711
        """return true if we can handle sorting in the rql query. E.g.  if
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   712
        sortfunc is set or if we have not to transform the returned value (eg no
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   713
        label_vid and not i18nable)
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   714
        """
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   715
        return self.sortfunc is not None or (self.label_vid is None
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   716
                                             and not self.i18nable)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   717
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   718
    def rset_vocabulary(self, rset):
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   719
        if self.i18nable:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
   720
            _ = self._cw._
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   721
        else:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   722
            _ = unicode
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   723
        if self.rql_sort:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   724
            values = [(_(label), eid) for eid, label in rset]
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   725
        else:
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   726
            if self.label_vid is None:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   727
                values = [(_(label), eid) for eid, label in rset]
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   728
            else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   729
                values = [(entity.view(self.label_vid), entity.eid)
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   730
                          for entity in rset.entities()]
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   731
            values = sorted(values)
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   732
            if not self.sortasc:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   733
                values = list(reversed(values))
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   734
        return values
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   735
7608
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   736
    @property
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   737
    def support_and(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   738
        return self._search_card('+*')
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   739
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   740
    # internal utilities #######################################################
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   741
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
   742
    @cached
7608
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   743
    def _support_and_compat(self):
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   744
        support = self.support_and
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   745
        if callable(support):
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   746
            warn('[3.13] %s.support_and is now a property' % self.__class__,
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   747
                 DeprecationWarning)
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   748
            support = support()
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   749
        return support
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   750
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   751
    def value_restriction(self, restrvar, rel, value):
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   752
        # XXX handle rel is None case in RQLPathFacet?
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   753
        if self.restr_attr != 'eid':
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   754
            self.select.set_distinct(True)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   755
        if isinstance(value, basestring):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   756
            # only one value selected
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   757
            if value:
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   758
                self.select.add_constant_restriction(
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   759
                    restrvar, self.restr_attr, value,
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   760
                    self.restr_attr_type)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   761
            else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   762
                rel.parent.replace(rel, nodes.Not(rel))
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   763
        elif self.operator == 'OR':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   764
            # set_distinct only if rtype cardinality is > 1
7608
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   765
            if self._support_and_compat():
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   766
                self.select.set_distinct(True)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   767
            # multiple ORed values: using IN is fine
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   768
            if '' in value:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   769
                value.remove('')
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   770
                self._add_not_rel_restr(rel)
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   771
            self._and_restriction(rel, restrvar, value)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   772
        else:
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   773
            # multiple values with AND operator. We've to generate a query like
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   774
            # "X relation A, A eid 1, X relation B, B eid 1", hence the new
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   775
            # relations at each iteration in the while loop below 
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   776
            if '' in value:
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   777
                raise RequestError("this doesn't make sense")
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   778
            self._and_restriction(rel, restrvar, value.pop())
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   779
            while value:
7678
ab3d1a77be55 [facets] fix missing 'warnings' import and missing self reference on 'filtered_variable'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7632
diff changeset
   780
                restrvar, rtrel = _make_relation(self.select, self.filtered_variable,
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   781
                                                 self.rtype, self.role)
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   782
                if rel is None:
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7874
diff changeset
   783
                    self.select.add_restriction(rtrel)
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   784
                else:
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
   785
                    rel.parent.replace(rel, nodes.And(rel, rtrel))
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   786
                self._and_restriction(rel, restrvar, value.pop())
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   787
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   788
    def _and_restriction(self, rel, restrvar, value):
7625
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   789
        if rel is None:
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   790
            self.select.add_constant_restriction(restrvar, self.restr_attr,
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   791
                                                 value, self.restr_attr_type)
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   792
        else:
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   793
            rrel = nodes.make_constant_restriction(restrvar, self.restr_attr,
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   794
                                                   value, self.restr_attr_type)
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   795
            rel.parent.replace(rel, nodes.And(rel, rrel))
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   796
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   797
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   798
    @cached
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   799
    def _search_card(self, cards):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   800
        for rdef in self._iter_rdefs():
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   801
            if rdef.role_cardinality(self.role) in cards:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   802
                return True
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   803
        return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   804
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   805
    def _iter_rdefs(self):
3456
1a63a252601f [facets] typo fix
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3451
diff changeset
   806
        rschema = self._cw.vreg.schema.rschema(self.rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
        # XXX when called via ajax, no rset to compute possible types
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
   808
        possibletypes = self.cw_rset and self.cw_rset.column_types(0)
4087
2b8bc4cfd6ee api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4074
diff changeset
   809
        for rdef in rschema.rdefs.itervalues():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   810
            if possibletypes is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
                if self.role == 'subject':
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   812
                    if rdef.subject not in possibletypes:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   813
                        continue
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   814
                elif rdef.object not in possibletypes:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   815
                    continue
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   816
            if self.target_type is not None:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   817
                if self.role == 'subject':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   818
                    if rdef.object != self.target_type:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   819
                        continue
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   820
                elif rdef.subject != self.target_type:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   821
                    continue
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   822
            yield rdef
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   824
    def _include_no_relation(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   825
        if not self.no_relation:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   826
            return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   827
        if self._cw.vreg.schema.rschema(self.rtype).final:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   828
            return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   829
        if self.role == 'object':
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   830
            subj = utils.rqlvar_maker(defined=self.select.defined_vars,
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   831
                                      aliases=self.select.aliases).next()
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   832
            obj = self.filtered_variable.name
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   833
        else:
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   834
            subj = self.filtered_variable.name
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   835
            obj = utils.rqlvar_maker(defined=self.select.defined_vars,
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   836
                                     aliases=self.select.aliases).next()
6681
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   837
        restrictions = []
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   838
        if self.select.where:
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   839
            restrictions.append(self.select.where.as_string())
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   840
        if self.select.with_:
6681
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   841
            restrictions.append('WITH ' + ','.join(
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   842
                term.as_string() for term in self.select.with_))
6681
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   843
        if restrictions:
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   844
            restrictions = ',' + ','.join(restrictions)
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   845
        else:
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   846
            restrictions = ''
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   847
        rql = 'Any %s LIMIT 1 WHERE NOT %s %s %s%s' % (
674461009c7c fix #1376317: facet: no_relation feature crash when rql has no restriction
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6662
diff changeset
   848
            self.filtered_variable.name, subj, self.rtype, obj, restrictions)
6599
d3008cb6d1c3 [ms] catch exception on executing rql, work-around #1356884 until a proper fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   849
        try:
d3008cb6d1c3 [ms] catch exception on executing rql, work-around #1356884 until a proper fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   850
            return bool(self.rqlexec(rql, self.cw_rset and self.cw_rset.args))
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   851
        except Exception:
6599
d3008cb6d1c3 [ms] catch exception on executing rql, work-around #1356884 until a proper fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   852
            # catch exception on executing rql, work-around #1356884 until a
d3008cb6d1c3 [ms] catch exception on executing rql, work-around #1356884 until a proper fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   853
            # proper fix
d3008cb6d1c3 [ms] catch exception on executing rql, work-around #1356884 until a proper fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   854
            self.exception('cant handle rql generated by %s', self)
d3008cb6d1c3 [ms] catch exception on executing rql, work-around #1356884 until a proper fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   855
            return False
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   856
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   857
    def _add_not_rel_restr(self, rel):
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   858
        nrrel = nodes.Not(_make_relation(self.select, self.filtered_variable,
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   859
                                         self.rtype, self.role)[1])
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   860
        rel.parent.replace(rel, nodes.Or(nrrel, rel))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   861
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   863
class RelationAttributeFacet(RelationFacet):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   864
    """Base facet to filter some entities according to an attribute of other
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   865
    entities to which they are related. Most things work similarly as
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   866
    :class:`RelationFacet`, except that:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   867
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   868
    * `label_vid` doesn't make sense here
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   869
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   870
    * you should specify the attribute type using `target_attr_type` if it's not a
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   871
      String
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   872
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   873
    * you can specify a comparison operator using `comparator`
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   874
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   875
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   876
    Back to our example... if you want to search office by postal code and that
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   877
    you use a :class:`RelationFacet` for that, you won't get the expected
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   878
    behaviour: if two offices have the same postal code, they've however two
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   879
    different addresses.  So you'll see in the facet the same postal code twice,
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   880
    though linked to a different address entity. There is a great chance your
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   881
    users won't understand that...
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   882
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   883
    That's where this class come in ! It's used to said that you want to filter
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   884
    according to the *attribute value* of a relatied entity, not to the entity
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   885
    itself. Now here is the source code for the facet:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   886
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   887
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   888
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   889
      class PostalCodeFacet(RelationAttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   890
          __regid__ = 'postalcode'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   891
          # this facet should only be selected when visualizing offices
6152
6824f8b61098 use is_instance in a number of places (esp. documentation) rather than the deprecated implements
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6120
diff changeset
   892
          __select__ = RelationAttributeFacet.__select__ & is_instance('Office')
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   893
          # this facet is a filter on the PostalAddress entities linked to the
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   894
          # office through the 'has_address' relation, where the office is the
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   895
          # subject of the relation
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   896
          rtype = 'has_address'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   897
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   898
          # we want to search according to address 'postal_code' attribute
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   899
          target_attr = 'postalcode'
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   900
    """
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   901
    _select_target_entity = False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   902
    # attribute type
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   903
    target_attr_type = 'String'
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   904
    # type of comparison: default is an exact match on the attribute value
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   905
    comparator = '=' # could be '<', '<=', '>', '>='
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   906
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   907
    @property
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   908
    def restr_attr(self):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   909
        return self.target_attr
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   910
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   911
    @property
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   912
    def restr_attr_type(self):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   913
        return self.target_attr_type
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   914
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   915
    def rset_vocabulary(self, rset):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   916
        if self.i18nable:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   917
            _ = self._cw._
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   918
        else:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   919
            _ = unicode
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   920
        if self.rql_sort:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   921
            return [(_(value), value) for value, in rset]
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   922
        values = [(_(value), value) for value, in rset]
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   923
        if self.sortasc:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   924
            return sorted(values)
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   925
        return reversed(sorted(values))
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   926
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   927
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   928
class AttributeFacet(RelationAttributeFacet):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   929
    """Base facet to filter some entities according one of their attribute.
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   930
    Configuration is mostly similarly as :class:`RelationAttributeFacet`, except that:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   931
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   932
    * `target_attr` doesn't make sense here (you specify the attribute using `rtype`
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   933
    * `role` neither, it's systematically 'subject'
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   934
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   935
    So, suppose that in our office search example you want to refine search according
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   936
    to the office's surface. Here is a code snippet achieving this:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   937
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   938
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   939
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   940
      class SurfaceFacet(AttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   941
          __regid__ = 'surface'
6152
6824f8b61098 use is_instance in a number of places (esp. documentation) rather than the deprecated implements
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6120
diff changeset
   942
          __select__ = AttributeFacet.__select__ & is_instance('Office')
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   943
          # this facet is a filter on the office'surface
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   944
          rtype = 'surface'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   945
          # override the default value of operator since we want to filter
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   946
          # according to a minimal value, not an exact one
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   947
          comparator = '>='
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   948
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   949
          def vocabulary(self):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   950
              '''override the default vocabulary method since we want to
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   951
              hard-code our threshold values.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   952
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   953
              Not overriding would generate a filter containing all existing
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   954
              surfaces defined in the database.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   955
              '''
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   956
              return [('> 200', '200'), ('> 250', '250'),
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   957
                      ('> 275', '275'), ('> 300', '300')]
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   958
    """
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   959
7608
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
   960
    support_and = False
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   961
    _select_target_entity = True
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   962
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   963
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   964
    def i18nable(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   965
        """should label be internationalized"""
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   966
        for rdef in self._iter_rdefs():
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   967
            # no 'internationalizable' property for rdef whose object is not a
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   968
            # String
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   969
            if not getattr(rdef, 'internationalizable', False):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   970
                return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   971
        return True
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   972
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   973
    def vocabulary(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   974
        """return vocabulary for this facet, eg a list of 2-uple (label, value)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   975
        """
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   976
        select = self.select
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   977
        select.save_state()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   978
        try:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   979
            filtered_variable = self.filtered_variable
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   980
            cleanup_select(select, filtered_variable)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   981
            newvar = prepare_vocabulary_select(select, filtered_variable, self.rtype, self.role)
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   982
            _set_orderby(select, newvar, self.sortasc, self.sortfunc)
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
   983
            if self.cw_rset:
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
   984
                args = self.cw_rset.args
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
   985
            else: # vocabulary used for possible_values
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
   986
                args = None
346
5bbb01a133ae add try except to avoid error w/ unsupported stuff, log it and return incomplete filter form
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 203
diff changeset
   987
            try:
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
   988
                rset = self.rqlexec(select.as_string(), args)
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   989
            except Exception:
346
5bbb01a133ae add try except to avoid error w/ unsupported stuff, log it and return incomplete filter form
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 203
diff changeset
   990
                self.exception('error while getting vocabulary for %s, rql: %s',
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   991
                               self, select.as_string())
346
5bbb01a133ae add try except to avoid error w/ unsupported stuff, log it and return incomplete filter form
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 203
diff changeset
   992
                return ()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   993
        finally:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   994
            select.recover()
5225
9ff0dee81eb2 [facet] don't crash in rset_vocabulary if an unauthorized error was raised in rqlexec
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5006
diff changeset
   995
        # don't call rset_vocabulary on empty result set, it may be an empty
9ff0dee81eb2 [facet] don't crash in rset_vocabulary if an unauthorized error was raised in rqlexec
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5006
diff changeset
   996
        # *list* (see rqlexec implementation)
9ff0dee81eb2 [facet] don't crash in rset_vocabulary if an unauthorized error was raised in rqlexec
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5006
diff changeset
   997
        return rset and self.rset_vocabulary(rset)
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
   998
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   999
    def add_rql_restrictions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1000
        """add restriction for this facet into the rql syntax tree"""
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1001
        value = self._cw.form.get(self.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1002
        if not value:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1003
            return
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1004
        filtered_variable = self.filtered_variable
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1005
        self.select.add_constant_restriction(filtered_variable, self.rtype, value,
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1006
                                            self.target_attr_type, self.comparator)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1007
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1008
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1009
class RQLPathFacet(RelationFacet):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1010
    """Base facet to filter some entities according to an arbitrary rql
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1011
    path. Path should be specified as a list of 3-uples or triplet string, where
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1012
    'X' represent the filtered variable. You should specify using
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1013
    `filter_variable` the snippet variable that will be used to filter out
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1014
    results. You may also specify a `label_variable`. If you want to filter on
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1015
    an attribute value, you usually don't want to specify the later since it's
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1016
    the same as the filter variable, though you may have to specify the attribute
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1017
    type using `restr_attr_type` if there are some type ambiguity in the schema
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1018
    for the attribute.
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1019
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1020
    Using this facet, we can rewrite facets we defined previously:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1021
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1022
    .. sourcecode:: python
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1023
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1024
      class AgencyFacet(RQLPathFacet):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1025
          __regid__ = 'agency'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1026
          # this facet should only be selected when visualizing offices
7860
ee233d5365b4 [web/facet] fix example selector in docstring
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7851
diff changeset
  1027
          __select__ = is_instance('Office')
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1028
          # this facet is a filter on the 'Agency' entities linked to the office
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1029
          # through the 'proposed_by' relation, where the office is the subject
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1030
          # of the relation
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1031
          path = ['X has_address O', 'O name N']
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1032
          filter_variable = 'O'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1033
          label_variable = 'N'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1034
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1035
      class PostalCodeFacet(RQLPathFacet):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1036
          __regid__ = 'postalcode'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1037
          # this facet should only be selected when visualizing offices
7860
ee233d5365b4 [web/facet] fix example selector in docstring
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7851
diff changeset
  1038
          __select__ = is_instance('Office')
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1039
          # this facet is a filter on the PostalAddress entities linked to the
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1040
          # office through the 'has_address' relation, where the office is the
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1041
          # subject of the relation
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1042
          path = ['X has_address O', 'O postal_code PC']
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1043
          filter_variable = 'PC'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1044
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1045
    Though some features, such as 'no value' or automatic internationalization,
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1046
    won't work. This facet class is designed to be used for cases where
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1047
    :class:`RelationFacet` or :class:`RelationAttributeFacet` can't do the trick
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1048
    (e.g when you want to filter on entities where are not directly linked to
7632
3c9dfc6e820b [book] fix some rest/sphinx errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7629
diff changeset
  1049
    the filtered entities).
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1050
    """
7874
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1051
    __select__ = yes() # we don't want RelationFacet's selector
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1052
    # must be specified
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1053
    path = None
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1054
    filter_variable = None
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1055
    # may be specified
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1056
    label_variable = None
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1057
    # usually guessed, but may be explicitly specified
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1058
    restr_attr = None
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1059
    restr_attr_type = None
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1060
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1061
    # XXX disabled features
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1062
    i18nable = False
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1063
    no_relation = False
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1064
    support_and = False
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1065
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1066
    def __init__(self, *args, **kwargs):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1067
        super(RQLPathFacet, self).__init__(*args, **kwargs)
7874
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1068
        assert self.filter_variable != self.label_variable, \
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1069
            ('filter_variable and label_variable should be different. '
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1070
             'You may want to let label_variable undefined (ie None).')
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1071
        assert self.path and isinstance(self.path, (list, tuple)), \
7874
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1072
            'path should be a list of 3-uples, not %s' % self.path
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1073
        for part in self.path:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1074
            if isinstance(part, basestring):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1075
                part = part.split()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1076
            assert len(part) == 3, \
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1077
                   'path should be a list of 3-uples, not %s' % part
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1078
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1079
    def __repr__(self):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1080
        return '<%s %s>' % (self.__class__.__name__,
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1081
                            ','.join(str(p) for p in self.path))
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1082
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1083
    def vocabulary(self):
7874
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1084
        """return vocabulary for this facet, eg a list of (label, value)"""
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1085
        select = self.select
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1086
        select.save_state()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1087
        if self.rql_sort:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1088
            sort = self.sortasc
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1089
        else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1090
            sort = None # will be sorted on label
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1091
        try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1092
            cleanup_select(select, self.filtered_variable)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1093
            varmap, restrvar = self.add_path_to_select()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1094
            select.append_selected(nodes.VariableRef(restrvar))
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1095
            if self.label_variable:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1096
                attrvar = varmap[self.label_variable]
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1097
            else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1098
                attrvar = restrvar
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1099
            select.append_selected(nodes.VariableRef(attrvar))
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1100
            if sort is not None:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1101
                _set_orderby(select, attrvar, sort, self.sortfunc)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1102
            try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1103
                rset = self.rqlexec(select.as_string(), self.cw_rset.args)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1104
            except Exception:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1105
                self.exception('error while getting vocabulary for %s, rql: %s',
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1106
                               self, select.as_string())
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1107
                return ()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1108
        finally:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1109
            select.recover()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1110
        # don't call rset_vocabulary on empty result set, it may be an empty
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1111
        # *list* (see rqlexec implementation)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1112
        values = rset and self.rset_vocabulary(rset) or []
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1113
        if self._include_no_relation():
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1114
            values.insert(0, (self._cw._(self.no_relation_label), ''))
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1115
        return values
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1116
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1117
    def possible_values(self):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1118
        """return a list of possible values (as string since it's used to
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1119
        compare to a form value in javascript) for this facet
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1120
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1121
        select = self.select
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1122
        select.save_state()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1123
        try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1124
            cleanup_select(select, self.filtered_variable)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1125
            varmap, restrvar = self.add_path_to_select(skiplabel=True)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1126
            select.append_selected(nodes.VariableRef(restrvar))
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1127
            values = [unicode(x) for x, in self.rqlexec(select.as_string())]
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1128
        except Exception:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1129
            self.exception('while computing values for %s', self)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1130
            return []
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1131
        finally:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1132
            select.recover()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1133
        if self._include_no_relation():
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1134
            values.append('')
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1135
        return values
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1136
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1137
    def add_rql_restrictions(self):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1138
        """add restriction for this facet into the rql syntax tree"""
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1139
        value = self._cw.form.get(self.__regid__)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1140
        if value is None:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1141
            return
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1142
        varmap, restrvar = self.add_path_to_select(
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1143
            skiplabel=True, skipattrfilter=True)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1144
        self.value_restriction(restrvar, None, value)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1145
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1146
    def add_path_to_select(self, skiplabel=False, skipattrfilter=False):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1147
        varmap = {'X': self.filtered_variable}
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1148
        actual_filter_variable = None
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1149
        for part in self.path:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1150
            if isinstance(part, basestring):
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1151
                part = part.split()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1152
            subject, rtype, object = part
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1153
            if skiplabel and object == self.label_variable:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1154
                continue
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1155
            if object == self.filter_variable:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1156
                rschema = self._cw.vreg.schema.rschema(rtype)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1157
                if rschema.final:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1158
                    # filter variable is an attribute variable
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1159
                    if self.restr_attr is None:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1160
                        self.restr_attr = rtype
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1161
                    if self.restr_attr_type is None:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1162
                        attrtypes = set(obj for subj,obj in rschema.rdefs)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1163
                        if len(attrtypes) > 1:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1164
                            raise Exception('ambigous attribute %s, specify attrtype on %s'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1165
                                            % (rtype, self.__class__))
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1166
                        self.restr_attr_type = iter(attrtypes).next()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1167
                    if skipattrfilter:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1168
                        actual_filter_variable = subject
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1169
                        continue
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1170
            subjvar = _get_var(self.select, subject, varmap)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1171
            objvar = _get_var(self.select, object, varmap)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1172
            rel = nodes.make_relation(subjvar, rtype, (objvar,),
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1173
                                      nodes.VariableRef)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1174
            self.select.add_restriction(rel)
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1175
        if self.restr_attr is None:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1176
            self.restr_attr = 'eid'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1177
        if self.restr_attr_type is None:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1178
            self.restr_attr_type = 'Int'
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1179
        if actual_filter_variable:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1180
            restrvar = varmap[actual_filter_variable]
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1181
        else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1182
            restrvar = varmap[self.filter_variable]
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1183
        return varmap, restrvar
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1184
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1185
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1186
class RangeFacet(AttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1187
    """This class allows to filter entities according to an attribute of
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1188
    numerical type.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1189
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1190
    It displays a slider using `jquery`_ to choose a lower bound and an upper
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1191
    bound.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1192
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1193
    The example below provides an alternative to the surface facet seen earlier,
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1194
    in a more powerful way since
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1195
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1196
    * lower/upper boundaries are computed according to entities to filter
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1197
    * user can specify lower/upper boundaries, not only the lower one
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1198
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1199
    .. sourcecode:: python
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
  1200
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1201
      class SurfaceFacet(RangeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1202
          __regid__ = 'surface'
6152
6824f8b61098 use is_instance in a number of places (esp. documentation) rather than the deprecated implements
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6120
diff changeset
  1203
          __select__ = RangeFacet.__select__ & is_instance('Office')
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1204
          # this facet is a filter on the office'surface
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1205
          rtype = 'surface'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1206
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1207
    All this with even less code!
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
  1208
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1209
    The image below display the rendering of the slider:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1210
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1211
    .. image:: ../images/facet_range.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1212
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1213
    .. _jquery: http://www.jqueryui.com/
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1214
    """
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1215
    target_attr_type = 'Float' # only numerical types are supported
7609
fbefd1b9e587 [facets] DontUpdateConstraint mecanism introduced a few commit ago isn't needed: we already have the 'needs_update' property controlling this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7608
diff changeset
  1216
    needs_update = False # not supported actually
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1217
7204
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1218
    @property
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1219
    def wdgclass(self):
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1220
        return FacetRangeWidget
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1221
7629
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1222
    def _range_rset(self):
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1223
        select = self.select
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1224
        select.save_state()
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1225
        try:
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1226
            filtered_variable = self.filtered_variable
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1227
            cleanup_select(select, filtered_variable)
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1228
            newvar = _add_rtype_relation(select, filtered_variable, self.rtype, self.role)[0]
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1229
            minf = nodes.Function('MIN')
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1230
            minf.append(nodes.VariableRef(newvar))
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1231
            select.add_selected(minf)
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1232
            maxf = nodes.Function('MAX')
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1233
            maxf.append(nodes.VariableRef(newvar))
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1234
            select.add_selected(maxf)
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1235
            # add is restriction if necessary
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1236
            if filtered_variable.stinfo['typerel'] is None:
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1237
                etypes = frozenset(sol[filtered_variable.name] for sol in select.solutions)
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1238
                select.add_type_restriction(filtered_variable, etypes)
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1239
            try:
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1240
                return self.rqlexec(select.as_string(), self.cw_rset.args)
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1241
            except Exception:
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1242
                self.exception('error while getting vocabulary for %s, rql: %s',
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1243
                               self, select.as_string())
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1244
                return ()
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1245
        finally:
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1246
            select.recover()
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1247
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1248
    def vocabulary(self):
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1249
        """return vocabulary for this facet, eg a list of 2-uple (label, value)
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1250
        """
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1251
        rset = self._range_rset()
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1252
        if rset:
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1253
            minv, maxv = rset[0]
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1254
            return [(unicode(minv), minv), (unicode(maxv), maxv)]
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1255
        return []
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1256
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1257
    def possible_values(self):
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1258
        """Return a list of possible values (as string since it's used to
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1259
        compare to a form value in javascript) for this facet.
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1260
        """
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1261
        return [strval for strval, val in self.vocabulary()]
58f11f7dad68 [range facet] closes #1806937: simply retrieve min/max values when computing vocabulary/possible_values, this is enough
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7627
diff changeset
  1262
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1263
    def get_widget(self):
4546
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4466
diff changeset
  1264
        """return the widget instance to use to display this facet"""
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1265
        values = set(value for _, value in self.vocabulary() if value is not None)
4615
d69d7ccbe046 Fix: RangeFacet is selected (valid rset) but without any values
Charles Hébert <charles.hebert@logilab.fr>
parents: 4614
diff changeset
  1266
        # Rset with entities (the facet is selected) but without values
7248
f20fc41e3f7d [facets] fix RangeFacet get_widget: do no return a widget unless there are at least 2 values; closes #1625203
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7235
diff changeset
  1267
        if len(values) < 2:
4615
d69d7ccbe046 Fix: RangeFacet is selected (valid rset) but without any values
Charles Hébert <charles.hebert@logilab.fr>
parents: 4614
diff changeset
  1268
            return None
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1269
        return self.wdgclass(self, min(values), max(values))
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1270
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1271
    def formatvalue(self, value):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1272
        """format `value` before in order to insert it in the RQL query"""
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1273
        return unicode(value)
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1274
7205
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1275
    def infvalue(self, min=False):
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1276
        if min:
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1277
            return self._cw.form.get('min_%s_inf' % self.__regid__)
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1278
        return self._cw.form.get('%s_inf' % self.__regid__)
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1279
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1280
    def supvalue(self, max=False):
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1281
        if max:
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1282
            return self._cw.form.get('max_%s_sup' % self.__regid__)
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1283
        return self._cw.form.get('%s_sup' % self.__regid__)
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1284
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1285
    def add_rql_restrictions(self):
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1286
        infvalue = self.infvalue()
7205
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1287
        supvalue = self.supvalue()
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1288
        if infvalue is None or supvalue is None: # nothing sent
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1289
            return
7205
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1290
        # when a value is equal to one of the limit, don't add the restriction,
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1291
        # else we filter out NULL values implicitly
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1292
        if infvalue != self.infvalue(min=True):
7607
d332ecfc224a [range facet] refactor to ease overriding, possible_values raise DontUpdateFacet (not handled by js actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7605
diff changeset
  1293
            self._add_restriction(infvalue, '>=')
7205
9220ae2cacf1 [facet] ignore range extremas to avoid filtering out rows where value is NULL (closes #1251192)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7204
diff changeset
  1294
        if supvalue != self.supvalue(max=True):
7607
d332ecfc224a [range facet] refactor to ease overriding, possible_values raise DontUpdateFacet (not handled by js actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7605
diff changeset
  1295
            self._add_restriction(supvalue, '<=')
d332ecfc224a [range facet] refactor to ease overriding, possible_values raise DontUpdateFacet (not handled by js actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7605
diff changeset
  1296
7615
e5ad51352eb3 [facet] fix argument inversion in date range facet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7609
diff changeset
  1297
    def _add_restriction(self, value, operator):
7607
d332ecfc224a [range facet] refactor to ease overriding, possible_values raise DontUpdateFacet (not handled by js actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7605
diff changeset
  1298
        self.select.add_constant_restriction(self.filtered_variable,
d332ecfc224a [range facet] refactor to ease overriding, possible_values raise DontUpdateFacet (not handled by js actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7605
diff changeset
  1299
                                             self.rtype,
d332ecfc224a [range facet] refactor to ease overriding, possible_values raise DontUpdateFacet (not handled by js actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7605
diff changeset
  1300
                                             self.formatvalue(value),
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1301
                                             self.target_attr_type, operator)
7607
d332ecfc224a [range facet] refactor to ease overriding, possible_values raise DontUpdateFacet (not handled by js actually)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7605
diff changeset
  1302
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1303
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1304
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1305
class DateRangeFacet(RangeFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1306
    """This class works similarly as the :class:`RangeFacet` but for attribute
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1307
    of date type.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1308
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1309
    The image below display the rendering of the slider for a date range:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1310
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1311
    .. image:: ../images/facet_date_range.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1312
    """
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1313
    target_attr_type = 'Date' # only date types are supported
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1314
7204
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1315
    @property
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1316
    def wdgclass(self):
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1317
        return DateFacetRangeWidget
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1318
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1319
    def formatvalue(self, value):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1320
        """format `value` before in order to insert it in the RQL query"""
7117
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1321
        try:
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1322
            date_value = ticks2datetime(float(value))
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1323
        except (ValueError, OverflowError):
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1324
            return u'"date out-of-range"'
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1325
        return '"%s"' % ustrftime(date_value, '%Y/%m/%d')
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1326
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1327
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1328
class HasRelationFacet(AbstractFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1329
    """This class simply filter according to the presence of a relation
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1330
    (whatever the entity at the other end). It display a simple checkbox that
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1331
    lets you refine your selection in order to get only entities that actually
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1332
    have this relation. You simply have to define which relation using the
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1333
    `rtype` and `role` attributes.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1334
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1335
    Here is an example of the rendering of thos facet to filter book with image
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1336
    and the corresponding code:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1337
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1338
    .. image:: ../images/facet_has_image.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1339
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1340
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1341
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1342
      class HasImageFacet(HasRelationFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1343
          __regid__ = 'hasimage'
6152
6824f8b61098 use is_instance in a number of places (esp. documentation) rather than the deprecated implements
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6120
diff changeset
  1344
          __select__ = HasRelationFacet.__select__ & is_instance('Book')
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1345
          rtype = 'has_image'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1346
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1347
    """
7280
571b29842ef1 [facet] add missing selector to HasRelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7279
diff changeset
  1348
    __select__ = partial_relation_possible() & match_context_prop()
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1349
    rtype = None # override me in subclass
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1350
    role = 'subject' # role of filtered entity in the relation
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1351
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
  1352
    title = property(rtype_facet_title)
7609
fbefd1b9e587 [facets] DontUpdateConstraint mecanism introduced a few commit ago isn't needed: we already have the 'needs_update' property controlling this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7608
diff changeset
  1353
    needs_update = False # not supported actually
7608
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
  1354
    support_and = False
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1355
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1356
    def get_widget(self):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1357
        return CheckBoxFacetWidget(self._cw, self,
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1358
                                   '%s:%s' % (self.rtype, self),
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1359
                                   self._cw.form.get(self.__regid__))
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1360
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1361
    def add_rql_restrictions(self):
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1362
        """add restriction for this facet into the rql syntax tree"""
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1363
        self.select.set_distinct(True) # XXX
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1364
        value = self._cw.form.get(self.__regid__)
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1365
        if not value: # no value sent for this facet
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1366
            return
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1367
        var = self.select.make_variable()
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1368
        if self.role == 'subject':
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1369
            self.select.add_relation(self.filtered_variable, self.rtype, var)
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1370
        else:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1371
            self.select.add_relation(var, self.rtype, self.filtered_variable)
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1372
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1373
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1374
class BitFieldFacet(AttributeFacet):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1375
    """Base facet class for Int field holding some bit values using binary
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1376
    masks.
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1377
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1378
    label / value for each bit should be given using the :attr:`choices`
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1379
    attribute.
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1380
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1381
    See also :class:`~cubicweb.web.formwidgets.BitSelect`.
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1382
    """
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1383
    choices = None # to be set on concret class
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1384
    def add_rql_restrictions(self):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1385
        value = self._cw.form.get(self.__regid__)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1386
        if not value:
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1387
            return
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1388
        if isinstance(value, list):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1389
            value = reduce(lambda x, y: int(x) | int(y), value)
8598
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1390
        else:
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1391
            value = int(value)
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1392
        attr_var = self.select.make_variable()
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1393
        self.select.add_relation(self.filtered_variable, self.rtype, attr_var)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1394
        comp = nodes.Comparison('=', nodes.Constant(value, 'Int'))
8598
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1395
        if value == 0:
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1396
            comp.append(nodes.variable_ref(attr_var))
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1397
        else:
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1398
            comp.append(nodes.MathExpression('&', nodes.variable_ref(attr_var),
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1399
                                             nodes.Constant(value, 'Int')))
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1400
        having = self.select.having
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1401
        if having:
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1402
            self.select.replace(having[0], nodes.And(having[0], comp))
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1403
        else:
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1404
            self.select.set_having([comp])
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1405
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1406
    def rset_vocabulary(self, rset):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1407
        mask = reduce(lambda x, y: x | (y[0] or 0), rset, 0)
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1408
        return sorted([(self._cw._(label), val) for label, val in self.choices
8598
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1409
                       if not val or val & mask])
8029
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1410
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1411
    def possible_values(self):
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1412
        return [unicode(val) for label, val in self.vocabulary()]
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1413
805d4e121b65 [ui lib] facet and form widget for Integer used to store binary mask. Closes #2054771
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7953
diff changeset
  1414
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1415
## html widets ################################################################
8104
71d9fb78b772 [facets] forcing a fixed height to the group is a bad idea: the container will not properly overflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8093
diff changeset
  1416
_DEFAULT_VOCAB_WIDGET_HEIGHT = 12
71d9fb78b772 [facets] forcing a fixed height to the group is a bad idea: the container will not properly overflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8093
diff changeset
  1417
_DEFAULT_FACET_GROUP_HEIGHT = 15
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1418
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
  1419
class FacetVocabularyWidget(htmlwidgets.HTMLWidget):
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
  1420
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1421
    def __init__(self, facet):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1422
        self.facet = facet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1423
        self.items = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1424
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1425
    @cachedproperty
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1426
    def css_overflow_limit(self):
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1427
        """ we try to deduce a number of displayed lines from a css property
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1428
        if we get another unit we're out of luck and resort to one constant
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1429
        hence, it is strongly advised not to specify but ems for this css prop
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1430
        """
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1431
        return css_em_num_value(self.facet._cw.vreg, 'facet_vocabMaxHeight',
8104
71d9fb78b772 [facets] forcing a fixed height to the group is a bad idea: the container will not properly overflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8093
diff changeset
  1432
                                _DEFAULT_VOCAB_WIDGET_HEIGHT)
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1433
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1434
    @cachedproperty
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1435
    def height(self):
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1436
        """ title, optional and/or dropdown, len(items) or upper limit """
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1437
        return (1.5 + # title + small magic constant
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1438
                int(self.facet._support_and_compat() +
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1439
                    min(len(self.items), self.css_overflow_limit)))
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1440
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1441
    @property
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1442
    @cached
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1443
    def overflows(self):
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1444
        return len(self.items) >= self.css_overflow_limit
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1445
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1446
    scrollbar_padding_factor = 4
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
  1447
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1448
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1449
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1450
        title = xml_escape(self.facet.title)
8859
6ed22ac7257c [facet] ensure a facet DOM id is a valid jQuery identifier. Closes #2789089
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8598
diff changeset
  1451
        facetid = domid(make_uid(self.facet.__regid__))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1452
        w(u'<div id="%s" class="facet">\n' % facetid)
8165
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1453
        cssclass = 'facetTitle'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1454
        if self.facet.allow_hide:
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1455
            cssclass += ' hideFacetBody'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1456
        w(u'<div class="%s" cubicweb:facetName="%s">%s</div>\n' %
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1457
          (cssclass, xml_escape(self.facet.__regid__), title))
7608
47311917a548 [facet] more api cleanup: support_and should be a property, so it's easier to deactivate.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7607
diff changeset
  1458
        if self.facet._support_and_compat():
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1459
            self._render_and_or(w)
8067
3841d8793efb [facets] reenable facet hiding (was lost in the previous refactoring)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8029
diff changeset
  1460
        cssclass = 'facetBody vocabularyFacet'
368
84a5106840fa facet widgets css cleanup
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 346
diff changeset
  1461
        if not self.facet.start_unfolded:
84a5106840fa facet widgets css cleanup
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 346
diff changeset
  1462
            cssclass += ' hidden'
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1463
        overflow = self.overflows
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1464
        if overflow:
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1465
            if self.facet._support_and_compat():
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1466
                cssclass += ' vocabularyFacetBodyWithLogicalSelector'
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1467
            else:
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1468
                cssclass += ' vocabularyFacetBody'
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1469
        w(u'<div class="%s">\n' % cssclass)
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1470
        for value, label, selected in self.items:
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1471
            if value is None:
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1472
                continue
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1473
            self._render_value(w, value, label, selected, overflow)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1474
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1475
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1476
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1477
    def _render_and_or(self, w):
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1478
        _ = self.facet._cw._
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1479
        w(u"""<select name='%s' class='radio facetOperator' title='%s'>
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1480
  <option value='OR'>%s</option>
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1481
  <option value='AND'>%s</option>
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1482
</select>""" % (xml_escape(self.facet.__regid__) + '_andor',
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1483
                _('and/or between different values'),
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1484
                _('OR'), _('AND')))
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1485
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1486
    def _render_value(self, w, value, label, selected, overflow):
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1487
        cssclass = 'facetValue facetCheckBox'
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1488
        if selected:
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1489
            cssclass += ' facetValueSelected'
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1490
        w(u'<div class="%s" cubicweb:value="%s">\n'
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1491
          % (cssclass, xml_escape(unicode(value))))
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1492
        # If it is overflowed one must add padding to compensate for the vertical
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1493
        # scrollbar; given current css values, 4 blanks work perfectly ...
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1494
        padding = u'&#160;' * self.scrollbar_padding_factor if overflow else u''
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1495
        w('<span>%s</span>' % xml_escape(label))
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1496
        w(padding)
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1497
        w(u'</div>')
467
a6f056bc7d1d [facets] AttributeFacet can now declare which kind of comparator they want to use, default is '=' (+ tidy trailing white spaces)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 446
diff changeset
  1498
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
  1499
class FacetStringWidget(htmlwidgets.HTMLWidget):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1500
    def __init__(self, facet):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1501
        self.facet = facet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1502
        self.value = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1503
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1504
    @property
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1505
    def height(self):
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1506
        return 2.5
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1507
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1508
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1509
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1510
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1511
        facetid = make_uid(self.facet.__regid__)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1512
        w(u'<div id="%s" class="facet">\n' % facetid)
8165
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1513
        cssclass = 'facetTitle'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1514
        if self.facet.allow_hide:
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1515
            cssclass += ' hideFacetBody'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1516
        w(u'<div class="%s" cubicweb:facetName="%s">%s</div>\n' %
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1517
               (cssclass, xml_escape(self.facet.__regid__), title))
9139
5ca6e0ab0227 [facet] use facet name as input name for text widget (eg has_text)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9135
diff changeset
  1518
        w(u'<input name="%s" type="text" value="%s" />\n' % (
5ca6e0ab0227 [facet] use facet name as input name for text widget (eg has_text)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9135
diff changeset
  1519
                xml_escape(self.facet.__regid__), self.value or u''))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1520
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1521
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1522
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
  1523
class FacetRangeWidget(htmlwidgets.HTMLWidget):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1524
    formatter = 'function (value) {return value;}'
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1525
    onload = u'''
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1526
    var _formatter = %(formatter)s;
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1527
    jQuery("#%(sliderid)s").slider({
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1528
        range: true,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1529
        min: %(minvalue)s,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1530
        max: %(maxvalue)s,
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1531
        values: [%(minvalue)s, %(maxvalue)s],
1933
f40ee76ecdf1 [facet][RangeFacet] submit facet form when the user stops sliding
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1896
diff changeset
  1532
        stop: function(event, ui) { // submit when the user stops sliding
f40ee76ecdf1 [facet][RangeFacet] submit facet form when the user stops sliding
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1896
diff changeset
  1533
           var form = $('#%(sliderid)s').closest('form');
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1534
           buildRQL.apply(null, cw.evalJSON(form.attr('cubicweb:facetargs')));
1933
f40ee76ecdf1 [facet][RangeFacet] submit facet form when the user stops sliding
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1896
diff changeset
  1535
        },
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1536
        slide: function(event, ui) {
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1537
            jQuery('#%(sliderid)s_inf').html(_formatter(ui.values[0]));
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1538
            jQuery('#%(sliderid)s_sup').html(_formatter(ui.values[1]));
7627
b837c1ca5009 [facet slider] quote attribute value, else may break with earlier jquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7626
diff changeset
  1539
            jQuery('input[name="%(facetname)s_inf"]').val(ui.values[0]);
b837c1ca5009 [facet slider] quote attribute value, else may break with earlier jquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7626
diff changeset
  1540
            jQuery('input[name="%(facetname)s_sup"]').val(ui.values[1]);
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1541
        }
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1542
   });
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1543
   // use JS formatter to format value on page load
7627
b837c1ca5009 [facet slider] quote attribute value, else may break with earlier jquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7626
diff changeset
  1544
   jQuery('#%(sliderid)s_inf').html(_formatter(jQuery('input[name="%(facetname)s_inf"]').val()));
b837c1ca5009 [facet slider] quote attribute value, else may break with earlier jquery
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7626
diff changeset
  1545
   jQuery('#%(sliderid)s_sup').html(_formatter(jQuery('input[name="%(facetname)s_sup"]').val()));
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1546
'''
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1547
    #'# make emacs happier
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1548
    def __init__(self, facet, minvalue, maxvalue):
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1549
        self.facet = facet
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1550
        self.minvalue = minvalue
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1551
        self.maxvalue = maxvalue
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1552
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1553
    @property
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1554
    def height(self):
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1555
        return 2.5
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1556
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1557
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1558
        w = self.w
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1559
        facet = self.facet
7233
614f23606091 [js/css] remove old versions of ui.tabs/slider etc.; closes #1625085
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7205
diff changeset
  1560
        facet._cw.add_js('jquery.ui.js')
614f23606091 [js/css] remove old versions of ui.tabs/slider etc.; closes #1625085
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7205
diff changeset
  1561
        facet._cw.add_css('jquery.ui.css')
3333
c61a526b530e [widgets] change make_uid() seed to make slider ids xhtml-valid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3329
diff changeset
  1562
        sliderid = make_uid('theslider')
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1563
        facetname = self.facet.__regid__
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1564
        facetid = make_uid(facetname)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1565
        facet._cw.html_headers.add_onload(self.onload % {
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1566
            'sliderid': sliderid,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1567
            'facetid': facetid,
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1568
            'facetname': facetname,
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1569
            'minvalue': self.minvalue,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1570
            'maxvalue': self.maxvalue,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1571
            'formatter': self.formatter,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1572
            })
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1573
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1574
        facetname = xml_escape(facetname)
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1575
        w(u'<div id="%s" class="facet rangeFacet">\n' % facetid)
8165
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1576
        cssclass = 'facetTitle'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1577
        if facet.allow_hide:
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1578
            cssclass += ' hideFacetBody'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1579
        w(u'<div class="%s" cubicweb:facetName="%s">%s</div>\n' %
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1580
          (cssclass, facetname, title))
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1581
        cssclass = 'facetBody'
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1582
        if not self.facet.start_unfolded:
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1583
            cssclass += ' hidden'
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1584
        w(u'<div class="%s">\n' % cssclass)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1585
        w(u'<span id="%s_inf"></span> - <span id="%s_sup"></span>'
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1586
          % (sliderid, sliderid))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1587
        w(u'<input type="hidden" name="%s_inf" value="%s" />'
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1588
          % (facetname, self.minvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1589
        w(u'<input type="hidden" name="%s_sup" value="%s" />'
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1590
          % (facetname, self.maxvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1591
        w(u'<input type="hidden" name="min_%s_inf" value="%s" />'
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1592
          % (facetname, self.minvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1593
        w(u'<input type="hidden" name="max_%s_sup" value="%s" />'
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1594
          % (facetname, self.maxvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1595
        w(u'<div id="%s"></div>' % sliderid)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1596
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1597
        w(u'</div>\n')
1896
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1598
8182746170c6 work in progress: new 'range facet' usable for numerical values, still lacks the form.submit on mouseUp
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1433
diff changeset
  1599
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1600
class DateFacetRangeWidget(FacetRangeWidget):
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1601
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1602
    formatter = 'function (value) {return (new Date(parseFloat(value))).strftime(DATE_FMT);}'
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1603
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1604
    def round_max_value(self, d):
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1605
        'round to upper value to avoid filtering out the max value'
2152
Florent <florent@secondweb.fr>
parents: 2149
diff changeset
  1606
        return datetime(d.year, d.month, d.day) + timedelta(days=1)
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1607
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1608
    def __init__(self, facet, minvalue, maxvalue):
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1609
        maxvalue = self.round_max_value(maxvalue)
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1610
        super(DateFacetRangeWidget, self).__init__(facet,
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1611
                                                   datetime2ticks(minvalue),
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1612
                                                   datetime2ticks(maxvalue))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1613
        fmt = facet._cw.property_value('ui.date-format')
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1614
        facet._cw.html_headers.define_var('DATE_FMT', fmt)
2010
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1615
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1616
7768
bd44f506ca86 closes #1914824: fix retrieval of _andor input, test and fix generated rql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7678
diff changeset
  1617
class CheckBoxFacetWidget(htmlwidgets.HTMLWidget):
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1618
    selected_img = "black-check.png"
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1619
    unselected_img = "black-uncheck.png"
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1620
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1621
    def __init__(self, req, facet, value, selected):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1622
        self._cw = req
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1623
        self.facet = facet
2016
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1624
        self.value = value
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1625
        self.selected = selected
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1626
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1627
    @property
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1628
    def height(self):
8093
3efb83e4e8f3 [facets] do no stretch to the right when there are many facets; instead use a floating layout (closes #2093160)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8067
diff changeset
  1629
        return 1.5
7402
826e5663a686 [facets/table] vertically group facets by two when possible in order to have a more compact horizontal layout in table filter form
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7280
diff changeset
  1630
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1631
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1632
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1633
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1634
        facetid = make_uid(self.facet.__regid__)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1635
        w(u'<div id="%s" class="facet">\n' % facetid)
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1636
        cssclass = 'facetValue facetCheckBox'
2016
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1637
        if self.selected:
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1638
            cssclass += ' facetValueSelected'
7070
5f8e52d722c5 [web] provide a data_url() method on req and get_rid of explicit datadir_url usage (#1438736)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6681
diff changeset
  1639
            imgsrc = self._cw.data_url(self.selected_img)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1640
            imgalt = self._cw._('selected')
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1641
        else:
7070
5f8e52d722c5 [web] provide a data_url() method on req and get_rid of explicit datadir_url usage (#1438736)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6681
diff changeset
  1642
            imgsrc = self._cw.data_url(self.unselected_img)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1643
            imgalt = self._cw._('not selected')
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1644
        w(u'<div class="%s" cubicweb:value="%s">\n'
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1645
          % (cssclass, xml_escape(unicode(self.value))))
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1646
        w(u'<div>')
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1647
        w(u'<img src="%s" alt="%s" cubicweb:unselimg="true" />&#160;' % (imgsrc, imgalt))
7943
ad0581296e2c [facets] try to get rid of arbitrary constants, be prettier and eat less space (closes #1988706)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7879
diff changeset
  1648
        w(u'<label class="facetTitle" cubicweb:facetName="%s">%s</label>'
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1649
          % (xml_escape(self.facet.__regid__), title))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1650
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1651
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1652
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1653
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1654
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1655
# other classes ################################################################
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1656
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1657
class FilterRQLBuilder(object):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1658
    """called by javascript to get a rql string from filter form"""
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1659
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1660
    def __init__(self, req):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1661
        self._cw = req
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1662
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1663
    def build_rql(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1664
        form = self._cw.form
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1665
        facetids = form['facets'].split(',')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1666
        # XXX Union unsupported yet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1667
        select = self._cw.vreg.parse(self._cw, form['baserql']).children[0]
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1668
        filtered_variable = get_filtered_variable(select, form.get('mainvar'))
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1669
        toupdate = []
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1670
        for facetid in facetids:
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
  1671
            facet = get_facet(self._cw, facetid, select, filtered_variable)
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1672
            facet.add_rql_restrictions()
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1673
            if facet.needs_update:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1674
                toupdate.append(facetid)
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1675
        return select.as_string(), toupdate