web/facet.py
author Pierre-Yves David <pierre-yves.david@logilab.fr>
Thu, 13 Oct 2011 09:44:14 +0200
branchstable
changeset 7944 1faa8edb5ae3
parent 7879 9aae456abab5
child 7953 a37531c8a4a6
permissions -rw-r--r--
init_facets: Add documentation init_facets is not included in the default sphinx documentation but this docstring should help people digging into cubicweb core. This could go in an Advanced developer section of the book.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
     1
# copyright 2003-2011 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
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    36
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    37
Classes for facets implementor
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    38
------------------------------
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    39
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
    40
to skip those classes...
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    41
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    42
.. autoclass:: cubicweb.web.facet.AbstractFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    43
.. autoclass:: cubicweb.web.facet.VocabularyFacet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    44
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
    45
.. 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
    46
"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
__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
    49
_ = unicode
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
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
    51
from warnings import warn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
from copy import deepcopy
2152
Florent <florent@secondweb.fr>
parents: 2149
diff changeset
    53
from datetime import date, datetime, timedelta
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
    55
from logilab.mtconverter import xml_escape
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
from logilab.common.graph import has_path
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
from logilab.common.decorators import cached
7117
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
    58
from logilab.common.date import datetime2ticks, ustrftime, ticks2datetime
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
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
    60
from logilab.common.deprecation import deprecated
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
    62
from rql import parse, nodes, utils
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
from cubicweb import Unauthorized, typed_eid
2305
8f6dbe884700 import display_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2152
diff changeset
    65
from cubicweb.schema import display_name
4466
8b0ca7904820 moved generic datetime manipulation function to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4333
diff changeset
    66
from cubicweb.utils import make_uid
7874
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
    67
from cubicweb.selectors import match_context_prop, partial_relation_possible, yes
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
    68
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
    69
from cubicweb.web import RequestError, htmlwidgets
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    71
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    72
def rtype_facet_title(facet):
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    73
    ptypes = facet.cw_rset.column_types(0)
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    74
    if len(ptypes) == 1:
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    75
        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
    76
                            context=iter(ptypes).next())
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
    77
    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
    78
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
    79
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
    80
    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
    81
                                           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
    82
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
    83
@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
    84
            '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
    85
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
    86
    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
    87
    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
    88
75d208ab8444 [facets] factorize table filter form / facets box generation, moving out filter form from the table view so it's usable from other views. Closes #1794009
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7414
diff changeset
    89
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    90
## rqlst manipulation functions used by facets ################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
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
    92
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
    93
    """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
    94
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
    95
    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
    96
    :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
    97
    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
    98
    details.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
    99
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   100
    :param rset: ResultSet we init facet for.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   101
    :type rset: :class:`~cubicweb.rset.ResultSet`
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
    :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
   104
    :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
   105
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   106
    :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
   107
    :type mainvar:  string
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   108
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   109
    :rtype: (filtered_variable, baserql) tuple.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   110
    :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
   111
                                instance as returned by
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   112
                                :func:`get_filtered_variable`.
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
    :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
   115
                     :func:`prepare_select` but after
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   116
                     :func:`get_filtered_variable`.
1faa8edb5ae3 init_facets: Add documentation
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 7879
diff changeset
   117
    """
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
   118
    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
   119
    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
   120
    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
   121
    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
   122
    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
   123
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   124
def get_filtered_variable(select, mainvar=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
   125
    """drop any limit/offset from select (in-place modification) and return the
48abeac162fd [facets] refactor / cleanup 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
    variable whose name is `mainvar` or the first variable selected in column 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
   127
    """
48abeac162fd [facets] refactor / cleanup 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
    select.set_limit(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
   129
    select.set_offset(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
   130
    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
   131
        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
   132
        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
   133
    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
   134
48abeac162fd [facets] refactor / cleanup 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
def prepare_select(select, filtered_variable):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
    """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
   137
7601
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   138
    * remove ORDERBY/GROUPBY clauses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
    * cleanup selection (remove everything)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
    * undefine unnecessary variables
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
    * 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
   142
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   143
    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
   144
    :func:`get_filtered_variable`.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
    """
7601
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   146
    # cleanup sort terms / group by
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
    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
   148
    select.remove_groups()
9030e8a4481e [facets] should remove groupby from base rqlst. Closes #1796196
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7280
diff changeset
   149
    # XXX remove aggregat from having
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   150
    # selection: only vocabulary entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
    for term in select.selection[:]:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
        select.remove_selected(term)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    # remove unbound variables which only have some type restriction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    for dvar in select.defined_vars.values():
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
   155
        if not (dvar is filtered_variable or dvar.stinfo['relations']):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
            select.undefine_variable(dvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    # global tree config: DISTINCT, LIMIT, OFFSET
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
    select.set_distinct(True)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
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
   160
@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
   161
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
   162
    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
   163
    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
   164
    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
   165
    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
   166
    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
   167
    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
   168
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
   169
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
   170
                              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
   171
    """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
   172
    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
   173
    * 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
   174
    * 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
   175
    * 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
   176
    * 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
   177
    """
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
   178
    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
   179
    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
   180
        # 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
   181
        #     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
   182
        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
   183
    # 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
   184
    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
   185
        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
   186
        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
   187
    return newvar
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
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
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
   191
                                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
   192
                                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
   193
    """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
   194
    * 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
   195
    * 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
   196
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
    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
   198
    * 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
   199
    * 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
   200
    * 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
   201
    """
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
   202
    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
   203
    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
   204
                                   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
   205
    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
   206
    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
   207
    # 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
   208
    #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
   209
    #    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
   210
    #        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
   211
    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
   212
        _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
   213
    # 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
   214
    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
   215
    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
   216
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
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
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
   219
    """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
   220
    * 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
   221
    * 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
   222
    * 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
   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
    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
   225
        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
   226
    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
   227
    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
   228
    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
   229
    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
   230
        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
   231
        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
   232
            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
   233
    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
   234
    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
   235
        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
   236
        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
   237
        # 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
   238
        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
   239
        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
   240
            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
   241
        # 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
   242
        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
   243
            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
   244
                # 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
   245
                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
   246
            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
   247
            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
   248
        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
   249
        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
   250
            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
   251
            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
   252
        # 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
   253
        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
   254
            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
   255
                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
   256
                    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
   257
        # 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
   258
        # 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
   259
        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
   260
            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
   261
                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
   262
            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
   263
                toremove.add(select.defined_vars[ovarname])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   264
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   265
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
def _may_be_removed(rel, schema, variable):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   267
    """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
   268
    on the other side of `variable`, else return None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   269
    Conditions:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
    * the relation is an attribute selection of the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
    * the relation is optional relation linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
    * the relation is a mandatory relation linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
      without any restriction on the other variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
    lhs, rhs = rel.get_variable_parts()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
    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
   277
    if lhs.variable is variable:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   278
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
            ovar = rhs.variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
        except AttributeError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
            # constant restriction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
            # XXX: X title LOWER(T) if it makes sense?
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   283
            return None
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3333
diff changeset
   284
        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
   285
            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
   286
                   and not ovar.stinfo.get('having'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
                # attribute selection
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   288
                return ovar
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   289
            return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
        opt = 'right'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
        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
   292
    elif getattr(rhs, 'variable', None) is variable:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
        ovar = lhs.variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
        opt = 'left'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
        cardidx = 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
        # not directly linked to the main variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
        return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
    if rel.optional in (opt, 'both'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
        # optional relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   301
        return ovar
4073
03681ba6da0b cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3720
diff changeset
   302
    if all(rdef.cardinality[cardidx] in '1+'
03681ba6da0b cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3720
diff changeset
   303
           for rdef in rschema.rdefs.values()):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
        # mandatory relation without any restriction on the other variable
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
        for orel in ovar.stinfo['relations']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
            if rel is orel:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
                continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
            if _may_be_removed(orel, schema, ovar) is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
                return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
        return ovar
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
    return None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
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
   313
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
   314
    newvar = select.make_variable()
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   315
    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
   316
        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
   317
    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
   318
        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
   319
    return newvar, rel
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   320
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   321
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
   322
    """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
   323
    relation (where `variable` has `role`)
1149
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   324
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
   325
    return the inserted variable for linked entities.
1e19b6ef53a1 pylint cleanup
sylvain.thenault@logilab.fr
parents: 1132
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
    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
   328
    select.add_restriction(newrel)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   329
    return newvar, newrel
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   330
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
   331
def _remove_relation(select, rel, var):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
    """remove a constraint relation from the syntax tree"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
    # 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
   334
    select.remove_node(rel)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
    # remove relations where the filtered variable appears on the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
    # lhs and rhs is a constant restriction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
    extra = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
    for vrel in var.stinfo['relations']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
        if vrel is rel:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   340
            continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   341
        if vrel.children[0].variable is var:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   342
            if not vrel.children[1].get_nodes(nodes.Constant):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   343
                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
   344
            select.remove_node(vrel)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
    return extra
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   346
7605
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   347
def _set_orderby(select, newvar, sortasc, sortfuncname):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
    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
   349
        select.add_sort_var(newvar, sortasc)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
        vref = nodes.variable_ref(newvar)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        vref.register_reference()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
        sortfunc = nodes.Function(sortfuncname)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
        sortfunc.append(vref)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
        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
   356
        select.add_sort_term(term)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   357
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   358
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
   359
    try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   360
        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
   361
    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
   362
        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
   363
        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
   364
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
   365
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
   366
_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
   367
    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
   368
_cleanup_rqlst = deprecated('[3.13] renamed to cleanup_select')(cleanup_select)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   369
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
   370
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   371
## 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
   372
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2650
diff changeset
   373
class AbstractFacet(AppObject):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   374
    """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
   375
    '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
   376
    the following configurable properties:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   377
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   378
    * `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
   379
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   380
    * `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
   381
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   382
    * `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
   383
      (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
   384
      both (context = '')
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
    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
   387
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   388
    .. 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
   389
    .. 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
   390
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   391
    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
   392
    :class:`~cubicweb.appobject.AppObject` ones):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   393
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
   394
    * `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
   395
      filtered
6120
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
    * `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
   398
      interested in filtering
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   399
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   400
    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
   401
    methods:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   402
7632
3c9dfc6e820b [book] fix some rest/sphinx errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7629
diff changeset
   403
    .. 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
   404
    .. automethod:: cubicweb.web.facet.AbstractFacet.rqlexec
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   405
    """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   406
    __abstract__ = True
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   407
    __registry__ = 'facets'
2799
b703639614e7 refactor property handling to avoid name conflicts
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2770
diff changeset
   408
    cw_property_defs = {
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
        _('visible'): dict(type='Boolean', default=True,
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   410
                           help=_('display the facet or not')),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   411
        _('order'):   dict(type='Int', default=99,
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   412
                           help=_('display order of the facet')),
496
e25a3c2f5393 set default to empty string, not None
sylvain.thenault@logilab.fr
parents: 467
diff changeset
   413
        _('context'): dict(type='String', default='',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   414
                           # 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
   415
                           vocabulary=(_('tablefilter'), _('facetbox'), ''),
6038
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   416
                           help=_('context where this facet should be displayed, '
5c5d819e8e93 small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5774
diff changeset
   417
                                  'leave empty for both')),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   418
        }
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   419
    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
   420
    context = ''
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   421
    needs_update = False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   422
    start_unfolded = 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
   423
    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
   424
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
   425
    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
   426
                 **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
   427
        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
   428
        assert select is not None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   429
        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
   430
        # 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
   431
        # 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
   432
        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
   433
        self.filtered_variable = filtered_variable
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   434
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
    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
   436
        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
   437
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   438
    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
   439
        """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
   440
        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
   441
        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
   442
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   443
        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
   444
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 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
   446
        """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
   447
        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
   448
        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
   449
        (`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
   450
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   451
        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
   452
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   453
    @property
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   454
    def operator(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   455
        """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
   456
        values are selected.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   457
        """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   458
        # 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
   459
        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
   460
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   461
    def rqlexec(self, rql, args=None):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   462
        """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
   463
        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
   464
        """
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   465
        try:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   466
            return self._cw.execute(rql, args)
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   467
        except Unauthorized:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   468
            return []
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   469
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
   470
    @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
   471
    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
   472
        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
   473
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
   474
    @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
   475
    @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
   476
    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
   477
        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
   478
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   479
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   480
class VocabularyFacet(AbstractFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   481
    """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
   482
    :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
   483
    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
   484
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   485
    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
   486
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   487
    .. automethod:: cubicweb.web.facet.VocabularyFacet.vocabulary
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   488
    .. 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
   489
    """
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   490
    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
   491
    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
   492
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
   493
    @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
   494
    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
   495
        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
   496
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   497
    def get_widget(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   498
        """Return the widget instance to use to display this facet.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   499
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   500
        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
   501
        return a combobox displaying this vocabulary.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   502
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   503
        vocab = self.vocabulary()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   504
        if len(vocab) <= 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   505
            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
   506
        wdg = self.wdgclass(self)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
   507
        selected = frozenset(typed_eid(eid) for eid in self._cw.list_form_param(self.__regid__))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   508
        for label, value in vocab:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   509
            if value is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
                wdg.append(FacetSeparator(label))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
            else:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
   512
                wdg.append(FacetItem(self._cw, label, value, value in selected))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
        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
   514
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
    def vocabulary(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   516
        """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
   517
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   518
        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
   519
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   520
    def possible_values(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   521
        """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
   522
        compare to a form value in javascript) for this facet.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   523
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
        raise NotImplementedError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   525
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
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   528
class RelationFacet(VocabularyFacet):
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   529
    """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
   530
    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
   531
    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
   532
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   533
    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
   534
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   535
    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
   536
    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
   537
    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
   538
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   539
    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
   540
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   541
    * 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
   542
    * 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
   543
    * 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
   544
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   545
    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
   546
    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
   547
    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
   548
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   549
    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
   550
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   551
    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
   552
    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
   553
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   554
    * `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
   555
      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
   556
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   557
    * `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
   558
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   559
    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
   560
    of an office location search application:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   561
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   562
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   563
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   564
      class Office(WorkflowableEntityType):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   565
          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
   566
          surface = Int(description='m2')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   567
          has_address = SubjectRelation('PostalAddress',
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   568
                                        cardinality='1?',
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   569
                                        composite='subject')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   570
          proposed_by = SubjectRelation('Agency')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   571
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   572
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   573
    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
   574
    proposing it:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   575
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   576
    .. sourcecode:: python
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
      class AgencyFacet(RelationFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   579
          __regid__ = 'agency'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   580
          # 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
   581
          __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
   582
          # 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
   583
          # 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
   584
          # of the relation
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   585
          rtype = 'has_address'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   586
          # '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
   587
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   588
          # 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
   589
          target_attr = 'name'
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   590
    """
838
f2c56312b03a rename abstract_* selectors into partial_* + add docstrings
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 782
diff changeset
   591
    __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
   592
    # class attributes to configure the relation facet
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   593
    rtype = None
1433
091ac3ba5d51 remove trailing white spaces
sylvain.thenault@logilab.fr
parents: 1432
diff changeset
   594
    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
   595
    target_type = None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
    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
   597
    # 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
   598
    # RelationFacet
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   599
    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
   600
    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
   601
    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
   602
    comparator = '=' # could be '<', '<=', '>', '>='
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   603
    # 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
   604
    # this function's result instead of direct value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   605
    sortfunc = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   606
    # ascendant/descendant sorting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   607
    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
   608
    # 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
   609
    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
   610
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   611
    # internal purpose
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   612
    _select_target_entity = True
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   613
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
   614
    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
   615
    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
   616
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
   617
    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
   618
        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
   619
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   620
    # 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
   621
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   622
    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
   623
        """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
   624
        """
48abeac162fd [facets] refactor / cleanup facet api: more consistent variable naming and easier to reuse function. Closes #1796804
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7604
diff changeset
   625
        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
   626
        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
   627
        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
   628
            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
   629
        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
   630
            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
   631
        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
   632
            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
   633
                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
   634
                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
   635
                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
   636
            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
   637
                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
   638
            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
   639
                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
   640
            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
   641
                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
   642
                               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
   643
                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
   644
        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
   645
            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
   646
        # 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
   647
        # *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
   648
        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
   649
        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
   650
            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
   651
        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
   652
48abeac162fd [facets] refactor / cleanup 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
    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
   654
        """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
   655
        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
   656
        """
48abeac162fd [facets] refactor / cleanup 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
        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
   658
        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
   659
        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
   660
            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
   661
            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
   662
                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
   663
                                         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
   664
            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
   665
                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
   666
                    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
   667
                    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
   668
            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
   669
        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
   670
            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
   671
            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
   672
        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
   673
            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
   674
        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
   675
            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
   676
        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
   677
48abeac162fd [facets] refactor / cleanup 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
    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
   679
        """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
   680
        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
   681
        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
   682
            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
   683
        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
   684
        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
   685
                                            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
   686
        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
   687
48abeac162fd [facets] refactor / cleanup 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
    # 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
   689
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   690
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   691
    def i18nable(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   692
        """should label be internationalized"""
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   693
        if self.target_type:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   694
            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
   695
        elif self.role == 'subject':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   696
            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
   697
        else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   698
            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
   699
        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
   700
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   701
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   702
    def no_relation(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   703
        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
   704
                and self._search_card('?*'))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   705
6251
afc757568492 [facet] add missing @property making subsequent access always true
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6152
diff changeset
   706
    @property
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   707
    def rql_sort(self):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   708
        """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
   709
        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
   710
        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
   711
        """
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   712
        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
   713
                                             and not self.i18nable)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   714
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   715
    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
   716
        if self.i18nable:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
   717
            _ = self._cw._
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   718
        else:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   719
            _ = unicode
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   720
        if self.rql_sort:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   721
            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
   722
        else:
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   723
            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
   724
                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
   725
            else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   726
                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
   727
                          for entity in rset.entities()]
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   728
            values = sorted(values)
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   729
            if not self.sortasc:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   730
                values = list(reversed(values))
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   731
        return values
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   732
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
   733
    @property
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   734
    def support_and(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   735
        return self._search_card('+*')
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   736
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
   737
    # 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
   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
    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
   740
        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
   741
        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
   742
            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
   743
                 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
   744
            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
   745
        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
   746
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
   747
    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
   748
        # 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
   749
        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
   750
            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
   751
        if isinstance(value, basestring):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   752
            # only one value selected
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   753
            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
   754
                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
   755
                    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
   756
                    self.restr_attr_type)
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   757
            else:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   758
                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
   759
        elif self.operator == 'OR':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   760
            # 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
   761
            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
   762
                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
   763
            # 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
   764
            if '' in value:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   765
                value.remove('')
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   766
                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
   767
            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
   768
        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
   769
            # 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
   770
            # "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
   771
            # 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
   772
            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
   773
                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
   774
            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
   775
            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
   776
                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
   777
                                                 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
   778
                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
   779
                    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
   780
                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
   781
                    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
   782
                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
   783
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   784
    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
   785
        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
   786
            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
   787
                                                 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
   788
        else:
ae4cb4153490 [facet] with rql path facet rel may be None, handle it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7624
diff changeset
   789
            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
   790
                                                   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
   791
            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
   792
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   793
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   794
    @cached
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   795
    def _search_card(self, cards):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   796
        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
   797
            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
   798
                return True
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   799
        return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   800
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   801
    def _iter_rdefs(self):
3456
1a63a252601f [facets] typo fix
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3451
diff changeset
   802
        rschema = self._cw.vreg.schema.rschema(self.rtype)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   803
        # 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
   804
        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
   805
        for rdef in rschema.rdefs.itervalues():
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
            if possibletypes is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   807
                if self.role == 'subject':
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   808
                    if rdef.subject not in possibletypes:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   809
                        continue
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   810
                elif rdef.object not in possibletypes:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
                    continue
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   812
            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
   813
                if self.role == 'subject':
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   814
                    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
   815
                        continue
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   816
                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
   817
                    continue
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   818
            yield rdef
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   819
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   820
    def _include_no_relation(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   821
        if not self.no_relation:
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   822
            return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   823
        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
   824
            return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   825
        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
   826
            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
   827
                                      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
   828
            obj = self.filtered_variable.name
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   829
        else:
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   830
            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
   831
            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
   832
                                     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
   833
        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
   834
        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
   835
            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
   836
        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
   837
            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
   838
                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
   839
        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
   840
            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
   841
        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
   842
            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
   843
        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
   844
            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
   845
        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
   846
            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
   847
        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
   848
            # 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
   849
            # 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
   850
            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
   851
            return False
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   852
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   853
    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
   854
        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
   855
                                         self.rtype, self.role)[1])
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   856
        rel.parent.replace(rel, nodes.Or(nrrel, rel))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   857
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   858
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   859
class RelationAttributeFacet(RelationFacet):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   860
    """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
   861
    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
   862
    :class:`RelationFacet`, except that:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   863
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   864
    * `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
   865
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   866
    * 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
   867
      String
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   868
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   869
    * 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
   870
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   871
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   872
    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
   873
    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
   874
    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
   875
    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
   876
    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
   877
    users won't understand that...
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
    That's where this class come in ! It's used to said that you want to filter
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   880
    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
   881
    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
   882
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   883
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   884
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   885
      class PostalCodeFacet(RelationAttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   886
          __regid__ = 'postalcode'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   887
          # 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
   888
          __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
   889
          # 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
   890
          # 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
   891
          # subject of the relation
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   892
          rtype = 'has_address'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   893
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   894
          # 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
   895
          target_attr = 'postalcode'
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   896
    """
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   897
    _select_target_entity = False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   898
    # 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
   899
    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
   900
    # 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
   901
    comparator = '=' # could be '<', '<=', '>', '>='
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   902
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   903
    @property
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   904
    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
   905
        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
   906
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   907
    @property
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
   908
    def restr_attr_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
   909
        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
   910
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   911
    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
   912
        if self.i18nable:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   913
            _ = self._cw._
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   914
        else:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   915
            _ = unicode
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   916
        if self.rql_sort:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   917
            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
   918
        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
   919
        if self.sortasc:
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   920
            return sorted(values)
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   921
        return reversed(sorted(values))
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   922
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   923
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   924
class AttributeFacet(RelationAttributeFacet):
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   925
    """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
   926
    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
   927
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   928
    * `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
   929
    * `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
   930
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   931
    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
   932
    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
   933
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   934
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   935
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   936
      class SurfaceFacet(AttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   937
          __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
   938
          __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
   939
          # 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
   940
          rtype = 'surface'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   941
          # 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
   942
          # 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
   943
          comparator = '>='
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   944
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   945
          def vocabulary(self):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   946
              '''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
   947
              hard-code our threshold values.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   948
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   949
              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
   950
              surfaces defined in the database.
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
              return [('> 200', '200'), ('> 250', '250'),
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   953
                      ('> 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
   954
    """
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
   955
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
   956
    support_and = False
6119
b217635d3b28 new RelationAttributeFacet + other fixes and cleanup + facets test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6038
diff changeset
   957
    _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
   958
6380
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   959
    @property
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   960
    def i18nable(self):
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   961
        """should label be internationalized"""
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   962
        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
   963
            # 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
   964
            # String
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   965
            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
   966
                return False
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   967
        return True
63d5dbaef999 [facets] support for `no_relation` on RelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6336
diff changeset
   968
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   969
    def vocabulary(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   970
        """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
   971
        """
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
   972
        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
   973
        select.save_state()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   974
        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
   975
            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
   976
            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
   977
            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
   978
            _set_orderby(select, newvar, self.sortasc, self.sortfunc)
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
   979
            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
   980
                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
   981
            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
   982
                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
   983
                               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
   984
                return ()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   985
        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
   986
            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
   987
        # 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
   988
        # *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
   989
        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
   990
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   991
    def add_rql_restrictions(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   992
        """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
   993
        value = self._cw.form.get(self.__regid__)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   994
        if not value:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   995
            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
   996
        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
   997
        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
   998
                                            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
   999
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1000
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1001
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
  1002
    """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
  1003
    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
  1004
    '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
  1005
    `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
  1006
    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
  1007
    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
  1008
    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
  1009
    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
  1010
    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
  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
    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
  1013
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1014
    .. 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
  1015
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1016
      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
  1017
          __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
  1018
          # 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
  1019
          __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
  1020
          # 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
  1021
          # 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
  1022
          # 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
  1023
          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
  1024
          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
  1025
          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
  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 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
  1028
          __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
  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 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
  1032
          # 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
  1033
          # 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
  1034
          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
  1035
          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
  1036
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1037
    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
  1038
    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
  1039
    :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
  1040
    (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
  1041
    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
  1042
    """
7874
be04706eacc9 [facet] add safety belt to rql path facet init (closes #1965481)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7860
diff changeset
  1043
    __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
  1044
    # 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
  1045
    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
  1046
    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
  1047
    # 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
  1048
    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
  1049
    # 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
  1050
    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
  1051
    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
  1052
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1053
    # 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
  1054
    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
  1055
    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
  1056
    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
  1057
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1058
    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
  1059
        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
  1060
        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
  1061
            ('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
  1062
             '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
  1063
        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
  1064
            '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
  1065
        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
  1066
            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
  1067
                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
  1068
            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
  1069
                   '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
  1070
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1071
    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
  1072
        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
  1073
                            ','.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
  1074
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1075
    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
  1076
        """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
  1077
        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
  1078
        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
  1079
        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
  1080
            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
  1081
        else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1082
            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
  1083
        try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1084
            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
  1085
            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
  1086
            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
  1087
            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
  1088
                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
  1089
            else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1090
                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
  1091
            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
  1092
            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
  1093
                _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
  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
                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
  1096
            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
  1097
                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
  1098
                               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
  1099
                return ()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1100
        finally:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1101
            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
  1102
        # 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
  1103
        # *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
  1104
        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
  1105
        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
  1106
            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
  1107
        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
  1108
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1109
    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
  1110
        """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
  1111
        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
  1112
        """
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1113
        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
  1114
        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
  1115
        try:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1116
            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
  1117
            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
  1118
            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
  1119
            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
  1120
        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
  1121
            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
  1122
            return []
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1123
        finally:
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.recover()
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1125
        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
  1126
            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
  1127
        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
  1128
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1129
    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
  1130
        """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
  1131
        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
  1132
        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
  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
        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
  1135
            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
  1136
        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
  1137
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1138
    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
  1139
        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
  1140
        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
  1141
        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
  1142
            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
  1143
                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
  1144
            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
  1145
            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
  1146
                continue
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1147
            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
  1148
                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
  1149
                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
  1150
                    # 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
  1151
                    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
  1152
                        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
  1153
                    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
  1154
                        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
  1155
                        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
  1156
                            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
  1157
                                            % (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
  1158
                        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
  1159
                    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
  1160
                        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
  1161
                        continue
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1162
            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
  1163
            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
  1164
            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
  1165
                                      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
  1166
            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
  1167
        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
  1168
            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
  1169
        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
  1170
            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
  1171
        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
  1172
            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
  1173
        else:
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1174
            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
  1175
        return varmap, restrvar
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1176
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1177
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1178
class RangeFacet(AttributeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1179
    """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
  1180
    numerical type.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1181
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1182
    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
  1183
    bound.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1184
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1185
    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
  1186
    in a more powerful way since
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1187
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1188
    * 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
  1189
    * 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
  1190
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1191
    .. 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
  1192
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1193
      class SurfaceFacet(RangeFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1194
          __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
  1195
          __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
  1196
          # 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
  1197
          rtype = 'surface'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1198
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1199
    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
  1200
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1201
    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
  1202
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1203
    .. image:: ../images/facet_range.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1204
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1205
    .. _jquery: http://www.jqueryui.com/
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1206
    """
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1207
    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
  1208
    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
  1209
7204
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1210
    @property
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1211
    def wdgclass(self):
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1212
        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
  1213
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
  1214
    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
  1215
        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
  1216
        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
  1217
        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
  1218
            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
  1219
            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
  1220
            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
  1221
            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
  1222
            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
  1223
            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
  1224
            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
  1225
            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
  1226
            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
  1227
            # 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
  1228
            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
  1229
                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
  1230
                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
  1231
            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
  1232
                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
  1233
            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
  1234
                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
  1235
                               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
  1236
                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
  1237
        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
  1238
            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
  1239
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
    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
  1241
        """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
  1242
        """
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
        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
  1244
        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
  1245
            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
  1246
            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
  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
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
    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
  1250
        """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
  1251
        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
  1252
        """
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
        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
  1254
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
  1255
    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
  1256
        """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
  1257
        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
  1258
        # 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
  1259
        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
  1260
            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
  1261
        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
  1262
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1263
    def formatvalue(self, value):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1264
        """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
  1265
        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
  1266
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
  1267
    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
  1268
        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
  1269
            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
  1270
        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
  1271
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
  1272
    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
  1273
        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
  1274
            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
  1275
        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
  1276
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
  1277
    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
  1278
        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
  1279
        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
  1280
        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
  1281
            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
  1282
        # 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
  1283
        # 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
  1284
        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
  1285
            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
  1286
        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
  1287
            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
  1288
7615
e5ad51352eb3 [facet] fix argument inversion in date range facet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7609
diff changeset
  1289
    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
  1290
        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
  1291
                                             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
  1292
                                             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
  1293
                                             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
  1294
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
  1295
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1296
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
  1297
class DateRangeFacet(RangeFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1298
    """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
  1299
    of date type.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1300
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1301
    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
  1302
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1303
    .. image:: ../images/facet_date_range.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1304
    """
7618
5395007c415c [facet] closes #1806931: new facet type, based on arbitrary rql path
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7615
diff changeset
  1305
    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
  1306
7204
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1307
    @property
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1308
    def wdgclass(self):
2b6d3c9455a7 Backed out changeset e0e802afa8e1, widgets are actually defined below
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7203
diff changeset
  1309
        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
  1310
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1311
    def formatvalue(self, value):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1312
        """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
  1313
        try:
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1314
            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
  1315
        except (ValueError, OverflowError):
44775b275d45 [facets] closes #1569459 (date-range facet with year < 1900)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7070
diff changeset
  1316
            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
  1317
        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
  1318
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1319
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1320
class HasRelationFacet(AbstractFacet):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1321
    """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
  1322
    (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
  1323
    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
  1324
    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
  1325
    `rtype` and `role` attributes.
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1326
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1327
    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
  1328
    and the corresponding code:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1329
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1330
    .. image:: ../images/facet_has_image.png
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1331
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1332
    .. sourcecode:: python
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1333
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1334
      class HasImageFacet(HasRelationFacet):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1335
          __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
  1336
          __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
  1337
          rtype = 'has_image'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1338
          role = 'subject'
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1339
    """
7280
571b29842ef1 [facet] add missing selector to HasRelationFacet
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7279
diff changeset
  1340
    __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
  1341
    rtype = None # override me in subclass
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1342
    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
  1343
6336
ae80aed607f2 [facet] use contextified label when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6251
diff changeset
  1344
    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
  1345
    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
  1346
    support_and = False
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1347
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1348
    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
  1349
        return CheckBoxFacetWidget(self._cw, self,
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1350
                                   '%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
  1351
                                   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
  1352
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1353
    def add_rql_restrictions(self):
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1354
        """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
  1355
        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
  1356
        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
  1357
        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
  1358
            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
  1359
        var = self.select.make_variable()
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1360
        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
  1361
            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
  1362
        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
  1363
            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
  1364
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1365
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1366
## html widets ################################################################
7849
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1367
_DEFAULT_CONSTANT_VOCAB_WIDGET_HEIGHT = 9
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1368
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1369
@cached
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1370
def _css_height_to_line_count(vreg):
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1371
    cssprop = vreg.config.uiprops['facet_overflowedHeight'].lower().strip()
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1372
    # let's talk a bit ...
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1373
    # we try to deduce a number of displayed lines from a css property
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1374
    # there is a linear (rough empiric coefficient == 0.73) relation between
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1375
    # css _em_ value and line qty
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1376
    # if we get another unit we're out of luck and resort to one constant
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1377
    # hence, it is strongly advised not to specify but ems for this css prop
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1378
    if cssprop.endswith('em'):
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1379
        try:
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1380
            return int(cssprop[:-2]) * .73
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1381
        except Exception:
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1382
            vreg.warning('css property facet_overflowedHeight looks malformed (%r)',
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1383
                         cssprop)
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1384
    return _DEFAULT_CONSTANT_VOCAB_WIDGET_HEIGHT
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1385
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
  1386
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
  1387
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1388
    def __init__(self, facet):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1389
        self.facet = facet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1390
        self.items = []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1391
7849
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1392
    @cached
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
  1393
    def height(self):
7849
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1394
        maxheight = _css_height_to_line_count(self.facet._cw.vreg)
7937cf60f2ce [facets] fix height computation (incorporates and/or element if present, use css value to compute likely maximum height, kill wdg_stack_size) (closes #1954077)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7768
diff changeset
  1395
        return 1 + min(len(self.items), maxheight) + int(self.facet._support_and_compat())
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
  1396
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1397
    def append(self, item):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1398
        self.items.append(item)
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
  1399
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1400
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1401
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1402
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1403
        facetid = make_uid(self.facet.__regid__)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1404
        w(u'<div id="%s" class="facet">\n' % facetid)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1405
        w(u'<div class="facetTitle" cubicweb:facetName="%s">%s</div>\n' %
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1406
          (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
  1407
        if self.facet._support_and_compat():
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1408
            _ = self.facet._cw._
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1409
            w(u'''<select name="%s" class="radio facetOperator" title="%s">
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1410
  <option value="OR">%s</option>
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1411
  <option value="AND">%s</option>
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
  1412
</select>''' % (xml_escape(self.facet.__regid__) + '_andor', _('and/or between different values'),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1413
                _('OR'), _('AND')))
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1414
        cssclass = 'facetBody'
368
84a5106840fa facet widgets css cleanup
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 346
diff changeset
  1415
        if not self.facet.start_unfolded:
84a5106840fa facet widgets css cleanup
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents: 346
diff changeset
  1416
            cssclass += ' hidden'
949
1fba39d6ee70 fix in facets (avoid to have an horizontal space between facets when facets are unfold)
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 536
diff changeset
  1417
        if len(self.items) > 6:
1132
96752791c2b6 pylint cleanup
sylvain.thenault@logilab.fr
parents: 985
diff changeset
  1418
            cssclass += ' overflowed'
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1419
        w(u'<div class="%s">\n' % cssclass)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1420
        for item in self.items:
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1421
            item.render(w=w)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1422
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1423
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1424
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
  1425
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
  1426
class FacetStringWidget(htmlwidgets.HTMLWidget):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1427
    def __init__(self, facet):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1428
        self.facet = facet
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1429
        self.value = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1430
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
  1431
    def height(self):
7413
94ad9523abb7 [web/facet|views/table] bump a bit some heights, split table view methods for easier subclassing
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7402
diff changeset
  1432
        return 3
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
  1433
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1434
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1435
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1436
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1437
        facetid = make_uid(self.facet.__regid__)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1438
        w(u'<div id="%s" class="facet">\n' % facetid)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1439
        w(u'<div class="facetTitle" cubicweb:facetName="%s">%s</div>\n' %
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1440
               (xml_escape(self.facet.__regid__), title))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1441
        w(u'<input name="%s" type="text" value="%s" />\n' % (facetid, self.value or u''))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1442
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1443
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1444
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
  1445
class FacetRangeWidget(htmlwidgets.HTMLWidget):
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1446
    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
  1447
    onload = u'''
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1448
    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
  1449
    jQuery("#%(sliderid)s").slider({
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1450
        range: true,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1451
        min: %(minvalue)s,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1452
        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
  1453
        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
  1454
        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
  1455
           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
  1456
           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
  1457
        },
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1458
        slide: function(event, ui) {
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1459
            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
  1460
            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
  1461
            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
  1462
            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
  1463
        }
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
  1464
   });
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1465
   // 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
  1466
   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
  1467
   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
  1468
'''
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1469
    #'# 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
  1470
    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
  1471
        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
  1472
        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
  1473
        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
  1474
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
  1475
    def height(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
  1476
        return 3
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
  1477
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
  1478
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1479
        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
  1480
        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
  1481
        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
  1482
        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
  1483
        sliderid = make_uid('theslider')
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1484
        facetname = self.facet.__regid__
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1485
        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
  1486
        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
  1487
            'sliderid': sliderid,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1488
            'facetid': facetid,
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1489
            'facetname': facetname,
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1490
            'minvalue': self.minvalue,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1491
            'maxvalue': self.maxvalue,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1492
            'formatter': self.formatter,
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1493
            })
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1494
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1495
        facetname = xml_escape(facetname)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1496
        w(u'<div id="%s" class="facet">\n' % facetid)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1497
        w(u'<div class="facetTitle" cubicweb:facetName="%s">%s</div>\n' %
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1498
          (facetname, title))
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1499
        cssclass = 'facetBody'
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1500
        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
  1501
            cssclass += ' hidden'
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1502
        w(u'<div class="%s">\n' % cssclass)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1503
        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
  1504
          % (sliderid, sliderid))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1505
        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
  1506
          % (facetname, self.minvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1507
        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
  1508
          % (facetname, self.maxvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1509
        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
  1510
          % (facetname, self.minvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1511
        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
  1512
          % (facetname, self.maxvalue))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1513
        w(u'<div id="%s"></div>' % sliderid)
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1514
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1515
        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
  1516
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
  1517
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
  1518
class DateFacetRangeWidget(FacetRangeWidget):
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1519
2020
fe437afc8fb7 [facet] refactor values formatting in RangeFacets
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2016
diff changeset
  1520
    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
  1521
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1522
    def round_max_value(self, d):
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1523
        'round to upper value to avoid filtering out the max value'
2152
Florent <florent@secondweb.fr>
parents: 2149
diff changeset
  1524
        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
  1525
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
  1526
    def __init__(self, facet, minvalue, maxvalue):
2149
6a631ec5cc71 fix date rounding issue in DateFacetRangeWidget
Florent <florent@secondweb.fr>
parents: 2130
diff changeset
  1527
        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
  1528
        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
  1529
                                                   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
  1530
                                                   datetime2ticks(maxvalue))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1531
        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
  1532
        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
  1533
c594323929cb [facet] provide a DateRangeFacet (still need to refactor, maybe create a CWWidget)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1977
diff changeset
  1534
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
  1535
class FacetItem(htmlwidgets.HTMLWidget):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1536
203
60cd67acf7fd FacetItem now takes req as first parameter of __init__, THIS IS BACKWARD INCOMPATIBLE
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 0
diff changeset
  1537
    selected_img = "black-check.png"
60cd67acf7fd FacetItem now takes req as first parameter of __init__, THIS IS BACKWARD INCOMPATIBLE
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 0
diff changeset
  1538
    unselected_img = "no-check-no-border.png"
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1539
203
60cd67acf7fd FacetItem now takes req as first parameter of __init__, THIS IS BACKWARD INCOMPATIBLE
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 0
diff changeset
  1540
    def __init__(self, req, label, value, selected=False):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3369
diff changeset
  1541
        self._cw = req
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1542
        self.label = label
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1543
        self.value = value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1544
        self.selected = selected
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1545
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1546
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1547
        w = self.w
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1548
        cssclass = 'facetValue facetCheckBox'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1549
        if self.selected:
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1550
            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
  1551
            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
  1552
            imgalt = self._cw._('selected')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1553
        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
  1554
            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
  1555
            imgalt = self._cw._('not selected')
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1556
        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
  1557
          % (cssclass, xml_escape(unicode(self.value))))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1558
        w(u'<img src="%s" alt="%s"/>&#160;' % (imgsrc, imgalt))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1559
        w(u'<a href="javascript: {}">%s</a>' % xml_escape(self.label))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1560
        w(u'</div>')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1561
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1562
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
  1563
class CheckBoxFacetWidget(htmlwidgets.HTMLWidget):
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1564
    selected_img = "black-check.png"
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1565
    unselected_img = "black-uncheck.png"
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1566
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1567
    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
  1568
        self._cw = req
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1569
        self.facet = facet
2016
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1570
        self.value = value
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1571
        self.selected = selected
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1572
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
  1573
    def height(self):
7413
94ad9523abb7 [web/facet|views/table] bump a bit some heights, split table view methods for easier subclassing
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7402
diff changeset
  1574
        return 2
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
  1575
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1576
    def _render(self):
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1577
        w = self.w
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2305
diff changeset
  1578
        title = xml_escape(self.facet.title)
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1579
        facetid = make_uid(self.facet.__regid__)
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1580
        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
  1581
        cssclass = 'facetValue facetCheckBox'
2016
a6638de6d4da [views] reindent web/facet.py
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2014
diff changeset
  1582
        if self.selected:
7225
a4a115aab086 [facets] make rangefacet comply with start_unfolded (closes #1615869)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7205
diff changeset
  1583
            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
  1584
            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
  1585
            imgalt = self._cw._('selected')
2014
71a9ab77d9f8 [facet] provide hasRelationFacet (backport from CMHN)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2010
diff changeset
  1586
        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
  1587
            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
  1588
            imgalt = self._cw._('not selected')
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1589
        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
  1590
          % (cssclass, xml_escape(unicode(self.value))))
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1591
        w(u'<div class="facetCheckBoxWidget">')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1592
        w(u'<img src="%s" alt="%s" cubicweb:unselimg="true" />&#160;' % (imgsrc, imgalt))
7626
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1593
        w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>'
56300bec75f8 [facets] use unique dom id
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7625
diff changeset
  1594
          % (xml_escape(self.facet.__regid__), title))
7414
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1595
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1596
        w(u'</div>\n')
de802bcb6348 [web.facet] self.w -> w
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7413
diff changeset
  1597
        w(u'</div>\n')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1598
3329
8430f6c693a1 cleanup, smarter sort control to avoid it when not necessary
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3328
diff changeset
  1599
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
  1600
class FacetSeparator(htmlwidgets.HTMLWidget):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1601
    def __init__(self, label=None):
2996
866a2c135c33 B #345282 xhtml requires to use &#160; instead of &nbsp;
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2658
diff changeset
  1602
        self.label = label or u'&#160;'
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
  1603
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1604
    def _render(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1605
        pass
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1606
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1607
# other classes ################################################################
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1608
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1609
class FilterRQLBuilder(object):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1610
    """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
  1611
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1612
    def __init__(self, req):
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1613
        self._cw = req
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1614
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
  1615
    def build_rql(self):
6120
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1616
        form = self._cw.form
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1617
        facetids = form['facets'].split(',')
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1618
        # XXX Union unsupported yet
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1619
        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
  1620
        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
  1621
        toupdate = []
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1622
        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
  1623
            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
  1624
            facet.add_rql_restrictions()
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1625
            if facet.needs_update:
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1626
                toupdate.append(facetid)
c000e41316ec [book] some more documentation and cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6119
diff changeset
  1627
        return select.as_string(), toupdate