소스 검색

HUE-2857 [search] Better UX for the document update form

Enrico Berti 10 년 전
부모
커밋
a01cdfa

+ 26 - 2
apps/search/src/search/static/search/css/search.css

@@ -249,10 +249,28 @@ em {
   border-bottom: 1px solid #338bb8;
 }
 
-.document-details {
+.document-details-actions {
   background-color: #F6F6F6;
   padding: 10px;
-  border: 1px solid #e5e5e5;
+  margin-top: 8px;
+}
+
+.document-details-actions a {
+  display: table;
+}
+
+.document-details {
+  padding: 10px;
+  border-left: 1px solid #e5e5e5;
+}
+
+.document-details td, .document-details th  {
+  height: 28px;
+  vertical-align: middle;
+}
+
+.document-details tr.readonly:hover {
+  background-color: #F6F6F6;
 }
 
 .result-row:nth-child(even) {
@@ -608,3 +626,9 @@ em {
 .player-toolbar .link {
   display: inline-block;
 }
+
+.grid-th {
+  text-align: left;
+  white-space: nowrap;
+  padding-right: 20px;
+}

+ 9 - 2
apps/search/src/search/static/search/js/search.ko.js

@@ -1391,6 +1391,7 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
                   'hasChanged': ko.observable(false),
                   'externalLink': ko.observable(_externalLink),
                   'details': ko.observableArray(_details),
+                  'originalDetails': ko.observable(''),
                   'showDetails': ko.observable(false),
                   'leafletmap': leafletmap
                 };
@@ -1488,7 +1489,10 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
       collection: ko.mapping.toJSON(self.collection),
       id: doc.id
     }, function (data) {
+      var details = [];
+      doc.details.removeAll();
       if (data.status == 0) {
+
         $.each(data.doc.doc, function(key, val) {
           var _field = ko.mapping.fromJS({
               key: key,
@@ -1499,12 +1503,12 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
             doc.hasChanged(true);
             _field.hasChanged(true);
           });
-          doc['details'].push(_field);
+          details.push(_field);
         });
       }
       else if (data.status == 1) {
         $(document).trigger("info", data.message);
-        doc['details'].push(ko.mapping.fromJS({
+        details.push(ko.mapping.fromJS({
             key: '',
             value: ''
         }));
@@ -1512,6 +1516,8 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
       else {
         $(document).trigger("error", data.message);
       }
+      doc.details(details);
+      doc.originalDetails(ko.toJSON(doc.details()));
     }).fail(function (xhr, textStatus, errorThrown) {
       $(document).trigger("error", xhr.responseText);
     });
@@ -1525,6 +1531,7 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
     }, function (data) {
       if (data.status == 0) {
         doc.showEdit(false);
+        doc.originalDetails(ko.toJSON(doc.details()));
       }
       else {
         $(document).trigger("error", data.message);

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

@@ -608,30 +608,41 @@ ${ dashboard.layout_skeleton() }
                   <td data-bind="html: $data"></td>
                 <!-- /ko -->
               </tr>
-              <tr data-bind="visible: doc.showDetails">
+              <tr data-bind="visible: doc.showDetails" class="show-details">
                 <td data-bind="attr: {'colspan': $root.collection.template.fieldsSelected().length > 0 ? $root.collection.template.fieldsSelected().length + 1 : 2}">
                   <!-- ko if: $data.details().length == 0 -->
                     <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
                     <!--[if IE]><img src="${ static('desktop/art/spinner.gif') }" /><![endif]-->
                   <!-- /ko -->
                   <!-- ko if: $data.details().length > 0 -->
-                    <div class="document-details">
-                      <a href="javascript:void(0)" data-bind="click: function() { showEdit(true); }">
-                        <i class="fa fa-edit" data-bind="visible: ! showEdit()"></i>
+                    <div class="document-details-actions pull-left">
+                      <a href="javascript:void(0)" data-bind="visible: ! showEdit(), click: function() { showEdit(true); }" title="${ _('Edit this document') }">
+                        <i class="fa fa-edit fa-fw"></i>
                       </a>
-                      <a href="javascript:void(0)" data-bind="click: $root.updateDocument">
-                        <i class="fa fa-save" data-bind="visible: showEdit"></i>
+                      <a href="javascript:void(0)" data-bind="visible: showEdit(), click: function(data, e) { $(e.currentTarget).parent().css('marginTop', '8px'); $root.getDocument($data); showEdit(false); }" title="${ _('Undo changes') }">
+                        <i class="fa fa-undo fa-fw"></i>
                       </a>
-                      <a href="javascript:void(0)" data-bind="attr: { href: externalLink}" target="_blank">
-                        <i class="fa fa-external-link" data-bind="visible: externalLink"></i>
+                      <a href="javascript:void(0)" data-bind="visible: showEdit() && originalDetails() != ko.toJSON(details), click: $root.updateDocument" title="${ _('Update this document') }">
+                        <i class="fa fa-save fa-fw"></i>
                       </a>
+                      <a href="javascript:void(0)" data-bind="visible: externalLink(), attr: { href: externalLink}" target="_blank" title="${ _('Show original document') }">
+                        <i class="fa fa-external-link fa-fw"></i>
+                      </a>
+                    </div>
+                    <div class="document-details pull-left">
                       <table>
                         <tbody data-bind="foreach: details">
-                          <tr>
-                             <th style="text-align: left; white-space: nowrap; vertical-align:top; padding-right:20px" data-bind="text: key"></th>
+                          <tr data-bind="css: {'readonly': ! $parent.showEdit()}">
+                             <th class="grid-th" data-bind="text: key"></th>
                              <td width="100%">
                                <span data-bind="text: value, visible: ! $parent.showEdit()"></span>
-                               <input data-bind="value: value, visible: $parent.showEdit" class="input-xxlarge"></input>
+                               <input data-bind="value: value, visible: $parent.showEdit, valueUpdate: 'afterkeydown',
+                               click: function(detail, e){
+                                var target = $(e.currentTarget);
+                                target.parents('.show-details').find('.document-details-actions').animate({
+                                  'marginTop': (target.position().top - target.parents('table').position().top) + 'px'
+                                }, 200)
+                               }" class="input-xxlarge" style="width: 600px" />
                              </td>
                           </tr>
                         </tbody>

+ 12 - 0
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -1482,6 +1482,18 @@ ko.toJSONObject = function (koObj) {
   return JSON.parse(ko.toJSON(koObj));
 }
 
+ko.toCleanJSON = function (koObj) {
+  return ko.toJSON(koObj, function (key, value) {
+    if (key == "__ko_mapping__") {
+      return;
+    }
+    else {
+      return value;
+    }
+  });
+}
+
+
 ko.bindingHandlers.aceEditor = {
   init: function (element, valueAccessor) {
     var $el = $(element);