瀏覽代碼

HUE-2272 [fb] Improve UX of Copy/Move modal windows

Added support for the new jHueHdfsTree plugin
Enrico Berti 11 年之前
父節點
當前提交
e09cad0

+ 42 - 21
apps/filebrowser/src/filebrowser/templates/listdir_components.mako

@@ -277,19 +277,15 @@ from django.utils.translation import ugettext as _
     <form id="moveForm" action="/filebrowser/move" method="POST" enctype="multipart/form-data" class="form-inline form-padding-fix">
       <div class="modal-header">
         <a href="#" class="close" data-dismiss="modal">&times;</a>
-        <h3>${_('Move:')}</h3>
+        <h3>${_('Move to:')}</h3>
       </div>
       <div class="modal-body">
-        <div style="padding-left: 15px;">
-          <label for="moveDestination">${_('Destination')}</label>
-          <input type="text" class="input-xlarge pathChooser" value="" name="dest_path" id="moveDestination" /><a class="btn fileChooserBtn" href="#" data-filechooser-destination="dest_path">..</a>
-        </div>
-        <br/>
-        <div class="fileChooserModal" class="hide"></div>
+        <div id="moveHdfsTree" style="padding-left: 15px;"></div>
       </div>
       <div class="modal-footer">
-        <div id="moveNameRequiredAlert" class="hide" style="position: absolute; left: 10;">
-          <span class="label label-important">${_('Name is required.')}</span>
+        <div style="position: absolute; left: 10;">
+          <input type="text" class="input-xlarge" value="" name="dest_path" id="moveDestination" placeholder="${_('Select a folder or paste a path...')}" />
+          <span id="moveNameRequiredAlert" class="hide label label-important">${_('Required')}</span>
         </div>
         <a class="btn" onclick="$('#moveModal').modal('hide');">${_('Cancel')}</a>
         <input class="btn btn-primary" type="submit" value="${_('Move')}"/>
@@ -302,19 +298,18 @@ from django.utils.translation import ugettext as _
     <form id="copyForm" action="/filebrowser/copy" method="POST" enctype="multipart/form-data" class="form-inline form-padding-fix">
       <div class="modal-header">
         <a href="#" class="close" data-dismiss="modal">&times;</a>
-        <h3>${_('Copy:')}</h3>
+        <h3>${_('Copy to:')}</h3>
       </div>
       <div class="modal-body">
-        <div style="padding-left: 15px;">
-          <label for="copyDestination">${_('Destination')}</label>
-          <input type="text" class="input-xlarge pathChooser" value="" name="dest_path" id="copyDestination" /><a class="btn fileChooserBtn" href="#" data-filechooser-destination="dest_path">..</a>
-        </div>
-        <br/>
-        <div class="fileChooserModal" class="hide"></div>
+        <div id="copyHdfsTree"></div>
       </div>
       <div class="modal-footer">
         <div id="copyNameRequiredAlert" class="hide" style="position: absolute; left: 10;">
-          <span class="label label-important">${_('Name is required.')}</span>
+          <span class="label label-important">${_('Please select a folder.')}</span>
+        </div>
+        <div style="position: absolute; left: 10;">
+          <input type="text" class="input-xlarge" value="" name="dest_path" id="copyDestination" placeholder="${_('Select a folder or paste a path...')}" />
+          <span id="copyNameRequiredAlert" class="hide label label-important">${_('Required')}</span>
         </div>
         <a class="btn" onclick="$('#copyModal').modal('hide');">${_('Cancel')}</a>
         <input class="btn btn-primary" type="submit" value="${_('Copy')}"/>
@@ -439,12 +434,13 @@ from django.utils.translation import ugettext as _
   </script>
 
   <script src="/static/js/jquery.hdfsautocomplete.js" type="text/javascript" charset="utf-8"></script>
+  <script src="/static/js/jquery.hdfstree.js" type="text/javascript" charset="utf-8"></script>
   <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
   <script src="/static/ext/js/datatables-paging-0.1.js" type="text/javascript" charset="utf-8"></script>
   <script src="/static/js/dropzone.js" type="text/javascript" charset="utf-8"></script>
 
+
   <script charset="utf-8">
-  (function () {
     var getHistory = function () {
       return $.totalStorage('hue_fb_history') || [];
     };
@@ -880,6 +876,18 @@ from django.utils.translation import ugettext as _
           keyboard:true,
           show:true
         });
+
+        $("#moveModal").on("shown", function(){
+          $("#moveHdfsTree").remove();
+          $("<div>").attr("id", "moveHdfsTree").appendTo($("#moveModal .modal-body"));
+          $("#moveHdfsTree").jHueHdfsTree({
+            home: viewModel.currentPath(),
+            onPathChange: function(path){
+              $("#moveDestination").val(path);
+              $("#moveNameRequiredAlert").hide();
+            }
+          });
+        });
       };
 
       self.copy = function () {
@@ -897,6 +905,19 @@ from django.utils.translation import ugettext as _
           keyboard:true,
           show:true
         });
+
+        $("#copyModal").on("shown", function(){
+          $("#copyHdfsTree").remove();
+          $("<div>").attr("id", "copyHdfsTree").appendTo($("#copyModal .modal-body"));
+          $("#copyHdfsTree").jHueHdfsTree({
+            home: viewModel.currentPath(),
+            onPathChange: function(path){
+              $("#copyDestination").val(path);
+              $("#copyNameRequiredAlert").hide();
+            }
+          });
+        });
+
       };
 
       self.changeOwner = function () {
@@ -1172,6 +1193,7 @@ from django.utils.translation import ugettext as _
     ko.applyBindings(viewModel);
 
     $(document).ready(function () {
+
       // Drag and drop uploads from anywhere on filebrowser screen
       if (window.FileReader) {
         var showHoverMsg = function (msg) {
@@ -1379,7 +1401,7 @@ from django.utils.translation import ugettext as _
       });
 
       $("#moveForm").on("submit", function () {
-        if ($.trim($("#moveForm").find("input.pathChooser").val()) == "") {
+        if ($.trim($("#moveDestination").val()) == "") {
           $("#moveNameRequiredAlert").show();
           $("#moveForm").find("input[name='*dest_path']").addClass("fieldError");
           resetPrimaryButtonsStatus(); //globally available
@@ -1394,7 +1416,7 @@ from django.utils.translation import ugettext as _
       });
 
       $("#copyForm").on("submit", function () {
-        if ($.trim($("#copyForm").find("input.pathChooser").val()) == "") {
+        if ($.trim($("#copyDestination").val()) == "") {
           $("#copyNameRequiredAlert").show();
           $("#copyForm").find("input[name='*dest_path']").addClass("fieldError");
           resetPrimaryButtonsStatus(); //globally available
@@ -1609,6 +1631,5 @@ from django.utils.translation import ugettext as _
         }
       });
     });
-  }());
   </script>
 </%def>

+ 8 - 0
desktop/core/static/css/hue3.css

@@ -1828,4 +1828,12 @@ input.no-margin {
 
 .break-word {
   word-wrap: break-word
+}
+
+.jHueHdfsTree .content {
+  margin-left: 14px;
+}
+
+.jHueHdfsTree a.selected {
+  font-weight: bold;
 }

+ 149 - 0
desktop/core/static/js/jquery.hdfstree.js

@@ -0,0 +1,149 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+/*
+ * jHue HDFS tree plugin
+ * shows a tree HDFS picker, if home is set it pre-populates the path
+ * use attached to an element, ie:
+ * $("#el").jHueHdfsTree({
+ *    home: "/user",
+ *    onPathChange: function (path) {
+ *      console.log(path);
+ *    }
+ * });
+ */
+
+(function ($, window, document, undefined) {
+  var pluginName = "jHueHdfsTree",
+      defaults = {
+        home: "/",
+        onPathChange: function () {
+        }
+      };
+
+  function Plugin(element, options) {
+    this.element = element;
+    this.options = $.extend({}, defaults, options);
+    this._defaults = defaults;
+    this._name = pluginName;
+    this.init();
+  }
+
+  Plugin.prototype.init = function () {
+    var _this = this;
+    var _el = $(_this.element);
+    _el.empty();
+    _el.addClass("jHueHdfsTree");
+    var _tree = $("<ul>").addClass("content unstyled").html('<li><a class="pointer"><i class="fa fa-folder-open-o"></i> /</a></li>');
+    _tree.appendTo(_el);
+
+    _tree.find("a").on("click", function () {
+      _this.options.onPathChange("/");
+      _tree.find("a").removeClass("selected");
+      _tree.find("a:eq(0)").addClass("selected");
+    });
+
+    var _root = $("<ul>").addClass("content unstyled").attr("data-path", "").attr("data-loaded", "true");
+    _root.appendTo(_tree.find("li"));
+
+    var BASE_PATH = "/filebrowser/view";
+    var _currentFiles = [];
+
+    function showHdfsLeaf(options) {
+      var autocompleteUrl = BASE_PATH;
+      if (options.paths != null) {
+        autocompleteUrl += options.paths.shift();
+      }
+      else {
+        autocompleteUrl += (options.leaf != null ? options.leaf : "");
+      }
+      $.getJSON(autocompleteUrl + "?pagesize=1000&format=json", function (data) {
+        _currentFiles = [];
+        if (data.error == null) {
+          if (options.leaf != null) {
+            _el.find("[data-path='" + options.leaf + "']").attr("data-loaded", true);
+          }
+          $(data.files).each(function (cnt, item) {
+            if (item.name != "." && item.name != ".." && item.type == "dir") {
+              var _path = item.path;
+              var _li = $("<li>").html('<a class="pointer"><i class="fa fa-folder-o"></i> ' + item.name + '</a><ul class="content unstyled" data-path="' + _path + '" data-loaded="false"></ul>');
+              var _destination = _path.substr(0, _path.lastIndexOf("/"));
+              _li.appendTo(_el.find("[data-path='" + _destination + "']"));
+              _li.find("a").on("click", function () {
+                _this.options.onPathChange(_path);
+                _tree.find("a").removeClass("selected");
+                _li.find("a:eq(0)").addClass("selected");
+                if (_li.find(".content").attr("data-loaded") == "false") {
+                  _li.find(".fa-folder-o").removeClass("fa-folder-o").addClass("fa-folder-open-o");
+                  showHdfsLeaf({
+                    leaf: _path
+                  });
+                }
+                else {
+                  if (_li.find(".content").is(":visible")) {
+                    _li.find(".content").hide();
+                  }
+                  else {
+                    _li.find(".content").show();
+                  }
+                }
+              });
+            }
+          });
+          if (options.paths.length > 0) {
+            showHdfsLeaf({
+              paths: options.paths
+            });
+          }
+        }
+      });
+    }
+
+    var _paths = [];
+    if (_this.options.home != "/") {
+      var _re = /\//g;
+      while ((match = _re.exec(_this.options.home)) != null) {
+        _paths.push(_this.options.home.substr(0, match.index));
+      }
+      _paths.push(_this.options.home);
+      console.log(_paths)
+    }
+    showHdfsLeaf({
+      paths: _paths
+    });
+
+
+  };
+
+  Plugin.prototype.setOptions = function (options) {
+    this.options = $.extend({}, defaults, options);
+  };
+
+  $.fn[pluginName] = function (options) {
+    return this.each(function () {
+      if (!$.data(this, 'plugin_' + pluginName)) {
+        $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
+      }
+    });
+  }
+
+  $[pluginName] = function (options) {
+    if (typeof console != "undefined") {
+      console.warn("$(elem).jHueHdfsTree() is a preferred call method.");
+    }
+    $(options.element).jHueHdfsTree(options);
+  };
+
+})(jQuery, window, document);