display.mako 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. ## -*- coding: utf-8 -*-
  2. ## Licensed to Cloudera, Inc. under one
  3. ## or more contributor license agreements. See the NOTICE file
  4. ## distributed with this work for additional information
  5. ## regarding copyright ownership. Cloudera, Inc. licenses this file
  6. ## to you under the Apache License, Version 2.0 (the
  7. ## "License"); you may not use this file except in compliance
  8. ## with the License. You may obtain a copy of the License at
  9. ##
  10. ## http://www.apache.org/licenses/LICENSE-2.0
  11. ##
  12. ## Unless required by applicable law or agreed to in writing, software
  13. ## distributed under the License is distributed on an "AS IS" BASIS,
  14. ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. ## See the License for the specific language governing permissions and
  16. ## limitations under the License.
  17. <%!
  18. import datetime
  19. from django.template.defaultfilters import urlencode, stringformat, date, filesizeformat, time
  20. from filebrowser.views import truncate
  21. from desktop.views import commonheader, commonfooter
  22. from django.utils.translation import ugettext as _
  23. %>
  24. <%
  25. path_enc = urlencode(path)
  26. dirname_enc = urlencode(view['dirname'])
  27. base_url = url('filebrowser.views.view', path=path_enc)
  28. %>
  29. <%namespace name="fb_components" file="fb_components.mako" />
  30. ${ commonheader(_('%(filename)s - File Viewer') % dict(filename=truncate(filename)), 'filebrowser', user) | n,unicode }
  31. <div class="container-fluid">
  32. % if breadcrumbs:
  33. ${fb_components.breadcrumbs(path, breadcrumbs)}
  34. %endif
  35. </div>
  36. <div class="container-fluid">
  37. <div class="row-fluid">
  38. <div class="span2">
  39. <div class="well sidebar-nav">
  40. <ul class="nav nav-list">
  41. <li class="nav-header">${_('Actions')}</li>
  42. % if view['mode'] == "binary":
  43. <li><a href="${base_url}?offset=${view['offset']}&length=${view['length']}&mode=text&compression=${view['compression']}">${_('View As Text')}</a></li>
  44. % endif
  45. % if view['mode'] == "text":
  46. <li><a href="${base_url}?offset=${view['offset']}&length=${view['length']}&mode=binary&compression=${view['compression']}">${_('View As Binary')}</a></li>
  47. % endif
  48. % if view['compression'] != "gzip" and path.endswith('.gz'):
  49. <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=gzip">${_('Preview As Gzip')}</a></li>
  50. % endif
  51. % if view['compression'] != "avro" and view['compression'] != "snappy_avro" and path.endswith('.avro'):
  52. <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=avro">${_('Preview As Avro')}</a></li>
  53. % endif
  54. % if view['compression'] and view['compression'] != "none":
  55. <li><a href="${base_url}?offset=0&length=2000&mode=${view['mode']}&compression=none">${_('Stop preview')}</a></li>
  56. % endif
  57. % if editable and view['compression'] == "none":
  58. <li><a href="${url('filebrowser.views.edit', path=path_enc)}">${_('Edit File')}</a></li>
  59. % endif
  60. <li><a href="${url('filebrowser.views.download', path=path_enc)}">${_('Download')}</a></li>
  61. <li><a href="${url('filebrowser.views.view', path=dirname_enc)}">${_('View File Location')}</a></li>
  62. <li><a id="refreshBtn">${_('Refresh')}</a></li>
  63. <li class="nav-header">${_('Info')}</li>
  64. <li>
  65. <dl>
  66. <dt>${_('Last Modified')}</dt>
  67. <dd>${date(datetime.datetime.fromtimestamp(stats['mtime']))} ${time(datetime.datetime.fromtimestamp(stats['mtime']))}</dd>
  68. <dt>${_('User')}</dt>
  69. <dd>${stats['user']}</dd>
  70. <dt>${_('Group')}</dt>
  71. <dd>${stats['group']}</dd>
  72. <dt>${_('Size')}</dt>
  73. <dd>${stats['size']|filesizeformat}</dd>
  74. <dt>${_('Mode')}</dt>
  75. <dd>${stringformat(stats['mode'], "o")}</dd>
  76. </dl>
  77. </li>
  78. </ul>
  79. </div>
  80. </div>
  81. <div class="span10">
  82. % if not view['compression'] or view['compression'] in ("none", "avro"):
  83. <div class="pagination">
  84. <ul>
  85. <li class="first-block prev disabled"><a href="javascript:void(0);" data-bind="click: firstBlock">${_('First Block')}</a></li>
  86. <li class="previous-block disabled"><a href="javascript:void(0);" data-bind="click: previousBlock">${_('Previous Block')}</a></li>
  87. <li class="next-block"><a href="javascript:void(0);" data-bind="click: nextBlock">${_('Next Block')}</a></li>
  88. <li class="last-block next"><a href="javascript:void(0);" data-bind="click: lastBlock">${_('Last Block')}</a></li>
  89. </ul>
  90. <form action="${url('filebrowser.views.view', path=path_enc)}" method="GET" class="form-inline pull-right">
  91. <span>${_('Viewing Bytes:')}</span>
  92. <input type="text" name="begin" value="${view['offset'] + 1}" data-bind="value: begin" class="input-mini" />
  93. -
  94. <input type="text" name="end" value="${view['end']}" data-bind="value: end" class="input-mini" /> of
  95. <span>${stats['size']}</span>
  96. <span>${_('(%(length)s B block size)' % dict(length=view['length']))}</span>
  97. % if view['mode']:
  98. <input type="hidden" name="mode" value="${view['mode']}"/>
  99. % endif
  100. </form>
  101. </div>
  102. % endif
  103. %if 'contents' in view:
  104. % if view['masked_binary_data']:
  105. <div class="alert-message warning">${_("Warning: some binary data has been masked out with '&#xfffd'.")}</div>
  106. % endif
  107. % endif
  108. <div>
  109. % if 'contents' in view:
  110. <div id="file-contents"><pre>${view['contents']}</pre></div>
  111. % else:
  112. <table>
  113. % for offset, words, masked in view['xxd']:
  114. <tr>
  115. <td><tt>${stringformat(offset, "07x")}:&nbsp;</tt></td>
  116. <td>
  117. <tt>
  118. % for word in words:
  119. % for byte in word:
  120. ${stringformat(byte, "02x")}
  121. % endfor
  122. % endfor
  123. </tt>
  124. </td>
  125. <td>
  126. <tt>
  127. &nbsp;&nbsp;${masked}
  128. </tt>
  129. </td>
  130. </tr>
  131. % endfor
  132. </table>
  133. % endif
  134. </div>
  135. % if not view['compression'] or view['compression'] in ("none", "avro"):
  136. <div class="pagination">
  137. <ul>
  138. <li class="first-block prev disabled"><a href="javascript:void(0);" data-bind="click: firstBlock">${_('First Block')}</a></li>
  139. <li class="previous-block disabled"><a href="javascript:void(0);" data-bind="click: previousBlock">${_('Previous Block')}</a></li>
  140. <li class="next-block"><a href="javascript:void(0);" data-bind="click: nextBlock">${_('Next Block')}</a></li>
  141. <li class="last-block next"><a href="javascript:void(0);" data-bind="click: lastBlock">${_('Last Block')}</a></li>
  142. </ul>
  143. </div>
  144. % endif
  145. </div>
  146. </div>
  147. </div>
  148. <script src="/static/ext/js/knockout-2.1.0.js" type="text/javascript" charset="utf-8"></script>
  149. <script type="text/javascript" charset="utf-8">
  150. function displayViewModel(base_url, compression, mode, begin, end, length, size, max_size) {
  151. var self = this;
  152. self.base_url = ko.observable(base_url);
  153. self.compression = ko.observable(compression);
  154. self.mode = ko.observable(mode);
  155. self.begin = ko.observable(begin);
  156. self.end = ko.observable(end);
  157. self.length = ko.observable(length);
  158. self.size = ko.observable(size);
  159. self.offset = ko.computed(function() {
  160. return self.begin() - 1;
  161. });
  162. self.url = ko.computed(function() {
  163. return self.base_url()
  164. + "?offset=" + self.offset()
  165. + "&length=" + self.length()
  166. + "&compression="+ self.compression()
  167. + "&mode=" + self.mode();
  168. });
  169. var change_length = function() {
  170. var length = self.end() - self.offset();
  171. if (length > max_size) {
  172. length = max_size;
  173. }
  174. self.length(length);
  175. };
  176. self.begin.subscribe(change_length);
  177. self.end.subscribe(change_length);
  178. var reloading = false;
  179. self.reload = function() {
  180. if (!reloading) {
  181. reloading = true;
  182. window.location.href = self.url();
  183. }
  184. };
  185. self.toggleDisables = function() {
  186. if (self.offset() + self.length() >= self.size()) {
  187. $(".next-block").addClass("disabled");
  188. $(".last-block").addClass("disabled");
  189. } else {
  190. $(".next-block").removeClass("disabled");
  191. $(".last-block").removeClass("disabled");
  192. }
  193. if (self.offset() <= 0) {
  194. $(".first-block").addClass("disabled");
  195. $(".previous-block").addClass("disabled");
  196. } else {
  197. $(".first-block").removeClass("disabled");
  198. $(".previous-block").removeClass("disabled");
  199. }
  200. };
  201. self.begin.subscribe(self.toggleDisables);
  202. self.end.subscribe(self.toggleDisables);
  203. var changeBlock = function(begin, end) {
  204. if (begin < self.size() && end > 0 && end > begin && !reloading) {
  205. self.begin(begin);
  206. self.end(end);
  207. self.toggleDisables();
  208. self.reload();
  209. }
  210. };
  211. self.nextBlock = function() {
  212. var offset = self.offset() + self.length();
  213. changeBlock(offset + 1, offset + self.length());
  214. };
  215. self.previousBlock = function() {
  216. var offset = ( self.offset() >= self.length() ) ? self.offset() - self.length() : 0;
  217. changeBlock(offset + 1, offset + self.length());
  218. };
  219. self.lastBlock = function() {
  220. var offset = self.size() - self.length();
  221. if (offset < 0) {
  222. offset = 0;
  223. }
  224. changeBlock(offset + 1, offset + self.length());
  225. };
  226. self.firstBlock = function() {
  227. changeBlock(1, self.length());
  228. }
  229. };
  230. var viewModel = new displayViewModel(
  231. "${ base_url }",
  232. "${view['compression']}",
  233. "${ view['mode'] }",
  234. ${view['offset'] + 1},
  235. ${view['end']},
  236. ${view['length']},
  237. ${stats['size']},
  238. ${view['max_chunk_size']}
  239. );
  240. $(window).load(function(){
  241. $("#refreshBtn").click(function(){
  242. window.location.reload();
  243. });
  244. ko.applyBindings(viewModel);
  245. viewModel.toggleDisables();
  246. });
  247. </script>
  248. ${ commonfooter(messages) | n,unicode }