/* eslint-disable */ /* global OC, Handlebars */ /* * Copyright (c) 2015 * * This file is licensed under the Affero General Public License version 3 * or later. * * See the COPYING-README file. * */ /* globals Handlebars */ (function() { var PASSWORD_PLACEHOLDER = '**********' var PASSWORD_PLACEHOLDER_MESSAGE = t('core', 'Choose a password for the mail share') if (!OC.Share) { OC.Share = {} } /** * @class OCA.Share.ShareDialogShareeListView * @member {OC.Share.ShareItemModel} model * @member {jQuery} $el * @memberof OCA.Sharing * @classdesc * * Represents the sharee list part in the GUI of the share dialogue * */ var ShareDialogShareeListView = OC.Backbone.View.extend({ /** @type {string} **/ id: 'shareDialogLinkShare', /** @type {OC.Share.ShareConfigModel} **/ configModel: undefined, _menuOpen: false, /** @type {boolean|number} **/ _renderPermissionChange: false, events: { 'click .unshare': 'onUnshare', 'click .share-add': 'showNoteForm', 'click .share-note-delete': 'deleteNote', 'click .share-note-submit': 'updateNote', 'click .share-menu .icon-more': 'onToggleMenu', 'click .permissions': 'onPermissionChange', 'click .expireDate': 'onExpireDateChange', 'click .password': 'onMailSharePasswordProtectChange', 'click .passwordByTalk': 'onMailSharePasswordProtectByTalkChange', 'click .secureDrop': 'onSecureDropChange', 'keyup input.passwordField': 'onMailSharePasswordKeyUp', 'focusout input.passwordField': 'onMailSharePasswordEntered', 'change .datepicker': 'onChangeExpirationDate', 'click .datepicker': 'showDatePicker' }, initialize: function(options) { if (!_.isUndefined(options.configModel)) { this.configModel = options.configModel } else { throw 'missing OC.Share.ShareConfigModel' } var view = this this.model.on('change:shares', function() { view.render() }) }, /** * * @param {OC.Share.Types.ShareInfo} shareInfo * @returns {object} */ getShareeObject: function(shareIndex) { var shareWith = this.model.getShareWith(shareIndex) var shareWithDisplayName = this.model.getShareWithDisplayName(shareIndex) var shareWithAvatar = this.model.getShareWithAvatar(shareIndex) var shareWithTitle = '' var shareType = this.model.getShareType(shareIndex) var sharedBy = this.model.getSharedBy(shareIndex) var sharedByDisplayName = this.model.getSharedByDisplayName(shareIndex) var fileOwnerUid = this.model.getFileOwnerUid(shareIndex) var hasPermissionOverride = {} if (shareType === OC.Share.SHARE_TYPE_GROUP) { shareWithDisplayName = shareWithDisplayName + ' (' + t('core', 'group') + ')' } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) { shareWithDisplayName = shareWithDisplayName + ' (' + t('core', 'remote') + ')' } else if (shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) { shareWithDisplayName = shareWithDisplayName + ' (' + t('core', 'remote group') + ')' } else if (shareType === OC.Share.SHARE_TYPE_EMAIL) { shareWithDisplayName = shareWithDisplayName + ' (' + t('core', 'email') + ')' } else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) { } else if (shareType === OC.Share.SHARE_TYPE_ROOM) { shareWithDisplayName = shareWithDisplayName + ' (' + t('core', 'conversation') + ')' } if (shareType === OC.Share.SHARE_TYPE_GROUP) { shareWithTitle = shareWith + ' (' + t('core', 'group') + ')' } else if (shareType === OC.Share.SHARE_TYPE_REMOTE) { shareWithTitle = shareWith + ' (' + t('core', 'remote') + ')' } else if (shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP) { shareWithTitle = shareWith + ' (' + t('core', 'remote group') + ')' } else if (shareType === OC.Share.SHARE_TYPE_EMAIL) { shareWithTitle = shareWith + ' (' + t('core', 'email') + ')' } else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) { shareWithTitle = shareWith // Force "shareWith" in the template to a safe value, as the // original "shareWith" returned by the model may contain // problematic characters like "'". shareWith = 'circle-' + shareIndex } if (sharedBy !== OC.getCurrentUser().uid) { var empty = shareWithTitle === '' if (!empty) { shareWithTitle += ' (' } shareWithTitle += t('core', 'shared by {sharer}', { sharer: sharedByDisplayName }) if (!empty) { shareWithTitle += ')' } } var share = this.model.get('shares')[shareIndex] var password = share.password var hasPassword = password !== null && password !== '' var sendPasswordByTalk = share.send_password_by_talk var shareNote = this.model.getNote(shareIndex) return _.extend(hasPermissionOverride, { cid: this.cid, hasSharePermission: this.model.hasSharePermission(shareIndex), editPermissionState: this.model.editPermissionState(shareIndex), hasCreatePermission: this.model.hasCreatePermission(shareIndex), hasUpdatePermission: this.model.hasUpdatePermission(shareIndex), hasDeletePermission: this.model.hasDeletePermission(shareIndex), sharedBy: sharedBy, sharedByDisplayName: sharedByDisplayName, shareWith: shareWith, shareWithDisplayName: shareWithDisplayName, shareWithAvatar: shareWithAvatar, shareWithTitle: shareWithTitle, shareType: shareType, shareId: this.model.get('shares')[shareIndex].id, modSeed: shareWithAvatar || (shareType !== OC.Share.SHARE_TYPE_USER && shareType !== OC.Share.SHARE_TYPE_CIRCLE && shareType !== OC.Share.SHARE_TYPE_ROOM), owner: fileOwnerUid, isShareWithCurrentUser: (shareType === OC.Share.SHARE_TYPE_USER && shareWith === OC.getCurrentUser().uid), canUpdateShareSettings: (sharedBy === OC.getCurrentUser().uid || fileOwnerUid === OC.getCurrentUser().uid), isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE, isRemoteGroupShare: shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP, isNoteAvailable: shareType !== OC.Share.SHARE_TYPE_REMOTE && shareType !== OC.Share.SHARE_TYPE_REMOTE_GROUP, isMailShare: shareType === OC.Share.SHARE_TYPE_EMAIL, isCircleShare: shareType === OC.Share.SHARE_TYPE_CIRCLE, isFileSharedByMail: shareType === OC.Share.SHARE_TYPE_EMAIL && !this.model.isFolder(), isPasswordSet: hasPassword && !sendPasswordByTalk, isPasswordByTalkSet: hasPassword && sendPasswordByTalk, isTalkEnabled: OC.appswebroots['spreed'] !== undefined, secureDropMode: !this.model.hasReadPermission(shareIndex), hasExpireDate: this.model.getExpireDate(shareIndex) !== null, shareNote: shareNote, hasNote: shareNote !== '', expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'), // The password placeholder does not take into account if // sending the password by Talk is enabled or not; when // switching from sending the password by Talk to sending the // password by email the password is reused and the share // updated, so the placeholder already shows the password in the // brief time between disabling sending the password by email // and receiving the updated share. passwordPlaceholder: hasPassword ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, passwordByTalkPlaceholder: (hasPassword && sendPasswordByTalk) ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE }) }, getShareProperties: function() { return { unshareLabel: t('core', 'Unshare'), addNoteLabel: t('core', 'Note to recipient'), canShareLabel: t('core', 'Can reshare'), canEditLabel: t('core', 'Can edit'), createPermissionLabel: t('core', 'Can create'), updatePermissionLabel: t('core', 'Can change'), deletePermissionLabel: t('core', 'Can delete'), secureDropLabel: t('core', 'File drop (upload only)'), expireDateLabel: t('core', 'Set expiration date'), passwordLabel: t('core', 'Password protect'), passwordByTalkLabel: t('core', 'Password protect by Talk'), crudsLabel: t('core', 'Access control'), expirationDatePlaceholder: t('core', 'Expiration date'), defaultExpireDate: moment().add(1, 'day').format('DD-MM-YYYY'), // Can't expire today triangleSImage: OC.imagePath('core', 'actions/triangle-s'), isResharingAllowed: this.configModel.get('isResharingAllowed'), isPasswordForMailSharesRequired: this.configModel.get('isPasswordForMailSharesRequired'), sharePermissionPossible: this.model.sharePermissionPossible(), editPermissionPossible: this.model.editPermissionPossible(), createPermissionPossible: this.model.createPermissionPossible(), updatePermissionPossible: this.model.updatePermissionPossible(), deletePermissionPossible: this.model.deletePermissionPossible(), sharePermission: OC.PERMISSION_SHARE, createPermission: OC.PERMISSION_CREATE, updatePermission: OC.PERMISSION_UPDATE, deletePermission: OC.PERMISSION_DELETE, readPermission: OC.PERMISSION_READ, isFolder: this.model.isFolder() } }, /** * get an array of sharees' share properties * * @returns {Array} */ getShareeList: function() { var universal = this.getShareProperties() if (!this.model.hasUserShares()) { return [] } var shares = this.model.get('shares') var list = [] for (var index = 0; index < shares.length; index++) { var share = this.getShareeObject(index) if (share.shareType === OC.Share.SHARE_TYPE_LINK) { continue } // first empty {} is necessary, otherwise we get in trouble // with references list.push(_.extend({}, universal, share)) } return list }, getLinkReshares: function() { var universal = { unshareLabel: t('core', 'Unshare') } if (!this.model.hasUserShares()) { return [] } var shares = this.model.get('shares') var list = [] for (var index = 0; index < shares.length; index++) { var share = this.getShareeObject(index) if (share.shareType !== OC.Share.SHARE_TYPE_LINK) { continue } // first empty {} is necessary, otherwise we get in trouble // with references list.push(_.extend({}, universal, share, { shareInitiator: shares[index].uid_owner, shareInitiatorText: t('core', '{shareInitiatorDisplayName} shared via link', { shareInitiatorDisplayName: shares[index].displayname_owner }) })) } return list }, render: function() { if (!this._renderPermissionChange) { this.$el.html(this.template({ cid: this.cid, sharees: this.getShareeList(), linkReshares: this.getLinkReshares() })) this.$('.avatar').each(function() { var $this = $(this) if ($this.hasClass('imageplaceholderseed')) { $this.css({ width: 32, height: 32 }) if ($this.data('avatar')) { $this.css('border-radius', '0%') $this.css('background', 'url(' + $this.data('avatar') + ') no-repeat') $this.css('background-size', '31px') } else { $this.imageplaceholder($this.data('seed')) } } else { // user, size, ie8fix, hidedefault, callback, displayname $this.avatar($this.data('username'), 32, undefined, undefined, undefined, $this.data('displayname')) } }) this.$('.has-tooltip').tooltip({ placement: 'bottom' }) this.$('ul.shareWithList > li').each(function() { var $this = $(this) var shareWith = $this.data('share-with') var shareType = $this.data('share-type') $this.find('div.avatar, span.username').contactsMenu(shareWith, shareType, $this) }) } else { var permissionChangeShareId = parseInt(this._renderPermissionChange, 10) var shareWithIndex = this.model.findShareWithIndex(permissionChangeShareId) var sharee = this.getShareeObject(shareWithIndex) $.extend(sharee, this.getShareProperties()) var $li = this.$('li[data-share-id=' + permissionChangeShareId + ']') $li.find('.sharingOptionsGroup .popovermenu').replaceWith(this.popoverMenuTemplate(sharee)) } var _this = this this.getShareeList().forEach(function(sharee) { var $edit = _this.$('#canEdit-' + _this.cid + '-' + sharee.shareId) if ($edit.length === 1) { $edit.prop('checked', sharee.editPermissionState === 'checked') if (sharee.isFolder) { $edit.prop('indeterminate', sharee.editPermissionState === 'indeterminate') } } }) this.$('.popovermenu').on('afterHide', function() { _this._menuOpen = false }) this.$('.popovermenu').on('beforeHide', function() { var shareId = parseInt(_this._menuOpen, 10) if (!_.isNaN(shareId)) { var datePickerClass = '.expirationDateContainer-' + _this.cid + '-' + shareId var datePickerInput = '#expirationDatePicker-' + _this.cid + '-' + shareId var expireDateCheckbox = '#expireDate-' + _this.cid + '-' + shareId if ($(expireDateCheckbox).prop('checked')) { $(datePickerInput).removeClass('hidden-visually') $(datePickerClass).removeClass('hasDatepicker') $(datePickerClass + ' .ui-datepicker').hide() } } }) if (this._menuOpen !== false) { // Open menu again if it was opened before var shareId = parseInt(this._menuOpen, 10) if (!_.isNaN(shareId)) { var liSelector = 'li[data-share-id=' + shareId + ']' OC.showMenu(null, this.$(liSelector + ' .sharingOptionsGroup .popovermenu')) } } this._renderPermissionChange = false // new note autosize autosize(this.$el.find('.share-note-form .share-note')) this.delegateEvents() return this }, /** * @returns {Function} from Handlebars * @private */ template: function(data) { var sharees = data.sharees if (_.isArray(sharees)) { for (var i = 0; i < sharees.length; i++) { data.sharees[i].popoverMenu = this.popoverMenuTemplate(sharees[i]) } } return OC.Share.Templates['sharedialogshareelistview'](data) }, /** * renders the popover template and returns the resulting HTML * * @param {Object} data * @returns {string} */ popoverMenuTemplate: function(data) { return OC.Share.Templates['sharedialogshareelistview_popover_menu'](data) }, showNoteForm: function(event) { event.preventDefault() event.stopPropagation() var $element = $(event.target) var $menu = $element.closest('li') var $form = $menu.next('li.share-note-form') // show elements $menu.find('.share-note-delete').toggleClass('hidden') $form.toggleClass('hidden') $form.find('textarea').focus() }, deleteNote: function(event) { event.preventDefault() event.stopPropagation() var self = this var $element = $(event.target) var $li = $element.closest('li[data-share-id]') var shareId = $li.data('share-id') var $menu = $element.closest('li') var $form = $menu.next('li.share-note-form') console.log($form.find('.share-note')) $form.find('.share-note').val('') $form.addClass('hidden') $menu.find('.share-note-delete').addClass('hidden') self.sendNote('', shareId, $menu) }, updateNote: function(event) { event.preventDefault() event.stopPropagation() var self = this var $element = $(event.target) var $li = $element.closest('li[data-share-id]') var shareId = $li.data('share-id') var $form = $element.closest('li.share-note-form') var $menu = $form.prev('li') var message = $form.find('.share-note').val().trim() if (message.length < 1) { return } self.sendNote(message, shareId, $menu) }, sendNote: function(note, shareId, $menu) { var $form = $menu.next('li.share-note-form') var $submit = $form.find('input.share-note-submit') var $error = $form.find('input.share-note-error') $submit.prop('disabled', true) $menu.find('.icon-loading-small').removeClass('hidden') $menu.find('.icon-edit').hide() var complete = function() { $submit.prop('disabled', false) $menu.find('.icon-loading-small').addClass('hidden') $menu.find('.icon-edit').show() } var error = function() { $error.show() setTimeout(function() { $error.hide() }, 3000) } // send data $.ajax({ method: 'PUT', url: OC.linkToOCS('apps/files_sharing/api/v1/shares', 2) + shareId + '?' + OC.buildQueryString({ format: 'json' }), data: { note: note }, complete: complete, error: error }) }, onUnshare: function(event) { event.preventDefault() event.stopPropagation() var self = this var $element = $(event.target) if (!$element.is('a')) { $element = $element.closest('a') } var $loading = $element.find('.icon-loading-small').eq(0) if (!$loading.hasClass('hidden')) { // in process return false } $loading.removeClass('hidden') var $li = $element.closest('li[data-share-id]') var shareId = $li.data('share-id') self.model.removeShare(shareId) .done(function() { $li.remove() }) .fail(function() { $loading.addClass('hidden') OC.Notification.showTemporary(t('core', 'Could not unshare')) }) return false }, onToggleMenu: function(event) { event.preventDefault() event.stopPropagation() var $element = $(event.target) var $li = $element.closest('li[data-share-id]') var $menu = $li.find('.sharingOptionsGroup .popovermenu') OC.showMenu(null, $menu) this._menuOpen = $li.data('share-id') }, onExpireDateChange: function(event) { var $element = $(event.target) var li = $element.closest('li[data-share-id]') var shareId = li.data('share-id') var datePickerClass = '.expirationDateContainer-' + this.cid + '-' + shareId var datePicker = $(datePickerClass) var state = $element.prop('checked') datePicker.toggleClass('hidden', !state) if (!state) { // disabled, let's hide the input and // set the expireDate to nothing $element.closest('li').next('li').addClass('hidden') this.setExpirationDate(shareId, '') } else { // enabled, show the input and the datepicker $element.closest('li').next('li').removeClass('hidden') this.showDatePicker(event) } }, showDatePicker: function(event) { var element = $(event.target) var li = element.closest('li[data-share-id]') var shareId = li.data('share-id') var expirationDatePicker = '#expirationDatePicker-' + this.cid + '-' + shareId var view = this $(expirationDatePicker).datepicker({ dateFormat: 'dd-mm-yy', onSelect: function(expireDate) { view.setExpirationDate(shareId, expireDate) } }) $(expirationDatePicker).focus() }, setExpirationDate: function(shareId, expireDate) { this.model.updateShare(shareId, { expireDate: expireDate }, {}) }, onMailSharePasswordProtectChange: function(event) { var element = $(event.target) var li = element.closest('li[data-share-id]') var shareId = li.data('share-id') var passwordContainerClass = '.passwordMenu-' + this.cid + '-' + shareId var passwordContainer = $(passwordContainerClass) var loading = this.$el.find(passwordContainerClass + ' .icon-loading-small') var inputClass = '#passwordField-' + this.cid + '-' + shareId var passwordField = $(inputClass) var state = element.prop('checked') var passwordByTalkElement = $('#passwordByTalk-' + this.cid + '-' + shareId) var passwordByTalkState = passwordByTalkElement.prop('checked') if (!state && !passwordByTalkState) { this.model.updateShare(shareId, { password: '', sendPasswordByTalk: false }) passwordField.attr('value', '') passwordField.removeClass('error') passwordField.tooltip('hide') loading.addClass('hidden') passwordField.attr('placeholder', PASSWORD_PLACEHOLDER_MESSAGE) // We first need to reset the password field before we hide it passwordContainer.toggleClass('hidden', !state) } else if (state) { if (passwordByTalkState) { // Switching from sending the password by Talk to sending // the password by mail can be done keeping the previous // password sent by Talk. this.model.updateShare(shareId, { sendPasswordByTalk: false }) var passwordByTalkContainerClass = '.passwordByTalkMenu-' + this.cid + '-' + shareId var passwordByTalkContainer = $(passwordByTalkContainerClass) passwordByTalkContainer.addClass('hidden') passwordByTalkElement.prop('checked', false) } passwordContainer.toggleClass('hidden', !state) passwordField = '#passwordField-' + this.cid + '-' + shareId this.$(passwordField).focus() } }, onMailSharePasswordProtectByTalkChange: function(event) { var element = $(event.target) var li = element.closest('li[data-share-id]') var shareId = li.data('share-id') var passwordByTalkContainerClass = '.passwordByTalkMenu-' + this.cid + '-' + shareId var passwordByTalkContainer = $(passwordByTalkContainerClass) var loading = this.$el.find(passwordByTalkContainerClass + ' .icon-loading-small') var inputClass = '#passwordByTalkField-' + this.cid + '-' + shareId var passwordByTalkField = $(inputClass) var state = element.prop('checked') var passwordElement = $('#password-' + this.cid + '-' + shareId) var passwordState = passwordElement.prop('checked') if (!state) { this.model.updateShare(shareId, { password: '', sendPasswordByTalk: false }) passwordByTalkField.attr('value', '') passwordByTalkField.removeClass('error') passwordByTalkField.tooltip('hide') loading.addClass('hidden') passwordByTalkField.attr('placeholder', PASSWORD_PLACEHOLDER_MESSAGE) // We first need to reset the password field before we hide it passwordByTalkContainer.toggleClass('hidden', !state) } else if (state) { if (passwordState) { // Enabling sending the password by Talk requires a new // password to be given (the one sent by mail is not reused, // as it would defeat the purpose of checking the identity // of the sharee by Talk if it was already sent by mail), so // the share is not updated until the user explicitly gives // the new password. var passwordContainerClass = '.passwordMenu-' + this.cid + '-' + shareId var passwordContainer = $(passwordContainerClass) passwordContainer.addClass('hidden') passwordElement.prop('checked', false) } passwordByTalkContainer.toggleClass('hidden', !state) passwordByTalkField = '#passwordByTalkField-' + this.cid + '-' + shareId this.$(passwordByTalkField).focus() } }, onMailSharePasswordKeyUp: function(event) { if (event.keyCode === 13) { this.onMailSharePasswordEntered(event) } }, onMailSharePasswordEntered: function(event) { var passwordField = $(event.target) var li = passwordField.closest('li[data-share-id]') var shareId = li.data('share-id') var passwordContainerClass = '.passwordMenu-' + this.cid + '-' + shareId var passwordByTalkContainerClass = '.passwordByTalkMenu-' + this.cid + '-' + shareId var sendPasswordByTalk = passwordField.attr('id').startsWith('passwordByTalk') var loading if (sendPasswordByTalk) { loading = this.$el.find(passwordByTalkContainerClass + ' .icon-loading-small') } else { loading = this.$el.find(passwordContainerClass + ' .icon-loading-small') } if (!loading.hasClass('hidden')) { // still in process return } passwordField.removeClass('error') var password = passwordField.val() // in IE9 the password might be the placeholder due to bugs in the placeholders polyfill if (password === '' || password === PASSWORD_PLACEHOLDER || password === PASSWORD_PLACEHOLDER_MESSAGE) { return } loading .removeClass('hidden') .addClass('inlineblock') this.model.updateShare(shareId, { password: password, sendPasswordByTalk: sendPasswordByTalk }, { error: function(model, msg) { // destroy old tooltips passwordField.tooltip('destroy') loading.removeClass('inlineblock').addClass('hidden') passwordField.addClass('error') passwordField.attr('title', msg) passwordField.tooltip({ placement: 'bottom', trigger: 'manual' }) passwordField.tooltip('show') }, success: function(model, msg) { passwordField.blur() passwordField.attr('value', '') passwordField.attr('placeholder', PASSWORD_PLACEHOLDER) loading.removeClass('inlineblock').addClass('hidden') } }) }, onPermissionChange: function(event) { event.preventDefault() event.stopPropagation() var $element = $(event.target) var $li = $element.closest('li[data-share-id]') var shareId = $li.data('share-id') var permissions = OC.PERMISSION_READ if (this.model.isFolder()) { // adjust checkbox states var $checkboxes = $('.permissions', $li).not('input[name="edit"]').not('input[name="share"]') var checked if ($element.attr('name') === 'edit') { checked = $element.is(':checked') // Check/uncheck Create, Update, and Delete checkboxes if Edit is checked/unck $($checkboxes).prop('checked', checked) if (checked) { permissions |= OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE } } else { var numberChecked = $checkboxes.filter(':checked').length checked = numberChecked === $checkboxes.length var $editCb = $('input[name="edit"]', $li) $editCb.prop('checked', checked) $editCb.prop('indeterminate', !checked && numberChecked > 0) } } else { if ($element.attr('name') === 'edit' && $element.is(':checked')) { permissions |= OC.PERMISSION_UPDATE } } $('.permissions', $li).not('input[name="edit"]').filter(':checked').each(function(index, checkbox) { permissions |= $(checkbox).data('permissions') }) /** disable checkboxes during save operation to avoid race conditions **/ $li.find('input[type=checkbox]').prop('disabled', true) var enableCb = function() { $li.find('input[type=checkbox]').prop('disabled', false) } var errorCb = function(elem, msg) { OC.dialogs.alert(msg, t('core', 'Error while sharing')) enableCb() } this.model.updateShare(shareId, { permissions: permissions }, { error: errorCb, success: enableCb }) this._renderPermissionChange = shareId }, onSecureDropChange: function(event) { event.preventDefault() event.stopPropagation() var $element = $(event.target) var $li = $element.closest('li[data-share-id]') var shareId = $li.data('share-id') var permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE | OC.PERMISSION_READ if ($element.is(':checked')) { permissions = OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE } /** disable checkboxes during save operation to avoid race conditions **/ $li.find('input[type=checkbox]').prop('disabled', true) var enableCb = function() { $li.find('input[type=checkbox]').prop('disabled', false) } var errorCb = function(elem, msg) { OC.dialogs.alert(msg, t('core', 'Error while sharing')) enableCb() } this.model.updateShare(shareId, { permissions: permissions }, { error: errorCb, success: enableCb }) this._renderPermissionChange = shareId } }) OC.Share.ShareDialogShareeListView = ShareDialogShareeListView })()