sharedialogshareelistview.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  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. var PASSWORD_PLACEHOLDER = '**********';
  14. var PASSWORD_PLACEHOLDER_MESSAGE = t('core', 'Choose a password for the mail share');
  15. if (!OC.Share) {
  16. OC.Share = {};
  17. }
  18. var TEMPLATE =
  19. '<ul id="shareWithList" class="shareWithList">' +
  20. '{{#each sharees}}' +
  21. '<li data-share-id="{{shareId}}" data-share-type="{{shareType}}" data-share-with="{{shareWith}}">' +
  22. '<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" data-displayname="{{shareWithDisplayName}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
  23. '<span class="username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
  24. '<span class="sharingOptionsGroup">' +
  25. '{{#if editPermissionPossible}}' +
  26. '<span class="shareOption">' +
  27. '<input id="canEdit-{{cid}}-{{shareWith}}" type="checkbox" name="edit" class="permissions checkbox" {{#if hasEditPermission}}checked="checked"{{/if}} />' +
  28. '<label for="canEdit-{{cid}}-{{shareWith}}">{{canEditLabel}}</label>' +
  29. '</span>' +
  30. '{{/if}}' +
  31. '<a href="#"><span class="icon icon-more"></span></a>' +
  32. '{{{popoverMenu}}}' +
  33. '</span>' +
  34. '</li>' +
  35. '{{/each}}' +
  36. '{{#each linkReshares}}' +
  37. '<li data-share-id="{{shareId}}" data-share-type="{{shareType}}">' +
  38. '<div class="avatar" data-username="{{shareInitiator}}"></div>' +
  39. '<span class="has-tooltip username" title="{{shareInitiator}}">' + t('core', '{{shareInitiatorDisplayName}} shared via link') + '</span>' +
  40. '<span class="sharingOptionsGroup">' +
  41. '<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span class="hidden-visually">{{unshareLabel}}</span></a>' +
  42. '</span>' +
  43. '</li>' +
  44. '{{/each}}' +
  45. '</ul>'
  46. ;
  47. var TEMPLATE_POPOVER_MENU =
  48. '<div class="popovermenu bubble hidden menu">' +
  49. '<ul>' +
  50. '{{#if isResharingAllowed}} {{#if sharePermissionPossible}} {{#unless isMailShare}}' +
  51. '<li>' +
  52. '<span class="shareOption menuitem">' +
  53. '<input id="canShare-{{cid}}-{{shareWith}}" type="checkbox" name="share" class="permissions checkbox" {{#if hasSharePermission}}checked="checked"{{/if}} data-permissions="{{sharePermission}}" />' +
  54. '<label for="canShare-{{cid}}-{{shareWith}}">{{canShareLabel}}</label>' +
  55. '</span>' +
  56. '</li>' +
  57. '{{/unless}} {{/if}} {{/if}}' +
  58. '{{#if isFolder}}' +
  59. '{{#if createPermissionPossible}}{{#unless isMailShare}}' +
  60. '<li>' +
  61. '<span class="shareOption menuitem">' +
  62. '<input id="canCreate-{{cid}}-{{shareWith}}" type="checkbox" name="create" class="permissions checkbox" {{#if hasCreatePermission}}checked="checked"{{/if}} data-permissions="{{createPermission}}"/>' +
  63. '<label for="canCreate-{{cid}}-{{shareWith}}">{{createPermissionLabel}}</label>' +
  64. '</span>' +
  65. '</li>' +
  66. '{{/unless}}{{/if}}' +
  67. '{{#if updatePermissionPossible}}{{#unless isMailShare}}' +
  68. '<li>' +
  69. '<span class="shareOption menuitem">' +
  70. '<input id="canUpdate-{{cid}}-{{shareWith}}" type="checkbox" name="update" class="permissions checkbox" {{#if hasUpdatePermission}}checked="checked"{{/if}} data-permissions="{{updatePermission}}"/>' +
  71. '<label for="canUpdate-{{cid}}-{{shareWith}}">{{updatePermissionLabel}}</label>' +
  72. '</span>' +
  73. '</li>' +
  74. '{{/unless}}{{/if}}' +
  75. '{{#if deletePermissionPossible}}{{#unless isMailShare}}' +
  76. '<li>' +
  77. '<span class="shareOption menuitem">' +
  78. '<input id="canDelete-{{cid}}-{{shareWith}}" type="checkbox" name="delete" class="permissions checkbox" {{#if hasDeletePermission}}checked="checked"{{/if}} data-permissions="{{deletePermission}}"/>' +
  79. '<label for="canDelete-{{cid}}-{{shareWith}}">{{deletePermissionLabel}}</label>' +
  80. '</span>' +
  81. '</li>' +
  82. '{{/unless}}{{/if}}' +
  83. '{{/if}}' +
  84. '{{#if isMailShare}}' +
  85. '{{#if hasCreatePermission}}' +
  86. '<li>' +
  87. '<span class="shareOption menuitem">' +
  88. '<input id="secureDrop-{{cid}}-{{shareId}}" type="checkbox" name="secureDrop" class="checkbox secureDrop" {{#if secureDropMode}}checked="checked"{{/if}} data-permissions="{{readPermission}}"/>' +
  89. '<label for="secureDrop-{{cid}}-{{shareId}}">{{secureDropLabel}}</label>' +
  90. '</span>' +
  91. '</li>' +
  92. '{{/if}}' +
  93. '<li>' +
  94. '<span class="shareOption menuitem">' +
  95. '<input id="password-{{cid}}-{{shareId}}" type="checkbox" name="password" class="password checkbox" {{#if isPasswordSet}}checked="checked"{{/if}}{{#if isPasswordSet}}{{#if isPasswordForMailSharesRequired}}disabled=""{{/if}}{{/if}}" />' +
  96. '<label for="password-{{cid}}-{{shareId}}">{{passwordLabel}}</label>' +
  97. '<div class="passwordContainer-{{cid}}-{{shareId}} {{#unless isPasswordSet}}hidden{{/unless}}">' +
  98. ' <label for="passwordField-{{cid}}-{{shareId}}" class="hidden-visually" value="{{password}}">{{passwordLabel}}</label>' +
  99. ' <input id="passwordField-{{cid}}-{{shareId}}" class="passwordField" type="password" placeholder="{{passwordPlaceholder}}" value="{{passwordValue}}" />' +
  100. ' <span class="icon-loading-small hidden"></span>' +
  101. '</div>' +
  102. '</span>' +
  103. '</li>' +
  104. '{{/if}}' +
  105. '<li>' +
  106. '<span class="shareOption menuitem">' +
  107. '<input id="expireDate-{{cid}}-{{shareId}}" type="checkbox" name="expirationDate" class="expireDate checkbox" {{#if hasExpireDate}}checked="checked"{{/if}}" />' +
  108. '<label for="expireDate-{{cid}}-{{shareId}}">{{expireDateLabel}}</label>' +
  109. '<div class="expirationDateContainer-{{cid}}-{{shareId}} {{#unless hasExpireDate}}hidden{{/unless}}">' +
  110. ' <label for="expirationDatePicker-{{cid}}-{{shareId}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' +
  111. ' <input id="expirationDatePicker-{{cid}}-{{shareId}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{expireDate}}" />' +
  112. '</div>' +
  113. '</span>' +
  114. '</li>' +
  115. '<li>' +
  116. '<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' +
  117. '</li>' +
  118. '</ul>' +
  119. '</div>';
  120. /**
  121. * @class OCA.Share.ShareDialogShareeListView
  122. * @member {OC.Share.ShareItemModel} model
  123. * @member {jQuery} $el
  124. * @memberof OCA.Sharing
  125. * @classdesc
  126. *
  127. * Represents the sharee list part in the GUI of the share dialogue
  128. *
  129. */
  130. var ShareDialogShareeListView = OC.Backbone.View.extend({
  131. /** @type {string} **/
  132. id: 'shareDialogLinkShare',
  133. /** @type {OC.Share.ShareConfigModel} **/
  134. configModel: undefined,
  135. /** @type {Function} **/
  136. _template: undefined,
  137. /** @type {Function} **/
  138. _popoverMenuTemplate: undefined,
  139. _menuOpen: false,
  140. /** @type {boolean|number} **/
  141. _renderPermissionChange: false,
  142. events: {
  143. 'click .unshare': 'onUnshare',
  144. 'click .icon-more': 'onToggleMenu',
  145. 'click .permissions': 'onPermissionChange',
  146. 'click .expireDate' : 'onExpireDateChange',
  147. 'click .password' : 'onMailSharePasswordProtectChange',
  148. 'click .secureDrop' : 'onSecureDropChange',
  149. 'keyup input.passwordField': 'onMailSharePasswordKeyUp',
  150. 'focusout input.passwordField': 'onMailSharePasswordEntered',
  151. 'change .datepicker': 'onChangeExpirationDate',
  152. 'click .datepicker' : 'showDatePicker'
  153. },
  154. initialize: function(options) {
  155. if(!_.isUndefined(options.configModel)) {
  156. this.configModel = options.configModel;
  157. } else {
  158. throw 'missing OC.Share.ShareConfigModel';
  159. }
  160. var view = this;
  161. this.model.on('change:shares', function() {
  162. view.render();
  163. });
  164. },
  165. /**
  166. *
  167. * @param {OC.Share.Types.ShareInfo} shareInfo
  168. * @returns {object}
  169. */
  170. getShareeObject: function(shareIndex) {
  171. var shareWith = this.model.getShareWith(shareIndex);
  172. var shareWithDisplayName = this.model.getShareWithDisplayName(shareIndex);
  173. var shareWithTitle = '';
  174. var shareType = this.model.getShareType(shareIndex);
  175. var sharedBy = this.model.getSharedBy(shareIndex);
  176. var sharedByDisplayName = this.model.getSharedByDisplayName(shareIndex);
  177. var hasPermissionOverride = {};
  178. if (shareType === OC.Share.SHARE_TYPE_GROUP) {
  179. shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'group') + ')';
  180. } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
  181. shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'remote') + ')';
  182. } else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
  183. shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'email') + ')';
  184. } else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
  185. }
  186. if (shareType === OC.Share.SHARE_TYPE_GROUP) {
  187. shareWithTitle = shareWith + " (" + t('core', 'group') + ')';
  188. } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) {
  189. shareWithTitle = shareWith + " (" + t('core', 'remote') + ')';
  190. } else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
  191. shareWithTitle = shareWith + " (" + t('core', 'email') + ')';
  192. } else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
  193. shareWithTitle = shareWith;
  194. }
  195. if (sharedBy !== oc_current_user) {
  196. var empty = shareWithTitle === '';
  197. if (!empty) {
  198. shareWithTitle += ' (';
  199. }
  200. shareWithTitle += t('core', 'shared by {sharer}', {sharer: sharedByDisplayName});
  201. if (!empty) {
  202. shareWithTitle += ')';
  203. }
  204. }
  205. var share = this.model.get('shares')[shareIndex];
  206. var password = share.password;
  207. var hasPassword = password !== null && password !== '';
  208. return _.extend(hasPermissionOverride, {
  209. cid: this.cid,
  210. hasSharePermission: this.model.hasSharePermission(shareIndex),
  211. hasEditPermission: this.model.hasEditPermission(shareIndex),
  212. hasCreatePermission: this.model.hasCreatePermission(shareIndex),
  213. hasUpdatePermission: this.model.hasUpdatePermission(shareIndex),
  214. hasDeletePermission: this.model.hasDeletePermission(shareIndex),
  215. shareWith: shareWith,
  216. shareWithDisplayName: shareWithDisplayName,
  217. shareWithTitle: shareWithTitle,
  218. shareType: shareType,
  219. shareId: this.model.get('shares')[shareIndex].id,
  220. modSeed: shareType !== OC.Share.SHARE_TYPE_USER,
  221. isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE,
  222. isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL,
  223. isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE,
  224. isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder(),
  225. isPasswordSet: hasPassword,
  226. secureDropMode: !this.model.hasReadPermission(shareIndex),
  227. hasExpireDate: this.model.getExpireDate(shareIndex) !== null,
  228. expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'),
  229. passwordPlaceholder: hasPassword ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE,
  230. });
  231. },
  232. getShareProperties: function() {
  233. return {
  234. unshareLabel: t('core', 'Unshare'),
  235. canShareLabel: t('core', 'Can reshare'),
  236. canEditLabel: t('core', 'Can edit'),
  237. createPermissionLabel: t('core', 'Can create'),
  238. updatePermissionLabel: t('core', 'Can change'),
  239. deletePermissionLabel: t('core', 'Can delete'),
  240. secureDropLabel: t('core', 'File drop (upload only)'),
  241. expireDateLabel: t('core', 'Set expiration date'),
  242. passwordLabel: t('core', 'Password protect'),
  243. crudsLabel: t('core', 'Access control'),
  244. triangleSImage: OC.imagePath('core', 'actions/triangle-s'),
  245. isResharingAllowed: this.configModel.get('isResharingAllowed'),
  246. isPasswordForMailSharesRequired: this.configModel.get('isPasswordForMailSharesRequired'),
  247. sharePermissionPossible: this.model.sharePermissionPossible(),
  248. editPermissionPossible: this.model.editPermissionPossible(),
  249. createPermissionPossible: this.model.createPermissionPossible(),
  250. updatePermissionPossible: this.model.updatePermissionPossible(),
  251. deletePermissionPossible: this.model.deletePermissionPossible(),
  252. sharePermission: OC.PERMISSION_SHARE,
  253. createPermission: OC.PERMISSION_CREATE,
  254. updatePermission: OC.PERMISSION_UPDATE,
  255. deletePermission: OC.PERMISSION_DELETE,
  256. readPermission: OC.PERMISSION_READ,
  257. isFolder: this.model.isFolder()
  258. };
  259. },
  260. /**
  261. * get an array of sharees' share properties
  262. *
  263. * @returns {Array}
  264. */
  265. getShareeList: function() {
  266. var universal = this.getShareProperties();
  267. if(!this.model.hasUserShares()) {
  268. return [];
  269. }
  270. var shares = this.model.get('shares');
  271. var list = [];
  272. for(var index = 0; index < shares.length; index++) {
  273. var share = this.getShareeObject(index);
  274. if (share.shareType === OC.Share.SHARE_TYPE_LINK) {
  275. continue;
  276. }
  277. // first empty {} is necessary, otherwise we get in trouble
  278. // with references
  279. list.push(_.extend({}, universal, share));
  280. }
  281. return list;
  282. },
  283. getLinkReshares: function() {
  284. var universal = {
  285. unshareLabel: t('core', 'Unshare'),
  286. };
  287. if(!this.model.hasUserShares()) {
  288. return [];
  289. }
  290. var shares = this.model.get('shares');
  291. var list = [];
  292. for(var index = 0; index < shares.length; index++) {
  293. var share = this.getShareeObject(index);
  294. if (share.shareType !== OC.Share.SHARE_TYPE_LINK) {
  295. continue;
  296. }
  297. // first empty {} is necessary, otherwise we get in trouble
  298. // with references
  299. list.push(_.extend({}, universal, share, {
  300. shareInitiator: shares[index].uid_owner,
  301. shareInitiatorDisplayName: shares[index].displayname_owner
  302. }));
  303. }
  304. return list;
  305. },
  306. render: function() {
  307. if(!this._renderPermissionChange) {
  308. this.$el.html(this.template({
  309. cid: this.cid,
  310. sharees: this.getShareeList(),
  311. linkReshares: this.getLinkReshares()
  312. }));
  313. this.$('.avatar').each(function () {
  314. var $this = $(this);
  315. if ($this.hasClass('imageplaceholderseed')) {
  316. $this.css({width: 32, height: 32});
  317. $this.imageplaceholder($this.data('seed'));
  318. } else {
  319. // user, size, ie8fix, hidedefault, callback, displayname
  320. $this.avatar($this.data('username'), 32, undefined, undefined, undefined, $this.data('displayname'));
  321. }
  322. });
  323. this.$('.has-tooltip').tooltip({
  324. placement: 'bottom'
  325. });
  326. this.$('ul.shareWithList > li').each(function() {
  327. var $this = $(this);
  328. var shareWith = $this.data('share-with');
  329. var shareType = $this.data('share-type');
  330. $this.find('div.avatar, span.username').contactsMenu(shareWith, shareType, $this);
  331. });
  332. } else {
  333. var permissionChangeShareId = parseInt(this._renderPermissionChange, 10);
  334. var shareWithIndex = this.model.findShareWithIndex(permissionChangeShareId);
  335. var sharee = this.getShareeObject(shareWithIndex);
  336. $.extend(sharee, this.getShareProperties());
  337. var $li = this.$('li[data-share-id=' + permissionChangeShareId + ']');
  338. $li.find('.sharingOptionsGroup .popovermenu').replaceWith(this.popoverMenuTemplate(sharee));
  339. var checkBoxId = 'canEdit-' + this.cid + '-' + sharee.shareWith;
  340. checkBoxId = '#' + checkBoxId.replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1");
  341. var $edit = $li.parent().find(checkBoxId);
  342. if($edit.length === 1) {
  343. $edit.prop('checked', sharee.hasEditPermission);
  344. }
  345. }
  346. var _this = this;
  347. this.$('.popovermenu').on('afterHide', function() {
  348. _this._menuOpen = false;
  349. });
  350. this.$('.popovermenu').on('beforeHide', function() {
  351. var shareId = parseInt(_this._menuOpen, 10);
  352. if(!_.isNaN(shareId)) {
  353. var datePickerClass = '.expirationDateContainer-' + _this.cid + '-' + shareId;
  354. var datePickerInput = '#expirationDatePicker-' + _this.cid + '-' + shareId;
  355. var expireDateCheckbox = '#expireDate-' + _this.cid + '-' + shareId;
  356. if ($(expireDateCheckbox).prop('checked')) {
  357. $(datePickerInput).removeClass('hidden-visually');
  358. $(datePickerClass).removeClass('hasDatepicker');
  359. $(datePickerClass + ' .ui-datepicker').hide();
  360. }
  361. }
  362. });
  363. if (this._menuOpen !== false) {
  364. // Open menu again if it was opened before
  365. var shareId = parseInt(this._menuOpen, 10);
  366. if(!_.isNaN(shareId)) {
  367. var liSelector = 'li[data-share-id=' + shareId + ']';
  368. OC.showMenu(null, this.$(liSelector + ' .sharingOptionsGroup .popovermenu'));
  369. }
  370. }
  371. this._renderPermissionChange = false;
  372. this.delegateEvents();
  373. return this;
  374. },
  375. /**
  376. * @returns {Function} from Handlebars
  377. * @private
  378. */
  379. template: function (data) {
  380. if (!this._template) {
  381. this._template = Handlebars.compile(TEMPLATE);
  382. }
  383. var sharees = data.sharees;
  384. if(_.isArray(sharees)) {
  385. for (var i = 0; i < sharees.length; i++) {
  386. data.sharees[i].popoverMenu = this.popoverMenuTemplate(sharees[i]);
  387. }
  388. }
  389. return this._template(data);
  390. },
  391. /**
  392. * renders the popover template and returns the resulting HTML
  393. *
  394. * @param {Object} data
  395. * @returns {string}
  396. */
  397. popoverMenuTemplate: function(data) {
  398. if(!this._popoverMenuTemplate) {
  399. this._popoverMenuTemplate = Handlebars.compile(TEMPLATE_POPOVER_MENU);
  400. }
  401. return this._popoverMenuTemplate(data);
  402. },
  403. onUnshare: function(event) {
  404. event.preventDefault();
  405. event.stopPropagation();
  406. var self = this;
  407. var $element = $(event.target);
  408. if (!$element.is('a')) {
  409. $element = $element.closest('a');
  410. }
  411. var $loading = $element.find('.icon-loading-small').eq(0);
  412. if(!$loading.hasClass('hidden')) {
  413. // in process
  414. return false;
  415. }
  416. $loading.removeClass('hidden');
  417. var $li = $element.closest('li[data-share-id]');
  418. var shareId = $li.data('share-id');
  419. self.model.removeShare(shareId)
  420. .done(function() {
  421. $li.remove();
  422. })
  423. .fail(function() {
  424. $loading.addClass('hidden');
  425. OC.Notification.showTemporary(t('core', 'Could not unshare'));
  426. });
  427. return false;
  428. },
  429. onToggleMenu: function(event) {
  430. event.preventDefault();
  431. event.stopPropagation();
  432. var $element = $(event.target);
  433. var $li = $element.closest('li[data-share-id]');
  434. var $menu = $li.find('.sharingOptionsGroup .popovermenu');
  435. OC.showMenu(null, $menu);
  436. this._menuOpen = $li.data('share-id');
  437. },
  438. onExpireDateChange: function(event) {
  439. var element = $(event.target);
  440. var li = element.closest('li[data-share-id]');
  441. var shareId = li.data('share-id');
  442. var datePickerClass = '.expirationDateContainer-' + this.cid + '-' + shareId;
  443. var datePicker = $(datePickerClass);
  444. var state = element.prop('checked');
  445. datePicker.toggleClass('hidden', !state);
  446. if (!state) {
  447. this.setExpirationDate(shareId, '');
  448. } else {
  449. this.showDatePicker(event);
  450. }
  451. },
  452. showDatePicker: function(event) {
  453. var element = $(event.target);
  454. var li = element.closest('li[data-share-id]');
  455. var shareId = li.data('share-id');
  456. var expirationDatePicker = '#expirationDatePicker-' + this.cid + '-' + shareId;
  457. var view = this;
  458. $(expirationDatePicker).closest('div').datepicker({
  459. dateFormat : 'dd-mm-yy',
  460. onSelect:
  461. function (expireDate) {
  462. view.setExpirationDate(shareId, expireDate);
  463. },
  464. onClose:
  465. function () {
  466. $(expirationDatePicker).removeClass('hidden-visually');
  467. }
  468. });
  469. $(expirationDatePicker).addClass('hidden-visually');
  470. },
  471. setExpirationDate: function(shareId, expireDate) {
  472. this.model.updateShare(shareId, {expireDate: expireDate}, {});
  473. },
  474. onMailSharePasswordProtectChange: function(event) {
  475. var element = $(event.target);
  476. var li = element.closest('li[data-share-id]');
  477. var shareId = li.data('share-id');
  478. var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId;
  479. var passwordContainer = $(passwordContainerClass);
  480. var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small');
  481. var inputClass = '#passwordField-' + this.cid + '-' + shareId;
  482. var passwordField = $(inputClass);
  483. var state = element.prop('checked');
  484. if (!state) {
  485. this.model.updateShare(shareId, {password: ''});
  486. passwordField.attr('value', '');
  487. passwordField.removeClass('error');
  488. passwordField.tooltip('hide');
  489. loading.addClass('hidden');
  490. passwordField.attr('placeholder', PASSWORD_PLACEHOLDER_MESSAGE);
  491. // We first need to reset the password field before we hide it
  492. passwordContainer.toggleClass('hidden', !state);
  493. } else {
  494. passwordContainer.toggleClass('hidden', !state);
  495. passwordField = '#passwordField-' + this.cid + '-' + shareId;
  496. this.$(passwordField).focus();
  497. }
  498. },
  499. onMailSharePasswordKeyUp: function(event) {
  500. if(event.keyCode === 13) {
  501. this.onMailSharePasswordEntered(event);
  502. }
  503. },
  504. onMailSharePasswordEntered: function(event) {
  505. var passwordField = $(event.target);
  506. var li = passwordField.closest('li[data-share-id]');
  507. var shareId = li.data('share-id');
  508. var passwordContainerClass = '.passwordContainer-' + this.cid + '-' + shareId;
  509. var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small');
  510. if (!loading.hasClass('hidden')) {
  511. // still in process
  512. return;
  513. }
  514. passwordField.removeClass('error');
  515. var password = passwordField.val();
  516. // in IE9 the password might be the placeholder due to bugs in the placeholders polyfill
  517. if(password === '' || password === PASSWORD_PLACEHOLDER || password === PASSWORD_PLACEHOLDER_MESSAGE) {
  518. return;
  519. }
  520. loading
  521. .removeClass('hidden')
  522. .addClass('inlineblock');
  523. this.model.updateShare(shareId, {
  524. password: password
  525. }, {
  526. error: function(model, msg) {
  527. // destroy old tooltips
  528. passwordField.tooltip('destroy');
  529. loading.removeClass('inlineblock').addClass('hidden');
  530. passwordField.addClass('error');
  531. passwordField.attr('title', msg);
  532. passwordField.tooltip({placement: 'bottom', trigger: 'manual'});
  533. passwordField.tooltip('show');
  534. },
  535. success: function(model, msg) {
  536. passwordField.blur();
  537. passwordField.attr('value', '');
  538. passwordField.attr('placeholder', PASSWORD_PLACEHOLDER);
  539. loading.removeClass('inlineblock').addClass('hidden');
  540. }
  541. });
  542. },
  543. onPermissionChange: function(event) {
  544. event.preventDefault();
  545. event.stopPropagation();
  546. var $element = $(event.target);
  547. var $li = $element.closest('li[data-share-id]');
  548. var shareId = $li.data('share-id');
  549. var permissions = OC.PERMISSION_READ;
  550. if (this.model.isFolder()) {
  551. // adjust checkbox states
  552. var $checkboxes = $('.permissions', $li).not('input[name="edit"]').not('input[name="share"]');
  553. var checked;
  554. if ($element.attr('name') === 'edit') {
  555. checked = $element.is(':checked');
  556. // Check/uncheck Create, Update, and Delete checkboxes if Edit is checked/unck
  557. $($checkboxes).prop('checked', checked);
  558. if (checked) {
  559. permissions |= OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE;
  560. }
  561. } else {
  562. var numberChecked = $checkboxes.filter(':checked').length;
  563. checked = numberChecked > 0;
  564. $('input[name="edit"]', $li).prop('checked', checked);
  565. }
  566. } else {
  567. if ($element.attr('name') === 'edit' && $element.is(':checked')) {
  568. permissions |= OC.PERMISSION_UPDATE;
  569. }
  570. }
  571. $('.permissions', $li).not('input[name="edit"]').filter(':checked').each(function(index, checkbox) {
  572. permissions |= $(checkbox).data('permissions');
  573. });
  574. /** disable checkboxes during save operation to avoid race conditions **/
  575. $li.find('input[type=checkbox]').prop('disabled', true);
  576. var enableCb = function() {
  577. $li.find('input[type=checkbox]').prop('disabled', false);
  578. };
  579. var errorCb = function(elem, msg) {
  580. OC.dialogs.alert(msg, t('core', 'Error while sharing'));
  581. enableCb();
  582. };
  583. this.model.updateShare(shareId, {permissions: permissions}, {error: errorCb, success: enableCb});
  584. this._renderPermissionChange = shareId;
  585. },
  586. onSecureDropChange: function(event) {
  587. event.preventDefault();
  588. event.stopPropagation();
  589. var $element = $(event.target);
  590. var $li = $element.closest('li[data-share-id]');
  591. var shareId = $li.data('share-id');
  592. var permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE | OC.PERMISSION_READ;
  593. if ($element.is(':checked')) {
  594. permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE;
  595. }
  596. /** disable checkboxes during save operation to avoid race conditions **/
  597. $li.find('input[type=checkbox]').prop('disabled', true);
  598. var enableCb = function() {
  599. $li.find('input[type=checkbox]').prop('disabled', false);
  600. };
  601. var errorCb = function(elem, msg) {
  602. OC.dialogs.alert(msg, t('core', 'Error while sharing'));
  603. enableCb();
  604. };
  605. this.model.updateShare(shareId, {permissions: permissions}, {error: errorCb, success: enableCb});
  606. this._renderPermissionChange = shareId;
  607. }
  608. });
  609. OC.Share.ShareDialogShareeListView = ShareDialogShareeListView;
  610. })();