--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/facets.py Wed Nov 05 15:52:50 2008 +0100
@@ -0,0 +1,161 @@
+"""the facets box and some basic facets
+
+:organization: Logilab
+:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+
+from simplejson import dumps
+
+from logilab.mtconverter import html_escape
+
+from cubicweb.common.selectors import (chainfirst, chainall, nfentity_selector,
+ twolinerset_selector, contextprop_selector,
+ yes_selector, one_has_relation_selector)
+from cubicweb.web.box import BoxTemplate
+from cubicweb.web.facet import (AbstractFacet, VocabularyFacet, FacetStringWidget,
+ RelationFacet, prepare_facets_rqlst, filter_hiddens)
+
+def contextview_selector(cls, req, rset, row=None, col=None, view=None,
+ **kwargs):
+ if view and getattr(view, 'filter_box_context_info', lambda: None)():
+ return 1
+ return 0
+
+
+class FilterBox(BoxTemplate):
+ """filter results of a query"""
+ id = 'filter_box'
+ __selectors__ = (chainfirst(contextview_selector,
+ chainall(nfentity_selector, twolinerset_selector)),
+ contextprop_selector)
+ context = 'left'
+ title = _('boxes_filter_box')
+ visible = True # functionality provided by the search box by default
+ order = 1
+
+ def facetargs(self):
+ """this method returns the list of extra arguments that should
+ be used by the facet
+ """
+ return {}
+
+ def _get_context(self, view):
+ context = getattr(view, 'filter_box_context_info', lambda: None)()
+ if context:
+ rset, vid, divid, paginate = context
+ else:
+ rset = self.rset
+ vid, divid = None, 'pageContent'
+ paginate = view.need_navigation
+ return rset, vid, divid, paginate
+
+ def call(self, view=None):
+ self.req.add_js( ('cubicweb.ajax.js', 'cubicweb.formfilter.js') )
+ rset, vid, divid, paginate = self._get_context(view)
+ if rset.rowcount < 2: # XXX done by selectors, though maybe necessary when rset has been hijacked
+ return
+ if vid is None:
+ vid = self.req.form.get('vid')
+ rqlst = rset.syntax_tree()
+ rqlst.save_state()
+ try:
+ mainvar, baserql = prepare_facets_rqlst(rqlst, rset.args)
+ widgets = []
+ for facet in self.get_facets(rset, mainvar):
+ if facet.propval('visible'):
+ wdg = facet.get_widget()
+ if wdg is not None:
+ widgets.append(wdg)
+ if not widgets:
+ return
+ w = self.w
+ w(u'<form method="post" id="%sForm" cubicweb:facetargs="%s" action="">' % (
+ divid, html_escape(dumps([divid, vid, paginate, self.facetargs()]))))
+ w(u'<fieldset>')
+ hiddens = {'facets': ','.join(wdg.facet.id for wdg in widgets),
+ 'baserql': baserql}
+ for param in ('subvid', 'vtitle'):
+ if param in self.req.form:
+ hiddens[param] = self.req.form[param]
+ filter_hiddens(w, **hiddens)
+ for wdg in widgets:
+ wdg.render(w=self.w)
+ w(u'</fieldset>\n</form>\n')
+ finally:
+ rqlst.recover()
+ print 'after facets', rqlst
+
+ def get_facets(self, rset, mainvar):
+ return self.vreg.possible_vobjects('facets', self.req, rset,
+ context='facetbox',
+ filtered_variable=mainvar)
+
+# facets ######################################################################
+
+class CreatedByFacet(RelationFacet):
+ id = 'created_by-facet'
+ rtype = 'created_by'
+ target_attr = 'login'
+
+class InGroupFacet(RelationFacet):
+ id = 'in_group-facet'
+ rtype = 'in_group'
+ target_attr = 'name'
+
+class InStateFacet(RelationFacet):
+ id = 'in_state-facet'
+ rtype = 'in_state'
+ target_attr = 'name'
+
+# inherit from RelationFacet to benefit from its possible_values implementation
+class ETypeFacet(RelationFacet):
+ id = 'etype-facet'
+ __selectors__ = (yes_selector,)
+ order = 1
+ rtype = 'is'
+ target_attr = 'name'
+
+ @property
+ def title(self):
+ return self.req._('entity type')
+
+ def vocabulary(self):
+ """return vocabulary for this facet, eg a list of 2-uple (label, value)
+ """
+ etypes = self.rset.column_types(0)
+ return sorted((self.req._(etype), etype) for etype in etypes)
+
+ def add_rql_restrictions(self):
+ """add restriction for this facet into the rql syntax tree"""
+ value = self.req.form.get(self.id)
+ if not value:
+ return
+ self.rqlst.add_type_restriction(self.filtered_variable, value)
+
+
+class HasTextFacet(AbstractFacet):
+ __selectors__ = (one_has_relation_selector, contextprop_selector)
+ id = 'has_text-facet'
+ rtype = 'has_text'
+ role = 'subject'
+ order = 0
+ @property
+ def title(self):
+ return self.req._('has_text')
+
+ def get_widget(self):
+ """return the widget instance to use to display this facet
+
+ default implentation expects a .vocabulary method on the facet and
+ return a combobox displaying this vocabulary
+ """
+ return FacetStringWidget(self)
+
+ def add_rql_restrictions(self):
+ """add restriction for this facet into the rql syntax tree"""
+ value = self.req.form.get(self.id)
+ if not value:
+ return
+ self.rqlst.add_constant_restriction(self.filtered_variable, 'has_text', value, 'String')