web/facet.py
changeset 3369 7b88d12b4ee2
parent 3023 7864fee8b4ec
parent 3333 c61a526b530e
child 3451 6b46d73823f5
equal deleted inserted replaced
3300:c7c4775a5619 3369:7b88d12b4ee2
   174         term = nodes.SortTerm(sortfunc, sortasc)
   174         term = nodes.SortTerm(sortfunc, sortasc)
   175         rqlst.add_sort_term(term)
   175         rqlst.add_sort_term(term)
   176 
   176 
   177 def insert_attr_select_relation(rqlst, mainvar, rtype, role, attrname,
   177 def insert_attr_select_relation(rqlst, mainvar, rtype, role, attrname,
   178                                 sortfuncname=None, sortasc=True):
   178                                 sortfuncname=None, sortasc=True):
   179     """modify a syntax tree to retrieve only relevant attribute `attr` of `var`"""
   179     """modify a syntax tree to :
       
   180     * link a new variable to `mainvar` through `rtype` (where mainvar has `role`)
       
   181     * retrieve only the newly inserted variable and its `attrname`
       
   182 
       
   183     Sorting:
       
   184     * on `attrname` ascendant (`sortasc`=True) or descendant (`sortasc`=False)
       
   185     * on `sortfuncname`(`attrname`) if `sortfuncname` is specified
       
   186     * no sort if `sortasc` is None
       
   187     """
   180     _cleanup_rqlst(rqlst, mainvar)
   188     _cleanup_rqlst(rqlst, mainvar)
   181     var = _prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role)
   189     var = _prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role)
   182     # not found, create one
   190     # not found, create one
   183     attrvar = rqlst.make_variable()
   191     attrvar = rqlst.make_variable()
   184     rqlst.add_relation(var, attrname, attrvar)
   192     rqlst.add_relation(var, attrname, attrvar)
   185     # if query is grouped, we have to add the attribute variable
   193     # if query is grouped, we have to add the attribute variable
   186     if rqlst.groupby:
   194     if rqlst.groupby:
   187         if not attrvar in rqlst.groupby:
   195         if not attrvar in rqlst.groupby:
   188             rqlst.add_group_var(attrvar)
   196             rqlst.add_group_var(attrvar)
   189     _set_orderby(rqlst, attrvar, sortasc, sortfuncname)
   197     if sortasc is not None:
       
   198         _set_orderby(rqlst, attrvar, sortasc, sortfuncname)
   190     # add attribute variable to selection
   199     # add attribute variable to selection
   191     rqlst.add_selected(attrvar)
   200     rqlst.add_selected(attrvar)
   192     # add is restriction if necessary
   201     # add is restriction if necessary
   193     if not mainvar.stinfo['typerels']:
   202     if not mainvar.stinfo['typerels']:
   194         etypes = frozenset(sol[mainvar.name] for sol in rqlst.solutions)
   203         etypes = frozenset(sol[mainvar.name] for sol in rqlst.solutions)
   344     # set this to a stored procedure name if you want to sort on the result of
   353     # set this to a stored procedure name if you want to sort on the result of
   345     # this function's result instead of direct value
   354     # this function's result instead of direct value
   346     sortfunc = None
   355     sortfunc = None
   347     # ascendant/descendant sorting
   356     # ascendant/descendant sorting
   348     sortasc = True
   357     sortasc = True
       
   358     # if you want to call a view on the entity instead of using `target_attr`
       
   359     label_vid = None
   349 
   360 
   350     @property
   361     @property
   351     def title(self):
   362     def title(self):
   352         return display_name(self.req, self.rtype, form=self.role)
   363         return display_name(self.req, self.rtype, form=self.role)
   353 
   364 
   354     def vocabulary(self):
   365     def vocabulary(self):
   355         """return vocabulary for this facet, eg a list of 2-uple (label, value)
   366         """return vocabulary for this facet, eg a list of 2-uple (label, value)
   356         """
   367         """
   357         rqlst = self.rqlst
   368         rqlst = self.rqlst
   358         rqlst.save_state()
   369         rqlst.save_state()
       
   370         if self.label_vid is not None and self.sortfunc is None:
       
   371             sort = None # will be sorted on label
       
   372         else:
       
   373             sort = self.sortasc
   359         try:
   374         try:
   360             mainvar = self.filtered_variable
   375             mainvar = self.filtered_variable
   361             insert_attr_select_relation(rqlst, mainvar, self.rtype, self.role,
   376             insert_attr_select_relation(rqlst, mainvar, self.rtype, self.role,
   362                                         self.target_attr, self.sortfunc, self.sortasc)
   377                                         self.target_attr, self.sortfunc, sort)
   363             try:
   378             try:
   364                 rset = self.rqlexec(rqlst.as_string(), self.rset.args, self.rset.cachekey)
   379                 rset = self.rqlexec(rqlst.as_string(), self.rset.args, self.rset.cachekey)
   365             except:
   380             except:
   366                 self.exception('error while getting vocabulary for %s, rql: %s',
   381                 self.exception('error while getting vocabulary for %s, rql: %s',
   367                                self, rqlst.as_string())
   382                                self, rqlst.as_string())
   382             return [str(x) for x, in self.rqlexec(rqlst.as_string())]
   397             return [str(x) for x, in self.rqlexec(rqlst.as_string())]
   383         finally:
   398         finally:
   384             rqlst.recover()
   399             rqlst.recover()
   385 
   400 
   386     def rset_vocabulary(self, rset):
   401     def rset_vocabulary(self, rset):
   387         _ = self.req._
   402         if self.label_vid is None:
   388         return [(_(label), eid) for eid, label in rset]
   403             _ = self.req._
       
   404             return [(_(label), eid) for eid, label in rset]
       
   405         if self.sortfunc is None:
       
   406             return sorted((entity.view(self.label_vid), entity.eid)
       
   407                           for entity in rset.entities())
       
   408         return [(entity.view(self.label_vid), entity.eid)
       
   409                 for entity in rset.entities()]
   389 
   410 
   390     @cached
   411     @cached
   391     def support_and(self):
   412     def support_and(self):
   392         rschema = self.schema.rschema(self.rtype)
   413         rschema = self.schema.rschema(self.rtype)
   393         if self.role == 'subject':
   414         if self.role == 'subject':
   529         self.rqlst.add_constant_restriction(self.filtered_variable,
   550         self.rqlst.add_constant_restriction(self.filtered_variable,
   530                                             self.rtype,
   551                                             self.rtype,
   531                                             self.formatvalue(supvalue),
   552                                             self.formatvalue(supvalue),
   532                                             self.attrtype, '<=')
   553                                             self.attrtype, '<=')
   533 
   554 
       
   555 
   534 class DateRangeFacet(RangeFacet):
   556 class DateRangeFacet(RangeFacet):
   535     attrtype = 'Date' # only date types are supported
   557     attrtype = 'Date' # only date types are supported
   536 
   558 
   537     @property
   559     @property
   538     def wdgclass(self):
   560     def wdgclass(self):
   568         var = self.rqlst.make_variable()
   590         var = self.rqlst.make_variable()
   569         if self.role == 'subject':
   591         if self.role == 'subject':
   570             self.rqlst.add_relation(self.filtered_variable, self.rtype, var)
   592             self.rqlst.add_relation(self.filtered_variable, self.rtype, var)
   571         else:
   593         else:
   572             self.rqlst.add_relation(var, self.rtype, self.filtered_variable)
   594             self.rqlst.add_relation(var, self.rtype, self.filtered_variable)
       
   595 
   573 
   596 
   574 ## html widets ################################################################
   597 ## html widets ################################################################
   575 
   598 
   576 class FacetVocabularyWidget(HTMLWidget):
   599 class FacetVocabularyWidget(HTMLWidget):
   577 
   600 
   654 
   677 
   655     def _render(self):
   678     def _render(self):
   656         facet = self.facet
   679         facet = self.facet
   657         facet.req.add_js('ui.slider.js')
   680         facet.req.add_js('ui.slider.js')
   658         facet.req.add_css('ui.all.css')
   681         facet.req.add_css('ui.all.css')
   659         sliderid = make_uid('the slider')
   682         sliderid = make_uid('theslider')
   660         facetid = xml_escape(self.facet.id)
   683         facetid = xml_escape(self.facet.id)
   661         facet.req.html_headers.add_onload(self.onload % {
   684         facet.req.html_headers.add_onload(self.onload % {
   662             'sliderid': sliderid,
   685             'sliderid': sliderid,
   663             'facetid': facetid,
   686             'facetid': facetid,
   664             'minvalue': self.minvalue,
   687             'minvalue': self.minvalue,
   720                % (cssclass, xml_escape(unicode(self.value))))
   743                % (cssclass, xml_escape(unicode(self.value))))
   721         self.w(u'<img src="%s" alt="%s"/>&#160;' % (imgsrc, imgalt))
   744         self.w(u'<img src="%s" alt="%s"/>&#160;' % (imgsrc, imgalt))
   722         self.w(u'<a href="javascript: {}">%s</a>' % xml_escape(self.label))
   745         self.w(u'<a href="javascript: {}">%s</a>' % xml_escape(self.label))
   723         self.w(u'</div>')
   746         self.w(u'</div>')
   724 
   747 
       
   748 
   725 class CheckBoxFacetWidget(HTMLWidget):
   749 class CheckBoxFacetWidget(HTMLWidget):
   726     selected_img = "black-check.png"
   750     selected_img = "black-check.png"
   727     unselected_img = "black-uncheck.png"
   751     unselected_img = "black-uncheck.png"
   728 
   752 
   729     def __init__(self, req, facet, value, selected):
   753     def __init__(self, req, facet, value, selected):
   751         self.w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>' % (facetid, title))
   775         self.w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>' % (facetid, title))
   752         self.w(u'</div>\n')
   776         self.w(u'</div>\n')
   753         self.w(u'</div>\n')
   777         self.w(u'</div>\n')
   754         self.w(u'</div>\n')
   778         self.w(u'</div>\n')
   755 
   779 
       
   780 
   756 class FacetSeparator(HTMLWidget):
   781 class FacetSeparator(HTMLWidget):
   757     def __init__(self, label=None):
   782     def __init__(self, label=None):
   758         self.label = label or u'&#160;'
   783         self.label = label or u'&#160;'
   759 
   784 
   760     def _render(self):
   785     def _render(self):