Forráskód Böngészése

HUE-2231 [fb] Make current directory selectable

Refactored templates (moved css to external file, cleaned up js, improved readability)
Updated handleSelect to toggle off select all text box when a box is toggled off
added checkbox to cwd
updated view data to add parent directory to list before cwd to ensure check boxes are grouped together in table layout
Paul McCaughtry 11 éve
szülő
commit
2209fca371

+ 127 - 0
apps/filebrowser/src/filebrowser/static/css/fb.css

@@ -0,0 +1,127 @@
+#fileArea {
+  overflow: auto;
+  background-color: #F5F5F5;
+  position: relative;
+}
+
+#fileArea.loading {
+  opacity: .7;
+}
+
+#loader {
+  position: fixed;
+  margin-top: 40px;
+  font-size: 50px;
+  text-align: center;
+  width: 140px;
+  height: 140px;
+  line-height: 140px;
+  -webkit-border-radius: 20px;
+  -moz-border-radius: 20px;
+  border-radius: 20px;
+}
+
+.binary {
+  font-family: "Courier New", Courier, monospace;
+}
+
+pre {
+  border: none;
+}
+
+pre a {
+  color: #444;
+  cursor: default;
+}
+
+pre a:hover {
+  color: #444;
+  text-decoration: none;
+}
+
+.fixed {
+  position: fixed;
+  top: 40px;
+  filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
+  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+  -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+}
+
+.sortable {
+  cursor: pointer;
+}
+
+.file-row {
+  height: 37px;
+}
+
+.fileChooserModal {
+  padding: 14px;
+}
+
+.fileChooserModal .hueBreadcrumb {
+  margin: 0 0 18px !important;
+}
+
+.fieldError {
+  border-color: #B94A48 !important;
+}
+
+.pagination {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  width: 100%;
+  background-color: #f5f5f5;
+  margin: 0;
+  border-top: 1px solid #e3e3e3;
+  -webkit-box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.1);
+  -moz-box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.1);
+  box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.1);
+  padding: 0px;
+}
+
+.pagination p {
+  padding-top: 10px;
+  padding-left: 10px;
+  margin: 0;
+}
+
+.pagination select {
+  margin-top: 4px;
+}
+
+.pagination ul {
+  margin-top: 14px;
+  margin-right: 20px;
+}
+
+.actionbar {
+  padding-top: 6px;
+  background-color: #FFFFFF;
+}
+
+.shadow {
+  -webkit-box-shadow: 0px 2px 3px rgba(50, 50, 50, 0.1);
+  -moz-box-shadow: 0px 2px 3px rgba(50, 50, 50, 0.1);
+  box-shadow: 0px 1px 2px rgba(50, 50, 50, 0.1);
+}
+
+.scrollable {
+  margin-bottom: 80px;
+}
+
+#jHueHdfsAutocomplete ul li {
+  cursor: pointer;
+}
+
+#jHueHdfsAutocomplete ul li:hover,  #jHueHdfsAutocomplete ul li.active {
+  color: #FFFFFF;
+  background: #338BB8;
+}
+
+#jHueHdfsAutocomplete .popover-content {
+  max-height: 200px;
+  overflow-y: auto;
+}

+ 297 - 355
apps/filebrowser/src/filebrowser/templates/display.mako

@@ -31,50 +31,7 @@
 ${ commonheader(_('%(filename)s - File Viewer') % dict(filename=truncate(filename)), 'filebrowser', user) | n,unicode }
 ${ fb_components.menubar() }
 
-<script src="/static/ext/js/jquery/plugins/jquery.visible.min.js" type="text/javascript" charset="utf-8"></script>
-
-<style type="text/css">
-  #fileArea {
-    overflow: auto;
-    background-color: #F5F5F5;
-    position: relative;
-  }
-
-  #fileArea.loading {
-    opacity: .7;
-  }
-
-  #loader {
-    position: fixed;
-    margin-top: 40px;
-    font-size: 50px;
-    text-align: center;
-    width: 140px;
-    height: 140px;
-    line-height: 140px;
-    -webkit-border-radius: 20px;
-    -moz-border-radius: 20px;
-    border-radius: 20px;
-  }
-
-  .binary {
-    font-family: "Courier New", Courier, monospace;
-  }
-
-  pre {
-    border: none;
-  }
-
-  pre a {
-    color: #444;
-    cursor: default;
-  }
-
-  pre a:hover {
-    color: #444;
-    text-decoration: none;
-  }
-</style>
+<link rel="stylesheet" type="text/css" href="/filebrowser/static/css/fb.css">
 
 <div class="container-fluid">
   <div class="row-fluid">
@@ -140,366 +97,351 @@ ${ fb_components.menubar() }
   </div>
 </div>
 
+<script src="/static/ext/js/jquery/plugins/jquery.visible.min.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
-
 <script type="text/javascript" charset="utf-8">
-
 <%
   MAX_ALLOWED_PAGES_PER_REQUEST = 255
 %>
+(function() {
+  var pages = {};
 
-function displayViewModel(params) {
-  var self = this;
-
-  self.MAX_ALLOWED_PAGES_PER_REQUEST = ${MAX_ALLOWED_PAGES_PER_REQUEST};
-  self.MAX_PAGES_TO_ENABLE_SCROLLING = 300;
-  self.PAGES_PER_CHUNK = 50;
-
-  self.base_url = ko.observable(params.base_url);
-  self.compression = ko.observable(params.compression);
-  self.mode = ko.observable(params.mode);
-  self.begin = ko.observable(params.begin);
-  self.end = ko.observable(params.end);
-  self.length = ko.observable(params.length);
-  self.size = ko.observable(params.size);
-  self.page = ko.observable(1);
-  self.isLoading = ko.observable(true);
-
-  self.totalPages = ko.computed(function () {
-    return Math.max(Math.floor(self.size() / self.length()), 1);
-  });
-
-  self.upperPage = ko.observable(Math.min(self.totalPages(), 50));
-
-  self.begin = ko.computed(function () {
-    return (self.page() - 1) * self.length();
-  });
-
-  self.offset = ko.computed(function () {
-    return ((self.page() - 1) * self.length()) - 1;
-  });
-
-  self.url = ko.computed(function () {
-    return self.base_url()
-            + "?offset=" + self.offset()
-            + "&length=" + self.length()
-            + "&compression=" + self.compression()
-            + "&mode=" + self.mode();
-  });
+  var resizeText = function () {
+    $("#fileArea").height($(window).height() - $("#fileArea").offset().top - 26);
+    $("#loader").css("marginLeft", ($("#fileArea").width() - $("#loader").width()) / 2);
+  };
 
-  self.jsonParams = ko.computed(function () {
-    return {
-      offset: self.begin(),
-      length: self.length() * (self.upperPage() - self.page() + 1),
-      compression: self.compression(),
-      mode: self.mode()
+  var formatHex function = (number, padding) {
+    if ("undefined" != typeof number){
+      var _filler = "";
+      for (var i = 0; i < padding - 1; i++) {
+        _filler += "0";
+      }
+      return (_filler + number.toString(16)).substr(-padding);
     }
-  });
-
-  self.toggleDisables = function () {
-    $(".next-page").removeClass("disabled");
-    $(".last-page").removeClass("disabled");
-    $(".first-page").removeClass("disabled");
-    $(".previous-page").removeClass("disabled");
+    return "";
+  };
 
-    if (self.page() == self.totalPages() || self.upperPage() == self.totalPages()) {
-      $(".next-page").addClass("disabled");
-      $(".last-page").addClass("disabled");
-    }
-    if (self.page() == 1) {
-      $(".first-page").addClass("disabled");
-      $(".previous-page").addClass("disabled");
+  var pageContent = function (page) {
+    var _html = "";
+    if ($("#page" + page).length == 0) {
+      if (pages[page] == null) {
+        _html += "<a id='page" + page + "'><div style='height: " + $("#fileArea").height() + "px'></div></a>";
+      } else {
+        _html += "<a id='page" + page + "'><div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div></a>";
+      }
+    } else {
+      if (pages[page] == null) {
+        $("#page" + page).html("<div style='height: " + $("#fileArea").height() + "px'></div>");
+      } else {
+        $("#page" + page).html("<div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div>");
+      }
     }
+    return _html;
   };
 
-  self.pageChanged = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (self.page() > self.totalPages()) {
-      self.page(self.totalPages());
-    }
-    if (self.page() < 1 || !$.isNumeric(self.page())) {
-      self.page(1);
+  var renderPages = function () {
+    var _html = "";
+    if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING) { // enable scrolling
+      for (var i = 1; i <= viewModel.totalPages(); i++) {
+        _html += pageContent(i);
+      }
+    } else {
+      _html += pageContent(viewModel.page());
     }
-    if (self.page() > self.upperPage()) {
-      self.upperPage(self.page());
+    if (_html != "") {
+      $("#fileArea pre").html(_html);
     }
-    changePage();
   };
 
-  self.upperPageChanged = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (self.upperPage() > self.totalPages()) {
-      self.upperPage(self.totalPages());
-    }
-    if (self.upperPage() < 1 || !$.isNumeric(self.upperPage())) {
-      self.upperPage(1);
-    }
-    if (self.upperPage() < self.page()) {
-      self.page(self.upperPage());
-    }
-    if (self.upperPage() - self.page() > self.MAX_ALLOWED_PAGES_PER_REQUEST) {
-      self.upperPage(self.page() + self.MAX_ALLOWED_PAGES_PER_REQUEST);
-      $.jHueNotify.info("${_('Sorry, you cannot request for more than %s pages.' % MAX_ALLOWED_PAGES_PER_REQUEST)}");
-    }
-    changePage();
+  var getContent = function (callback) {
+    viewModel.isLoading(true);
+    var _baseUrl = "${url('filebrowser.views.view', path=path_enc)}";
+    $.getJSON(_baseUrl, viewModel.jsonParams(), function (data) {
+      if (data.view.contents != null) {
+        pages[viewModel.page()] = data.view.contents;
+        renderPages();
+      }
+      if (data.view.xxd != null) {
+        pages[viewModel.page()] = data.view.xxd;
+        var _html = "";
+        $(data.view.xxd).each(function (cnt, item) {
+          _html += "<tr><td>" + formatHex(item[0], 7) + ":&nbsp;</td><td>";
+          for (var i = 0; i < item[1].length; i++) {
+            _html += formatHex(item[1][i][0], 2) + " " + formatHex(item[1][i][1], 2) + " ";
+          }
+          _html += "</td><td>&nbsp;&nbsp;" + $("<span>").text(item[2]).html() + "</td></tr>";
+        });
+        $(".binary tbody").html(_html);
+      }
+      if (callback) {
+        callback();
+      }
+      viewModel.isLoading(false);
+    });
   };
 
-  self.page.subscribe(function (value) {
-    self.toggleDisables();
-  });
+  var DisplayViewModel = function (params) {
+    var self = this;
 
-  self.upperPage.subscribe(function (value) {
-    self.toggleDisables();
-  });
+    var changePage = function () {
+      getContent(function () {
+        if (viewModel.totalPages() >= viewModel.MAX_PAGES_TO_ENABLE_SCROLLING || viewModel.mode() == "binary") {
+          window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
+          $("#fileArea").scrollTop(0);
+        } else {
+          window.location.hash = "#page" + viewModel.page();
+        }
+      });
+    };
+
+    self.MAX_ALLOWED_PAGES_PER_REQUEST = ${MAX_ALLOWED_PAGES_PER_REQUEST};
+    self.MAX_PAGES_TO_ENABLE_SCROLLING = 300;
+    self.PAGES_PER_CHUNK = 50;
+
+    self.base_url = ko.observable(params.base_url);
+    self.compression = ko.observable(params.compression);
+    self.mode = ko.observable(params.mode);
+    self.begin = ko.observable(params.begin);
+    self.end = ko.observable(params.end);
+    self.length = ko.observable(params.length);
+    self.size = ko.observable(params.size);
+    self.page = ko.observable(1);
+    self.isLoading = ko.observable(true);
+
+    self.totalPages = ko.computed(function () {
+      return Math.max(Math.floor(self.size() / self.length()), 1);
+    });
 
-  var changePage = function () {
-    getContent(function () {
-      if (viewModel.totalPages() >= viewModel.MAX_PAGES_TO_ENABLE_SCROLLING || viewModel.mode() == "binary") {
-        window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
-        $("#fileArea").scrollTop(0);
-      }
-      else {
-        window.location.hash = "#page" + viewModel.page();
+    self.upperPage = ko.observable(Math.min(self.totalPages(), 50));
+
+    self.begin = ko.computed(function () {
+      return (self.page() - 1) * self.length();
+    });
+
+    self.offset = ko.computed(function () {
+      return ((self.page() - 1) * self.length()) - 1;
+    });
+
+    self.url = ko.computed(function () {
+      return self.base_url()
+              + "?offset=" + self.offset()
+              + "&length=" + self.length()
+              + "&compression=" + self.compression()
+              + "&mode=" + self.mode();
+    });
+
+    self.jsonParams = ko.computed(function () {
+      return {
+        offset: self.begin(),
+        length: self.length() * (self.upperPage() - self.page() + 1),
+        compression: self.compression(),
+        mode: self.mode()
       }
     });
-  };
 
-  self.nextPage = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (!($(".next-page").hasClass("disabled"))) {
-      if (viewModel.page() == viewModel.upperPage()) {
-        viewModel.page(viewModel.page() + 1);
-        viewModel.upperPage(viewModel.upperPage() + 1);
+    self.toggleDisables = function () {
+      $(".next-page").removeClass("disabled");
+      $(".last-page").removeClass("disabled");
+      $(".first-page").removeClass("disabled");
+      $(".previous-page").removeClass("disabled");
+
+      if (self.page() == self.totalPages() || self.upperPage() == self.totalPages()) {
+        $(".next-page").addClass("disabled");
+        $(".last-page").addClass("disabled");
       }
-      else {
-        var _difference = self.upperPage() - self.page();
-        self.page(self.upperPage() + 1);
-        self.upperPage(Math.min(self.page() + _difference, self.totalPages()));
+      if (self.page() == 1) {
+        $(".first-page").addClass("disabled");
+        $(".previous-page").addClass("disabled");
       }
-      changePage();
-    }
-  };
+    };
 
-  self.previousPage = function () {
-    self.page(self.page() * 1);
-    self.upperPage(self.upperPage() * 1);
-    if (!($(".previous-page").hasClass("disabled"))) {
-      if (viewModel.page() == viewModel.upperPage()) {
-        viewModel.page(viewModel.page() - 1);
-        viewModel.upperPage(viewModel.upperPage() - 1);
+    self.pageChanged = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (self.page() > self.totalPages()) {
+        self.page(self.totalPages());
+      }
+      if (self.page() < 1 || !$.isNumeric(self.page())) {
+        self.page(1);
       }
-      else {
-        var _difference = self.upperPage() - self.page();
-        self.upperPage(self.page() - 1);
-        self.page(Math.max(self.page() - _difference - 1, 1));
+      if (self.page() > self.upperPage()) {
+        self.upperPage(self.page());
       }
       changePage();
-    }
-  };
+    };
 
-  self.lastPage = function () {
-    if (!($(".last-page").hasClass("disabled"))) {
-      var _page = viewModel.totalPages();
-      if (_page > 50) {
-        _page = Math.min(viewModel.totalPages() - viewModel.totalPages()%50 + 1, viewModel.totalPages());
+    self.upperPageChanged = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (self.upperPage() > self.totalPages()) {
+        self.upperPage(self.totalPages());
+      }
+      if (self.upperPage() < 1 || !$.isNumeric(self.upperPage())) {
+        self.upperPage(1);
+      }
+      if (self.upperPage() < self.page()) {
+        self.page(self.upperPage());
+      }
+      if (self.upperPage() - self.page() > self.MAX_ALLOWED_PAGES_PER_REQUEST) {
+        self.upperPage(self.page() + self.MAX_ALLOWED_PAGES_PER_REQUEST);
+        $.jHueNotify.info("${_('Sorry, you cannot request for more than %s pages.' % MAX_ALLOWED_PAGES_PER_REQUEST)}");
       }
-      viewModel.page(_page);
-      viewModel.upperPage(viewModel.totalPages());
       changePage();
-    }
-  };
+    };
 
-  self.firstPage = function () {
-    if (!($(".first-page").hasClass("disabled"))) {
-      viewModel.page(1);
-      viewModel.upperPage(Math.min(self.totalPages(), 50));
-      changePage();
-    }
-  }
-}
-;
-
-var viewModel = new displayViewModel({
-          base_url: "${ base_url }",
-          compression: "${view['compression']}",
-          mode: "${ view['mode'] }",
-          begin: ${view['offset'] + 1},
-          end: ${view['end']},
-          length: ${view['length']},
-          size: ${stats['size']},
-          max_size: ${view['max_chunk_size']}
-        }
-);
-
-function resizeText() {
-  $("#fileArea").height($(window).height() - $("#fileArea").offset().top - 26);
-  $("#loader").css("marginLeft", ($("#fileArea").width() - $("#loader").width()) / 2);
-}
-
-function formatHex(number, padding) {
-  if ("undefined" != typeof number){
-    var _filler = "";
-    for (var i = 0; i < padding - 1; i++) {
-      _filler += "0";
-    }
-    return (_filler + number.toString(16)).substr(-padding);
-  }
-  return "";
-}
-
-var pages = {};
-
-function pageContent(page) {
-  var _html = "";
-  if ($("#page" + page).length == 0) {
-    if (pages[page] == null) {
-      _html += "<a id='page" + page + "'><div style='height: " + $("#fileArea").height() + "px'></div></a>";
-    }
-    else {
-      _html += "<a id='page" + page + "'><div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div></a>";
-    }
-  }
-  else {
-    if (pages[page] == null) {
-      $("#page" + page).html("<div style='height: " + $("#fileArea").height() + "px'></div>");
-    }
-    else {
-      $("#page" + page).html("<div style='display: inline'>" + $("<span>").text(pages[page]).html() + "</div>");
-    }
+    self.page.subscribe(function (value) {
+      self.toggleDisables();
+    });
 
-  }
-  return _html;
-}
+    self.upperPage.subscribe(function (value) {
+      self.toggleDisables();
+    });
 
-function renderPages() {
-  var _html = "";
-  if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING) { // enable scrolling
-    for (var i = 1; i <= viewModel.totalPages(); i++) {
-      _html += pageContent(i);
-    }
-  }
-  else {
-    _html += pageContent(viewModel.page());
-  }
-  if (_html != "") {
-    $("#fileArea pre").html(_html);
-  }
-}
-
-
-function getContent(callback) {
-  viewModel.isLoading(true);
-  var _baseUrl = "${url('filebrowser.views.view', path=path_enc)}";
-  $.getJSON(_baseUrl, viewModel.jsonParams(), function (data) {
-    if (data.view.contents != null) {
-      pages[viewModel.page()] = data.view.contents;
-      renderPages();
-    }
-    if (data.view.xxd != null) {
-      pages[viewModel.page()] = data.view.xxd;
-      var _html = "";
-      $(data.view.xxd).each(function (cnt, item) {
-        _html += "<tr><td>" + formatHex(item[0], 7) + ":&nbsp;</td><td>";
-        for (var i = 0; i < item[1].length; i++) {
-          _html += formatHex(item[1][i][0], 2) + " " + formatHex(item[1][i][1], 2) + " ";
+    self.nextPage = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (! ($(".next-page").hasClass("disabled"))) {
+        if (viewModel.page() == viewModel.upperPage()) {
+          viewModel.page(viewModel.page() + 1);
+          viewModel.upperPage(viewModel.upperPage() + 1);
+        } else {
+          var _difference = self.upperPage() - self.page();
+          self.page(self.upperPage() + 1);
+          self.upperPage(Math.min(self.page() + _difference, self.totalPages()));
         }
-        _html += "</td><td>&nbsp;&nbsp;" + $("<span>").text(item[2]).html() + "</td></tr>";
-      });
-      $(".binary tbody").html(_html);
-    }
-    if (callback) {
-      callback();
-    }
-    viewModel.isLoading(false);
-  });
-}
-
-
-$(document).ready(function () {
-  ko.applyBindings(viewModel);
+        changePage();
+      }
+    };
+
+    self.previousPage = function () {
+      self.page(self.page() * 1);
+      self.upperPage(self.upperPage() * 1);
+      if (! ($(".previous-page").hasClass("disabled"))) {
+        if (viewModel.page() == viewModel.upperPage()) {
+          viewModel.page(viewModel.page() - 1);
+          viewModel.upperPage(viewModel.upperPage() - 1);
+        } else {
+          var _difference = self.upperPage() - self.page();
+          self.upperPage(self.page() - 1);
+          self.page(Math.max(self.page() - _difference - 1, 1));
+        }
+        changePage();
+      }
+    };
 
-  $(document).ajaxError(function () {
-    $.jHueNotify.error("${_('There was an unexpected server error.')}");
-  });
+    self.lastPage = function () {
+      if (! ($(".last-page").hasClass("disabled"))) {
+        var _page = viewModel.totalPages();
+        if (_page > 50) {
+          _page = Math.min(viewModel.totalPages() - viewModel.totalPages()%50 + 1, viewModel.totalPages());
+        }
+        viewModel.page(_page);
+        viewModel.upperPage(viewModel.totalPages());
+        changePage();
+      }
+    };
 
-  var _hash = window.location.hash;
-  if (_hash != "") {
-    var _hashPage = 1;
-    var _hashUpperPage = 1;
-    if (_hash.indexOf("-") > -1) {
-      _hashPage = _hash.split("-")[0].substr(2) * 1;
-      _hashUpperPage = _hash.split("-")[1].substr(1) * 1;
-    }
-    else {
-      _hashPage = _hash.substr(2) * 1;
-      _hashUpperPage = Math.min(viewModel.totalPages(), _hashPage + 50 - 1);
-    }
-    if (isNaN(_hashPage)) {
-      _hashPage = 1;
-    }
-    if (isNaN(_hashUpperPage)) {
-      _hashUpperPage = Math.min(viewModel.totalPages(), 50);
-    }
-    if (_hashUpperPage - _hashPage > viewModel.MAX_ALLOWED_PAGES_PER_REQUEST) {
-      _hashUpperPage = _hashPage + viewModel.MAX_ALLOWED_PAGES_PER_REQUEST;
+    self.firstPage = function () {
+      if (! ($(".first-page").hasClass("disabled"))) {
+        viewModel.page(1);
+        viewModel.upperPage(Math.min(self.totalPages(), 50));
+        changePage();
+      }
     }
-    viewModel.page(_hashPage);
-    viewModel.upperPage(_hashUpperPage);
-  }
-
-  viewModel.toggleDisables();
+  };
 
-  window.setTimeout(function () {
-    getContent(function () {
-      if (window.location.hash != "") {
-        window.location.hash = "#page" + viewModel.page();
-        window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
-      }
+  $(document).ready(function () {
+    var viewModel = new DisplayViewModel({
+      base_url: "${ base_url }",
+      compression: "${view['compression']}",
+      mode: "${ view['mode'] }",
+      begin: ${view['offset'] + 1},
+      end: ${view['end']},
+      length: ${view['length']},
+      size: ${stats['size']},
+      max_size: ${view['max_chunk_size']}
     });
-  }, 100);
-
-  resizeText();
 
-  var _resizeTimeout = -1;
-  $(window).on("resize", function () {
-    window.clearTimeout(_resizeTimeout);
-    _resizeTimeout = window.setTimeout(function () {
-      resizeText();
-      renderPages();
-    }, 300);
-  });
+    ko.applyBindings(viewModel);
 
-  $("#fileArea").jHueScrollUp();
+    $(document).ajaxError(function () {
+      $.jHueNotify.error("${_('There was an unexpected server error.')}");
+    });
 
-  if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING && viewModel.mode() == "text") { // enable scrolling
-    var _fileAreaScrollTimeout = -1;
-    $("#fileArea").on("scroll", function () {
-      if ($("#fileArea").scrollTop() < 30) {
-        viewModel.page(1);
-        viewModel.upperPage(viewModel.page());
+    var _hash = window.location.hash;
+    if (_hash != "") {
+      var _hashPage = 1;
+      var _hashUpperPage = 1;
+      if (_hash.indexOf("-") > -1) {
+        _hashPage = _hash.split("-")[0].substr(2) * 1;
+        _hashUpperPage = _hash.split("-")[1].substr(1) * 1;
+      } else {
+        _hashPage = _hash.substr(2) * 1;
+        _hashUpperPage = Math.min(viewModel.totalPages(), _hashPage + 50 - 1);
       }
-      else {
-        for (var i = 1; i <= viewModel.totalPages(); i++) {
-          if ($("#page" + i + " div").visible(true)) {
-            viewModel.page(i);
-            viewModel.upperPage(viewModel.page());
-          }
-        }
+      if (isNaN(_hashPage)) {
+        _hashPage = 1;
       }
-      window.clearTimeout(_fileAreaScrollTimeout);
-      _fileAreaScrollTimeout = window.setTimeout(function () {
-        location.hash = "#p" + viewModel.page();
-        if (pages[viewModel.page()] == null) {
-          getContent();
+      if (isNaN(_hashUpperPage)) {
+        _hashUpperPage = Math.min(viewModel.totalPages(), 50);
+      }
+      if (_hashUpperPage - _hashPage > viewModel.MAX_ALLOWED_PAGES_PER_REQUEST) {
+        _hashUpperPage = _hashPage + viewModel.MAX_ALLOWED_PAGES_PER_REQUEST;
+      }
+      viewModel.page(_hashPage);
+      viewModel.upperPage(_hashUpperPage);
+    };
+
+    viewModel.toggleDisables();
+
+    window.setTimeout(function () {
+      getContent(function () {
+        if (window.location.hash != "") {
+          window.location.hash = "#page" + viewModel.page();
+          window.location.hash = "#p" + viewModel.page() + (viewModel.page() != viewModel.upperPage() ? "-p" + viewModel.upperPage() : "");
         }
-      }, 100);
+      });
+    }, 100);
+
+    resizeText();
+
+    var _resizeTimeout = -1;
+    $(window).on("resize", function () {
+      window.clearTimeout(_resizeTimeout);
+      _resizeTimeout = window.setTimeout(function () {
+        resizeText();
+        renderPages();
+      }, 300);
     });
-  }
 
-});
+    $("#fileArea").jHueScrollUp();
+
+    if (viewModel.totalPages() < viewModel.MAX_PAGES_TO_ENABLE_SCROLLING && viewModel.mode() == "text") { // enable scrolling
+      var _fileAreaScrollTimeout = -1;
+      $("#fileArea").on("scroll", function () {
+        if ($("#fileArea").scrollTop() < 30) {
+          viewModel.page(1);
+          viewModel.upperPage(viewModel.page());
+        } else {
+          for (var i = 1; i <= viewModel.totalPages(); i++) {
+            if ($("#page" + i + " div").visible(true)) {
+              viewModel.page(i);
+              viewModel.upperPage(viewModel.page());
+            }
+          }
+        }
+        window.clearTimeout(_fileAreaScrollTimeout);
+        _fileAreaScrollTimeout = window.setTimeout(function () {
+          location.hash = "#p" + viewModel.page();
+          if (pages[viewModel.page()] == null) {
+            getContent();
+          }
+        }, 100);
+      });
+    }
+  });
+}());
 </script>
 
 ${ commonfooter(messages) | n,unicode }

+ 63 - 63
apps/filebrowser/src/filebrowser/templates/listdir.mako

@@ -32,74 +32,74 @@ ${ fb_components.menubar() }
   <div class="card card-small">
     <div class="actionbar">
     <%actionbar:render>
-        <%def name="search()">
-            <input type="text" class="input-large search-query" placeholder="${_('Search for file name')}" data-bind="value: searchQuery">
-        </%def>
+      <%def name="search()">
+        <input type="text" class="input-large search-query" placeholder="${_('Search for file name')}" data-bind="value: searchQuery">
+      </%def>
 
-        <%def name="actions()">
-          <div class="btn-toolbar" style="display: inline; vertical-align: middle">
-            <button class="btn fileToolbarBtn" title="${_('Rename')}" data-bind="visible: !inTrash(), click: renameFile, enable: selectedFiles().length == 1"><i class="fa fa-font"></i> ${_('Rename')}</button>
-            <button class="btn fileToolbarBtn" title="${_('Move')}" data-bind="click: move, enable: selectedFiles().length > 0"><i class="fa fa-random"></i> ${_('Move')}</button>
-            <button class="btn fileToolbarBtn" title="${_('Copy')}" data-bind="click: copy, enable: selectedFiles().length > 0"><i class="fa fa-files-o"></i> ${_('Copy')}</button>
-            %if is_fs_superuser:
-            <div id="ch-dropdown" class="btn-group" style="vertical-align: middle">
-              <button href="#" class="btn dropdown-toggle" title="${_('Chown / Chmod')}" data-toggle="dropdown" data-bind="visible: !inTrash(), enable: selectedFiles().length > 0">
-                <i class="fa fa-user"></i> ${_('Chmod / Chown')}
-                <span class="caret" style="line-height: 15px"></span>
-              </button>
-              <ul class="dropdown-menu" style="top: auto">
-                <li><a href="#" title="${_('Change owner/group')}" data-bind="visible: !inTrash(), click: changeOwner, enable: selectedFiles().length > 0"><i class="fa fa-user"></i> ${_('Change owner / group')}</a></li>
-                <li><a href="#" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</a></li>
-              </ul>
-            </div>
-            %else:
-              <button class="btn fileToolbarBtn" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</button>
-            %endif
-            <button class="btn fileToolbarBtn" title="${_('Download')}" data-bind="visible: !inTrash(), click: downloadFile, enable: selectedFiles().length == 1 && selectedFile().type == 'file'"><i class="fa fa-arrow-circle-o-down"></i> ${_('Download')}</button>
-            <button class="btn fileToolbarBtn" title="${_('Restore from trash')}" data-bind="visible: inRestorableTrash(), click: restoreTrashSelected, enable: selectedFiles().length > 0"><i class="fa fa-cloud-upload"></i> ${_('Restore')}</button>
-            <!-- ko ifnot: inTrash -->
-                <div id="delete-dropdown" class="btn-group" style="vertical-align: middle">
-                  <button id="trash-btn" class="btn toolbarBtn" data-bind="enable: selectedFiles().length > 0, click: trashSelected"><i class="fa fa-times"></i> ${_('Move to trash')}</button>
-                  <button id="trash-btn-caret" class="btn toolbarBtn dropdown-toggle" data-toggle="dropdown" data-bind="enable: selectedFiles().length > 0">
-                    <span class="caret"></span>
-                  </button>
-                  <ul class="dropdown-menu">
-                    <li><a href="#" class="delete-link" title="${_('Delete forever')}" data-bind="enable: selectedFiles().length > 0, click: deleteSelected"><i class="fa fa-bolt"></i> ${_('Delete forever')}</a></li>
-                  </ul>
-                </div>
-            <!-- /ko -->
-            <button class="btn fileToolbarBtn" title="${_('Submit')}"
-              data-bind="visible: selectedFiles().length == 1 && $.inArray(selectedFile().name, ['workflow.xml', 'coordinator.xml', 'bundle.xml']) > -1, click: submitSelected">
-              <i class="fa fa-play"></i> ${_('Submit')}
+      <%def name="actions()">
+        <div class="btn-toolbar" style="display: inline; vertical-align: middle">
+          <button class="btn fileToolbarBtn" title="${_('Rename')}" data-bind="visible: !inTrash(), click: renameFile, enable: selectedFiles().length == 1"><i class="fa fa-font"></i> ${_('Rename')}</button>
+          <button class="btn fileToolbarBtn" title="${_('Move')}" data-bind="click: move, enable: selectedFiles().length > 0"><i class="fa fa-random"></i> ${_('Move')}</button>
+          <button class="btn fileToolbarBtn" title="${_('Copy')}" data-bind="click: copy, enable: selectedFiles().length > 0"><i class="fa fa-files-o"></i> ${_('Copy')}</button>
+          %if is_fs_superuser:
+          <div id="ch-dropdown" class="btn-group" style="vertical-align: middle">
+            <button href="#" class="btn dropdown-toggle" title="${_('Chown / Chmod')}" data-toggle="dropdown" data-bind="visible: !inTrash(), enable: selectedFiles().length > 0">
+              <i class="fa fa-user"></i> ${_('Chmod / Chown')}
+              <span class="caret" style="line-height: 15px"></span>
             </button>
+            <ul class="dropdown-menu" style="top: auto">
+              <li><a href="#" title="${_('Change owner/group')}" data-bind="visible: !inTrash(), click: changeOwner, enable: selectedFiles().length > 0"><i class="fa fa-user"></i> ${_('Change owner / group')}</a></li>
+              <li><a href="#" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</a></li>
+            </ul>
           </div>
-        </%def>
+          %else:
+            <button class="btn fileToolbarBtn" title="${_('Change permissions')}" data-bind="visible: !inTrash(), click: changePermissions, enable: selectedFiles().length > 0"><i class="fa fa-list-alt"></i> ${_('Change permissions')}</button>
+          %endif
+          <button class="btn fileToolbarBtn" title="${_('Download')}" data-bind="visible: !inTrash(), click: downloadFile, enable: selectedFiles().length == 1 && selectedFile().type == 'file'"><i class="fa fa-arrow-circle-o-down"></i> ${_('Download')}</button>
+          <button class="btn fileToolbarBtn" title="${_('Restore from trash')}" data-bind="visible: inRestorableTrash(), click: restoreTrashSelected, enable: selectedFiles().length > 0"><i class="fa fa-cloud-upload"></i> ${_('Restore')}</button>
+          <!-- ko ifnot: inTrash -->
+              <div id="delete-dropdown" class="btn-group" style="vertical-align: middle">
+                <button id="trash-btn" class="btn toolbarBtn" data-bind="enable: selectedFiles().length > 0, click: trashSelected"><i class="fa fa-times"></i> ${_('Move to trash')}</button>
+                <button id="trash-btn-caret" class="btn toolbarBtn dropdown-toggle" data-toggle="dropdown" data-bind="enable: selectedFiles().length > 0">
+                  <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">
+                  <li><a href="#" class="delete-link" title="${_('Delete forever')}" data-bind="enable: selectedFiles().length > 0, click: deleteSelected"><i class="fa fa-bolt"></i> ${_('Delete forever')}</a></li>
+                </ul>
+              </div>
+          <!-- /ko -->
+          <button class="btn fileToolbarBtn" title="${_('Submit')}"
+            data-bind="visible: selectedFiles().length == 1 && $.inArray(selectedFile().name, ['workflow.xml', 'coordinator.xml', 'bundle.xml']) > -1, click: submitSelected">
+            <i class="fa fa-play"></i> ${_('Submit')}
+          </button>
+        </div>
+      </%def>
 
-        <%def name="creation()">
-          <button class="btn fileToolbarBtn" title="${_('Empty trash')}" data-bind="visible: inTrash(), click: purgeTrash"><i class="fa fa-fire"></i> ${_('Empty trash')}</button>
-          <div class="btn-toolbar" style="display: inline; vertical-align: middle">
-            <div id="upload-dropdown" class="btn-group" style="vertical-align: middle">
-              <a href="#" class="btn upload-link dropdown-toggle" title="${_('Upload')}" data-toggle="dropdown" data-bind="visible: !inTrash()">
-                <i class="fa fa-arrow-circle-o-up"></i> ${_('Upload')}
-                <span class="caret"></span>
-              </a>
-              <ul class="dropdown-menu">
-                <li><a href="#" class="upload-link" title="${_('Files')}" data-bind="click: uploadFile"><i class="fa fa-file-o"></i> ${_('Files')}</a></li>
-                <li><a href="#" class="upload-link" title="${_('Archive')}" data-bind="click: uploadArchive"><i class="fa fa-gift"></i> ${_('Zip/Tgz file')}</a></li>
-              </ul>
-            </div>
-            <div class="btn-group" style="vertical-align: middle">
-              <a href="#" data-toggle="dropdown" class="btn dropdown-toggle" data-bind="visible: !inTrash()">
-                <i class="fa fa-plus-circle"></i> ${_('New')}
-                <span class="caret"></span>
-              </a>
-              <ul class="dropdown-menu pull-right" style="top: auto">
-                <li><a href="#" class="create-file-link" title="${_('File')}"><i class="fa fa-file-o"></i> ${_('File')}</a></li>
-                <li><a href="#" class="create-directory-link" title="${_('Directory')}"><i class="fa fa-folder"></i> ${_('Directory')}</a></li>
-              </ul>
-            </div>
+      <%def name="creation()">
+        <button class="btn fileToolbarBtn" title="${_('Empty trash')}" data-bind="visible: inTrash(), click: purgeTrash"><i class="fa fa-fire"></i> ${_('Empty trash')}</button>
+        <div class="btn-toolbar" style="display: inline; vertical-align: middle">
+          <div id="upload-dropdown" class="btn-group" style="vertical-align: middle">
+            <a href="#" class="btn upload-link dropdown-toggle" title="${_('Upload')}" data-toggle="dropdown" data-bind="visible: !inTrash()">
+              <i class="fa fa-arrow-circle-o-up"></i> ${_('Upload')}
+              <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu">
+              <li><a href="#" class="upload-link" title="${_('Files')}" data-bind="click: uploadFile"><i class="fa fa-file-o"></i> ${_('Files')}</a></li>
+              <li><a href="#" class="upload-link" title="${_('Archive')}" data-bind="click: uploadArchive"><i class="fa fa-gift"></i> ${_('Zip/Tgz file')}</a></li>
+            </ul>
           </div>
-        </%def>
+          <div class="btn-group" style="vertical-align: middle">
+            <a href="#" data-toggle="dropdown" class="btn dropdown-toggle" data-bind="visible: !inTrash()">
+              <i class="fa fa-plus-circle"></i> ${_('New')}
+              <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu pull-right" style="top: auto">
+              <li><a href="#" class="create-file-link" title="${_('File')}"><i class="fa fa-file-o"></i> ${_('File')}</a></li>
+              <li><a href="#" class="create-directory-link" title="${_('Directory')}"><i class="fa fa-folder"></i> ${_('Directory')}</a></li>
+            </ul>
+          </div>
+        </div>
+      </%def>
     </%actionbar:render>
     </div>
     <div class="actionbarGhost hide"></div>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 446 - 825
apps/filebrowser/src/filebrowser/templates/listdir_components.mako


+ 1 - 1
apps/filebrowser/src/filebrowser/views.py

@@ -407,7 +407,7 @@ def listdir_paged(request, path):
     # actually '.' for display purposes. Encode it since _massage_stats expects byte strings.
     current_stat['path'] = path
     current_stat['name'] = "."
-    shown_stats.insert(0, current_stat)
+    shown_stats.insert(1, current_stat)
 
     page.object_list = [ _massage_stats(request, s) for s in shown_stats ]
 

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott