瀏覽代碼

[search] Add id to widgets to map them to a model object

Romain Rigaux 11 年之前
父節點
當前提交
1a325c27ed

+ 18 - 7
apps/search/src/search/models.py

@@ -250,11 +250,13 @@ class Collection(models.Model):
 
   def get_c(self, user):
     props = self.properties_dict
-    print props
+
     if 'collection' not in props:
       props['collection'] = self.get_default(user)
     if 'layout' not in props:
       props['layout'] = []    
+#    props['collection'] = self.get_default(user) # to reset
+#    props['layout'] = []  
 
     return json.dumps(props)
 
@@ -280,8 +282,9 @@ class Collection(models.Model):
       "fields": fields
     }
     
-    FACETS = {"dates": [], "fields": [],
-       "charts": [], "properties": {"sort": "count", "mincount": 1, "isEnabled": True, "limit": 10, 'schemd_id_field': 'id'}, "ranges": [], "order": []
+    FACETS = {
+      "dates": [], "fields": [],
+      "charts": [], "properties": {"sort": "count", "mincount": 1, "isEnabled": True, "limit": 10, 'schemd_id_field': 'id'}, "ranges": [], "order": []
     };  
     
     collection_properties = {
@@ -344,12 +347,11 @@ class Collection(models.Model):
     if self.name == 'twitter_demo':
       return '/search/static/art/icon_twitter.png'
     elif self.name == 'yelp_demo':
-          return '/search/static/art/icon_yelp.png'
+      return '/search/static/art/icon_yelp.png'
     elif self.name == 'log_demo':
-          return '/search/static/art/icon_logs.png'
+      return '/search/static/art/icon_logs.png'
     else:
-          return '/search/static/art/icon_search_24.png'
-
+      return '/search/static/art/icon_search_24.png'
 
 def get_facet_field_format(field, type, facets):
   format = ""
@@ -370,6 +372,13 @@ def get_facet_field_format(field, type, facets):
     pass
   return format
 
+def get_facet_field(field, facets):
+  facets = filter(lambda facet: facet['type'] == 'field' and facet['field'] == field, facets)
+  if facets:
+    return facets[0]
+  else:
+    return None
+
 def get_facet_field_label(field, facets):
   label = field
 
@@ -437,7 +446,9 @@ def augment_solr_response2(response, collection, solr_query):
     if response['facet_counts']['facet_fields']:
       for cat in response['facet_counts']['facet_fields']:
         selected_field = fq.get(cat, '')
+        collection_facet = get_facet_field(cat, collection['facets'])
         facet = {
+          'id': collection_facet['id'],
           'field': cat,
           'type': 'field',
           'label': get_facet_field_label(cat, collection['facets']),

+ 18 - 12
apps/search/src/search/templates/search2.mako

@@ -281,10 +281,11 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
         <li><a href="javascript: void(0)" class="widget-settings-pill">${_('Settings')}</a></li>
       </ul>
 
-      <div data-bind="template: { name: function() { return widgetType(); }, data: properties }" class="widget-main-section"></div>
+      <div data-bind="template: { name: function() { return widgetType(); } }" class="widget-main-section"></div>
       <div data-bind="visible: $root.isEditing()" class="widget-settings-section">
         <ul class="unstyled" style="margin: 10px">
-          <li> Name: <input type="text" data-bind="value: name" class="input-mini" /></li>
+          <li>Name: <input type="text" data-bind="value: name" class="input-mini" /></li>
+          ## Could add here extra non widget settings like facet or see for a nice popover
         </ul>
       </div>
     </div>
@@ -296,12 +297,15 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
 </script>
 
 <script type="text/html" id="facet-widget">
-  <!-- ko if: $root.getFacet() -->
-  <div class="row-fluid" data-bind="with: $root.getFacet">
-    <div data-bind="visible: $root.isEditing, with: $root.collection.getSingleFacet()" style="margin-bottom: 20px">
-      ##${_('Add field')}
-      ##&nbsp;<a data-bind="click: showAddFacetModal" class="btn" href="javascript:void(0)"><i class="fa fa-plus"></i></a>
+  <!-- ko ifnot: $root.getFacetFromQuery(id) -->
+    <a data-bind="click: showAddFacetModal" class="btn" href="javascript:void(0)"><i class="fa fa-plus"></i></a>
+  <!-- /ko -->
+
+  <!-- ko if: $root.getFacetFromQuery(id) -->
+  <div class="row-fluid" data-bind="with: $root.getFacetFromQuery(id)">
+    <div data-bind="visible: $root.isEditing, with: $root.collection.getFacetById($parent.id())" style="margin-bottom: 20px">      
       ${ _('Label') }: <input type="text" data-bind="value: label" />
+      <br/>      
       ${ _('Field') }: <input type="text" data-bind="value: field" />
     </div>  
 
@@ -366,7 +370,7 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
   <!-- /ko -->
 
   <div style="overflow-x: auto">
-	  <!-- ko if: $root.collection.template.isGridLayout() -->
+	<!-- ko if: $root.collection.template.isGridLayout() -->
     <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">
@@ -391,7 +395,7 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
 	  <div id="result-container" data-bind="foreach: $root.results">
 	    <div class="result-row" data-bind="html: $data"></div>
 	  </div>
-	  <!-- /ko -->
+	<!-- /ko -->
   </div>
 </script>
 
@@ -438,6 +442,7 @@ ${ commonheader(_('Search'), "search", user, "60px") | n,unicode }
       <div style="margin-top: 20px">
         <div class="input-append">
           <input id="facetName" type="text">
+          <input id="widgetId" type="hidden">
         </div>
       </div>
     </p>
@@ -533,12 +538,13 @@ $(document).ready(function () {
     };
   };  
 
-  function showAddFacetModal(facet) {
+  function showAddFacetModal(widget) {
+    $("#widgetId").val(widget.id());
     $("#addFacetModal").modal("show");
   };
 
-  function submitAddFacetModal(facet) {
-    viewModel.collection.addFacet({'name': $("#facetName").val()});
+  function submitAddFacetModal() {
+    viewModel.collection.addFacet({'name': $("#facetName").val(), 'widget_id': $("#widgetId").val()});
     $('#addFacetModal').modal("hide");
     viewModel.search();
   };

+ 46 - 50
apps/search/static/js/search.ko.js

@@ -73,11 +73,12 @@ var Row = function (widgets) {
   }
 }
 
-var Widget = function (size, name, widgetType, properties, offset) {
+var Widget = function (size, id, name, widgetType, properties, offset) {
   var self = this;
   self.size = ko.observable(size).extend({ numeric: 0 });
 
   self.name = ko.observable(name);
+  self.id = ko.observable(id);
   self.widgetType = ko.observable(typeof widgetType != "undefined" && widgetType != null ? widgetType : "empty-widget");
   self.properties = ko.observable(typeof properties != "undefined" && properties != null ? properties : {});
   self.offset = ko.observable(typeof offset != "undefined" && offset != null ? offset : 0).extend({ numeric: 0 });
@@ -90,6 +91,7 @@ var Widget = function (size, name, widgetType, properties, offset) {
   self.expand = function () {
     self.size(self.size() + 1);
   }
+  
   self.compress = function () {
     self.size(self.size() - 1);
   }
@@ -97,18 +99,19 @@ var Widget = function (size, name, widgetType, properties, offset) {
   self.moveLeft = function () {
     self.offset(self.offset() - 1);
   }
+  
   self.moveRight = function () {
     self.offset(self.offset() + 1);
   }
 
   self.remove = function (row, widget) {
-	viewModel.removeWidget(widget);
+    viewModel.removeWidget(widget);
     row.widgets.remove(widget);
   }
 };
 
 Widget.prototype.clone = function () {
-  return new Widget(this.size(), this.name(), this.widgetType());
+  return new Widget(this.size(), UUID(), this.name(), this.widgetType());
 };
 
 function fullLayout() {
@@ -165,11 +168,11 @@ function loadLayout(viewModel, json_layout) {
   var _columns = [];
   
   $(json_layout).each(function (cnt, json_col) { 
-	var _rows = [];
+    var _rows = [];
     $(json_col.rows).each(function (rcnt, json_row) {
       var row = new Row();
       $(json_row.widgets).each(function (wcnt, widget) {
-    	row.addWidget(new Widget(widget.size, widget.name, widget.widgetType, widget.properties, widget.offset));
+        row.addWidget(new Widget(widget.size, widget.id, widget.name, widget.widgetType, widget.properties, widget.offset));
       });
       _rows.push(row);
     });
@@ -222,18 +225,25 @@ var Collection = function (vm, collection) {
 
   self.addFacet = function (facet_json) {
     self.facets.push(ko.mapping.fromJS({
-      "uuid": "f6618a5c-bbba-2886-1886-bbcaf01409ca",
-      "verbatim": "", "isVerbatim": false, "label": facet_json.name,
+      "id": facet_json.widget_id,
+      "label": facet_json.name,
       "field": facet_json.name, "type": "field"
     }));
   }
 
-  self.getSingleFacet = function (normalized_facet_json) {
-	normalized_facet_json = 'user_location';
-	var _facet = null;
+  self.removeFacet = function (widget_id) {
+    $.each(self.facets(), function (index, item) {
+      if (item.id() == widget_id()) {
+        self.facets.remove(item);
+      }
+    });
+  }  
+  
+  self.getFacetById = function (facet_id) {
+    var _facet = null;
     $.each(self.facets(), function (index, facet) {
-      if (facet.field() == normalized_facet_json) {
-    	  _facet = facet;
+      if (facet.id() == facet_id) {
+        _facet = facet;
       }      
     });
     return _facet;
@@ -241,7 +251,7 @@ var Collection = function (vm, collection) {
   
   self.addDynamicFields = function () {
     $.post("/search/index/" + self.id + "/fields/dynamic", {
-    },function (data) {
+      }, function (data) {
       if (data.status == 0) {
         $.each(data.dynamic_fields, function (index, field) {
           if (self.fields.indexOf(field) == -1) {
@@ -269,30 +279,35 @@ var SearchViewModel = function (collection_json, query_json) {
   self.norm_facets = ko.computed(function () {
     return self.response().normalized_facets;
   });
-  self.getFacet = function (name) { // todo
-	return self.norm_facets() !== undefined ? self.norm_facets()[0] : false;
+  self.getFacetFromQuery = function (facet_id) {	
+    var _facet = null;
+    if (self.norm_facets() !== undefined) {
+	  $.each(self.norm_facets(), function (index, norm_facet) {//alert(ko.mapping.toJSON(norm_facet.id + " " + facet_id()));  
+	    if (norm_facet.id == facet_id()) {
+	      _facet = norm_facet;
+	    }      
+	  });
+    }
+    return _facet;	  
   };
 
-  self.selectedFacet = ko.observable(); //deprecated
-
   self.previewColumns = ko.observable("");
   self.columns = ko.observable({});
-  loadLayout(self, collection_json.layout);
+  loadLayout(self, collection_json.layout); // move to init + load dynamic fields?
   
   self.isEditing = ko.observable(false);
   self.toggleEditing = function () {
     self.isEditing(!self.isEditing());
   };
   self.isRetrievingResults = ko.observable(false);
-	  
-  self.draggableFacet = ko.observable(new Widget(12, "Facet", "facet-widget"));
-  self.draggableResultset = ko.observable(new Widget(12, "Results", "resultset-widget"));
-  self.draggableBar = ko.observable(new Widget(12, "Bar Chart", "bar-widget"));
-  self.draggableArea = ko.observable(new Widget(12, "Area Chart", "area-widget"));
-  self.draggableMap = ko.observable(new Widget(12, "Map", "map-widget"));
-  self.draggableLine = ko.observable(new Widget(12, "Line Chart", "line-widget"));
-  self.draggablePie = ko.observable(new Widget(12, "Pie Chart", "pie-widget"));
-
+    
+  self.draggableFacet = ko.observable(new Widget(12, UUID(), "Facet", "facet-widget"));
+  self.draggableResultset = ko.observable(new Widget(12, UUID(), "Results", "resultset-widget"));
+  self.draggableBar = ko.observable(new Widget(12, UUID(), "Bar Chart", "bar-widget"));
+  self.draggableArea = ko.observable(new Widget(12, UUID(), "Area Chart", "area-widget"));
+  self.draggableMap = ko.observable(new Widget(12, UUID(), "Map", "map-widget"));
+  self.draggableLine = ko.observable(new Widget(12, UUID(), "Line Chart", "line-widget"));
+  self.draggablePie = ko.observable(new Widget(12, UUID(), "Pie Chart", "pie-widget"));
   
 
   self.search = function () {
@@ -302,7 +317,7 @@ var SearchViewModel = function (collection_json, query_json) {
       collection: ko.mapping.toJSON(self.collection),
       query: ko.mapping.toJSON(self.query),
       layout: ko.mapping.toJSON(self.columns)
-    },function (data) {
+    }, function (data) {
       self.response(data); // If error we should probably update only the facets
       self.results.removeAll();
       if (data.error) {
@@ -339,30 +354,11 @@ var SearchViewModel = function (collection_json, query_json) {
       $(document).trigger("error", xhr.responseText);
     });
   };
-
-  // deprecated
-  // To move to collection
-  self.selectSingleFacet = function (normalized_facet_json) {
-    $.each(self.collection.facets(), function (index, facet) {
-      if (facet.field() == normalized_facet_json.field) {
-        self.selectedFacet(facet);
-      }
-    });
-  }
-
-  // widget.remove() --> callback to removeFacet() or other depending on type of widget  
-  self.removeWidget = function (facet_json) {
-	self.removeFacet({'field': 'user_location'}); 
-  }  
   
-  self.removeFacet = function (facet_json) {
-    $.each(self.collection.facets(), function (index, item) {
-      if (item.field() == facet_json.field) {
-        self.collection.facets.remove(item);
-      }
-    });
+  self.removeWidget = function (widget_json) {
+    self.collection.removeFacet(widget_json.id); 
     self.search();
-  }
+  }  
 
   self.save = function () {
     $.post("/search/save", {

+ 10 - 0
apps/search/static/js/search.utils.js

@@ -177,3 +177,13 @@ function stripHtml(html) {
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText;
 }
+
+function s4() {
+  return Math.floor((1 + Math.random()) * 0x10000)
+            .toString(16)
+            .substring(1);
+}
+
+function UUID() {
+   return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
+}