Explorar o código

HUE-1736 [fb] Editor windown is not high enough

Resize dinamically to fill up the browser screen estate
Empty file viz improved
Added side bar to file editor
Enrico Berti %!s(int64=12) %!d(string=hai) anos
pai
achega
d797404

+ 76 - 109
apps/filebrowser/src/filebrowser/templates/display.mako

@@ -31,58 +31,22 @@
 ${ commonheader(_('%(filename)s - File Viewer') % dict(filename=truncate(filename)), 'filebrowser', user) | n,unicode }
 ${ fb_components.menubar() }
 
+<style type="text/css">
+  .empty-wrapper {
+    margin-top: 50px;
+    color: #BBB;
+    line-height: 60px;
+  }
+
+  .empty-wrapper i {
+    font-size: 148px;
+  }
+</style>
+
 <div class="container-fluid">
   <div class="row-fluid">
     <div class="span2">
-      <div class="sidebar-nav" style="padding-top: 0">
-        <ul class="nav nav-list">
-          <li class="nav-header">${_('Actions')}</li>
-          % if view['mode'] == "binary":
-            <li><a href="${base_url}?offset=${view['offset']}&length=${view['length']}&mode=text&compression=${view['compression']}"><i class="fa fa-font"></i> ${_('View as text')}</a></li>
-          % endif
-
-          % if view['mode'] == "text":
-            <li><a href="${base_url}?offset=${view['offset']}&length=${view['length']}&mode=binary&compression=${view['compression']}"><i class="fa fa-barcode"></i> ${_('View as binary')}</a></li>
-          % endif
-
-          % if view['compression'] != "gzip" and path.endswith('.gz'):
-            <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=gzip"><i class="fa fa-youtube-play"></i> ${_('Preview as Gzip')}</a></li>
-          % endif
-
-          % if view['compression'] != "avro" and view['compression'] != "snappy_avro" and path.endswith('.avro'):
-            <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=avro"><i class="fa fa-youtube-play"></i> ${_('Preview as Avro')}</a></li>
-          % endif
-
-          % if view['compression'] and view['compression'] != "none":
-            <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=none"><i class="fa fa-times-circle"></i> ${_('Stop preview')}</a></li>
-          % endif
-
-          % if editable and view['compression'] == "none":
-            <li><a href="${url('filebrowser.views.edit', path=path_enc)}"><i class="fa fa-pencil"></i> ${_('Edit file')}</a></li>
-          % endif
-
-           <li><a href="${url('filebrowser.views.download', path=path_enc)}"><i class="fa fa-download"></i> ${_('Download')}</a></li>
-           <li><a href="${url('filebrowser.views.view', path=dirname_enc)}"><i class="fa fa-file-text"></i> ${_('View file location')}</a></li>
-           <li><a id="refreshBtn"><i class="fa fa-refresh"></i> ${_('Refresh')}</a></li>
-
-          <li class="nav-header">${_('Info')}</li>
-          <li class="white">
-            <dl>
-              <dt>${_('Last modified')}</dt>
-              <dd>${date(datetime.datetime.fromtimestamp(stats['mtime']))} ${time(datetime.datetime.fromtimestamp(stats['mtime']))}</dd>
-              <dt>${_('User')}</dt>
-              <dd>${stats['user']}</dd>
-              <dt>${_('Group')}</dt>
-              <dd>${stats['group']}</dd>
-              <dt>${_('Size')}</dt>
-              <dd>${stats['size']|filesizeformat}</dd>
-              <dt>${_('Mode')}</dt>
-              <dd>${stringformat(stats['mode'], "o")}</dd>
-            </dl>
-          </li>
-        </ul>
-
-      </div>
+      ${ fb_components.file_sidebar(path_enc, dirname_enc, stats, view) }
     </div>
     <div class="span10">
       <div class="card card-small">
@@ -91,74 +55,77 @@ ${ fb_components.menubar() }
       %endif
         <div class="card-body">
           <p>
-            % if not view['compression'] or view['compression'] in ("none", "avro"):
-        <div class="pagination">
-          <ul>
+        % if stats['size'] == 0:
+          <div class="center empty-wrapper">
+            <i class="fa fa-frown-o"></i>
+            <h1>${_('The current file is empty.')}</h1>
+            <br />
+          </div>
+        % else:
+          % if not view['compression'] or view['compression'] in ("none", "avro"):
+          <div class="pagination">
+            <ul>
               <li class="first-block prev disabled"><a href="javascript:void(0);" data-bind="click: firstBlock">${_('First Block')}</a></li>
               <li class="previous-block disabled"><a href="javascript:void(0);" data-bind="click: previousBlock">${_('Previous Block')}</a></li>
               <li class="next-block"><a href="javascript:void(0);" data-bind="click: nextBlock">${_('Next Block')}</a></li>
               <li class="last-block next"><a href="javascript:void(0);" data-bind="click: lastBlock">${_('Last Block')}</a></li>
-          </ul>
+            </ul>
+
+            <form action="${url('filebrowser.views.view', path=path_enc)}" method="GET" class="form-inline pull-right">
+              <span>${_('Viewing Bytes:')}</span>
+              <input type="text" name="begin" value="${view['offset'] + 1}" data-bind="value: begin" class="input-mini" />
+              -
+              <input type="text" name="end" value="${view['end']}" data-bind="value: end" class="input-mini" /> of
+              <span>${stats['size']}</span>
+              <span>${_('(%(length)s B block size)' % dict(length=view['length']))}</span>
+              % if view['mode']:
+                <input type="hidden" name="mode" value="${view['mode']}"/>
+              % endif
+            </form>
+          </div>
+          % endif
 
-          <form action="${url('filebrowser.views.view', path=path_enc)}" method="GET" class="form-inline pull-right">
-            <span>${_('Viewing Bytes:')}</span>
-            <input type="text" name="begin" value="${view['offset'] + 1}" data-bind="value: begin" class="input-mini" />
-            -
-            <input type="text" name="end" value="${view['end']}" data-bind="value: end" class="input-mini" /> of
-            <span>${stats['size']}</span>
-            <span>${_('(%(length)s B block size)' % dict(length=view['length']))}</span>
-            % if view['mode']:
-              <input type="hidden" name="mode" value="${view['mode']}"/>
+          %if 'contents' in view:
+            % if view['masked_binary_data']:
+              <div class="alert-message warning">${_("Warning: some binary data has been masked out with '&#xfffd'.")}</div>
             % endif
-          </form>
-
-        </div>
-      % endif
-
-      %if 'contents' in view:
-        % if view['masked_binary_data']:
-        <div class="alert-message warning">${_("Warning: some binary data has been masked out with '&#xfffd'.")}</div>
-        % endif
-      % endif
+          % endif
 
-      <div>
-      % if 'contents' in view:
-        <div id="file-contents"><pre>${view['contents']}</pre></div>
-      % else:
-        <table>
-          % for offset, words, masked in view['xxd']:
-          <tr>
-            <td><tt>${stringformat(offset, "07x")}:&nbsp;</tt></td>
-            <td>
-              <tt>
-                % for word in words:
-                  % for byte in word:
-                    ${stringformat(byte, "02x")}
+          <div>
+          % if 'contents' in view:
+            <div id="file-contents"><pre>${view['contents']}</pre></div>
+          % else:
+            <table>
+              % for offset, words, masked in view['xxd']:
+              <tr>
+                <td>${stringformat(offset, "07x")}:&nbsp;</td>
+                <td>
+                  % for word in words:
+                    % for byte in word:
+                      ${stringformat(byte, "02x")}
+                    % endfor
                   % endfor
-                % endfor
-              </tt>
-            </td>
-            <td>
-              <tt>
-                &nbsp;&nbsp;${masked}
-              </tt>
-            </td>
-          </tr>
-          % endfor
-        </table>
-      % endif
-      </div>
-
-      % if not view['compression'] or view['compression'] in ("none", "avro"):
-        <div class="pagination">
-          <ul>
-              <li class="first-block prev disabled"><a href="javascript:void(0);" data-bind="click: firstBlock">${_('First Block')}</a></li>
-              <li class="previous-block disabled"><a href="javascript:void(0);" data-bind="click: previousBlock">${_('Previous Block')}</a></li>
-              <li class="next-block"><a href="javascript:void(0);" data-bind="click: nextBlock">${_('Next Block')}</a></li>
-              <li class="last-block next"><a href="javascript:void(0);" data-bind="click: lastBlock">${_('Last Block')}</a></li>
-          </ul>
-        </div>
-      % endif
+                </td>
+                <td>
+                  &nbsp;&nbsp;${masked}
+                </td>
+              </tr>
+              % endfor
+            </table>
+          % endif
+          </div>
+
+          % if not view['compression'] or view['compression'] in ("none", "avro"):
+            <div class="pagination">
+              <ul>
+                <li class="first-block prev disabled"><a href="javascript:void(0);" data-bind="click: firstBlock">${_('First Block')}</a></li>
+                <li class="previous-block disabled"><a href="javascript:void(0);" data-bind="click: previousBlock">${_('Previous Block')}</a></li>
+                <li class="next-block"><a href="javascript:void(0);" data-bind="click: nextBlock">${_('Next Block')}</a></li>
+                <li class="last-block next"><a href="javascript:void(0);" data-bind="click: lastBlock">${_('Last Block')}</a></li>
+              </ul>
+            </div>
+          % endif
+        % endif
           </p>
         </div>
       </div>

+ 34 - 9
apps/filebrowser/src/filebrowser/templates/edit.mako

@@ -15,7 +15,8 @@
 ## limitations under the License.
 
 <%!
-  from django.template.defaultfilters import urlencode
+  import datetime
+  from django.template.defaultfilters import urlencode, stringformat, date, filesizeformat, time
   from filebrowser.views import truncate
   from desktop.views import commonheader, commonfooter
   from django.utils.translation import ugettext as _
@@ -34,12 +35,16 @@ ${ fb_components.menubar() }
 
 <div class="container-fluid">
   <div class="row-fluid">
-    <div class="span12">
+    <div class="span2">
+      ${ fb_components.file_sidebar(path_enc, dirname_enc, stats) }
+    </div>
+    <div class="span10">
       <div class="card card-small">
-        % if breadcrumbs:
-          ${fb_components.breadcrumbs(path, breadcrumbs)}
-        %endif
-        <div class="card-body" style="margin-top: -20px">
+      % if breadcrumbs:
+        ${fb_components.breadcrumbs(path, breadcrumbs)}
+      %endif
+        <div class="card-body">
+          <p>
             <form class="form-stacked" method="post" action="${url('filebrowser.views.save_file')}">
               % if form.errors:
               <div class="alert-message">
@@ -52,12 +57,12 @@ ${ fb_components.menubar() }
               % endif
               ${edit.render_field(form["path"], hidden=True, notitle=True)}
               ${edit.render_field(form["encoding"], hidden=True, notitle=True)}
-              <div style="width: 100%; height: 100%;">${edit.render_field(form["contents"], tag="textarea", nolabel=True, notitle=True, attrs=dict(
-                style="width:100%; height:400px;")) | n}</div>
+              <div style="width: 98%; height: 100%;">${edit.render_field(form["contents"], tag="textarea", nolabel=True, notitle=True, attrs=dict(
+                style="width:100%; height:400px; resize:none")) | n}</div>
               <input class="btn btn-primary" type="submit" name="save" value="${_('Save')}">
               <a id="saveAsBtn" class="btn">${_('Save as')}</a>
             </form>
-          <br/>
+          </p>
         </div>
       </div>
     </div>
@@ -133,6 +138,26 @@ ${ fb_components.menubar() }
         });
         $("#fileChooserSaveModal").slideDown();
       });
+
+      $("#refreshBtn").click(function(){
+        window.location.reload();
+      });
+
+      function resizeTextarea() {
+        var RESIZE_CORRECTION = 246;
+        $("textarea[name='contents']").height( $(window).height() - RESIZE_CORRECTION);
+      }
+
+      var _resizeTimeout = -1;
+      $(window).on("resize", function () {
+        window.clearTimeout(_resizeTimeout);
+        _resizeTimeout = window.setTimeout(function () {
+          resizeTextarea();
+        }, 100);
+      });
+
+      resizeTextarea();
+
     });
   </script>
 

+ 60 - 1
apps/filebrowser/src/filebrowser/templates/fb_components.mako

@@ -14,7 +14,8 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 <%!
-from django.template.defaultfilters import urlencode
+import datetime
+from django.template.defaultfilters import urlencode, stringformat, date, filesizeformat, time
 from django.utils.translation import ugettext as _
 %>
 
@@ -73,3 +74,61 @@ from django.utils.translation import ugettext as _
       </div>
   </div>
 </%def>
+
+<%def name="file_sidebar(path_enc, dirname_enc, stats, view=None)">
+  <div class="sidebar-nav" style="padding-top: 0">
+    <ul class="nav nav-list">
+      <li class="nav-header">${_('Actions')}</li>
+      % if view:
+        <%
+          base_url = url('filebrowser.views.view', path=path_enc)
+        %>
+        % if view['mode'] == "binary":
+          <li><a href="${base_url}?offset=${view['offset']}&length=${view['length']}&mode=text&compression=${view['compression']}"><i class="fa fa-font"></i> ${_('View as text')}</a></li>
+        % endif
+
+        % if view['mode'] == "text":
+          <li><a href="${base_url}?offset=${view['offset']}&length=${view['length']}&mode=binary&compression=${view['compression']}"><i class="fa fa-barcode"></i> ${_('View as binary')}</a></li>
+        % endif
+
+        % if view['compression'] != "gzip" and path.endswith('.gz'):
+          <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=gzip"><i class="fa fa-youtube-play"></i> ${_('Preview as Gzip')}</a></li>
+        % endif
+
+        % if view['compression'] != "avro" and view['compression'] != "snappy_avro" and path.endswith('.avro'):
+          <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=avro"><i class="fa fa-youtube-play"></i> ${_('Preview as Avro')}</a></li>
+        % endif
+
+        % if view['compression'] and view['compression'] != "none":
+          <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=none"><i class="fa fa-times-circle"></i> ${_('Stop preview')}</a></li>
+        % endif
+
+        % if editable and view['compression'] == "none":
+          <li><a href="${url('filebrowser.views.edit', path=path_enc)}"><i class="fa fa-pencil"></i> ${_('Edit file')}</a></li>
+        % endif
+      % else:
+        <li><a href="${url('filebrowser.views.view', path=path_enc)}"><i class="fa fa-eye"></i> ${_('View file')}</a></li>
+      % endif
+
+       <li><a href="${url('filebrowser.views.download', path=path_enc)}"><i class="fa fa-download"></i> ${_('Download')}</a></li>
+       <li><a href="${url('filebrowser.views.view', path=dirname_enc)}"><i class="fa fa-file-text"></i> ${_('View file location')}</a></li>
+       <li><a id="refreshBtn" href="#"><i class="fa fa-refresh"></i> ${_('Refresh')}</a></li>
+
+       <li class="nav-header">${_('Info')}</li>
+       <li class="white">
+        <dl>
+          <dt>${_('Last modified')}</dt>
+          <dd>${date(datetime.datetime.fromtimestamp(stats['mtime']))} ${time(datetime.datetime.fromtimestamp(stats['mtime']))}</dd>
+          <dt>${_('User')}</dt>
+          <dd>${stats['user']}</dd>
+          <dt>${_('Group')}</dt>
+          <dd>${stats['group']}</dd>
+          <dt>${_('Size')}</dt>
+          <dd>${stats['size']|filesizeformat}</dd>
+          <dt>${_('Mode')}</dt>
+          <dd>${stringformat(stats['mode'], "o")}</dd>
+        </dl>
+       </li>
+    </ul>
+  </div>
+</%def>

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

@@ -211,6 +211,7 @@ def edit(request, path, form=None):
 
     data = dict(
         exists=(stats is not None),
+        stats=stats,
         form=form,
         path=path,
         filename=os.path.basename(path),