versionstabview.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (c) 2015
  3. *
  4. * This file is licensed under the Affero General Public License version 3
  5. * or later.
  6. *
  7. * See the COPYING-README file.
  8. *
  9. */
  10. /* @global Handlebars */
  11. (function() {
  12. var TEMPLATE_ITEM =
  13. '<li data-revision="{{timestamp}}">' +
  14. '<img class="preview" src="{{previewUrl}}"/>' +
  15. '<a href="{{downloadUrl}}" class="downloadVersion"><img src="{{downloadIconUrl}}" />' +
  16. '<span class="versiondate has-tooltip" title="{{formattedTimestamp}}">{{relativeTimestamp}}</span>' +
  17. '</a>' +
  18. '{{#canRevert}}' +
  19. '<a href="#" class="revertVersion" title="{{revertLabel}}"><img src="{{revertIconUrl}}" /></a>' +
  20. '{{/canRevert}}' +
  21. '</li>';
  22. var TEMPLATE =
  23. '<ul class="versions"></ul>' +
  24. '<div class="clear-float"></div>' +
  25. '<div class="empty hidden">{{emptyResultLabel}}</div>' +
  26. '<input type="button" class="showMoreVersions hidden" value="{{moreVersionsLabel}}"' +
  27. ' name="show-more-versions" id="show-more-versions" />' +
  28. '<div class="loading hidden" style="height: 50px"></div>';
  29. /**
  30. * @memberof OCA.Versions
  31. */
  32. var VersionsTabView = OCA.Files.DetailTabView.extend(
  33. /** @lends OCA.Versions.VersionsTabView.prototype */ {
  34. id: 'versionsTabView',
  35. className: 'tab versionsTabView',
  36. _template: null,
  37. $versionsContainer: null,
  38. events: {
  39. 'click .revertVersion': '_onClickRevertVersion',
  40. 'click .showMoreVersions': '_onClickShowMoreVersions'
  41. },
  42. initialize: function() {
  43. OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments);
  44. this.collection = new OCA.Versions.VersionCollection();
  45. this.collection.on('request', this._onRequest, this);
  46. this.collection.on('sync', this._onEndRequest, this);
  47. this.collection.on('update', this._onUpdate, this);
  48. this.collection.on('error', this._onError, this);
  49. this.collection.on('add', this._onAddModel, this);
  50. },
  51. getLabel: function() {
  52. return t('files_versions', 'Versions');
  53. },
  54. nextPage: function() {
  55. if (this._loading || !this.collection.hasMoreResults()) {
  56. return;
  57. }
  58. if (this.collection.getFileInfo() && this.collection.getFileInfo().isDirectory()) {
  59. return;
  60. }
  61. this.collection.fetchNext();
  62. },
  63. _onClickShowMoreVersions: function(ev) {
  64. ev.preventDefault();
  65. this.nextPage();
  66. },
  67. _onClickRevertVersion: function(ev) {
  68. var self = this;
  69. var $target = $(ev.target);
  70. var fileInfoModel = this.collection.getFileInfo();
  71. var revision;
  72. if (!$target.is('li')) {
  73. $target = $target.closest('li');
  74. }
  75. ev.preventDefault();
  76. revision = $target.attr('data-revision');
  77. this.$el.find('.versions, .showMoreVersions').addClass('hidden');
  78. var versionModel = this.collection.get(revision);
  79. versionModel.revert({
  80. success: function() {
  81. // reset and re-fetch the updated collection
  82. self.$versionsContainer.empty();
  83. self.collection.setFileInfo(fileInfoModel);
  84. self.collection.reset([], {silent: true});
  85. self.collection.fetchNext();
  86. self.$el.find('.versions').removeClass('hidden');
  87. // update original model
  88. fileInfoModel.trigger('busy', fileInfoModel, false);
  89. fileInfoModel.set({
  90. size: versionModel.get('size'),
  91. mtime: versionModel.get('timestamp') * 1000,
  92. // temp dummy, until we can do a PROPFIND
  93. etag: versionModel.get('id') + versionModel.get('timestamp')
  94. });
  95. },
  96. error: function() {
  97. fileInfoModel.trigger('busy', fileInfoModel, false);
  98. self.$el.find('.versions').removeClass('hidden');
  99. self._toggleLoading(false);
  100. OC.Notification.showTemporary(
  101. t('files_version', 'Failed to revert {file} to revision {timestamp}.', {
  102. file: versionModel.getFullPath(),
  103. timestamp: OC.Util.formatDate(versionModel.get('timestamp') * 1000)
  104. })
  105. );
  106. }
  107. });
  108. // spinner
  109. this._toggleLoading(true);
  110. fileInfoModel.trigger('busy', fileInfoModel, true);
  111. },
  112. _toggleLoading: function(state) {
  113. this._loading = state;
  114. this.$el.find('.loading').toggleClass('hidden', !state);
  115. },
  116. _onRequest: function() {
  117. this._toggleLoading(true);
  118. this.$el.find('.showMoreVersions').addClass('hidden');
  119. },
  120. _onEndRequest: function() {
  121. this._toggleLoading(false);
  122. this.$el.find('.empty').toggleClass('hidden', !!this.collection.length);
  123. this.$el.find('.showMoreVersions').toggleClass('hidden', !this.collection.hasMoreResults());
  124. },
  125. _onAddModel: function(model) {
  126. var $el = $(this.itemTemplate(this._formatItem(model)));
  127. this.$versionsContainer.append($el);
  128. $el.find('.has-tooltip').tooltip();
  129. },
  130. template: function(data) {
  131. if (!this._template) {
  132. this._template = Handlebars.compile(TEMPLATE);
  133. }
  134. return this._template(data);
  135. },
  136. itemTemplate: function(data) {
  137. if (!this._itemTemplate) {
  138. this._itemTemplate = Handlebars.compile(TEMPLATE_ITEM);
  139. }
  140. return this._itemTemplate(data);
  141. },
  142. setFileInfo: function(fileInfo) {
  143. if (fileInfo) {
  144. this.render();
  145. this.collection.setFileInfo(fileInfo);
  146. this.collection.reset([], {silent: true});
  147. this.nextPage();
  148. } else {
  149. this.render();
  150. this.collection.reset();
  151. }
  152. },
  153. _formatItem: function(version) {
  154. var timestamp = version.get('timestamp') * 1000;
  155. return _.extend({
  156. formattedTimestamp: OC.Util.formatDate(timestamp),
  157. relativeTimestamp: OC.Util.relativeModifiedDate(timestamp),
  158. downloadUrl: version.getDownloadUrl(),
  159. downloadIconUrl: OC.imagePath('core', 'actions/download'),
  160. revertIconUrl: OC.imagePath('core', 'actions/history'),
  161. previewUrl: version.getPreviewUrl(),
  162. revertLabel: t('files_versions', 'Restore'),
  163. canRevert: (this.collection.getFileInfo().get('permissions') & OC.PERMISSION_UPDATE) !== 0
  164. }, version.attributes);
  165. },
  166. /**
  167. * Renders this details view
  168. */
  169. render: function() {
  170. this.$el.html(this.template({
  171. emptyResultLabel: t('files_versions', 'No other versions available'),
  172. moreVersionsLabel: t('files_versions', 'More versions...')
  173. }));
  174. this.$el.find('.has-tooltip').tooltip();
  175. this.$versionsContainer = this.$el.find('ul.versions');
  176. this.delegateEvents();
  177. },
  178. /**
  179. * Returns true for files, false for folders.
  180. *
  181. * @return {bool} true for files, false for folders
  182. */
  183. canDisplay: function(fileInfo) {
  184. if (!fileInfo) {
  185. return false;
  186. }
  187. return !fileInfo.isDirectory();
  188. }
  189. });
  190. OCA.Versions = OCA.Versions || {};
  191. OCA.Versions.VersionsTabView = VersionsTabView;
  192. })();