You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

339 lines
11 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /* global OC, Handlebars */
  2. /*
  3. * Copyright (c) 2015
  4. *
  5. * This file is licensed under the Affero General Public License version 3
  6. * or later.
  7. *
  8. * See the COPYING-README file.
  9. *
  10. */
  11. /* globals Handlebars */
  12. (function() {
  13. if (!OC.Share) {
  14. OC.Share = {};
  15. }
  16. var TEMPLATE =
  17. '<ul id="shareWithList" class="shareWithList">' +
  18. '{{#each sharees}}' +
  19. '<li data-share-id="{{shareId}}" data-share-type="{{shareType}}" data-share-with="{{shareWith}}">' +
  20. '{{#if avatarEnabled}}' +
  21. '<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
  22. '{{/if}}' +
  23. '<span class="has-tooltip username" title="{{shareWith}}">{{shareWithDisplayName}}</span>' +
  24. '{{#if mailNotificationEnabled}} {{#unless isRemoteShare}}' +
  25. '<span class="shareOption">' +
  26. '<input id="mail-{{cid}}-{{shareWith}}" type="checkbox" name="mailNotification" class="mailNotification checkbox" {{#if wasMailSent}}checked="checked"{{/if}} />' +
  27. '<label for="mail-{{cid}}-{{shareWith}}">{{notifyByMailLabel}}</label>' +
  28. '</span>' +
  29. '{{/unless}} {{/if}}' +
  30. '<span class="sharingOptionsGroup">' +
  31. '{{#if editPermissionPossible}}' +
  32. '<span class="shareOption">' +
  33. '<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' +
  34. '<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' +
  35. '</span>' +
  36. '{{/if}}' +
  37. '<a href="#"><span class="icon icon-more"></span></a>' +
  38. '<div class="popovermenu bubble hidden menu">' +
  39. '<ul>' +
  40. '{{#if isResharingAllowed}} {{#if sharePermissionPossible}}' +
  41. '<li>' +
  42. '<span class="shareOption">' +
  43. '<input id="canShare-{{cid}}-{{shareWith}}" type="checkbox" name="share" class="permissions checkbox" {{#if hasSharePermission}}checked="checked"{{/if}} data-permissions="{{sharePermission}}" />' +
  44. '<label for="canShare-{{cid}}-{{shareWith}}">{{canShareLabel}}</label>' +
  45. '</span>' +
  46. '</li>' +
  47. '{{/if}} {{/if}}' +
  48. '{{#if isFolder}}' +
  49. '{{#if createPermissionPossible}}' +
  50. '<li>' +
  51. '<span class="shareOption">' +
  52. '<input id="canCreate-{{cid}}-{{shareWith}}" type="checkbox" name="create" class="permissions checkbox" {{#if hasCreatePermission}}checked="checked"{{/if}} data-permissions="{{createPermission}}"/>' +
  53. '<label for="canCreate-{{cid}}-{{shareWith}}">{{createPermissionLabel}}</label>' +
  54. '</span>' +
  55. '</li>' +
  56. '{{/if}}' +
  57. '{{#if updatePermissionPossible}}' +
  58. '<li>' +
  59. '<span class="shareOption">' +
  60. '<input id="canUpdate-{{cid}}-{{shareWith}}" type="checkbox" name="update" class="permissions checkbox" {{#if hasUpdatePermission}}checked="checked"{{/if}} data-permissions="{{updatePermission}}"/>' +
  61. '<label for="canUpdate-{{cid}}-{{shareWith}}">{{updatePermissionLabel}}</label>' +
  62. '</span>' +
  63. '</li>' +
  64. '{{/if}}' +
  65. '{{#if deletePermissionPossible}}' +
  66. '<li>' +
  67. '<span class="shareOption">' +
  68. '<input id="canDelete-{{cid}}-{{shareWith}}" type="checkbox" name="delete" class="permissions checkbox" {{#if hasDeletePermission}}checked="checked"{{/if}} data-permissions="{{deletePermission}}"/>' +
  69. '<label for="canDelete-{{cid}}-{{shareWith}}">{{deletePermissionLabel}}</label>' +
  70. '</span>' +
  71. '</li>' +
  72. '{{/if}}' +
  73. '{{/if}}' +
  74. '</ul>' +
  75. '</div>' +
  76. '<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span class="hidden-visually">{{unshareLabel}}</span></a>' +
  77. '</span>' +
  78. '</li>' +
  79. '{{/each}}' +
  80. '</ul>';
  81. /**
  82. * @class OCA.Share.ShareDialogShareeListView
  83. * @member {OC.Share.ShareItemModel} model
  84. * @member {jQuery} $el
  85. * @memberof OCA.Sharing
  86. * @classdesc
  87. *
  88. * Represents the sharee list part in the GUI of the share dialogue
  89. *
  90. */
  91. var ShareDialogShareeListView = OC.Backbone.View.extend({
  92. /** @type {string} **/
  93. id: 'shareDialogLinkShare',
  94. /** @type {OC.Share.ShareConfigModel} **/
  95. configModel: undefined,
  96. /** @type {Function} **/
  97. _template: undefined,
  98. _menuOpen: false,
  99. events: {
  100. 'click .unshare': 'onUnshare',
  101. 'click .icon-more': 'onToggleMenu',
  102. 'click .permissions': 'onPermissionChange',
  103. 'click .mailNotification': 'onSendMailNotification'
  104. },
  105. initialize: function(options) {
  106. if(!_.isUndefined(options.configModel)) {
  107. this.configModel = options.configModel;
  108. } else {
  109. throw 'missing OC.Share.ShareConfigModel';
  110. }
  111. var view = this;
  112. this.model.on('change:shares', function() {
  113. view.render();
  114. });
  115. },
  116. /**
  117. *
  118. * @param {OC.Share.Types.ShareInfo} shareInfo
  119. * @returns {object}
  120. */
  121. getShareeObject: function(shareIndex) {
  122. var shareWith = this.model.getShareWith(shareIndex);
  123. var shareWithDisplayName = this.model.getShareWithDisplayName(shareIndex);
  124. var shareType = this.model.getShareType(shareIndex);
  125. var hasPermissionOverride = {};
  126. if (shareType === OC.Share.SHARE_TYPE_GROUP) {
  127. shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'group') + ')';
  128. } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
  129. shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'remote') + ')';
  130. }
  131. return _.extend(hasPermissionOverride, {
  132. cid: this.cid,
  133. hasSharePermission: this.model.hasSharePermission(shareIndex),
  134. hasEditPermission: this.model.hasEditPermission(shareIndex),
  135. hasCreatePermission: this.model.hasCreatePermission(shareIndex),
  136. hasUpdatePermission: this.model.hasUpdatePermission(shareIndex),
  137. hasDeletePermission: this.model.hasDeletePermission(shareIndex),
  138. wasMailSent: this.model.notificationMailWasSent(shareIndex),
  139. shareWith: shareWith,
  140. shareWithDisplayName: shareWithDisplayName,
  141. shareType: shareType,
  142. shareId: this.model.get('shares')[shareIndex].id,
  143. modSeed: shareType !== OC.Share.SHARE_TYPE_USER,
  144. isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE
  145. });
  146. },
  147. getShareeList: function() {
  148. var universal = {
  149. avatarEnabled: this.configModel.areAvatarsEnabled(),
  150. mailNotificationEnabled: this.configModel.isMailNotificationEnabled(),
  151. notifyByMailLabel: t('core', 'notify by email'),
  152. unshareLabel: t('core', 'Unshare'),
  153. canShareLabel: t('core', 'can reshare'),
  154. canEditLabel: t('core', 'can edit'),
  155. createPermissionLabel: t('core', 'create'),
  156. updatePermissionLabel: t('core', 'change'),
  157. deletePermissionLabel: t('core', 'delete'),
  158. crudsLabel: t('core', 'access control'),
  159. triangleSImage: OC.imagePath('core', 'actions/triangle-s'),
  160. isResharingAllowed: this.configModel.get('isResharingAllowed'),
  161. sharePermissionPossible: this.model.sharePermissionPossible(),
  162. editPermissionPossible: this.model.editPermissionPossible(),
  163. createPermissionPossible: this.model.createPermissionPossible(),
  164. updatePermissionPossible: this.model.updatePermissionPossible(),
  165. deletePermissionPossible: this.model.deletePermissionPossible(),
  166. sharePermission: OC.PERMISSION_SHARE,
  167. createPermission: OC.PERMISSION_CREATE,
  168. updatePermission: OC.PERMISSION_UPDATE,
  169. deletePermission: OC.PERMISSION_DELETE,
  170. isFolder: this.model.isFolder()
  171. };
  172. if(!this.model.hasUserShares()) {
  173. return [];
  174. }
  175. var shares = this.model.get('shares');
  176. var list = [];
  177. for(var index = 0; index < shares.length; index++) {
  178. // first empty {} is necessary, otherwise we get in trouble
  179. // with references
  180. list.push(_.extend({}, universal, this.getShareeObject(index)));
  181. }
  182. return list;
  183. },
  184. render: function() {
  185. this.$el.html(this.template({
  186. cid: this.cid,
  187. sharees: this.getShareeList()
  188. }));
  189. if(this.configModel.areAvatarsEnabled()) {
  190. this.$('.avatar').each(function() {
  191. var $this = $(this);
  192. if ($this.hasClass('imageplaceholderseed')) {
  193. $this.css({width: 32, height: 32});
  194. $this.imageplaceholder($this.data('seed'));
  195. } else {
  196. $this.avatar($this.data('username'), 32);
  197. }
  198. });
  199. }
  200. this.$('.has-tooltip').tooltip({
  201. placement: 'bottom'
  202. });
  203. var _this = this;
  204. this.$('.popovermenu').on('afterHide', function() {
  205. _this._menuOpen = false;
  206. });
  207. if (this._menuOpen) {
  208. // Open menu again if it was opened before
  209. OC.showMenu(null, this.$('.popovermenu'));
  210. }
  211. this.delegateEvents();
  212. return this;
  213. },
  214. /**
  215. * @returns {Function} from Handlebars
  216. * @private
  217. */
  218. template: function (data) {
  219. if (!this._template) {
  220. this._template = Handlebars.compile(TEMPLATE);
  221. }
  222. return this._template(data);
  223. },
  224. onUnshare: function(event) {
  225. event.preventDefault();
  226. event.stopPropagation();
  227. var self = this;
  228. var $element = $(event.target);
  229. if (!$element.is('a')) {
  230. $element = $element.closest('a');
  231. }
  232. var $loading = $element.find('.icon-loading-small').eq(0);
  233. if(!$loading.hasClass('hidden')) {
  234. // in process
  235. return false;
  236. }
  237. $loading.removeClass('hidden');
  238. var $li = $element.closest('li[data-share-id]');
  239. var shareId = $li.data('share-id');
  240. self.model.removeShare(shareId)
  241. .done(function() {
  242. $li.remove();
  243. })
  244. .fail(function() {
  245. $loading.addClass('hidden');
  246. OC.Notification.showTemporary(t('core', 'Could not unshare'));
  247. });
  248. return false;
  249. },
  250. onToggleMenu: function(event) {
  251. event.preventDefault();
  252. event.stopPropagation();
  253. var $element = $(event.target);
  254. var $li = $element.closest('li[data-share-id]');
  255. var $menu = $li.find('.popovermenu');
  256. OC.showMenu(null, $menu);
  257. this._menuOpen = true;
  258. },
  259. onPermissionChange: function(event) {
  260. event.preventDefault();
  261. event.stopPropagation();
  262. var $element = $(event.target);
  263. var $li = $element.closest('li[data-share-id]');
  264. var shareId = $li.data('share-id');
  265. var permissions = OC.PERMISSION_READ;
  266. if (this.model.isFolder()) {
  267. // adjust checkbox states
  268. var $checkboxes = $('.permissions', $li).not('input[name="edit"]').not('input[name="share"]');
  269. var checked;
  270. if ($element.attr('name') === 'edit') {
  271. checked = $element.is(':checked');
  272. // Check/uncheck Create, Update, and Delete checkboxes if Edit is checked/unck
  273. $($checkboxes).prop('checked', checked);
  274. } else {
  275. var numberChecked = $checkboxes.filter(':checked').length;
  276. checked = numberChecked > 0;
  277. $('input[name="edit"]', $li).prop('checked', checked);
  278. }
  279. } else {
  280. if ($element.attr('name') === 'edit' && $element.is(':checked')) {
  281. permissions |= OC.PERMISSION_UPDATE;
  282. }
  283. }
  284. $('.permissions', $li).not('input[name="edit"]').filter(':checked').each(function(index, checkbox) {
  285. permissions |= $(checkbox).data('permissions');
  286. });
  287. this.model.updateShare(shareId, {permissions: permissions});
  288. },
  289. onSendMailNotification: function(event) {
  290. var $target = $(event.target);
  291. var $li = $(event.target).closest('li[data-share-id]');
  292. var shareType = $li.data('share-type');
  293. var shareWith = $li.attr('data-share-with');
  294. this.model.sendNotificationForShare(shareType, shareWith, $target.is(':checked'));
  295. }
  296. });
  297. OC.Share.ShareDialogShareeListView = ShareDialogShareeListView;
  298. })();