浏览代码

HUE-2783 [search] Load and update search definitions

Restyled the definition demi-modal
Name and definition are updateable
Tracker of changes and reload of the initial definition
Got rid of share modal and button
Enrico Berti 10 年之前
父节点
当前提交
928e8ad

+ 82 - 11
apps/search/src/search/static/search/js/search.ko.js

@@ -54,6 +54,11 @@ var Query = function (vm, query) {
 
 
   self.uuid = ko.observable(typeof query.uuid != "undefined" && query.uuid != null ? query.uuid : UUID());
   self.uuid = ko.observable(typeof query.uuid != "undefined" && query.uuid != null ? query.uuid : UUID());
   self.qs = ko.mapping.fromJS(query.qs);
   self.qs = ko.mapping.fromJS(query.qs);
+  self.qs.subscribe(function(){
+    if (vm.selectedQDefinition() != null){
+      vm.selectedQDefinition().hasChanged(true);
+    }
+  });
   self.fqs = ko.mapping.fromJS(query.fqs);
   self.fqs = ko.mapping.fromJS(query.fqs);
   self.start = ko.mapping.fromJS(query.start);
   self.start = ko.mapping.fromJS(query.start);
 
 
@@ -98,10 +103,16 @@ var Query = function (vm, query) {
 
 
   self.addQ = function (data) {
   self.addQ = function (data) {
     self.qs.push(ko.mapping.fromJS({'q': ''}));
     self.qs.push(ko.mapping.fromJS({'q': ''}));
+    if (vm.selectedQDefinition() != null) {
+      vm.selectedQDefinition().hasChanged(true);
+    }
   };
   };
 
 
   self.removeQ = function (query) {
   self.removeQ = function (query) {
     self.qs.remove(query);
     self.qs.remove(query);
+    if (vm.selectedQDefinition() != null){
+      vm.selectedQDefinition().hasChanged(true);
+    }
   };
   };
 
 
   self.selectedMultiq.subscribe(function () { // To keep below the computed objects!
   self.selectedMultiq.subscribe(function () { // To keep below the computed objects!
@@ -134,6 +145,10 @@ var Query = function (vm, query) {
       });
       });
     }
     }
 
 
+    if (vm.selectedQDefinition() != null){
+      vm.selectedQDefinition().hasChanged(true);
+    }
+
     self.start(0);
     self.start(0);
     vm.search();
     vm.search();
   }
   }
@@ -196,6 +211,10 @@ var Query = function (vm, query) {
       }
       }
     }
     }
 
 
+    if (vm.selectedQDefinition() != null){
+      vm.selectedQDefinition().hasChanged(true);
+    }
+
     self.start(0);
     self.start(0);
     if (data.no_refresh == undefined) {
     if (data.no_refresh == undefined) {
       vm.search();
       vm.search();
@@ -253,6 +272,10 @@ var Query = function (vm, query) {
       }
       }
     }
     }
 
 
+    if (vm.selectedQDefinition() != null){
+      vm.selectedQDefinition().hasChanged(true);
+    }
+
     self.start(0);
     self.start(0);
     if (data.no_refresh == undefined) {
     if (data.no_refresh == undefined) {
       vm.search();
       vm.search();
@@ -535,14 +558,16 @@ var Collection = function (vm, collection) {
   self.newQDefinitionName = ko.observable("");
   self.newQDefinitionName = ko.observable("");
 
 
   self.addQDefinition = function () {
   self.addQDefinition = function () {
-    self.qdefinitions.push(
-        ko.mapping.fromJS({
-          'name': self.newQDefinitionName(),
-          'id': UUID(),
-          'data': ko.mapping.toJSON(vm.query)
-        })
-    );
-    self.newQDefinitionName("");
+    if ($.trim(self.newQDefinitionName()) != "") {
+      var _def = ko.mapping.fromJS({
+        'name': $.trim(self.newQDefinitionName()),
+        'id': UUID(),
+        'data': ko.mapping.toJSON(vm.query)
+      });
+      self.qdefinitions.push(_def);
+      self.loadQDefinition(_def);
+      self.newQDefinitionName("");
+    }
   };
   };
 
 
   self.removeQDefinition = function (qdef) {
   self.removeQDefinition = function (qdef) {
@@ -556,15 +581,53 @@ var Collection = function (vm, collection) {
 
 
   self.loadQDefinition = function (qdefinition) {
   self.loadQDefinition = function (qdefinition) {
     var qdef = ko.mapping.fromJSON(qdefinition.data());
     var qdef = ko.mapping.fromJSON(qdefinition.data());
-
     vm.query.uuid(qdef.uuid());
     vm.query.uuid(qdef.uuid());
     vm.query.qs(qdef.qs());
     vm.query.qs(qdef.qs());
     vm.query.fqs(qdef.fqs());
     vm.query.fqs(qdef.fqs());
     vm.query.start(qdef.start());
     vm.query.start(qdef.start());
     vm.query.selectedMultiq(qdef.selectedMultiq());
     vm.query.selectedMultiq(qdef.selectedMultiq());
 
 
-    vm.additionalInfo("<div class='center'><strong>" + qdefinition.name() + "</strong></div>");
+    qdefinition.hasChanged = ko.observable(false);
+    vm.selectedQDefinition(qdefinition);
     vm.search();
     vm.search();
+    $(document).trigger("loadedQDefinition");
+  }
+
+  self.reloadQDefinition = function () {
+    self.loadQDefinition(vm.selectedQDefinition());
+    vm.selectedQDefinition().hasChanged(false);
+  }
+
+  self.updateQDefinition = function () {
+    for (var i = 0; i < self.qdefinitions().length; i++) {
+      if (self.qdefinitions()[i].id() == vm.selectedQDefinition().id()) {
+        self.qdefinitions()[i].data(ko.mapping.toJSON(vm.query));
+        break;
+      }
+    }
+    vm.selectedQDefinition().hasChanged(false);
+  }
+
+  self.unloadQDefinition = function () {
+    vm.selectedQDefinition(null);
+    vm.query.uuid(null);
+    vm.query.qs([
+      {
+        q: ""
+      }
+    ]);
+    vm.query.fqs([]);
+    vm.query.start(0);
+    vm.query.selectedMultiq([]);
+  }
+
+  self.getQDefinition = function (qDefID) {
+    for (var i = 0; i < self.qdefinitions().length; i++) {
+      if (self.qdefinitions()[i].id() == qDefID) {
+        return self.qdefinitions()[i];
+      }
+    }
+    return null;
   }
   }
  
  
   self.addFacet = function (facet_json) {
   self.addFacet = function (facet_json) {
@@ -1050,7 +1113,7 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
   self.initial = new NewTemplate(self, initial_json);
   self.initial = new NewTemplate(self, initial_json);
 
 
   // UI
   // UI
-  self.additionalInfo = ko.observable("");
+  self.selectedQDefinition = ko.observable();
   self.response = ko.observable({});
   self.response = ko.observable({});
   self.results = ko.observableArray([]);
   self.results = ko.observableArray([]);
   self.resultsHash = '';
   self.resultsHash = '';
@@ -1189,6 +1252,14 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
     logGA('search');
     logGA('search');
     self.isRetrievingResults(true);
     self.isRetrievingResults(true);
 
 
+    if (self.selectedQDefinition() != null) {
+      var _prop = ko.mapping.fromJSON(self.selectedQDefinition().data());
+      if (ko.toJSON(_prop.qs()) != ko.mapping.toJSON(self.query.qs())
+          || ko.toJSON(_prop.selectedMultiq()) != ko.mapping.toJSON(self.query.selectedMultiq())) {
+        self.selectedQDefinition().hasChanged(true);
+      }
+    }
+
     // Multi queries
     // Multi queries
     var multiQs = [];
     var multiQs = [];
     var multiQ = self.query.getMultiq();
     var multiQ = self.query.getMultiq();

+ 31 - 60
apps/search/src/search/templates/search.mako

@@ -54,11 +54,6 @@ ${ commonheader(_('Search'), "search", user, "80px") | n,unicode }
         data-bind="css: {'btn': true}, visible: columns().length != 0">
         data-bind="css: {'btn': true}, visible: columns().length != 0">
       <i class="fa fa-bookmark-o"></i>
       <i class="fa fa-bookmark-o"></i>
     </a>
     </a>
-    <span data-bind="visible: columns().length != 0">&nbsp;&nbsp;</span>
-
-    <a class="btn pointer" title="${ _('Share search definition') }" rel="tooltip" data-placement="bottom" data-bind="click: showShareModal, css: {'btn': true}, visible: columns().length != 0, enable: $root.collection.id() != null">
-      <i class="fa fa-link"></i>
-    </a>
 
 
     <span data-bind="visible: columns().length != 0">&nbsp;&nbsp;&nbsp;</span>
     <span data-bind="visible: columns().length != 0">&nbsp;&nbsp;&nbsp;</span>
 
 
@@ -1531,21 +1526,6 @@ ${ dashboard.layout_skeleton() }
   </table>
   </table>
 </script>
 </script>
 
 
-<div id="shareModal" class="modal hide" data-backdrop="true">
-  <div class="modal-header">
-    <a href="javascript: void(0)" data-dismiss="modal" class="pull-right"><i class="fa fa-times"></i></a>
-    <h3>${_('Share this dashboard definition')}</h3>
-  </div>
-  <div class="modal-body">
-    <p>${_('The following URL will show the current dashboard and its applied filters.')}</p>
-    <input type="text" style="width: 540px" />
-  </div>
-  <div class="modal-footer">
-    <a href="#" class="btn" data-dismiss="modal">${_('Close')}</a>
-  </div>
-</div>
-
-
 <div id="addFacetDemiModal" class="demi-modal fade" data-backdrop="false">
 <div id="addFacetDemiModal" class="demi-modal fade" data-backdrop="false">
   <div class="modal-body">
   <div class="modal-body">
     <a href="javascript: void(0)" data-dismiss="modal" data-bind="click: addFacetDemiModalFieldCancel" class="pull-right"><i class="fa fa-times"></i></a>
     <a href="javascript: void(0)" data-dismiss="modal" data-bind="click: addFacetDemiModalFieldCancel" class="pull-right"><i class="fa fa-times"></i></a>
@@ -1604,32 +1584,32 @@ ${ dashboard.layout_skeleton() }
   <div class="modal-body">
   <div class="modal-body">
     <div class="row-fluid">
     <div class="row-fluid">
       <div class="span12">
       <div class="span12">
-        <form class="form-horizontal">
+        <form class="form-inline">
           <fieldset>
           <fieldset>
-            <legend><i class="fa fa-bookmark-o"></i> ${ _('Query definitions') }</legend>
-            <div class="control-group">
-              <label class="control-label" for="newqname">${ _('New defition') }</label>
-              <div class="controls">
-                <div class="input-append">
-                  <input id="newqname" type="text" class="input-xlarge" data-bind="value: $root.collection.newQDefinitionName" style="margin-bottom: 0" placeholder="${ _('Name') }" />
-                  <a title="${ _('Click on this button to add the currenty query as a new definition') }" class="btn plus-btn" data-bind="click: $root.collection.addQDefinition">
-                    <i class="fa fa-plus"></i>
-                  </a>
-                </div>
+            <legend><i class="fa fa-bookmark-o"></i> ${ _('Query definitions') }
+              <div class="input-append" style="margin-left: 30px; margin-top: 4px">
+                <input id="newqname" type="text" class="input-xxlarge" data-bind="value: $root.collection.newQDefinitionName, valueUpdate:'afterkeydown'" style="margin-bottom: 0" placeholder="${ _('Add current query as...') }" />
+                <a title="${ _('Click on this button to add the currenty query as a new definition') }" class="btn plus-btn" data-bind="click: $root.collection.addQDefinition, css:{'disabled': $.trim($root.collection.newQDefinitionName()) == ''}" style="margin-top: 1px">
+                  <i class="fa fa-plus"></i>
+                </a>
               </div>
               </div>
-            </div>
-            <div class="control-group" data-bind="visible: $root.collection.qdefinitions().length > 0">
-              <label class="control-label" for="settingsdescription">${ _('Saved definitions') }</label>
+            </legend>
+            <div class="control-group" data-bind="visible: $root.collection.qdefinitions().length > 0" style="margin-top: 0">
               <div class="controls">
               <div class="controls">
                 <ul class="unstyled airy qdefinitions" data-bind="foreach: $root.collection.qdefinitions">
                 <ul class="unstyled airy qdefinitions" data-bind="foreach: $root.collection.qdefinitions">
                   <li>
                   <li>
                     <span class="badge badge-info badge-left pointer">
                     <span class="badge badge-info badge-left pointer">
-                      <i class="fa fa-bookmark"></i> <span data-bind="text: name, attr:{'title': ko.mapping.toJSON(data, null, 2)}, click: $root.collection.loadQDefinition"></span>
+                      <span data-bind="text: name, attr:{'title': ko.mapping.toJSON(data, null, 2)}, click: $root.collection.loadQDefinition"></span>
                     </span><span class="badge badge-right trash-share" data-bind="click: $root.collection.removeQDefinition"> <i class="fa fa-times"></i></span></li>
                     </span><span class="badge badge-right trash-share" data-bind="click: $root.collection.removeQDefinition"> <i class="fa fa-times"></i></span></li>
                   </li>
                   </li>
                 </ul>
                 </ul>
               </div>
               </div>
             </div>
             </div>
+            <div class="control-group" data-bind="visible: $root.collection.qdefinitions().length == 0">
+              <div class="controls">
+                <h4>${ _('There are currently no query definitions.') }</h4>
+              </div>
+            </div>
           </fieldset>
           </fieldset>
 
 
         </form>
         </form>
@@ -2356,37 +2336,28 @@ $(document).ready(function () {
       $(".demi-modal.fade.in .demi-modal-chevron").click();
       $(".demi-modal.fade.in .demi-modal-chevron").click();
     }
     }
   });
   });
-});
 
 
-  function showShareModal() {
-    if (window.location.search.indexOf("collection") == -1 && window.location.hash.indexOf("collection") == -1) {
-      $(document).trigger("error", "${_('The current collection must be saved to be shared.')}");
+  $("#newqname").bind("keydown", "return", function (e) {
+    e.preventDefault();
+    viewModel.collection.addQDefinition();
+  });
+
+  $(document).on("loadedQDefinition", function() {
+    if ($(".demi-modal.fade.in").length > 0) {
+      $(".demi-modal.fade.in .demi-modal-chevron").click();
     }
     }
-    else {
-      $("#shareModal input[type='text']").on("focus", function () {
-        this.select();
-      });
-      if (!window.location.origin) {
-        window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port: "");
-      }
-      var _search = window.location.search;
-      var _pathname = window.location.pathname;
-      if (_pathname.indexOf("${ url('search:new_search') }") > -1) {
-        _pathname = "${ url('search:index') }";
-      }
-      if (_search == "" && window.location.hash.indexOf("collection") > -1) {
-        _search = "?" + window.location.hash.substr(1);
-      }
+  });
 
 
-      if (_search != "") {
-        $("#shareModal input[type='text']").val(window.location.origin + _pathname + _search + "#" + LZString.compressToBase64(ko.mapping.toJSON(viewModel.query))).focus();
-        $("#shareModal").modal("show");
-      }
-      else {
-        $(document).trigger("error", "${_('The current collection cannot be shared.')}");
+  if (window.location.hash != "") {
+    if (window.location.hash.indexOf("q=") > -1) {
+      var _qdef = viewModel.collection.getQDefinition(window.location.hash.substr(1).replace(/(<([^>]+)>)/ig, "").split("=")[1]);
+      if (_qdef != null){
+        viewModel.collection.loadQDefinition(_qdef);
       }
       }
     }
     }
   }
   }
+});
+
 
 
   function toggleGridFieldsSelection() {
   function toggleGridFieldsSelection() {
     if (viewModel.collection.template.fields().length > 0) {
     if (viewModel.collection.template.fields().length > 0) {

+ 1 - 0
desktop/core/src/desktop/static/desktop/css/common_dashboard.css

@@ -440,4 +440,5 @@ body.modal-open {
 .card-additional {
 .card-additional {
   padding: 10px;
   padding: 10px;
   margin-bottom: 10px;
   margin-bottom: 10px;
+  text-align: center;
 }
 }

+ 9 - 2
desktop/core/src/desktop/templates/common_dashboard.mako

@@ -121,9 +121,16 @@
 
 
 <div data-bind="css: {'dashboard': true, 'with-top-margin': isEditing()}">
 <div data-bind="css: {'dashboard': true, 'with-top-margin': isEditing()}">
   <div class="container-fluid">
   <div class="container-fluid">
-    <!-- ko if: $root.additionalInfo && $root.additionalInfo() != "" -->
+    <!-- ko if: $root.selectedQDefinition() != null -->
     <div class="row-fluid">
     <div class="row-fluid">
-      <div class="card card-additional card-home span12" data-bind="html: $root.additionalInfo"></div>
+      <div class="card card-additional card-home span12">
+        <a class="pointer pull-right" data-bind="click: $root.collection.unloadQDefinition"><i class="fa fa-times"></i></a>
+        <strong data-bind="editable: $root.selectedQDefinition().name, editableOptions: {enabled: true, placement: 'right'}"></strong>
+        <!-- ko if: $root.selectedQDefinition().hasChanged() -->
+        &nbsp;&nbsp;
+        <a class="pointer" data-bind="click: $root.collection.reloadQDefinition" title="${ _('Reload this definition') }"><i class="fa fa-undo"></i></a> <a class="pointer" data-bind="click: $root.collection.updateQDefinition" title="${ _('Update the definition') }"><i class="fa fa-save"></i></a>
+        <!-- /ko -->
+      </div>
     </div>
     </div>
     <!-- /ko -->
     <!-- /ko -->
     <div class="row-fluid" data-bind="template: { name: 'column-template', foreach: columns}">
     <div class="row-fluid" data-bind="template: { name: 'column-template', foreach: columns}">