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.
981 lines
30 KiB
981 lines
30 KiB
/* |
|
* Copyright (c) 2015 |
|
* |
|
* This file is licensed under the Affero General Public License version 3 |
|
* or later. |
|
* |
|
* See the COPYING-README file. |
|
* |
|
*/ |
|
|
|
/* globals Clipboard, Handlebars */ |
|
|
|
(function() { |
|
if (!OC.Share) { |
|
OC.Share = {}; |
|
} |
|
|
|
var PASSWORD_PLACEHOLDER = '**********'; |
|
var PASSWORD_PLACEHOLDER_MESSAGE = t('core', 'Choose a password for the public link'); |
|
var PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL = t('core', 'Choose a password for the public link or press the "Enter" key'); |
|
|
|
/** |
|
* @class OCA.Share.ShareDialogLinkShareView |
|
* @member {OC.Share.ShareItemModel} model |
|
* @member {jQuery} $el |
|
* @memberof OCA.Sharing |
|
* @classdesc |
|
* |
|
* Represents the GUI of the share dialogue |
|
* |
|
*/ |
|
var ShareDialogLinkShareView = OC.Backbone.View.extend({ |
|
/** @type {string} **/ |
|
id: 'shareDialogLinkShare', |
|
|
|
/** @type {OC.Share.ShareConfigModel} **/ |
|
configModel: undefined, |
|
|
|
/** @type {boolean} **/ |
|
showLink: true, |
|
|
|
/** @type {boolean} **/ |
|
showPending: false, |
|
|
|
/** @type {boolean} **/ |
|
hasPasswordChanged: false, |
|
|
|
/** @type {string} **/ |
|
password: '', |
|
|
|
/** @type {string} **/ |
|
newShareId: 'new-share', |
|
|
|
events: { |
|
// open menu |
|
'click .share-menu .icon-more': 'onToggleMenu', |
|
// hide download |
|
'change .hideDownloadCheckbox': 'onHideDownloadChange', |
|
// password |
|
'click input.share-pass-submit': 'onPasswordEntered', |
|
'keyup input.linkPassText': 'onPasswordKeyUp', // check for the enter key |
|
'change .showPasswordCheckbox': 'onShowPasswordClick', |
|
'change .passwordByTalkCheckbox': 'onPasswordByTalkChange', |
|
'change .publicEditingCheckbox': 'onAllowPublicEditingChange', |
|
// copy link url |
|
'click .linkText': 'onLinkTextClick', |
|
// social |
|
'click .pop-up': 'onPopUpClick', |
|
// permission change |
|
'change .publicUploadRadio': 'onPublicUploadChange', |
|
// expire date |
|
'click .expireDate' : 'onExpireDateChange', |
|
'change .datepicker': 'onChangeExpirationDate', |
|
'click .datepicker' : 'showDatePicker', |
|
// note |
|
'click .share-add': 'showNoteForm', |
|
'click .share-note-delete': 'deleteNote', |
|
'click .share-note-submit': 'updateNote', |
|
// remove |
|
'click .unshare': 'onUnshare', |
|
// new share |
|
'click .new-share': 'newShare', |
|
// enforced pass set |
|
'submit .enforcedPassForm': 'enforcedPasswordSet', |
|
}, |
|
|
|
initialize: function(options) { |
|
var view = this; |
|
|
|
this.model.on('change:permissions', function() { |
|
view.render(); |
|
}); |
|
|
|
this.model.on('change:itemType', function() { |
|
view.render(); |
|
}); |
|
|
|
this.model.on('change:allowPublicUploadStatus', function() { |
|
view.render(); |
|
}); |
|
|
|
this.model.on('change:hideFileListStatus', function() { |
|
view.render(); |
|
}); |
|
|
|
this.model.on('change:linkShares', function(model, linkShares) { |
|
// The "Password protect by Talk" item is shown only when there |
|
// is a password. Unfortunately there is no fine grained |
|
// rendering of items in the link shares, so the whole view |
|
// needs to be rendered again when the password of a share |
|
// changes. |
|
// Note that this event handler is concerned only about password |
|
// changes; other changes in the link shares does not trigger |
|
// a rendering, so the view must be rendered again as needed in |
|
// those cases (for example, when a link share is removed). |
|
|
|
var previousLinkShares = model.previous('linkShares'); |
|
if (previousLinkShares.length !== linkShares.length) { |
|
return; |
|
} |
|
|
|
var i; |
|
for (i = 0; i < linkShares.length; i++) { |
|
if (linkShares[i].id !== previousLinkShares[i].id) { |
|
// A resorting should never happen, but just in case. |
|
return; |
|
} |
|
|
|
if (linkShares[i].password !== previousLinkShares[i].password) { |
|
view.render(); |
|
|
|
return; |
|
} |
|
} |
|
}); |
|
|
|
if(!_.isUndefined(options.configModel)) { |
|
this.configModel = options.configModel; |
|
} else { |
|
throw 'missing OC.Share.ShareConfigModel'; |
|
} |
|
|
|
var clipboard = new Clipboard('.clipboard-button'); |
|
clipboard.on('success', function(e) { |
|
var $trigger = $(e.trigger); |
|
|
|
$trigger.tooltip('hide') |
|
.attr('data-original-title', t('core', 'Copied!')) |
|
.tooltip('fixTitle') |
|
.tooltip({placement: 'bottom', trigger: 'manual'}) |
|
.tooltip('show'); |
|
_.delay(function() { |
|
$trigger.tooltip('hide') |
|
.attr('data-original-title', t('core', 'Copy link')) |
|
.tooltip('fixTitle') |
|
}, 3000); |
|
}); |
|
clipboard.on('error', function (e) { |
|
var $trigger = $(e.trigger); |
|
var $menu = $trigger.next('.share-menu').find('.popovermenu'); |
|
var $linkTextMenu = $menu.find('li.linkTextMenu'); |
|
var $input = $linkTextMenu.find('.linkText'); |
|
|
|
var $li = $trigger.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
|
|
// show menu |
|
OC.showMenu(null, $menu); |
|
|
|
var actionMsg = ''; |
|
if (/iPhone|iPad/i.test(navigator.userAgent)) { |
|
actionMsg = t('core', 'Not supported!'); |
|
} else if (/Mac/i.test(navigator.userAgent)) { |
|
actionMsg = t('core', 'Press ⌘-C to copy.'); |
|
} else { |
|
actionMsg = t('core', 'Press Ctrl-C to copy.'); |
|
} |
|
|
|
$linkTextMenu.removeClass('hidden'); |
|
$input.select(); |
|
$input.tooltip('hide') |
|
.attr('data-original-title', actionMsg) |
|
.tooltip('fixTitle') |
|
.tooltip({placement: 'bottom', trigger: 'manual'}) |
|
.tooltip('show'); |
|
_.delay(function () { |
|
$input.tooltip('hide'); |
|
$input.attr('data-original-title', t('core', 'Copy')) |
|
.tooltip('fixTitle'); |
|
}, 3000); |
|
}); |
|
}, |
|
|
|
newShare: function(event) { |
|
var self = this; |
|
var $target = $(event.target); |
|
var $li = $target.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
var $loading = $li.find('.share-menu > .icon-loading-small'); |
|
|
|
if(!$loading.hasClass('hidden') && this.password === '') { |
|
// in process |
|
return false; |
|
} |
|
|
|
// hide all icons and show loading |
|
$li.find('.icon').addClass('hidden'); |
|
$loading.removeClass('hidden'); |
|
|
|
// hide menu |
|
OC.hideMenus(); |
|
|
|
var shareData = {} |
|
|
|
var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink'); |
|
var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); |
|
|
|
// set default expire date |
|
if (isExpirationEnforced) { |
|
var defaultExpireDays = this.configModel.get('defaultExpireDate'); |
|
var expireDate = moment().add(defaultExpireDays, 'day').format('DD-MM-YYYY') |
|
shareData.expireDate = expireDate; |
|
} |
|
|
|
// if password is set, add to data |
|
if (isPasswordEnforced && this.password !== '') { |
|
shareData.password = this.password |
|
} |
|
|
|
var newShareId = false; |
|
|
|
// We need a password before the share creation |
|
if (isPasswordEnforced && !this.showPending && this.password === '') { |
|
this.showPending = shareId; |
|
var self = this.render(); |
|
self.$el.find('.pending #enforcedPassText').focus(); |
|
} else { |
|
// else, we have a password or it is not enforced |
|
$.when(this.model.saveLinkShare(shareData, { |
|
success: function() { |
|
$loading.addClass('hidden'); |
|
$li.find('.icon').removeClass('hidden'); |
|
self.render(); |
|
// open the menu by default |
|
// we can only do that after the render |
|
if (newShareId) { |
|
var shares = self.$el.find('li[data-share-id]'); |
|
var $newShare = self.$el.find('li[data-share-id="'+newShareId+'"]'); |
|
} |
|
}, |
|
error: function() { |
|
// empty function to override the default Dialog warning |
|
} |
|
})).fail(function(response) { |
|
// password failure? Show error |
|
self.password = '' |
|
if (isPasswordEnforced && response && response.responseJSON && response.responseJSON.ocs.meta && response.responseJSON.ocs.meta.message) { |
|
var $input = self.$el.find('.pending #enforcedPassText') |
|
$input.tooltip('destroy'); |
|
$input.attr('title', response.responseJSON.ocs.meta.message); |
|
$input.tooltip({placement: 'bottom', trigger: 'manual'}); |
|
$input.tooltip('show'); |
|
} else { |
|
OC.Notification.showTemporary(t('core', 'Unable to create a link share')); |
|
$loading.addClass('hidden'); |
|
$li.find('.icon').removeClass('hidden'); |
|
} |
|
}).then(function(response) { |
|
// resolve before success |
|
newShareId = response.ocs.data.id |
|
}); |
|
} |
|
}, |
|
|
|
enforcedPasswordSet: function(event) { |
|
event.preventDefault(); |
|
var $form = $(event.target); |
|
var $input = $form.find('input.enforcedPassText'); |
|
this.password = $input.val(); |
|
this.showPending = false; |
|
this.newShare(event); |
|
}, |
|
|
|
onLinkTextClick: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var $el = $li.find('.linkText'); |
|
$el.focus(); |
|
$el.select(); |
|
}, |
|
|
|
onHideDownloadChange: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
var $checkbox = $li.find('.hideDownloadCheckbox'); |
|
$checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); |
|
|
|
var hideDownload = false; |
|
if($checkbox.is(':checked')) { |
|
hideDownload = true; |
|
} |
|
|
|
this.model.saveLinkShare({ |
|
hideDownload: hideDownload, |
|
cid: shareId |
|
}, { |
|
success: function() { |
|
$checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); |
|
}, |
|
error: function(obj, msg) { |
|
OC.Notification.showTemporary(t('core', 'Unable to toggle this option')); |
|
$checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); |
|
} |
|
}); |
|
}, |
|
|
|
onShowPasswordClick: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
$li.find('.linkPass').slideToggle(OC.menuSpeed); |
|
$li.find('.linkPassMenu').toggleClass('hidden'); |
|
if(!$li.find('.showPasswordCheckbox').is(':checked')) { |
|
this.model.saveLinkShare({ |
|
password: '', |
|
cid: shareId |
|
}); |
|
this.hasPasswordChanged = false |
|
} else { |
|
if (!OC.Util.isIE()) { |
|
$li.find('.linkPassText').focus(); |
|
} |
|
} |
|
}, |
|
|
|
onPasswordKeyUp: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
if (event.keyCode === 13) { |
|
this.onPasswordEntered(event); |
|
} else { |
|
this.hasPasswordChanged = shareId |
|
} |
|
}, |
|
|
|
onPasswordEntered: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
var $loading = $li.find('.linkPassMenu .icon-loading-small'); |
|
if (!$loading.hasClass('hidden')) { |
|
// still in process |
|
return; |
|
} |
|
var $input = $li.find('.linkPassText'); |
|
$input.removeClass('error'); |
|
$input.parent().find('input').removeClass('error'); |
|
var password = $input.val(); |
|
|
|
if ($li.find('.linkPassText').attr('placeholder') === PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL) { |
|
|
|
// in IE9 the password might be the placeholder due to bugs in the placeholders polyfill |
|
if(password === PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL) { |
|
password = ''; |
|
} |
|
} else { |
|
|
|
// 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.hasPasswordChanged = false |
|
|
|
this.model.saveLinkShare({ |
|
password: password, |
|
cid: shareId |
|
}, { |
|
complete: function(model) { |
|
$loading.removeClass('inlineblock').addClass('hidden'); |
|
}, |
|
error: function(model, msg) { |
|
// Add visual feedback to both the input and the submit button |
|
$input.parent().find('input').addClass('error'); |
|
|
|
// destroy old tooltips |
|
var $container = $input.parent(); |
|
$container.tooltip('destroy'); |
|
$input.addClass('error'); |
|
$container.attr('title', msg); |
|
$container.tooltip({placement: 'bottom', trigger: 'manual'}); |
|
$container.tooltip('show'); |
|
} |
|
}); |
|
}, |
|
|
|
onPasswordByTalkChange: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
var $checkbox = $li.find('.passwordByTalkCheckbox'); |
|
$checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); |
|
|
|
var sendPasswordByTalk = false; |
|
if($checkbox.is(':checked')) { |
|
sendPasswordByTalk = true; |
|
} |
|
|
|
this.model.saveLinkShare({ |
|
sendPasswordByTalk: sendPasswordByTalk, |
|
cid: shareId |
|
}, { |
|
success: function() { |
|
$checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); |
|
}, |
|
error: function(obj, msg) { |
|
OC.Notification.showTemporary(t('core', 'Unable to toggle this option')); |
|
$checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); |
|
} |
|
}); |
|
}, |
|
|
|
onAllowPublicEditingChange: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
var $checkbox = $li.find('.publicEditingCheckbox'); |
|
$checkbox.siblings('.icon-loading-small').removeClass('hidden').addClass('inlineblock'); |
|
|
|
var permissions = OC.PERMISSION_READ; |
|
if($checkbox.is(':checked')) { |
|
permissions = OC.PERMISSION_UPDATE | OC.PERMISSION_READ; |
|
} |
|
|
|
this.model.saveLinkShare({ |
|
permissions: permissions, |
|
cid: shareId |
|
}, { |
|
success: function() { |
|
$checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); |
|
}, |
|
error: function(obj, msg) { |
|
OC.Notification.showTemporary(t('core', 'Unable to toggle this option')); |
|
$checkbox.siblings('.icon-loading-small').addClass('hidden').removeClass('inlineblock'); |
|
} |
|
}); |
|
}, |
|
|
|
|
|
onPublicUploadChange: function(event) { |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
var shareId = $li.data('share-id'); |
|
var permissions = event.currentTarget.value; |
|
this.model.saveLinkShare({ |
|
permissions: permissions, |
|
cid: shareId |
|
}); |
|
}, |
|
|
|
showNoteForm: function(event) { |
|
event.preventDefault(); |
|
event.stopPropagation(); |
|
var self = this; |
|
var $element = $(event.target); |
|
var $li = $element.closest('li[data-share-id]'); |
|
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'); |
|
|
|
$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 |
|
}); |
|
}, |
|
|
|
render: function() { |
|
this.$el.find('.has-tooltip').tooltip(); |
|
|
|
// reset previously set passwords |
|
this.password = ''; |
|
|
|
var linkShareTemplate = this.template(); |
|
var resharingAllowed = this.model.sharePermissionPossible(); |
|
|
|
if(!resharingAllowed |
|
|| !this.showLink |
|
|| !this.configModel.isShareWithLinkAllowed()) |
|
{ |
|
var templateData = {shareAllowed: false}; |
|
if (!resharingAllowed) { |
|
// add message |
|
templateData.noSharingPlaceholder = t('core', 'Resharing is not allowed'); |
|
} |
|
this.$el.html(linkShareTemplate(templateData)); |
|
return this; |
|
} |
|
|
|
var publicUpload = |
|
this.model.isFolder() |
|
&& this.model.createPermissionPossible() |
|
&& this.configModel.isPublicUploadEnabled(); |
|
|
|
|
|
var publicEditingChecked = ''; |
|
if(this.model.isPublicEditingAllowed()) { |
|
publicEditingChecked = 'checked="checked"'; |
|
} |
|
|
|
var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink'); |
|
var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true; |
|
var passwordPlaceholderInitial = this.configModel.get('enforcePasswordForPublicLink') |
|
? PASSWORD_PLACEHOLDER_MESSAGE : PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL; |
|
|
|
var publicEditable = |
|
!this.model.isFolder() |
|
&& this.model.updatePermissionPossible(); |
|
|
|
var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); |
|
|
|
// what if there is another date picker on that page? |
|
var minDate = new Date(); |
|
// min date should always be the next day |
|
minDate.setDate(minDate.getDate()+1); |
|
|
|
$.datepicker.setDefaults({ |
|
minDate: minDate |
|
}); |
|
|
|
this.$el.find('.datepicker').datepicker({dateFormat : 'dd-mm-yy'}); |
|
|
|
var minPasswordLength = 4 |
|
// password policy? |
|
if(OC.getCapabilities().password_policy && OC.getCapabilities().password_policy.minLength) { |
|
minPasswordLength = OC.getCapabilities().password_policy.minLength; |
|
} |
|
|
|
var popoverBase = { |
|
urlLabel: t('core', 'Link'), |
|
hideDownloadLabel: t('core', 'Hide download'), |
|
enablePasswordLabel: isPasswordEnforced ? t('core', 'Password protection enforced') : t('core', 'Password protect'), |
|
passwordLabel: t('core', 'Password'), |
|
passwordPlaceholderInitial: passwordPlaceholderInitial, |
|
publicUpload: publicUpload, |
|
publicEditing: publicEditable, |
|
publicEditingChecked: publicEditingChecked, |
|
publicEditingLabel: t('core', 'Allow editing'), |
|
mailPrivatePlaceholder: t('core', 'Email link to person'), |
|
mailButtonText: t('core', 'Send'), |
|
publicUploadRWLabel: t('core', 'Allow upload and editing'), |
|
publicUploadRLabel: t('core', 'Read only'), |
|
publicUploadWLabel: t('core', 'File drop (upload only)'), |
|
publicUploadRWValue: OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE, |
|
publicUploadRValue: OC.PERMISSION_READ, |
|
publicUploadWValue: OC.PERMISSION_CREATE, |
|
expireDateLabel: isExpirationEnforced ? t('core', 'Expiration date enforced') : t('core', 'Set expiration date'), |
|
expirationLabel: t('core', 'Expiration'), |
|
expirationDatePlaceholder: t('core', 'Expiration date'), |
|
isExpirationEnforced: isExpirationEnforced, |
|
isPasswordEnforced: isPasswordEnforced, |
|
defaultExpireDate: moment().add(1, 'day').format('DD-MM-YYYY'), // Can't expire today |
|
addNoteLabel: t('core', 'Note to recipient'), |
|
unshareLabel: t('core', 'Unshare'), |
|
unshareLinkLabel: t('core', 'Delete share link'), |
|
newShareLabel: t('core', 'Add another link'), |
|
}; |
|
|
|
var pendingPopover = { |
|
isPasswordEnforced: isPasswordEnforced, |
|
enforcedPasswordLabel: t('core', 'Password protection for links is mandatory'), |
|
passwordPlaceholder: passwordPlaceholderInitial, |
|
minPasswordLength: minPasswordLength, |
|
}; |
|
var pendingPopoverMenu = this.pendingPopoverMenuTemplate(_.extend({}, pendingPopover)) |
|
|
|
var linkShares = this.getShareeList(); |
|
if(_.isArray(linkShares)) { |
|
for (var i = 0; i < linkShares.length; i++) { |
|
var social = []; |
|
OC.Share.Social.Collection.each(function (model) { |
|
var url = model.get('url'); |
|
url = url.replace('{{reference}}', linkShares[i].shareLinkURL); |
|
social.push({ |
|
url: url, |
|
label: t('core', 'Share to {name}', {name: model.get('name')}), |
|
name: model.get('name'), |
|
iconClass: model.get('iconClass'), |
|
newWindow: model.get('newWindow') |
|
}); |
|
}); |
|
var popover = this.getPopoverObject(linkShares[i]) |
|
linkShares[i].popoverMenu = this.popoverMenuTemplate(_.extend({}, popoverBase, popover, {social: social})); |
|
linkShares[i].pendingPopoverMenu = pendingPopoverMenu |
|
} |
|
} |
|
|
|
this.$el.on('beforeHide', function() { |
|
this.onMenuhide() |
|
}.bind(this)); |
|
|
|
this.$el.html(linkShareTemplate({ |
|
linkShares: linkShares, |
|
shareAllowed: true, |
|
nolinkShares: linkShares.length === 0, |
|
newShareLabel: t('core', 'Share link'), |
|
newShareTitle: t('core', 'New share link'), |
|
pendingPopoverMenu: pendingPopoverMenu, |
|
showPending: this.showPending === this.newShareId, |
|
newShareId: this.newShareId, |
|
})); |
|
|
|
this.delegateEvents(); |
|
|
|
// new note autosize |
|
autosize(this.$el.find('.share-note-form .share-note')); |
|
|
|
return this; |
|
}, |
|
|
|
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'); |
|
var shareId = $li.data('share-id'); |
|
|
|
OC.showMenu(null, $menu); |
|
|
|
// focus the password if not set and enforced |
|
var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true; |
|
var haspassword = $menu.find('.linkPassText').val() !== ''; |
|
|
|
if (!haspassword && isPasswordEnabledByDefault) { |
|
$menu.find('.linkPassText').focus(); |
|
} |
|
}, |
|
|
|
onMenuhide: function() { |
|
if (this.hasPasswordChanged) { |
|
var shareId = this.hasPasswordChanged |
|
var target = this.$el.find('li[data-share-id=' + shareId + '] #linkPassText-' + shareId); |
|
console.debug('Force saving password for share number ', shareId) |
|
this.onPasswordEntered({ target: target }) |
|
} |
|
}, |
|
|
|
/** |
|
* @returns {Function} from Handlebars |
|
* @private |
|
*/ |
|
template: function () { |
|
return OC.Share.Templates['sharedialoglinkshareview']; |
|
}, |
|
|
|
/** |
|
* renders the popover template and returns the resulting HTML |
|
* |
|
* @param {Object} data |
|
* @returns {string} |
|
*/ |
|
popoverMenuTemplate: function(data) { |
|
return OC.Share.Templates['sharedialoglinkshareview_popover_menu'](data); |
|
}, |
|
|
|
/** |
|
* renders the pending popover template and returns the resulting HTML |
|
* |
|
* @param {Object} data |
|
* @returns {string} |
|
*/ |
|
pendingPopoverMenuTemplate: function(data) { |
|
return OC.Share.Templates['sharedialoglinkshareview_popover_menu_pending'](data); |
|
}, |
|
|
|
onPopUpClick: function(event) { |
|
event.preventDefault(); |
|
event.stopPropagation(); |
|
|
|
var url = $(event.currentTarget).data('url'); |
|
var newWindow = $(event.currentTarget).data('window'); |
|
$(event.currentTarget).tooltip('hide'); |
|
if (url) { |
|
if (newWindow === true) { |
|
var width = 600; |
|
var height = 400; |
|
var left = (screen.width / 2) - (width / 2); |
|
var top = (screen.height / 2) - (height / 2); |
|
|
|
window.open(url, 'name', 'width=' + width + ', height=' + height + ', top=' + top + ', left=' + left); |
|
} else { |
|
window.location.href = url; |
|
} |
|
} |
|
}, |
|
|
|
onExpireDateChange: function(event) { |
|
var $element = $(event.target); |
|
var li = $element.closest('li[data-share-id]'); |
|
var shareId = li.data('share-id'); |
|
var expirationDatePicker = '#expirationDateContainer-' + shareId; |
|
var datePicker = $(expirationDatePicker); |
|
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 maxDate = $element.data('max-date'); |
|
var expirationDatePicker = '#expirationDatePicker-' + shareId; |
|
var self = this; |
|
|
|
$(expirationDatePicker).datepicker({ |
|
dateFormat : 'dd-mm-yy', |
|
onSelect: function (expireDate) { |
|
self.setExpirationDate(expireDate, shareId); |
|
}, |
|
maxDate: maxDate |
|
}); |
|
$(expirationDatePicker).datepicker('show'); |
|
$(expirationDatePicker).focus(); |
|
|
|
}, |
|
|
|
setExpirationDate: function(expireDate, shareId) { |
|
this.model.saveLinkShare({expireDate: expireDate, cid: shareId}); |
|
}, |
|
|
|
onChangeExpirationDate: function(event) { |
|
var $element = $(event.target); |
|
var expireDate = $element.val(); |
|
var li = $element.closest('li[data-share-id]'); |
|
var shareId = li.data('share-id'); |
|
var expirationDatePicker = '#expirationDatePicker-' + shareId; |
|
|
|
this.setExpirationDate(expireDate, shareId); |
|
$(expirationDatePicker).datepicker('hide'); |
|
}, |
|
|
|
/** |
|
* get an array of sharees' share properties |
|
* |
|
* @returns {Array} |
|
*/ |
|
getShareeList: function() { |
|
var shares = this.model.get('linkShares'); |
|
|
|
if(!this.model.hasLinkShares()) { |
|
return []; |
|
} |
|
|
|
var list = []; |
|
for(var index = 0; index < shares.length; index++) { |
|
var share = this.getShareeObject(index); |
|
// first empty {} is necessary, otherwise we get in trouble |
|
// with references |
|
list.push(_.extend({}, share)); |
|
} |
|
|
|
return list; |
|
}, |
|
|
|
/** |
|
* |
|
* @param {OC.Share.Types.ShareInfo} shareInfo |
|
* @returns {object} |
|
*/ |
|
getShareeObject: function(shareIndex) { |
|
var share = this.model.get('linkShares')[shareIndex]; |
|
|
|
return _.extend({}, share, { |
|
cid: share.id, |
|
shareAllowed: true, |
|
linkShareLabel: share.label ? share.label : t('core', 'Share link'), |
|
popoverMenu: {}, |
|
shareLinkURL: share.url, |
|
newShareTitle: t('core', 'New share link'), |
|
copyLabel: t('core', 'Copy link'), |
|
showPending: this.showPending === share.id, |
|
linkShareCreationDate: t('core', 'Created on {time}', { time: moment(share.stime * 1000).format('LLLL') }) |
|
}) |
|
}, |
|
|
|
getPopoverObject: function(share) { |
|
var publicUploadRWChecked = ''; |
|
var publicUploadRChecked = ''; |
|
var publicUploadWChecked = ''; |
|
|
|
switch (this.model.linkSharePermissions(share.id)) { |
|
case OC.PERMISSION_READ: |
|
publicUploadRChecked = 'checked'; |
|
break; |
|
case OC.PERMISSION_CREATE: |
|
publicUploadWChecked = 'checked'; |
|
break; |
|
case OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE: |
|
publicUploadRWChecked = 'checked'; |
|
break; |
|
} |
|
|
|
var isPasswordSet = !!share.password; |
|
var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true; |
|
var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink'); |
|
var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced'); |
|
var defaultExpireDays = this.configModel.get('defaultExpireDate'); |
|
var hasExpireDate = !!share.expiration || isExpirationEnforced; |
|
|
|
var expireDate; |
|
if (hasExpireDate) { |
|
expireDate = moment(share.expiration, 'YYYY-MM-DD').format('DD-MM-YYYY'); |
|
} |
|
|
|
var isTalkEnabled = OC.appswebroots['spreed'] !== undefined; |
|
var sendPasswordByTalk = share.sendPasswordByTalk; |
|
|
|
var hideDownload = share.hideDownload; |
|
|
|
var maxDate = null; |
|
|
|
if(hasExpireDate) { |
|
if(isExpirationEnforced) { |
|
// TODO: hack: backend returns string instead of integer |
|
var shareTime = share.stime; |
|
if (_.isNumber(shareTime)) { |
|
shareTime = new Date(shareTime * 1000); |
|
} |
|
if (!shareTime) { |
|
shareTime = new Date(); // now |
|
} |
|
shareTime = OC.Util.stripTime(shareTime).getTime(); |
|
maxDate = new Date(shareTime + defaultExpireDays * 24 * 3600 * 1000); |
|
} |
|
} |
|
|
|
return { |
|
cid: share.id, |
|
shareLinkURL: share.url, |
|
passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE, |
|
isPasswordSet: isPasswordSet || isPasswordEnabledByDefault || isPasswordEnforced, |
|
showPasswordByTalkCheckBox: isTalkEnabled && isPasswordSet, |
|
passwordByTalkLabel: t('core', 'Password protect by Talk'), |
|
isPasswordByTalkSet: sendPasswordByTalk, |
|
publicUploadRWChecked: publicUploadRWChecked, |
|
publicUploadRChecked: publicUploadRChecked, |
|
publicUploadWChecked: publicUploadWChecked, |
|
hasExpireDate: hasExpireDate, |
|
expireDate: expireDate, |
|
shareNote: share.note, |
|
hasNote: share.note !== '', |
|
maxDate: maxDate, |
|
hideDownload: hideDownload, |
|
isExpirationEnforced: isExpirationEnforced, |
|
} |
|
}, |
|
|
|
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, { |
|
success: function() { |
|
$li.remove(); |
|
self.render() |
|
}, |
|
error: function() { |
|
$loading.addClass('hidden'); |
|
OC.Notification.showTemporary(t('core', 'Could not unshare')); |
|
} |
|
}); |
|
return false; |
|
}, |
|
|
|
|
|
}); |
|
|
|
OC.Share.ShareDialogLinkShareView = ShareDialogLinkShareView; |
|
|
|
})();
|
|
|