浏览代码

HUE-2786 [hbase] Show current version in the cell history and allow revert to previous version

In the full editor for a cell it now shows the current version in the cell history as well as an indicator of when the current version is edited. I've also made it possible to revert to a previous version by selecting it and pressing revert.
Johan Ahlen 10 年之前
父节点
当前提交
d5d5cac
共有 2 个文件被更改,包括 74 次插入16 次删除
  1. 57 4
      apps/hbase/src/hbase/static/hbase/js/utils.js
  2. 17 12
      apps/hbase/src/hbase/templates/app.mako

+ 57 - 4
apps/hbase/src/hbase/static/hbase/js/utils.js

@@ -105,6 +105,21 @@ function launchModal(modal, data) {
           lineNumbers: true,
           readOnly: $(target).is(":disabled")
         });
+        data.codeMirror = cm;
+
+        var updateTimeout = 0;
+        cm.on("change", function(cm) {
+          clearTimeout(updateTimeout);
+          updateTimeout = setTimeout(function () {
+            data.value(cm.getValue());
+          }, 100);
+        });
+
+        data.showingCurrent.subscribe(function(showingCurrent) {
+          cm.options.readOnly = ! showingCurrent;
+          cm.refresh();
+        });
+
         setTimeout(function () {
           cm.refresh()
         }, 401); //CM invis bug workaround
@@ -124,6 +139,7 @@ function launchModal(modal, data) {
           multiple: false,
           onComplete: function (id, fileName, response) {
             data.content.reload();
+            data.value(data.content.value);
           }
         });
       }
@@ -158,12 +174,49 @@ function launchModal(modal, data) {
   logGA(modal.slice(0, modal.indexOf('_modal') != -1 ? modal.indexOf('_modal') : modal.length));
 }
 
+function showFullEditor(cellContent) {
+  var currentValue = ko.isObservable(cellContent.value) ? cellContent.value() : cellContent.value;
+  launchModal('cell_edit_modal', {
+    originalValue: currentValue,
+    currentValue: ko.observable(currentValue),
+    value: ko.observable(currentValue),
+    showingCurrent: ko.observable(true),
+    readOnly: ko.observable(false),
+    timestamp: ko.observable(cellContent.timestamp),
+    content: cellContent,
+    mime: detectMimeType(currentValue),
+
+    updateCodeMirror: function() {
+      if (this.codeMirror) {
+        this.codeMirror.setValue(this.value());
+        this.codeMirror.refresh()
+      }
+    },
+
+    switchToHistorical: function(item) {
+      if (this.showingCurrent()) {
+        this.currentValue(this.value());
+      }
+      this.value(item.value);
+      this.updateCodeMirror();
+      this.showingCurrent(false);
+      this.timestamp(item.timestamp)
+    },
+
+    switchToCurrent: function() {
+      if (!this.showingCurrent()) {
+        this.value(this.currentValue());
+        this.showingCurrent(true);
+        this.timestamp(this.content.timestamp);
+        this.updateCodeMirror();
+      }
+    }
+  });
+}
+
 function editCell($data) {
   if ($data.value().length > 146) {
-    launchModal('cell_edit_modal', {
-      content: $data,
-      mime: detectMimeType($data.value())
-    });
+    showFullEditor($data);
   } else {
     $data.editing(true);
   }

+ 17 - 12
apps/hbase/src/hbase/templates/app.mako

@@ -95,7 +95,7 @@ ${ commonheader(None, "hbase", user) | n,unicode }
             % if can_write:
               <a class="corner-btn btn" data-bind="click: $data.drop, clickBubble: false"><i class="fa fa-trash-o"></i></a>
             % endif
-            <a class="corner-btn btn" data-bind="event: { mousedown: function(){launchModal('cell_edit_modal', {content:$data, mime: detectMimeType($data.value())})} }"><i class="fa fa-pencil"></i> ${_('Full Editor')}</a>
+            <a class="corner-btn btn" data-bind="event: { mousedown: function(){ showFullEditor($data) } }"><i class="fa fa-pencil"></i> ${_('Full Editor')}</a>
             <pre data-bind="text: ($data.value().length > 146 ? $data.value().substring(0, 144) + '...' : $data.value()).replace(/(\r\n|\n|\r)/gm,''), click: editCell.bind(null, $data), clickBubble: false, visible: ! $data.isLoading() && ! $data.editing()"></pre>
             <textarea data-bind="visible: !$data.isLoading() && $data.editing(), disable: ! app.views.tabledata.canWrite(), hasfocus: $data.editing, value: $data.value, click:function(){}, clickBubble: false"></textarea>
             <img src="${ static('desktop/art/spinner.gif') }" data-bind="visible: $data.isLoading() " />
@@ -365,7 +365,7 @@ ${ commonheader(None, "hbase", user) | n,unicode }
     <script id="cell_edit_modal_template" type="text/html">
       <div class="modal-header">
         <a class="close pointer" data-dismiss="modal" aria-hidden="true">&times;</a>
-        <h3>${_('Edit Cell')} - <span data-bind="text: content.name || formatTimestamp(content.timestamp)"></span> <code data-bind="text: mime, visible: mime !== 'type/null'"></code> <small><i class="fa fa-clock-o"></i> <span data-bind="text: formatTimestamp($data.content.timestamp)"></span></small></h3>
+        <h3>${_('Edit Cell')} - <span data-bind="text: content.name || formatTimestamp(timestamp())"></span> <code data-bind="text: mime, visible: mime !== 'type/null'"></code> <small><i class="fa fa-clock-o"></i> <span data-bind="text: formatTimestamp(timestamp())"></span></small></h3>
       </div>
       <div class="modal-body container-fluid">
           <div class="row-fluid">
@@ -382,8 +382,9 @@ ${ commonheader(None, "hbase", user) | n,unicode }
             <div class="span3">
               <ul class="nav nav-list cell-history">
                 <li class="nav-header">${_('Cell History:')}</li>
+                <li data-bind="css: { 'active': showingCurrent }"><a data-bind="click: switchToCurrent()" class="pointer">${_('Current Version')}<span data-bind="if: (originalValue !== value() && showingCurrent()) || (originalValue !== currentValue() && !showingCurrent())"> (${_('Edited')})</span></a></li>
                 <!-- ko foreach: $data.content.history.items() -->
-                  <li data-bind="css: { 'active': $data.timestamp == $parent.content.timestamp }"><a data-bind="click: $parent.content.history.pickHistory.bind(null, $data), text: formatTimestamp($data.timestamp)" class="pointer"></a></li>
+                  <li data-bind="css: { 'active': $data.timestamp == $parent.timestamp() }"><a data-bind="click: function() { $root.switchToHistorical($data) }, text: formatTimestamp($data.timestamp)" class="pointer"></a></li>
                 <!-- /ko -->
                 <li data-bind="visible: $data.content.history.loading()"><img src="${ static('desktop/art/spinner.gif') }" /></li>
               </ul>
@@ -391,31 +392,35 @@ ${ commonheader(None, "hbase", user) | n,unicode }
           </div>
         </div>
       </div>
-      <div class="modal-footer" data-bind="if: ! $data.readonly">
-        % if can_write:
+      <div class="modal-footer">
+        <!-- ko if: showingCurrent -->
           <button class="btn" data-dismiss="modal" aria-hidden="true">${_('Cancel')}</button>
           <a id="file-upload-btn" class="btn fileChooserBtn" aria-hidden="true"><i class="fa fa-upload"></i> ${_('Upload')}</a>
           <input data-bind="visible: mime.split('/')[0].toLowerCase() != 'application' && mime.split('/')[0].toLowerCase() != 'image'" type="submit" class="btn btn-primary" value="${_('Save')}">
-        % else:
-          <button class="btn" data-dismiss="modal" aria-hidden="true">${_('OK')}</button>
-        % endif
+        <!-- /ko -->
+        <!-- ko ifnot: showingCurrent -->
+          <button class="btn" data-dismiss="modal" aria-hidden="true">${_('Cancel')}</button>
+          <input type="submit" class="btn btn-primary" value="${_('Revert')}">
+        <!-- /ko -->
       </div>
     </script>
 
     <script id="cell_image_template" type="text/html">
-      <img data-bind="attr: {src: 'data:image/' + $data.mime + ';base64,' + $data.content.value()}"/>
+      <img data-bind="attr: {src: 'data:image/' + $data.mime + ';base64,' + value()}"/>
+      <input type="hidden" data-bind="value: value"/>
     </script>
 
     <script id="cell_text_template" type="text/html">
-      <textarea id="codemirror_target" data-bind="text: $data.content.value, disable: ! app.views.tabledata.canWrite()" data-use-post="true"></textarea>
+      <textarea id="codemirror_target" data-bind="text: value, disable: !showingCurrent()" data-use-post="true"></textarea>
     </script>
 
     <script id="cell_application_template" type="text/html">
-      <iframe width="100%" height="100%" data-bind="attr: {src: 'data:' + $data.mime + ';base64,' + $data.content.value()}"></iframe>
+      <iframe width="100%" height="100%" data-bind="attr: {src: 'data:' + $data.mime + ';base64,' + value()}"></iframe>
+      <input type="hidden" data-bind="value: value"/>
     </script>
 
     <script id="cell_type_template" type="text/html">
-      <textarea style="width:100%; height: 450px;" data-bind="text: $data.content.value, disable: ! app.views.tabledata.canWrite()" data-use-post="true"></textarea>
+      <textarea style="width:100%; height: 450px;" data-bind="textInput: value, disable: !showingCurrent()" data-use-post="true"></textarea>
     </script>
   </div>