web/facet.py
branchstable
changeset 7768 bd44f506ca86
parent 7678 ab3d1a77be55
child 7849 7937cf60f2ce
equal deleted inserted replaced
7767:07c74f5585d1 7768:bd44f506ca86
    64 from cubicweb import Unauthorized, typed_eid
    64 from cubicweb import Unauthorized, typed_eid
    65 from cubicweb.schema import display_name
    65 from cubicweb.schema import display_name
    66 from cubicweb.utils import make_uid
    66 from cubicweb.utils import make_uid
    67 from cubicweb.selectors import match_context_prop, partial_relation_possible
    67 from cubicweb.selectors import match_context_prop, partial_relation_possible
    68 from cubicweb.appobject import AppObject
    68 from cubicweb.appobject import AppObject
    69 from cubicweb.web.htmlwidgets import HTMLWidget
    69 from cubicweb.web import RequestError, htmlwidgets
    70 
    70 
    71 
    71 
    72 def rtype_facet_title(facet):
    72 def rtype_facet_title(facet):
    73     ptypes = facet.cw_rset.column_types(0)
    73     ptypes = facet.cw_rset.column_types(0)
    74     if len(ptypes) == 1:
    74     if len(ptypes) == 1:
   429     def operator(self):
   429     def operator(self):
   430         """Return the operator (AND or OR) to use for this facet when multiple
   430         """Return the operator (AND or OR) to use for this facet when multiple
   431         values are selected.
   431         values are selected.
   432         """
   432         """
   433         # OR between selected values by default
   433         # OR between selected values by default
   434         return self._cw.form.get(self.__regid__ + '_andor', 'OR')
   434         return self._cw.form.get(xml_escape(self.__regid__) + '_andor', 'OR')
   435 
   435 
   436     def rqlexec(self, rql, args=None):
   436     def rqlexec(self, rql, args=None):
   437         """Utility method to execute some rql queries, and simply returning an
   437         """Utility method to execute some rql queries, and simply returning an
   438         empty list if :exc:`Unauthorized` is raised.
   438         empty list if :exc:`Unauthorized` is raised.
   439         """
   439         """
   718                  DeprecationWarning)
   718                  DeprecationWarning)
   719             support = support()
   719             support = support()
   720         return support
   720         return support
   721 
   721 
   722     def value_restriction(self, restrvar, rel, value):
   722     def value_restriction(self, restrvar, rel, value):
       
   723         # XXX handle rel is None case in RQLPathFacet?
   723         if self.restr_attr != 'eid':
   724         if self.restr_attr != 'eid':
   724             self.select.set_distinct(True)
   725             self.select.set_distinct(True)
   725         if isinstance(value, basestring):
   726         if isinstance(value, basestring):
   726             # only one value selected
   727             # only one value selected
   727             if value:
   728             if value:
   738             if '' in value:
   739             if '' in value:
   739                 value.remove('')
   740                 value.remove('')
   740                 self._add_not_rel_restr(rel)
   741                 self._add_not_rel_restr(rel)
   741             self._and_restriction(rel, restrvar, value)
   742             self._and_restriction(rel, restrvar, value)
   742         else:
   743         else:
   743             # multiple values with AND operator
   744             # multiple values with AND operator. We've to generate a query like
       
   745             # "X relation A, A eid 1, X relation B, B eid 1", hence the new
       
   746             # relations at each iteration in the while loop below 
   744             if '' in value:
   747             if '' in value:
   745                 value.remove('')
   748                 raise RequestError("this doesn't make sense")
   746                 self._add_not_rel_restr(rel)
       
   747             self._and_restriction(rel, restrvar, value.pop())
   749             self._and_restriction(rel, restrvar, value.pop())
   748             while value:
   750             while value:
   749                 restrvar, rtrel = _make_relation(self.select, self.filtered_variable,
   751                 restrvar, rtrel = _make_relation(self.select, self.filtered_variable,
   750                                                  self.rtype, self.role)
   752                                                  self.rtype, self.role)
       
   753                 if rel is None:
       
   754                     select.add_restriction(rtrel)
       
   755                 else:
       
   756                     rel.parent.replace(rel, nodes.And(rel, rtrel))
   751                 self._and_restriction(rel, restrvar, value.pop())
   757                 self._and_restriction(rel, restrvar, value.pop())
   752 
   758 
   753     def _and_restriction(self, rel, restrvar, value):
   759     def _and_restriction(self, rel, restrvar, value):
   754         if rel is None:
   760         if rel is None:
   755             self.select.add_constant_restriction(restrvar, self.restr_attr,
   761             self.select.add_constant_restriction(restrvar, self.restr_attr,
  1329             self.select.add_relation(var, self.rtype, self.filtered_variable)
  1335             self.select.add_relation(var, self.rtype, self.filtered_variable)
  1330 
  1336 
  1331 
  1337 
  1332 ## html widets ################################################################
  1338 ## html widets ################################################################
  1333 
  1339 
  1334 class FacetVocabularyWidget(HTMLWidget):
  1340 class FacetVocabularyWidget(htmlwidgets.HTMLWidget):
  1335 
  1341 
  1336     def __init__(self, facet):
  1342     def __init__(self, facet):
  1337         self.facet = facet
  1343         self.facet = facet
  1338         self.items = []
  1344         self.items = []
  1339 
  1345 
  1353         if self.facet._support_and_compat():
  1359         if self.facet._support_and_compat():
  1354             _ = self.facet._cw._
  1360             _ = self.facet._cw._
  1355             w(u'''<select name="%s" class="radio facetOperator" title="%s">
  1361             w(u'''<select name="%s" class="radio facetOperator" title="%s">
  1356   <option value="OR">%s</option>
  1362   <option value="OR">%s</option>
  1357   <option value="AND">%s</option>
  1363   <option value="AND">%s</option>
  1358 </select>''' % (facetid + '_andor', _('and/or between different values'),
  1364 </select>''' % (xml_escape(self.facet.__regid__) + '_andor', _('and/or between different values'),
  1359                 _('OR'), _('AND')))
  1365                 _('OR'), _('AND')))
  1360         cssclass = 'facetBody'
  1366         cssclass = 'facetBody'
  1361         if not self.facet.start_unfolded:
  1367         if not self.facet.start_unfolded:
  1362             cssclass += ' hidden'
  1368             cssclass += ' hidden'
  1363         if len(self.items) > 6:
  1369         if len(self.items) > 6:
  1367             item.render(w=w)
  1373             item.render(w=w)
  1368         w(u'</div>\n')
  1374         w(u'</div>\n')
  1369         w(u'</div>\n')
  1375         w(u'</div>\n')
  1370 
  1376 
  1371 
  1377 
  1372 class FacetStringWidget(HTMLWidget):
  1378 class FacetStringWidget(htmlwidgets.HTMLWidget):
  1373     def __init__(self, facet):
  1379     def __init__(self, facet):
  1374         self.facet = facet
  1380         self.facet = facet
  1375         self.value = None
  1381         self.value = None
  1376 
  1382 
  1377     def height(self):
  1383     def height(self):
  1386                (xml_escape(self.facet.__regid__), title))
  1392                (xml_escape(self.facet.__regid__), title))
  1387         w(u'<input name="%s" type="text" value="%s" />\n' % (facetid, self.value or u''))
  1393         w(u'<input name="%s" type="text" value="%s" />\n' % (facetid, self.value or u''))
  1388         w(u'</div>\n')
  1394         w(u'</div>\n')
  1389 
  1395 
  1390 
  1396 
  1391 class FacetRangeWidget(HTMLWidget):
  1397 class FacetRangeWidget(htmlwidgets.HTMLWidget):
  1392     formatter = 'function (value) {return value;}'
  1398     formatter = 'function (value) {return value;}'
  1393     onload = u'''
  1399     onload = u'''
  1394     var _formatter = %(formatter)s;
  1400     var _formatter = %(formatter)s;
  1395     jQuery("#%(sliderid)s").slider({
  1401     jQuery("#%(sliderid)s").slider({
  1396         range: true,
  1402         range: true,
  1476                                                    datetime2ticks(maxvalue))
  1482                                                    datetime2ticks(maxvalue))
  1477         fmt = facet._cw.property_value('ui.date-format')
  1483         fmt = facet._cw.property_value('ui.date-format')
  1478         facet._cw.html_headers.define_var('DATE_FMT', fmt)
  1484         facet._cw.html_headers.define_var('DATE_FMT', fmt)
  1479 
  1485 
  1480 
  1486 
  1481 class FacetItem(HTMLWidget):
  1487 class FacetItem(htmlwidgets.HTMLWidget):
  1482 
  1488 
  1483     selected_img = "black-check.png"
  1489     selected_img = "black-check.png"
  1484     unselected_img = "no-check-no-border.png"
  1490     unselected_img = "no-check-no-border.png"
  1485 
  1491 
  1486     def __init__(self, req, label, value, selected=False):
  1492     def __init__(self, req, label, value, selected=False):
  1504         w(u'<img src="%s" alt="%s"/>&#160;' % (imgsrc, imgalt))
  1510         w(u'<img src="%s" alt="%s"/>&#160;' % (imgsrc, imgalt))
  1505         w(u'<a href="javascript: {}">%s</a>' % xml_escape(self.label))
  1511         w(u'<a href="javascript: {}">%s</a>' % xml_escape(self.label))
  1506         w(u'</div>')
  1512         w(u'</div>')
  1507 
  1513 
  1508 
  1514 
  1509 class CheckBoxFacetWidget(HTMLWidget):
  1515 class CheckBoxFacetWidget(htmlwidgets.HTMLWidget):
  1510     selected_img = "black-check.png"
  1516     selected_img = "black-check.png"
  1511     unselected_img = "black-uncheck.png"
  1517     unselected_img = "black-uncheck.png"
  1512 
  1518 
  1513     def __init__(self, req, facet, value, selected):
  1519     def __init__(self, req, facet, value, selected):
  1514         self._cw = req
  1520         self._cw = req
  1541         w(u'</div>\n')
  1547         w(u'</div>\n')
  1542         w(u'</div>\n')
  1548         w(u'</div>\n')
  1543         w(u'</div>\n')
  1549         w(u'</div>\n')
  1544 
  1550 
  1545 
  1551 
  1546 class FacetSeparator(HTMLWidget):
  1552 class FacetSeparator(htmlwidgets.HTMLWidget):
  1547     def __init__(self, label=None):
  1553     def __init__(self, label=None):
  1548         self.label = label or u'&#160;'
  1554         self.label = label or u'&#160;'
  1549 
  1555 
  1550     def _render(self):
  1556     def _render(self):
  1551         pass
  1557         pass