web/facet.py
author Alain Leufroy <alain.leufroy@logilab.fr>
Tue, 03 Jun 2014 12:37:54 +0200
changeset 9886 1b26289217a3
parent 9562 0509880fec01
child 9892 928732ec00dd
child 9984 793377697c81
permissions -rw-r--r--
[devtools] improve error message when postgresql tools are missing By default in at least Debian, some pg tools are not present in the PATH. Or they may not be installed. But the tests tools expects them to be in the PATH, and give an unhelpful 'No such file or directory' backtrace if they're not found. To help devs using the pg tests we improve the error message.
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
9562
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
    37
.. autoclass:: cubicweb.web.facet.AbstractRangeRQLPathFacet
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
    38
.. autoclass:: cubicweb.web.facet.RangeRQLPathFacet
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
    39
.. autoclass:: cubicweb.web.facet.DateRangeRQLPathFacet
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    40
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    41
Classes for facets implementor
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
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
    44
to skip those classes...
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
.. autoclass:: cubicweb.web.facet.AbstractFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    47
.. autoclass:: cubicweb.web.facet.VocabularyFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    48
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    49
.. 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
    50
"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
__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
    53
_ = unicode
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
8719
539ed3fb27cb [towards py3k] import reduce() from functools (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8696
diff changeset
    55
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
    56
from warnings import warn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
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
    58
from datetime import datetime, timedelta
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
    60
from logilab.mtconverter import xml_escape
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
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
    62
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
    63
from logilab.common.date import datetime2ticks, ustrftime, ticks2datetime
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
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
    65
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
    66
from logilab.common.registry import yes
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
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
    68
from rql import nodes, utils
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
8748
f5027f8d2478 drop typed_eid() in favour of int() (closes #2742462)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8719
diff changeset
    70
from cubicweb import Unauthorized
2305
8f6dbe884700 import display_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2152
diff changeset
    71
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
    72
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
    73
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
    74
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
    75
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
    76
from cubicweb.web import RequestError, htmlwidgets
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    78
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    79
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
    80
    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
    81
        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
    82
        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
    83
            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
    84
                                context=iter(ptypes).next())
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    85
    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
    86
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
    87
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
    88
    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
    89
                                           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
    90
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
@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
    92
            '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
    93
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
    94
    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
    95
    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
    96
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
    97
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
## rqlst manipulation functions used by facets ################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    99
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
   100
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
   101
    """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
   102
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   103
    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
   104
    :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
   105
    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
   106
    details.
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 rset: ResultSet we init facet for.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   109
    :type rset: :class:`~cubicweb.rset.ResultSet`
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 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
   112
    :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
   113
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   114
    :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
   115
    :type mainvar:  string
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   116
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   117
    :rtype: (filtered_variable, baserql) tuple.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   118
    :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
   119
                                instance as returned by
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   120
                                :func:`get_filtered_variable`.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   121
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   122
    :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
   123
                     :func:`prepare_select` but after
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   124
                     :func:`get_filtered_variable`.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   125
    """
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
   126
    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
   127
    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
   128
    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
   129
    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
   130
    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
   131
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
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
   133
    """ 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
   134
    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
   135
    """
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
    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
   137
        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
   138
        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
   139
    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
   140
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
   141
def prepare_select(select, filtered_variable):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
    """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
   143
7601
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   144
    * remove ORDERBY/GROUPBY clauses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
    * cleanup selection (remove everything)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
    * undefine unnecessary variables
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
    * 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
   148
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
   149
    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
   150
    :func:`get_filtered_variable`.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
    """
7601
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   152
    # cleanup sort terms / group by
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    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
   154
    select.remove_groups()
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   155
    # XXX remove aggregat from having
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    # selection: only vocabulary entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    for term in select.selection[:]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
        select.remove_selected(term)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
    # 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
   160
    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
   161
        if not (dvar is filtered_variable or dvar.stinfo['relations']):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   162
            select.undefine_variable(dvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   163
    # global tree config: DISTINCT, LIMIT, OFFSET
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
    select.set_distinct(True)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
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
   166
@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
   167
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
   168
    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
   169
    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
   170
    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
   171
    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
   172
    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
   173
    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
   174
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
   175
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
   176
                              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
   177
    """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
   178
    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
   179
    * 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
   180
    * 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
   181
    * 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
   182
    * 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
   183
    """
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
   184
    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
   185
    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
   186
        # 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
   187
        #     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
   188
        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
   189
    # 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
   190
    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
   191
        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
   192
        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
   193
    return newvar
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
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
   196
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
   197
                                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
   198
                                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
   199
    """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
   200
    * 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
   201
    * 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
   202
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
    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
   204
    * 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
   205
    * 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
   206
    * 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
   207
    """
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
    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
   209
    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
   210
                                   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
   211
    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
   212
    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
   213
    # 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
   214
    #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
   215
    #    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
   216
    #        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
   217
    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
   218
        _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
   219
    # 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
   220
    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
   221
    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
   222
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
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
   224
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
   225
    """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
   226
    * 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
   227
    * 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
   228
    * 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
   229
    """
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
   230
    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
   231
        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
   232
    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
   233
    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
   234
    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
   235
    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
   236
        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
   237
        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
   238
            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
   239
    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
   240
    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
   241
        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
   242
        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
   243
        # 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
   244
        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
   245
        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
   246
            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
   247
        # 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
   248
        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
   249
            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
   250
                # 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
   251
                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
   252
            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
   253
            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
   254
        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
   255
        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
   256
            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
   257
            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
   258
        # 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
   259
        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
   260
            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
   261
                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
   262
                    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
   263
        # 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
   264
        # 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
   265
        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
   266
            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
   267
                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
   268
            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
   269
                toremove.add(select.defined_vars[ovarname])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
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
   272
def _may_be_removed(rel, schema, variable):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
    """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
   274
    on the other side of `variable`, else return None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
    Conditions:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
    * the relation is an attribute selection of the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   277
    * the relation is optional relation linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   278
    * the relation is a mandatory relation linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
      without any restriction on the other variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
    lhs, rhs = rel.get_variable_parts()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
    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
   283
    if lhs.variable is variable:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   285
            ovar = rhs.variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
        except AttributeError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
            # constant restriction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   288
            # XXX: X title LOWER(T) if it makes sense?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   289
            return None
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3333
diff changeset
   290
        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
   291
            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
   292
                   and not ovar.stinfo.get('having'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
                # attribute selection
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
                return ovar
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
        opt = 'right'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
        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
   298
    elif getattr(rhs, 'variable', None) is variable:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
        ovar = lhs.variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
        opt = 'left'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   301
        cardidx = 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
        # not directly linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
        return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
    if rel.optional in (opt, 'both'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
        # optional relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
        return ovar
4073
03681ba6da0b cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3720
diff changeset
   308
    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
   309
           for rdef in rschema.rdefs.itervalues()):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
        # mandatory relation without any restriction on the other variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
        for orel in ovar.stinfo['relations']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
            if rel is orel:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   313
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
            if _may_be_removed(orel, schema, ovar) is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
        return ovar
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   317
    return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
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
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
   320
    newvar = select.make_variable()
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   321
    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
   322
        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
   323
    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
   324
        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
   325
    return newvar, rel
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   326
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
   327
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
   328
    """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
   329
    relation (where `variable` has `role`)
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   330
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   331
    return the inserted variable for linked entities.
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   332
    """
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
   333
    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
   334
    select.add_restriction(newrel)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   335
    return newvar, newrel
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   336
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
def _remove_relation(select, rel, var):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
    """remove a constraint relation from the syntax tree"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
    # 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
   340
    select.remove_node(rel)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
    # remove relations where the filtered variable appears on the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
    # lhs and rhs is a constant restriction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
    extra = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
    for vrel in var.stinfo['relations']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
        if vrel is rel:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
            continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
        if vrel.children[0].variable is var:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
            if not vrel.children[1].get_nodes(nodes.Constant):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
                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
   350
            select.remove_node(vrel)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
    return extra
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
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
   353
def _set_orderby(select, newvar, sortasc, sortfuncname):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
    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
   355
        select.add_sort_var(newvar, sortasc)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
        vref = nodes.variable_ref(newvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   358
        vref.register_reference()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
        sortfunc = nodes.Function(sortfuncname)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
        sortfunc.append(vref)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
        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
   362
        select.add_sort_term(term)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   364
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
   365
    try:
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 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
   367
    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
   368
        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
   369
        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
   370
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
   371
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
   372
_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
   373
    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
   374
_cleanup_rqlst = deprecated('[3.13] renamed to cleanup_select')(cleanup_select)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   375
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
   376
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   377
## 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
   378
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   379
class AbstractFacet(AppObject):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   380
    """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
   381
    '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
   382
    the following configurable properties:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   383
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   384
    * `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
   385
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   386
    * `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
   387
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   388
    * `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
   389
      (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
   390
      both (context = '')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   391
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   392
    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
   393
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   394
    .. 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
   395
    .. 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
   396
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   397
    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
   398
    :class:`~cubicweb.appobject.AppObject` ones):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   399
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
   400
    * `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
   401
      filtered
6120
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
    * `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
   404
      interested in filtering
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   405
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   406
    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
   407
    methods:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   408
7632
3c9dfc6e820b [book] fix some rest/sphinx errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7629
diff changeset
   409
    .. 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
   410
    .. automethod:: cubicweb.web.facet.AbstractFacet.rqlexec
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   411
    """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   412
    __abstract__ = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   413
    __registry__ = 'facets'
2799
b703639614e7 refactor property handling to avoid name conflicts
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2770
diff changeset
   414
    cw_property_defs = {
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   415
        _('visible'): dict(type='Boolean', default=True,
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   416
                           help=_('display the facet or not')),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
        _('order'):   dict(type='Int', default=99,
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   418
                           help=_('display order of the facet')),
496
e25a3c2f5393 set default to empty string, not None
sylvain.thenault@logilab.fr
parents: 467
diff changeset
   419
        _('context'): dict(type='String', default='',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
                           # 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
   421
                           vocabulary=(_('tablefilter'), _('facetbox'), ''),
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   422
                           help=_('context where this facet should be displayed, '
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   423
                                  'leave empty for both')),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   424
        }
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   425
    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
   426
    context = ''
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   427
    needs_update = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   428
    start_unfolded = True
8165
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
   429
    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
   430
    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
   431
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
    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
   433
                 **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
   434
        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
   435
        assert select is not None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
        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
   437
        # 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
   438
        # 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
   439
        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
   440
        self.filtered_variable = filtered_variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
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
   442
    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
   443
        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
   444
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   445
    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
   446
        """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
   447
        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
   448
        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
   449
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   450
        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
   451
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   452
    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
   453
        """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
   454
        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
   455
        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
   456
        (`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
   457
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   458
        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
   459
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   460
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   461
    def operator(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   462
        """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
   463
        values are selected.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   464
        """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   465
        # 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
   466
        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
   467
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   468
    def rqlexec(self, rql, args=None):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   469
        """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
   470
        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
   471
        """
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   472
        try:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   473
            return self._cw.execute(rql, args)
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   474
        except Unauthorized:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   475
            return []
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   476
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
   477
    @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
   478
    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
   479
        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
   480
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
   481
    @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
   482
    @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
   483
    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
   484
        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
   485
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   486
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   487
class VocabularyFacet(AbstractFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   488
    """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
   489
    :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
   490
    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
   491
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   492
    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
   493
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   494
    .. automethod:: cubicweb.web.facet.VocabularyFacet.vocabulary
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   495
    .. 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
   496
    """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   497
    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
   498
    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
   499
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
   500
    @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
   501
    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
   502
        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
   503
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
   504
    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
   505
        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
   506
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   507
    def get_widget(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   508
        """Return the widget instance to use to display this facet.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   510
        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
   511
        return a combobox displaying this vocabulary.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
        vocab = self.vocabulary()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   514
        if len(vocab) <= 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
            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
   516
        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
   517
        selected = self.get_selected()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   518
        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
   519
            wdg.items.append((value, label, value in selected))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   520
        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
   521
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   522
    def vocabulary(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   523
        """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
   524
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   525
        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
   526
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   527
    def possible_values(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   528
        """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
   529
        compare to a form value in javascript) for this facet.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   530
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   531
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   532
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
   533
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
class RelationFacet(VocabularyFacet):
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   535
    """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
   536
    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
   537
    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
   538
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   539
    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
   540
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   541
    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
   542
    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
   543
    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
   544
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   545
    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
   546
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   547
    * 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
   548
    * 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
   549
    * 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
   550
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   551
    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
   552
    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
   553
    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
   554
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   555
    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
   556
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   557
    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
   558
    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
   559
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   560
    * `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
   561
      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
   562
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   563
    * `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
   564
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   565
    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
   566
    of an office location search application:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   567
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   568
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   569
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   570
      class Office(WorkflowableEntityType):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   571
          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
   572
          surface = Int(description='m2')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   573
          has_address = SubjectRelation('PostalAddress',
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   574
                                        cardinality='1?',
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   575
                                        composite='subject')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   576
          proposed_by = SubjectRelation('Agency')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   577
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
    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
   580
    proposing it:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   581
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   582
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   583
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   584
      class AgencyFacet(RelationFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   585
          __regid__ = 'agency'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   586
          # 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
   587
          __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
   588
          # 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
   589
          # 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
   590
          # of the relation
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   591
          rtype = 'has_address'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   592
          # '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
   593
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   594
          # 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
   595
          target_attr = 'name'
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   596
    """
838
f2c56312b03a rename abstract_* selectors into partial_* + add docstrings
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 782
diff changeset
   597
    __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
   598
    # class attributes to configure the relation facet
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
    rtype = None
1433
091ac3ba5d51 remove trailing white spaces
sylvain.thenault@logilab.fr
parents: 1432
diff changeset
   600
    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
   601
    target_type = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   602
    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
   603
    # 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
   604
    # RelationFacet
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   605
    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
   606
    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
   607
    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
   608
    comparator = '=' # could be '<', '<=', '>', '>='
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   609
    # 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
   610
    # this function's result instead of direct value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   611
    sortfunc = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   612
    # ascendant/descendant sorting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   613
    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
   614
    # 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
   615
    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
   616
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   617
    # internal purpose
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   618
    _select_target_entity = True
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   619
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
   620
    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
   621
    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
   622
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
   623
    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
   624
        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
   625
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
    # 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
   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
    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
   629
        """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
   630
        """
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
        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
   632
        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
   633
        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
   634
            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
   635
        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
   636
            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
   637
        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
   638
            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
   639
                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
   640
                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
   641
                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
   642
            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
   643
                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
   644
            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
   645
                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
   646
            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
   647
                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
   648
                               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
   649
                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
   650
        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
   651
            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
   652
        # 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
   653
        # *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
   654
        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
   655
        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
   656
            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
   657
        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
   658
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
    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
   660
        """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
   661
        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
   662
        """
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
        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
   664
        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
   665
        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
   666
            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
   667
            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
   668
                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
   669
                                         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
   670
            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
   671
                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
   672
                    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
   673
                    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
   674
            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
   675
        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
   676
            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
   677
            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
   678
        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
   679
            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
   680
        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
   681
            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
   682
        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
   683
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
    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
   685
        """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
   686
        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
   687
        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
   688
            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
   689
        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
   690
        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
   691
                                            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
   692
        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
   693
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
   694
    # 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
   695
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   696
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   697
    def i18nable(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   698
        """should label be internationalized"""
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   699
        if self.target_type:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   700
            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
   701
        elif self.role == 'subject':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   702
            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
   703
        else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   704
            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
   705
        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
   706
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   707
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   708
    def no_relation(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   709
        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
   710
                and self._search_card('?*'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   711
6251
afc757568492 [facet] add missing @property making subsequent access always true
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6152
diff changeset
   712
    @property
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   713
    def rql_sort(self):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   714
        """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
   715
        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
   716
        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
   717
        """
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   718
        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
   719
                                             and not self.i18nable)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   720
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   721
    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
   722
        if self.i18nable:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
   723
            _ = self._cw._
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   724
        else:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   725
            _ = unicode
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   726
        if self.rql_sort:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   727
            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
   728
        else:
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   729
            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
   730
                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
   731
            else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   732
                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
   733
                          for entity in rset.entities()]
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   734
            values = sorted(values)
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   735
            if not self.sortasc:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   736
                values = list(reversed(values))
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   737
        return values
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   738
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
   739
    @property
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   740
    def support_and(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   741
        return self._search_card('+*')
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   742
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
   743
    # 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
   744
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
   745
    @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
   746
    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
   747
        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
   748
        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
   749
            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
   750
                 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
   751
            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
   752
        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
   753
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
   754
    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
   755
        # 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
   756
        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
   757
            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
   758
        if isinstance(value, basestring):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   759
            # only one value selected
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   760
            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
   761
                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
   762
                    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
   763
                    self.restr_attr_type)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   764
            else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   765
                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
   766
        elif self.operator == 'OR':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   767
            # 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
   768
            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
   769
                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
   770
            # 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
   771
            if '' in value:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   772
                value.remove('')
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   773
                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
   774
            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
   775
        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
   776
            # 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
   777
            # "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
   778
            # 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
   779
            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
   780
                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
   781
            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
   782
            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
   783
                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
   784
                                                 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
   785
                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
   786
                    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
   787
                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
   788
                    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
   789
                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
   790
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   791
    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
   792
        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
   793
            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
   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
        else:
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   796
            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
   797
                                                   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
   798
            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
   799
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   800
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
    @cached
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   802
    def _search_card(self, cards):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   803
        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
   804
            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
   805
                return True
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   806
        return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   807
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   808
    def _iter_rdefs(self):
3456
1a63a252601f [facets] typo fix
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3451
diff changeset
   809
        rschema = self._cw.vreg.schema.rschema(self.rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   810
        # 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
   811
        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
   812
        for rdef in rschema.rdefs.itervalues():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   813
            if possibletypes is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   814
                if self.role == 'subject':
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   815
                    if rdef.subject not in possibletypes:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   816
                        continue
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   817
                elif rdef.object not in possibletypes:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   818
                    continue
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   819
            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
   820
                if self.role == 'subject':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   821
                    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
   822
                        continue
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   823
                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
   824
                    continue
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   825
            yield rdef
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   826
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   827
    def _include_no_relation(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   828
        if not self.no_relation:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   829
            return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   830
        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
   831
            return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   832
        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
   833
            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
   834
                                      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
   835
            obj = self.filtered_variable.name
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   836
        else:
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   837
            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
   838
            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
   839
                                     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
   840
        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
   841
        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
   842
            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
   843
        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
   844
            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
   845
                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
   846
        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
   847
            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
   848
        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
   849
            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
   850
        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
   851
            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
   852
        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
   853
            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
   854
        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
   855
            # 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
   856
            # 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
   857
            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
   858
            return False
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   859
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   860
    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
   861
        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
   862
                                         self.rtype, self.role)[1])
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   863
        rel.parent.replace(rel, nodes.Or(nrrel, rel))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   864
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   866
class RelationAttributeFacet(RelationFacet):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   867
    """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
   868
    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
   869
    :class:`RelationFacet`, except that:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   870
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   871
    * `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
   872
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   873
    * 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
   874
      String
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   875
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   876
    * 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
   877
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   878
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   879
    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
   880
    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
   881
    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
   882
    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
   883
    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
   884
    users won't understand that...
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   885
9492
c7fc56eecd1a English typography
Dimitri Papadopoulos <dimitri.papadopoulos@cea.fr>
parents: 9373
diff changeset
   886
    That's where this class come in! It's used to said that you want to filter
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   887
    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
   888
    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
   889
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   890
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   891
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   892
      class PostalCodeFacet(RelationAttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   893
          __regid__ = 'postalcode'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   894
          # 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
   895
          __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
   896
          # 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
   897
          # 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
   898
          # subject of the relation
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   899
          rtype = 'has_address'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   900
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   901
          # 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
   902
          target_attr = 'postalcode'
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   903
    """
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   904
    _select_target_entity = False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   905
    # 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
   906
    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
   907
    # 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
   908
    comparator = '=' # could be '<', '<=', '>', '>='
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   909
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   910
    @property
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   911
    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
   912
        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
   913
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   914
    @property
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   915
    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
   916
        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
   917
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   918
    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
   919
        if self.i18nable:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   920
            _ = self._cw._
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   921
        else:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   922
            _ = unicode
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   923
        if self.rql_sort:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   924
            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
   925
        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
   926
        if self.sortasc:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   927
            return sorted(values)
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   928
        return reversed(sorted(values))
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   929
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   930
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   931
class AttributeFacet(RelationAttributeFacet):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   932
    """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
   933
    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
   934
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   935
    * `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
   936
    * `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
   937
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   938
    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
   939
    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
   940
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   941
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   942
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   943
      class SurfaceFacet(AttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   944
          __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
   945
          __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
   946
          # 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
   947
          rtype = 'surface'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   948
          # 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
   949
          # 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
   950
          comparator = '>='
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   951
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   952
          def vocabulary(self):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   953
              '''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
   954
              hard-code our threshold values.
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
              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
   957
              surfaces defined in the database.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   958
              '''
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   959
              return [('> 200', '200'), ('> 250', '250'),
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   960
                      ('> 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
   961
    """
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   962
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
   963
    support_and = False
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   964
    _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
   965
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   966
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   967
    def i18nable(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   968
        """should label be internationalized"""
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   969
        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
   970
            # 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
   971
            # String
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   972
            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
   973
                return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   974
        return True
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   975
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   976
    def vocabulary(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   977
        """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
   978
        """
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
        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
   980
        select.save_state()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   981
        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
   982
            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
   983
            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
   984
            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
   985
            _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
   986
            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
   987
                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
   988
            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
   989
                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
   990
            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
   991
                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
   992
            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
   993
                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
   994
                               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
   995
                return ()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   996
        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
   997
            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
   998
        # 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
   999
        # *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
  1000
        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
  1001
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1002
    def add_rql_restrictions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1003
        """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
  1004
        value = self._cw.form.get(self.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1005
        if not value:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1006
            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
  1007
        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
  1008
        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
  1009
                                            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
  1010
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1011
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1012
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
  1013
    """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
  1014
    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
  1015
    '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
  1016
    `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
  1017
    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
  1018
    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
  1019
    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
  1020
    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
  1021
    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
  1022
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1023
    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
  1024
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1025
    .. 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
  1026
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1027
      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
  1028
          __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
  1029
          # 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
  1030
          __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
  1031
          # 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
  1032
          # 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
  1033
          # 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
  1034
          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
  1035
          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
  1036
          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
  1037
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1038
      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
  1039
          __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
  1040
          # 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
  1041
          __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
  1042
          # 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
  1043
          # 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
  1044
          # 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
  1045
          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
  1046
          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
  1047
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1048
    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
  1049
    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
  1050
    :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
  1051
    (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
  1052
    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
  1053
    """
7874
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1054
    __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
  1055
    # 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
  1056
    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
  1057
    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
  1058
    # 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
  1059
    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
  1060
    # 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
  1061
    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
  1062
    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
  1063
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1064
    # 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
  1065
    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
  1066
    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
  1067
    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
  1068
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1069
    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
  1070
        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
  1071
        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
  1072
            ('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
  1073
             '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
  1074
        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
  1075
            '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
  1076
        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
  1077
            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
  1078
                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
  1079
            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
  1080
                   '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
  1081
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1082
    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
  1083
        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
  1084
                            ','.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
  1085
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1086
    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
  1087
        """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
  1088
        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
  1089
        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
  1090
        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
  1091
            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
  1092
        else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1093
            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
  1094
        try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1095
            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
  1096
            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
  1097
            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
  1098
            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
  1099
                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
  1100
            else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1101
                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
  1102
            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
  1103
            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
  1104
                _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
  1105
            try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1106
                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
  1107
            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
  1108
                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
  1109
                               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
  1110
                return ()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1111
        finally:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1112
            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
  1113
        # 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
  1114
        # *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
  1115
        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
  1116
        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
  1117
            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
  1118
        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
  1119
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1120
    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
  1121
        """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
  1122
        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
  1123
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1124
        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
  1125
        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
  1126
        try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1127
            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
  1128
            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
  1129
            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
  1130
            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
  1131
        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
  1132
            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
  1133
            return []
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1134
        finally:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1135
            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
  1136
        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
  1137
            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
  1138
        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
  1139
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1140
    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
  1141
        """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
  1142
        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
  1143
        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
  1144
            return
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1145
        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
  1146
            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
  1147
        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
  1148
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1149
    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
  1150
        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
  1151
        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
  1152
        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
  1153
            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
  1154
                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
  1155
            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
  1156
            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
  1157
                continue
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1158
            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
  1159
                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
  1160
                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
  1161
                    # 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
  1162
                    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
  1163
                        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
  1164
                    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
  1165
                        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
  1166
                        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
  1167
                            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
  1168
                                            % (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
  1169
                        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
  1170
                    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
  1171
                        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
  1172
                        continue
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1173
            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
  1174
            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
  1175
            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
  1176
                                      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
  1177
            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
  1178
        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
  1179
            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
  1180
        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
  1181
            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
  1182
        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
  1183
            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
  1184
        else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1185
            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
  1186
        return varmap, restrvar
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1187
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1188
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1189
class RangeFacet(AttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1190
    """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
  1191
    numerical type.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1192
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1193
    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
  1194
    bound.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1195
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1196
    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
  1197
    in a more powerful way since
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
    * 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
  1200
    * 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
  1201
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1202
    .. 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
  1203
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1204
      class SurfaceFacet(RangeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1205
          __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
  1206
          __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
  1207
          # 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
  1208
          rtype = 'surface'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1209
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1210
    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
  1211
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1212
    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
  1213
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1214
    .. image:: ../images/facet_range.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1215
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1216
    .. _jquery: http://www.jqueryui.com/
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1217
    """
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1218
    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
  1219
    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
  1220
7204
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1221
    @property
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1222
    def wdgclass(self):
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1223
        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
  1224
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
  1225
    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
  1226
        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
  1227
        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
  1228
        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
  1229
            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
  1230
            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
  1231
            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
  1232
            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
  1233
            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
  1234
            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
  1235
            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
  1236
            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
  1237
            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
  1238
            # 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
  1239
            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
  1240
                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
  1241
                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
  1242
            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
  1243
                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
  1244
            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
  1245
                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
  1246
                               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
  1247
                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
  1248
        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
  1249
            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
  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
    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
  1252
        """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
  1253
        """
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
        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
  1255
        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
  1256
            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
  1257
            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
  1258
        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
  1259
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
    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
  1261
        """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
  1262
        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
  1263
        """
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
  1264
        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
  1265
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
  1266
    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
  1267
        """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
  1268
        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
  1269
        # 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
  1270
        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
  1271
            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
  1272
        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
  1273
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
    def formatvalue(self, value):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1275
        """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
  1276
        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
  1277
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
  1278
    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
  1279
        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
  1280
            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
  1281
        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
  1282
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
    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
  1284
        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
  1285
            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
  1286
        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
  1287
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
  1288
    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
  1289
        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
  1290
        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
  1291
        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
  1292
            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
  1293
        # 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
  1294
        # 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
  1295
        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
  1296
            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
  1297
        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
  1298
            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
  1299
7615
e5ad51352eb3 [facet] fix argument inversion in date range facet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7609
diff changeset
  1300
    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
  1301
        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
  1302
                                             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
  1303
                                             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
  1304
                                             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
  1305
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
  1306
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1307
class DateRangeFacet(RangeFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1308
    """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
  1309
    of date type.
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
    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
  1312
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1313
    .. image:: ../images/facet_date_range.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1314
    """
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1315
    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
  1316
7204
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1317
    @property
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1318
    def wdgclass(self):
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1319
        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
  1320
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1321
    def formatvalue(self, value):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1322
        """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
  1323
        try:
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1324
            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
  1325
        except (ValueError, OverflowError):
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1326
            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
  1327
        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
  1328
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1329
9562
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1330
class AbstractRangeRQLPathFacet(RQLPathFacet):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1331
    """
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1332
    The :class:`AbstractRangeRQLPathFacet` is the base class for
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1333
    RQLPathFacet-type facets allowing the use of RangeWidgets-like
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1334
    widgets (such as (:class:`FacetRangeWidget`,
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1335
    class:`DateFacetRangeWidget`) on the parent :class:`RQLPathFacet`
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1336
    target attribute.
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1337
    """
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1338
    __abstract__ = True
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1339
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1340
    def vocabulary(self):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1341
        """return vocabulary for this facet, eg a list of (label,
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1342
        value)"""
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1343
        select = self.select
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1344
        select.save_state()
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1345
        try:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1346
            filtered_variable = self.filtered_variable
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1347
            cleanup_select(select, filtered_variable)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1348
            varmap, restrvar = self.add_path_to_select()
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1349
            if self.label_variable:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1350
                attrvar = varmap[self.label_variable]
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1351
            else:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1352
                attrvar = restrvar
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1353
            # start RangeRQLPathFacet
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1354
            minf = nodes.Function('MIN')
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1355
            minf.append(nodes.VariableRef(restrvar))
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1356
            select.add_selected(minf)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1357
            maxf = nodes.Function('MAX')
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1358
            maxf.append(nodes.VariableRef(restrvar))
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1359
            select.add_selected(maxf)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1360
            # add is restriction if necessary
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1361
            if filtered_variable.stinfo['typerel'] is None:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1362
                etypes = frozenset(sol[filtered_variable.name] for sol in select.solutions)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1363
                select.add_type_restriction(filtered_variable, etypes)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1364
            # end RangeRQLPathFacet
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1365
            try:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1366
                rset = self.rqlexec(select.as_string(), self.cw_rset.args)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1367
            except Exception:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1368
                self.exception('error while getting vocabulary for %s, rql: %s',
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1369
                               self, select.as_string())
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1370
                return ()
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1371
        finally:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1372
            select.recover()
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1373
        # don't call rset_vocabulary on empty result set, it may be an empty
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1374
        # *list* (see rqlexec implementation)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1375
        if rset:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1376
            minv, maxv = rset[0]
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1377
            return [(unicode(minv), minv), (unicode(maxv), maxv)]
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1378
        return []
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1379
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1380
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1381
    def possible_values(self):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1382
        """return a list of possible values (as string since it's used to
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1383
        compare to a form value in javascript) for this facet
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1384
        """
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1385
        return [strval for strval, val in self.vocabulary()]
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1386
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1387
    def add_rql_restrictions(self):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1388
        infvalue = self.infvalue()
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1389
        supvalue = self.supvalue()
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1390
        if infvalue is None or supvalue is None: # nothing sent
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1391
            return
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1392
        varmap, restrvar = self.add_path_to_select(
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1393
            skiplabel=True, skipattrfilter=True)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1394
        restrel = None
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1395
        for part in self.path:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1396
            if isinstance(part, basestring):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1397
                part = part.split()
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1398
            subject, rtype, object = part
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1399
            if object == self.filter_variable:
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1400
                restrel = rtype
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1401
        assert restrel
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1402
        # when a value is equal to one of the limit, don't add the restriction,
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1403
        # else we filter out NULL values implicitly
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1404
        if infvalue != self.infvalue(min=True):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1405
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1406
            self._add_restriction(infvalue, '>=', restrvar, restrel)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1407
        if supvalue != self.supvalue(max=True):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1408
            self._add_restriction(supvalue, '<=', restrvar, restrel)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1409
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1410
    def _add_restriction(self, value, operator, restrvar, restrel):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1411
        self.select.add_constant_restriction(restrvar,
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1412
                                             restrel,
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1413
                                             self.formatvalue(value),
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1414
                                             self.target_attr_type, operator)
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1415
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1416
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1417
class RangeRQLPathFacet(AbstractRangeRQLPathFacet, RQLPathFacet):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1418
    """
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1419
    The :class:`RangeRQLPathFacet` uses the :class:`FacetRangeWidget`
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1420
    on the :class:`AbstractRangeRQLPathFacet` target attribute
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1421
    """
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1422
    pass
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1423
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1424
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1425
class DateRangeRQLPathFacet(AbstractRangeRQLPathFacet, DateRangeFacet):
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1426
    """
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1427
    The :class:`DateRangeRQLPathFacet` uses the
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1428
    :class:`DateFacetRangeWidget` on the
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1429
    :class:`AbstractRangeRQLPathFacet` target attribute
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1430
    """
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1431
    pass
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1432
0509880fec01 [facet] create a RangeRQLPathFacet (closes #2852512)
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 9492
diff changeset
  1433
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1434
class HasRelationFacet(AbstractFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1435
    """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
  1436
    (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
  1437
    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
  1438
    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
  1439
    `rtype` and `role` attributes.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1440
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1441
    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
  1442
    and the corresponding code:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1443
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1444
    .. image:: ../images/facet_has_image.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1445
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1446
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1447
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1448
      class HasImageFacet(HasRelationFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1449
          __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
  1450
          __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
  1451
          rtype = 'has_image'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1452
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1453
    """
7280
571b29842ef1 [facet] add missing selector to HasRelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7279
diff changeset
  1454
    __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
  1455
    rtype = None # override me in subclass
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1456
    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
  1457
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
  1458
    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
  1459
    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
  1460
    support_and = False
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1461
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1462
    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
  1463
        return CheckBoxFacetWidget(self._cw, self,
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1464
                                   '%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
  1465
                                   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
  1466
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1467
    def add_rql_restrictions(self):
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1468
        """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
  1469
        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
  1470
        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
  1471
        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
  1472
            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
  1473
        var = self.select.make_variable()
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1474
        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
  1475
            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
  1476
        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
  1477
            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
  1478
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1479
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
  1480
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
  1481
    """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
  1482
    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
  1483
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
  1484
    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
  1485
    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
  1486
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
  1487
    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
  1488
    """
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
  1489
    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
  1490
    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
  1491
        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
  1492
        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
  1493
            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
  1494
        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
  1495
            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
  1496
        else:
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1497
            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
  1498
        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
  1499
        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
  1500
        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
  1501
        if value == 0:
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1502
            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
  1503
        else:
95b3792a8947 [facet] make BitFieldFacet allow special 0 value. Closes #2522697
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8190
diff changeset
  1504
            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
  1505
                                             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
  1506
        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
  1507
        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
  1508
            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
  1509
        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
  1510
            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
  1511
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
  1512
    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
  1513
        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
  1514
        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
  1515
                       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
  1516
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
  1517
    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
  1518
        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
  1519
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
  1520
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1521
## 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
  1522
_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
  1523
_DEFAULT_FACET_GROUP_HEIGHT = 15
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1524
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
  1525
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
  1526
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1527
    def __init__(self, facet):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1528
        self.facet = facet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1529
        self.items = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1530
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
  1531
    @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
  1532
    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
  1533
        """ 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
  1534
        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
  1535
        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
  1536
        """
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
  1537
        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
  1538
                                _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
  1539
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
  1540
    @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
  1541
    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
  1542
        """ 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
  1543
        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
  1544
                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
  1545
                    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
  1546
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
  1547
    @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
  1548
    @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
  1549
    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
  1550
        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
  1551
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
  1552
    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
  1553
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1554
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1555
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1556
        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
  1557
        facetid = domid(make_uid(self.facet.__regid__))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1558
        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
  1559
        cssclass = 'facetTitle'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1560
        if self.facet.allow_hide:
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1561
            cssclass += ' hideFacetBody'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1562
        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
  1563
          (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
  1564
        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
  1565
            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
  1566
        cssclass = 'facetBody vocabularyFacet'
368
84a5106840fa facet widgets css cleanup
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 346
diff changeset
  1567
        if not self.facet.start_unfolded:
84a5106840fa facet widgets css cleanup
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 346
diff changeset
  1568
            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
  1569
        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
  1570
        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
  1571
            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
  1572
                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
  1573
            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
  1574
                cssclass += ' vocabularyFacetBody'
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1575
        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
  1576
        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
  1577
            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
  1578
                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
  1579
            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
  1580
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1581
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1582
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
  1583
    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
  1584
        _ = 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
  1585
        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
  1586
  <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
  1587
  <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
  1588
</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
  1589
                _('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
  1590
                _('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
  1591
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
  1592
    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
  1593
        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
  1594
        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
  1595
            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
  1596
        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
  1597
          % (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
  1598
        # 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
  1599
        # 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
  1600
        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
  1601
        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
  1602
        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
  1603
        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
  1604
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
  1605
class FacetStringWidget(htmlwidgets.HTMLWidget):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1606
    def __init__(self, facet):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1607
        self.facet = facet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1608
        self.value = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1609
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
  1610
    @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
  1611
    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
  1612
        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
  1613
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1614
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1615
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1616
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1617
        facetid = make_uid(self.facet.__regid__)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1618
        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
  1619
        cssclass = 'facetTitle'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1620
        if self.facet.allow_hide:
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1621
            cssclass += ' hideFacetBody'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1622
        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
  1623
               (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
  1624
        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
  1625
                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
  1626
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1627
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1628
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
  1629
class FacetRangeWidget(htmlwidgets.HTMLWidget):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1630
    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
  1631
    onload = u'''
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1632
    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
  1633
    jQuery("#%(sliderid)s").slider({
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1634
        range: true,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1635
        min: %(minvalue)s,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1636
        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
  1637
        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
  1638
        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
  1639
           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
  1640
           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
  1641
        },
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1642
        slide: function(event, ui) {
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1643
            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
  1644
            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
  1645
            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
  1646
            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
  1647
        }
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
  1648
   });
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1649
   // 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
  1650
   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
  1651
   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
  1652
'''
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1653
    #'# 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
  1654
    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
  1655
        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
  1656
        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
  1657
        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
  1658
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
  1659
    @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
  1660
    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
  1661
        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
  1662
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
  1663
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1664
        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
  1665
        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
  1666
        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
  1667
        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
  1668
        sliderid = make_uid('theslider')
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1669
        facetname = self.facet.__regid__
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1670
        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
  1671
        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
  1672
            'sliderid': sliderid,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1673
            'facetid': facetid,
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1674
            'facetname': facetname,
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1675
            'minvalue': self.minvalue,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1676
            'maxvalue': self.maxvalue,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1677
            'formatter': self.formatter,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1678
            })
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1679
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1680
        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
  1681
        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
  1682
        cssclass = 'facetTitle'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1683
        if facet.allow_hide:
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1684
            cssclass += ' hideFacetBody'
1fe089765187 [facets] Make hiding facet body optional (closes #2105862)
Julien Cristau <julien.cristau@logilab.fr>
parents: 8104
diff changeset
  1685
        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
  1686
          (cssclass, facetname, title))
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1687
        cssclass = 'facetBody'
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1688
        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
  1689
            cssclass += ' hidden'
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1690
        w(u'<div class="%s">\n' % cssclass)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1691
        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
  1692
          % (sliderid, sliderid))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1693
        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
  1694
          % (facetname, self.minvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1695
        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
  1696
          % (facetname, self.maxvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1697
        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
  1698
          % (facetname, self.minvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1699
        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
  1700
          % (facetname, self.maxvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1701
        w(u'<div id="%s"></div>' % sliderid)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1702
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1703
        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
  1704
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
  1705
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
  1706
class DateFacetRangeWidget(FacetRangeWidget):
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1707
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1708
    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
  1709
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1710
    def round_max_value(self, d):
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1711
        'round to upper value to avoid filtering out the max value'
2152
Florent <florent@secondweb.fr>
parents: 2149
diff changeset
  1712
        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
  1713
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
  1714
    def __init__(self, facet, minvalue, maxvalue):
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1715
        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
  1716
        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
  1717
                                                   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
  1718
                                                   datetime2ticks(maxvalue))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1719
        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
  1720
        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
  1721
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1722
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
  1723
class CheckBoxFacetWidget(htmlwidgets.HTMLWidget):
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1724
    selected_img = "black-check.png"
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1725
    unselected_img = "black-uncheck.png"
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1726
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1727
    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
  1728
        self._cw = req
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1729
        self.facet = facet
2016
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1730
        self.value = value
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1731
        self.selected = selected
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1732
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
  1733
    @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
  1734
    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
  1735
        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
  1736
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1737
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1738
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1739
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1740
        facetid = make_uid(self.facet.__regid__)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1741
        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
  1742
        cssclass = 'facetValue facetCheckBox'
2016
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1743
        if self.selected:
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1744
            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
  1745
            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
  1746
            imgalt = self._cw._('selected')
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1747
        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
  1748
            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
  1749
            imgalt = self._cw._('not selected')
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1750
        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
  1751
          % (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
  1752
        w(u'<div>')
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1753
        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
  1754
        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
  1755
          % (xml_escape(self.facet.__regid__), title))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1756
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1757
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1758
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1759
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1760
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1761
# other classes ################################################################
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1762
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1763
class FilterRQLBuilder(object):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1764
    """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
  1765
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1766
    def __init__(self, req):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1767
        self._cw = req
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1768
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
  1769
    def build_rql(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1770
        form = self._cw.form
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1771
        facetids = form['facets'].split(',')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1772
        # XXX Union unsupported yet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1773
        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
  1774
        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
  1775
        toupdate = []
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1776
        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
  1777
            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
  1778
            facet.add_rql_restrictions()
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1779
            if facet.needs_update:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1780
                toupdate.append(facetid)
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1781
        return select.as_string(), toupdate