filesummary.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /**
  2. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  3. * SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. (function() {
  7. /**
  8. * The FileSummary class encapsulates the file summary values and
  9. * the logic to render it in the given container
  10. *
  11. * @constructs FileSummary
  12. * @memberof OCA.Files
  13. *
  14. * @param $tr table row element
  15. * @param {OC.Backbone.Model} [options.filesConfig] files app configuration
  16. */
  17. var FileSummary = function($tr, options) {
  18. options = options || {};
  19. var self = this;
  20. this.$el = $tr;
  21. var filesConfig = options.config;
  22. if (filesConfig) {
  23. this._showHidden = !!filesConfig.show_hidden;
  24. window._nc_event_bus.subscribe('files:config:updated', ({ key, value }) => {
  25. if (key === 'show_hidden') {
  26. self._showHidden = !!value;
  27. self.update();
  28. }
  29. });
  30. }
  31. this.clear();
  32. this.render();
  33. };
  34. FileSummary.prototype = {
  35. _showHidden: null,
  36. summary: {
  37. totalFiles: 0,
  38. totalDirs: 0,
  39. totalHidden: 0,
  40. totalSize: 0,
  41. filter:'',
  42. sumIsPending:false
  43. },
  44. /**
  45. * Returns whether the given file info must be hidden
  46. *
  47. * @param {OC.Files.FileInfo} fileInfo file info
  48. *
  49. * @return {boolean} true if the file is a hidden file, false otherwise
  50. */
  51. _isHiddenFile: function(file) {
  52. return file.name && file.name.charAt(0) === '.';
  53. },
  54. /**
  55. * Adds file
  56. * @param {OC.Files.FileInfo} file file to add
  57. * @param {boolean} update whether to update the display
  58. */
  59. add: function(file, update) {
  60. if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) {
  61. return;
  62. }
  63. if (file.type === 'dir' || file.mime === 'httpd/unix-directory') {
  64. this.summary.totalDirs++;
  65. }
  66. else {
  67. this.summary.totalFiles++;
  68. }
  69. if (this._isHiddenFile(file)) {
  70. this.summary.totalHidden++;
  71. }
  72. var size = parseInt(file.size, 10) || 0;
  73. if (size >=0) {
  74. this.summary.totalSize += size;
  75. } else {
  76. this.summary.sumIsPending = true;
  77. }
  78. if (!!update) {
  79. this.update();
  80. }
  81. },
  82. /**
  83. * Removes file
  84. * @param {OC.Files.FileInfo} file file to remove
  85. * @param {boolean} update whether to update the display
  86. */
  87. remove: function(file, update) {
  88. if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) {
  89. return;
  90. }
  91. if (file.type === 'dir' || file.mime === 'httpd/unix-directory') {
  92. this.summary.totalDirs--;
  93. }
  94. else {
  95. this.summary.totalFiles--;
  96. }
  97. if (this._isHiddenFile(file)) {
  98. this.summary.totalHidden--;
  99. }
  100. var size = parseInt(file.size, 10) || 0;
  101. if (size >=0) {
  102. this.summary.totalSize -= size;
  103. }
  104. if (!!update) {
  105. this.update();
  106. }
  107. },
  108. setFilter: function(filter, files){
  109. this.summary.filter = filter.toLowerCase();
  110. this.calculate(files);
  111. },
  112. /**
  113. * Returns the total of files and directories
  114. */
  115. getTotal: function() {
  116. return this.summary.totalDirs + this.summary.totalFiles;
  117. },
  118. /**
  119. * Recalculates the summary based on the given files array
  120. * @param files array of files
  121. */
  122. calculate: function(files) {
  123. var file;
  124. var summary = {
  125. totalDirs: 0,
  126. totalFiles: 0,
  127. totalHidden: 0,
  128. totalSize: 0,
  129. filter: this.summary.filter,
  130. sumIsPending: false
  131. };
  132. for (var i = 0; i < files.length; i++) {
  133. file = files[i];
  134. if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) {
  135. continue;
  136. }
  137. if (file.type === 'dir' || file.mime === 'httpd/unix-directory') {
  138. summary.totalDirs++;
  139. }
  140. else {
  141. summary.totalFiles++;
  142. }
  143. if (this._isHiddenFile(file)) {
  144. summary.totalHidden++;
  145. }
  146. var size = parseInt(file.size, 10) || 0;
  147. if (size >=0) {
  148. summary.totalSize += size;
  149. } else {
  150. summary.sumIsPending = true;
  151. }
  152. }
  153. this.setSummary(summary);
  154. },
  155. /**
  156. * Clears the summary
  157. */
  158. clear: function() {
  159. this.calculate([]);
  160. },
  161. /**
  162. * Sets the current summary values
  163. * @param summary map
  164. */
  165. setSummary: function(summary) {
  166. this.summary = summary;
  167. if (typeof this.summary.filter === 'undefined') {
  168. this.summary.filter = '';
  169. }
  170. this.update();
  171. },
  172. _infoTemplate: function(data) {
  173. /* NOTE: To update the template make changes in filesummary.handlebars
  174. * and run:
  175. *
  176. * handlebars -n OCA.Files.FileSummary.Templates filesummary.handlebars -f filesummary_template.js
  177. */
  178. return OCA.Files.Templates['filesummary'](_.extend({
  179. connectorLabel: t('files', '{dirs} and {files}', {dirs: '', files: ''})
  180. }, data));
  181. },
  182. /**
  183. * Renders the file summary element
  184. */
  185. update: function() {
  186. if (!this.$el) {
  187. return;
  188. }
  189. if (!this.summary.totalFiles && !this.summary.totalDirs) {
  190. this.$el.addClass('hidden');
  191. return;
  192. }
  193. // There's a summary and data -> Update the summary
  194. this.$el.removeClass('hidden');
  195. var $dirInfo = this.$el.find('.dirinfo');
  196. var $fileInfo = this.$el.find('.fileinfo');
  197. var $connector = this.$el.find('.connector');
  198. var $filterInfo = this.$el.find('.filter');
  199. var $hiddenInfo = this.$el.find('.hiddeninfo');
  200. // Substitute old content with new translations
  201. $dirInfo.html(n('files', '%n folder', '%n folders', this.summary.totalDirs));
  202. $fileInfo.html(n('files', '%n file', '%n files', this.summary.totalFiles));
  203. $hiddenInfo.html(' (' + n('files', 'including %n hidden', 'including %n hidden', this.summary.totalHidden) + ')');
  204. var fileSize = this.summary.sumIsPending ? t('files', 'Pending') : OC.Util.humanFileSize(this.summary.totalSize, false, false);
  205. this.$el.find('.filesize').html(fileSize);
  206. // Show only what's necessary (may be hidden)
  207. if (this.summary.totalDirs === 0) {
  208. $dirInfo.addClass('hidden');
  209. $connector.addClass('hidden');
  210. } else {
  211. $dirInfo.removeClass('hidden');
  212. }
  213. if (this.summary.totalFiles === 0) {
  214. $fileInfo.addClass('hidden');
  215. $connector.addClass('hidden');
  216. } else {
  217. $fileInfo.removeClass('hidden');
  218. }
  219. if (this.summary.totalDirs > 0 && this.summary.totalFiles > 0) {
  220. $connector.removeClass('hidden');
  221. }
  222. $hiddenInfo.toggleClass('hidden', this.summary.totalHidden === 0 || this._showHidden)
  223. if (this.summary.filter === '') {
  224. $filterInfo.html('');
  225. $filterInfo.addClass('hidden');
  226. } else {
  227. $filterInfo.html(' ' + n('files', 'matches "{filter}"', 'match "{filter}"', this.summary.totalDirs + this.summary.totalFiles, {filter: this.summary.filter}));
  228. $filterInfo.removeClass('hidden');
  229. }
  230. },
  231. render: function() {
  232. if (!this.$el) {
  233. return;
  234. }
  235. var summary = this.summary;
  236. // don't show the filesize column, if filesize is NaN (e.g. in trashbin)
  237. var fileSize = '';
  238. if (!isNaN(summary.totalSize)) {
  239. fileSize = summary.sumIsPending ? t('files', 'Pending') : OC.Util.humanFileSize(summary.totalSize, false, false);
  240. fileSize = '<td class="filesize">' + fileSize + '</td>';
  241. }
  242. var $summary = $(
  243. '<td class="filesummary">'+ this._infoTemplate() + '</td>' +
  244. fileSize +
  245. '<td class="date"></td>'
  246. );
  247. this.$el.addClass('hidden');
  248. this.$el.append($summary);
  249. this.update();
  250. }
  251. };
  252. OCA.Files.FileSummary = FileSummary;
  253. })();