sharedialogshareelistview.js 10 KB

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