Browse Source

[search] Adding support for sorting the grid layout

Romain Rigaux 11 years ago
parent
commit
65022ca66d

+ 13 - 2
apps/search/src/search/api.py

@@ -105,7 +105,6 @@ class SolrApi(object):
         ('facet', 'true'),
         ('facet.mincount', 0),
         ('facet.limit', 10),
-        ##('facet.sort', properties.get('sort')),
       )
       params += tuple([('facet.field', '{!ex=%s}%s' % (facet['field'], facet['field'])) for facet in collection['facets']])
 
@@ -113,7 +112,7 @@ class SolrApi(object):
     for fq, val in fqs.iteritems():
       params += (('fq', urllib.unquote(utf_quoter('{!tag=%s}{!field f=%s}%s' % (fq, fq, val)))),)
 
-#    if collection['fields']:
+#    if collection['template']['fields']:
       # If we do this, need to parse the template and fill up the fields list
       #params += (('fl', urllib.unquote(utf_quoter(','.join(collection['fields'])))),)
     params += (('fl', '*'),)
@@ -124,6 +123,18 @@ class SolrApi(object):
       ('hl.snippets', 3)
     )
 
+    if collection['template']['fieldsSelected']:
+      fields = []
+      for field in collection['template']['fieldsSelected']:
+        attribute_field = filter(lambda attribute: field == attribute['name'], collection['template']['fieldsAttributes'])
+        if attribute_field:
+          if attribute_field[0]['sort']['direction']:
+            fields.append('%s %s' % (field, attribute_field[0]['sort']['direction']))
+      if fields:
+        params += (         
+          ('sort', ','.join(fields)),
+        )
+
     response = self._root.get('%(collection)s/select' % solr_query, params)
 
     return self._get_json(response)

+ 12 - 8
apps/search/src/search/models.py

@@ -260,17 +260,17 @@ class Collection(models.Model):
 #    props['collection'] = self.get_default(user) # to reset
 #    props['layout'] = []
     
-    # Adding dynamic properties
-    props['collection']['template']['extended_fields'] = self.fields_data(user)
+    # TODO: Adding dynamic properties, merge smartly
+    # props['collection']['template']['extended_fields'] = self.fields_data(user)
    
     return json.dumps(props)
 
   def get_default(self, user):      
-    extended_fields = self.fields_data(user)
-    id_field = [field['name'] for field in extended_fields if field.get('isId')]
+    fields = self.fields_data(user)
+    id_field = [field['name'] for field in fields if field.get('isId')]
     if id_field:
       id_field = id_field[0]
-    fields = [field.get('name') for field in self.fields_data(user)]
+#    fields = [field.get('name') for field in self.fields_data(user)]
   
     TEMPLATE = {
       "extracode": "<style type=\"text/css\">\nem {\n  font-weight: bold;\n  background-color: yellow;\n}</style>", "highlighting": [""],
@@ -281,10 +281,11 @@ class Collection(models.Model):
           <div class="span12">%s</div>
         </div>
         <br/>
-      </div>""" % ' '.join(['{{%s}}' % field for field in fields]), 
+      </div>""" % ' '.join(['{{%s}}' % field['name'] for field in fields]), 
       "isGridLayout": True,
       "showFieldList": True,
-      "fields": fields
+      "fieldsAttributes": [{'name': field['name'], 'sort': {'direction': None}} for field in fields], # sort priority, asc/desc/none
+      "fieldsSelected": [field['name'] for field in fields],
     }
     
     FACETS = {
@@ -310,7 +311,7 @@ class Collection(models.Model):
     schema_fields = schema_fields['schema']['fields']
 
     return sorted([{'name': str(field), 'type': str(attributes.get('type', '')),
-                    'isId': attributes.get('required') and attributes.get('uniqueKey')
+                    'isId': attributes.get('required') and attributes.get('uniqueKey'),
                   }
                   for field, attributes in schema_fields.iteritems()])
 
@@ -595,6 +596,9 @@ def augment_solr_response(response, facets, solr_query):
           normalized_facets[uuid] = facet
 
     if response and response.get('response'):
+      
+      # Todo, and not as ugly as below, probably simplify to go back beginning + < >
+      
       pages_to_show = 5 # always use an odd number since we do it symmetrically
 
 #      beginning = 0

+ 22 - 11
apps/search/src/search/templates/search2.mako

@@ -354,9 +354,9 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
         data-bind="click: toggleGridFieldsSelection, css: { 'btn-inverse': $root.collection.template.fields().length > 0 }">
         <i class="fa fa-square-o"></i>
       </a>
-      <div data-bind="foreach: $root.collection.fields">
-        <input type="checkbox" data-bind="value: $data, checked: $root.collection.template.fields" />
-        <span data-bind="text: '&nbsp;' + $data"></span>
+      <div data-bind="foreach: $root.collection.template.fieldsAttributes">
+        <input type="checkbox" data-bind="checkedValue: name, checked: $root.collection.template.fieldsSelected" /> 
+        <span data-bind="text: '&nbsp;' + name()"></span>
         <br/>
       </div>
     </span>
@@ -364,7 +364,7 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
   <!-- /ko -->
 
   <!-- ko if: !$root.collection.template.isGridLayout() && $root.isEditing() -->
-    <textarea data-bind="value: $root.collection.template.template, valueUpdate:'afterkeydown'" class="span12" style="height: 100px"></textarea>
+    <textarea data-bind="value: $root.collection.template.template, valueUpdate: 'afterkeydown'" class="span12" style="height: 100px"></textarea>
     <br/>
   <!-- /ko -->
 
@@ -378,12 +378,17 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
     <!-- /ko -->
     
 	<!-- ko if: $root.collection.template.isGridLayout() -->
-    <table id="result-container" data-bind="visible: !($root.isRetrievingResults())" style="margin-top: 0">
+    <table id="result-container" data-bind="visible: !$root.isRetrievingResults()" style="margin-top: 0">
       <thead>
         <tr data-bind="visible: $root.results().length > 0, foreach: $root.collection.template.fields">
-          <th data-bind="text: $data"></th>
+          <th>
+            <a href="javascript: void(0)" title="${ _('Sort') }">
+              <span data-bind="text: name, click: $root.collection.toggleSortColumnGridLayout"></span>
+              <i class="fa" data-bind="visible: sort.direction() != null, css: { 'fa-chevron-down': sort.direction() == 'desc', 'fa-chevron-up': sort.direction() == 'asc' }"></i>
+            </a>
+          </th>
         </tr>
-        <tr data-bind="visible: $root.collection.template.fields().length == 0">
+        <tr data-bind="visible: $root.collection.template.fieldsSelected().length == 0">
           <th>${ ('Document') }</th>
         </tr>
       </thead>
@@ -407,7 +412,7 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
 </script>
 
 <script type="text/html" id="resultset-pagination">
-  <span data-bind="text: $data.response.numFound"></span> ${ _(' results') } 
+  <span data-bind="text: $data.response.numFound"></span> ${ _(' results') } <i class="fa fa-arrow-right"></i>
 </script>
 
 <script type="text/html" id="timeline-widget">
@@ -419,7 +424,7 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
 </script>
 
 <script type="text/html" id="pie-widget">
-  This is the pie widget
+  This is the pai widget
 </script>
 
 <script type="text/html" id="area-widget">
@@ -537,15 +542,21 @@ $(document).ready(function () {
   viewModel = new SearchViewModel(${ collection.get_c(user) | n,unicode }, ${ query | n,unicode });
   ko.applyBindings(viewModel);
 
+  
+
   viewModel.isEditing(true);
   viewModel.search();
 });
 
   function toggleGridFieldsSelection() {
     if (viewModel.collection.template.fields().length > 0) {
-      viewModel.collection.template.fields([])
+      viewModel.collection.template.fieldsSelected([])
     } else {
-      viewModel.collection.template.fields(viewModel.collection.fields());
+      var _fields = [];
+      $.each(viewModel.collection.fields(), function (index, field) {
+        _fields.push(field.name());
+      });
+      viewModel.collection.template.fieldsSelected(_fields);
     };
   };  
 

+ 32 - 8
apps/search/static/js/search.ko.js

@@ -211,7 +211,7 @@ var Collection = function (vm, collection) {
   self.name = collection.name;
   self.idField = collection.idField;
   self.template = ko.mapping.fromJS(collection.template);
-  self.template.fields.subscribe(function () {
+  self.template.fieldsSelected.subscribe(function () {
     vm.search();
   });
   self.template.template.subscribe(function () {
@@ -222,13 +222,14 @@ var Collection = function (vm, collection) {
   });
   self.facets = ko.mapping.fromJS(collection.facets);
 
-  self.fields = ko.observableArray(collection.fields);
+  self.fields = ko.mapping.fromJS(collection.fields);
 
   self.addFacet = function (facet_json) {
     self.facets.push(ko.mapping.fromJS({
       "id": facet_json.widget_id,
       "label": facet_json.name,
-      "field": facet_json.name, "type": "field"
+      "field": facet_json.name,
+      "type": "field"
     }));
   }
 
@@ -250,6 +251,17 @@ var Collection = function (vm, collection) {
     return _facet;
   }  
   
+  self.template.fields = ko.computed(function () {
+    var _fields = [];
+    $.each(self.template.fieldsAttributes(), function (index, field) {
+      var position = self.template.fieldsSelected.indexOf(field.name());
+      if (position != -1) {
+    	_fields[position] = field;
+      }      
+    });
+    return _fields;
+  });    
+  
   self.addDynamicFields = function () {
     $.post("/search/index/" + self.id + "/fields/dynamic", {
       }, function (data) {
@@ -263,7 +275,19 @@ var Collection = function (vm, collection) {
     }).fail(function (xhr, textStatus, errorThrown) {});
   }
 
-  self.addDynamicFields();
+  self.toggleSortColumnGridLayout = function (template_field) {
+	 if (! template_field.sort.direction()) {
+	   template_field.sort.direction('desc');
+	 } else if (template_field.sort.direction() == 'desc') {
+	   template_field.sort.direction('asc');
+	 } else {
+	   template_field.sort.direction(null); 
+	 }
+
+	 vm.search();
+  };
+
+  //self.addDynamicFields(); + update fields in case
 };
 
 
@@ -294,7 +318,7 @@ var SearchViewModel = function (collection_json, query_json) {
 
   self.previewColumns = ko.observable("");
   self.columns = ko.observable({});
-  loadLayout(self, collection_json.layout); // move to init + load dynamic fields?
+  loadLayout(self, collection_json.layout); // move to init + load dynamic fields?  
   
   self.isEditing = ko.observable(false);
   self.toggleEditing = function () {
@@ -329,11 +353,11 @@ var SearchViewModel = function (collection_json, query_json) {
           // Table view
           $.each(data.response.docs, function (index, item) {
             var row = [];
-            var fields = self.collection.template.fields();
+            var fields = self.collection.template.fieldsSelected();
             // Field selection or whole record
             if (fields.length != 0) {
-              $.each(self.collection.template.fields(), function (index, column) {
-                row.push(item[column]);
+              $.each(self.collection.template.fieldsSelected(), function (index, field) {//alert(ko.mapping.toJSON(field));  
+                row.push(item[field]);
               });
             } else {
               row.push(ko.mapping.toJSON(item));