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: |
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"/> ' % (imgsrc, imgalt)) |
1510 w(u'<img src="%s" alt="%s"/> ' % (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 |