summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2018-10-29 13:58:14 +0100
committerDaniel Calviño Sánchez <danxuliu@gmail.com>2018-11-01 21:29:40 +0100
commit1bd6d39b39dd527ad095510173e9012afaafd3b0 (patch)
tree9b3cad7e1dc621498cf519c3aadc53247f0582e1 /core
parentfeb9f72e8bd4b5601974ec894d60e1bad3570dde (diff)
downloadnextcloud-server-1bd6d39b39dd527ad095510173e9012afaafd3b0.tar.gz
nextcloud-server-1bd6d39b39dd527ad095510173e9012afaafd3b0.zip
Migrate link shares to array
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Diffstat (limited to 'core')
-rw-r--r--core/js/share/sharedialoglinkshareview.handlebars27
-rw-r--r--core/js/share/sharedialoglinkshareview_popover_menu.handlebars17
-rw-r--r--core/js/share/sharedialogshareelistview.handlebars2
-rw-r--r--core/js/sharedialoglinkshareview.js421
-rw-r--r--core/js/shareitemmodel.js59
-rw-r--r--core/js/sharetemplates.js57
6 files changed, 366 insertions, 217 deletions
diff --git a/core/js/share/sharedialoglinkshareview.handlebars b/core/js/share/sharedialoglinkshareview.handlebars
index bc7051683a2..a8a6e795839 100644
--- a/core/js/share/sharedialoglinkshareview.handlebars
+++ b/core/js/share/sharedialoglinkshareview.handlebars
@@ -1,14 +1,19 @@
{{#if shareAllowed}}
<ul id="shareLink" class="shareWithList">
- <li data-share-id="{{cid}}">
- <div class="avatar icon-public-white"></div><span class="username" title="{{linkShareLabel}}">{{linkShareLabel}}</span>
- <span class="sharingOptionsGroup">
- <span class="shareOption">
- <span class="icon-loading-small hidden"></span>
- <input id="linkCheckbox-{{cid}}" {{#if isLinkShare}}checked="checked"{{/if}} type="checkbox" name="linkCheckbox" class="linkCheckbox permissions checkbox">
- <label for="linkCheckbox-{{cid}}">{{linkShareEnableLabel}}</label>
+ {{#if nolinkShares}}
+ <li>
+ <div class="avatar icon-public-white"></div>
+ <span class="username">{{newShareLabel}}</span>
+ <span class="sharingOptionsGroup">
+ <span class="icon icon-add new-share" title="{{newShareTitle}}"></span>
+ <span class="icon icon-loading-small hidden"></span>
</span>
- {{#if showMenu}}
+ </li>
+ {{/if}}
+ {{#each linkShares}}
+ <li data-share-id="{{cid}}">
+ <div class="avatar icon-public-white"></div><span class="username" title="{{linkShareLabel}}">{{linkShareLabel}}</span>
+ <span class="sharingOptionsGroup">
<div class="share-menu" tabindex="0"><span class="icon icon-more"></span>
{{#if showPending}}
{{{pendingPopoverMenu}}}
@@ -16,9 +21,9 @@
{{{popoverMenu}}}
{{/if}}
</div>
- {{/if}}
- </span>
- </li>
+ </span>
+ </li>
+ {{/each}}
</ul>
{{else}}
{{#if noSharingPlaceholder}}<input id="shareWith-{{cid}}" class="shareWithField" type="text" placeholder="{{noSharingPlaceholder}}" disabled="disabled"/>{{/if}}
diff --git a/core/js/share/sharedialoglinkshareview_popover_menu.handlebars b/core/js/share/sharedialoglinkshareview_popover_menu.handlebars
index baee3aa6630..6f504811be4 100644
--- a/core/js/share/sharedialoglinkshareview_popover_menu.handlebars
+++ b/core/js/share/sharedialoglinkshareview_popover_menu.handlebars
@@ -6,6 +6,13 @@
<span>{{copyLabel}}</span>
</a>
</li>
+ <li>
+ <a href="#" class="new-share">
+ <span class="icon-loading-small hidden"></span>
+ <span class="icon icon-add"></span>
+ <span>{{newShareTitle}}</span>
+ </a>
+ </li>
<li class="hidden linkTextMenu">
<span class="menuitem icon-link-text">
<input id="linkText-{{cid}}" class="linkText" type="text" readonly="readonly" value="{{shareLinkURL}}" />
@@ -70,14 +77,15 @@
<li>
<span class="shareOption menuitem">
<input id="expireDate-{{cid}}" type="checkbox" name="expirationDate" class="expireDate checkbox"
- {{#if hasExpireDate}}checked="checked"{{/if}} {{#if isExpirationEnforced}}disabled="disabled"{{/if}}" />
+ {{#if hasExpireDate}}checked="checked"{{/if}} {{#if isExpirationEnforced}}disabled="disabled"{{/if}} />
<label for="expireDate-{{cid}}">{{expireDateLabel}}</label>
</span>
</li>
<li class="{{#unless hasExpireDate}}hidden{{/unless}}">
<span class="menuitem icon-expiredate expirationDateContainer-{{cid}}">
<label for="expirationDatePicker-{{cid}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>
- <input id="expirationDatePicker-{{cid}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" />
+ <input id="expirationDatePicker-{{cid}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}"
+ value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" data-max-date="{{maxDate}}" />
</span>
</li>
<li>
@@ -88,7 +96,7 @@
<input type="button" class="share-note-delete icon-delete">
</a>
</li>
- <li class="share-note-form share-note-link hidden">
+ <li class="share-note-form share-note-link {{#unless hasNote}}hidden{{/unless}}">
<span class="menuitem icon-note">
<textarea class="share-note">{{shareNote}}</textarea>
<input type="submit" class="icon-confirm share-note-submit" value="" id="add-note-{{shareId}}" />
@@ -102,5 +110,8 @@
</a>
</li>
{{/each}}
+ <li>
+ <a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>
+ </li>
</ul>
</div>
diff --git a/core/js/share/sharedialogshareelistview.handlebars b/core/js/share/sharedialogshareelistview.handlebars
index a95949c8157..dc2496daaa8 100644
--- a/core/js/share/sharedialogshareelistview.handlebars
+++ b/core/js/share/sharedialogshareelistview.handlebars
@@ -15,7 +15,7 @@
</div>
</span>
</li>
- {{/each}}
+ {{/each}}
{{#each linkReshares}}
<li data-share-id="{{shareId}}" data-share-type="{{shareType}}">
<div class="avatar" data-username="{{shareInitiator}}"></div>
diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js
index 7603b058a96..6e3fce04dfe 100644
--- a/core/js/sharedialoglinkshareview.js
+++ b/core/js/sharedialoglinkshareview.js
@@ -43,8 +43,6 @@
showPending: false,
events: {
- // enable/disable
- 'change .linkCheckbox': 'onLinkCheckBoxChange',
// open menu
'click .share-menu .icon-more': 'onToggleMenu',
// hide download
@@ -67,7 +65,11 @@
// note
'click .share-add': 'showNoteForm',
'click .share-note-delete': 'deleteNote',
- 'click .share-note-submit': 'updateNote'
+ 'click .share-note-submit': 'updateNote',
+ // remove
+ 'click .unshare': 'onUnshare',
+ // new share
+ 'click .new-share': 'newShare',
},
initialize: function(options) {
@@ -89,10 +91,6 @@
view.render();
});
- this.model.on('change:linkShare', function() {
- view.render();
- });
-
if(!_.isUndefined(options.configModel)) {
this.configModel = options.configModel;
} else {
@@ -102,7 +100,6 @@
var clipboard = new Clipboard('.clipboardButton');
clipboard.on('success', function(e) {
var $menu = $(e.trigger);
- var $linkTextMenu = $menu.parent().next('li.linkTextMenu')
$menu.tooltip('hide')
.attr('data-original-title', t('core', 'Copied!'))
@@ -143,46 +140,44 @@
});
},
- onLinkCheckBoxChange: function() {
- var $checkBox = this.$el.find('.linkCheckbox');
- var $loading = $checkBox.siblings('.icon-loading-small');
+ newShare: function() {
+ var self = this;
+ var $loading = this.$el.find('.icon-loading-small').eq(0);
if(!$loading.hasClass('hidden')) {
+ // in process
return false;
}
-
- if($checkBox.is(':checked')) {
- if(this.configModel.get('enforcePasswordForPublicLink') === false) {
- $loading.removeClass('hidden');
- // this will create it
- this.model.saveLinkShare();
- $('.share-menu .icon-more').click();
- $('.share-menu .icon-more + .popovermenu .clipboardButton').click();
- } else {
- // force the rendering of the menu
- this.showPending = true;
- this.render()
- $('.share-menu .icon-more').click();
- $('.share-menu .icon-more + .popovermenu input:eq(1)').focus()
- }
- } else {
- if (this.model.get('linkShare').isLinkShare) {
- $loading.removeClass('hidden');
- this.model.removeLinkShare();
- } else {
- this.showPending = false;
- this.render()
+ // hide all icons and show loading
+ this.$el.find('.icon').addClass('hidden');
+ $loading.removeClass('hidden');
+
+ this.model.saveLinkShare({}, {
+ success: function() {
+ $loading.addClass('hidden');
+ self.$el.find('.icon').removeClass('hidden');
+ self.render();
+ },
+ error: function(obj, msg) {
+ OC.Notification.showTemporary(t('core', 'Unable to create a link share'));
+ $loading.addClass('hidden');
+ self.$el.find('.icon').removeClass('hidden');
}
- }
+ })
},
- onLinkTextClick: function() {
- var $el = this.$el.find('.linkText');
+ 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() {
- var $checkbox = this.$('.hideDownloadCheckbox');
+ 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;
@@ -191,41 +186,57 @@
}
this.model.saveLinkShare({
- hideDownload: hideDownload
+ 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() {
- this.$el.find('.linkPass').slideToggle(OC.menuSpeed);
- this.$el.find('.linkPassMenu').toggleClass('hidden');
- if(!this.$el.find('.showPasswordCheckbox').is(':checked')) {
+ 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: ''
+ password: '',
+ cid: shareId
});
} else {
if (!OC.Util.isIE()) {
- this.$el.find('.linkPassText').focus();
+ $li.find('.linkPassText').focus();
}
}
},
onPasswordKeyUp: function(event) {
if(event.keyCode === 13) {
- this.onPasswordEntered();
+ this.onPasswordEntered(event);
}
},
- onPasswordEntered: function() {
- var $loading = this.$el.find('.linkPassMenu .icon-loading-small');
+ 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 = this.$el.find('.linkPassText');
+ var $input = $li.find('.linkPassText');
$input.removeClass('error');
var password = $input.val();
- if (this.$el.find('.linkPassText').attr('placeholder') === PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL) {
+ 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) {
@@ -244,7 +255,8 @@
.addClass('inlineblock');
this.model.saveLinkShare({
- password: password
+ password: password,
+ cid: shareId
}, {
complete: function(model) {
$loading.removeClass('inlineblock').addClass('hidden');
@@ -260,8 +272,11 @@
});
},
- onAllowPublicEditingChange: function() {
- var $checkbox = this.$('.publicEditingCheckbox');
+ 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;
@@ -270,15 +285,28 @@
}
this.model.saveLinkShare({
- permissions: permissions
+ 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(e) {
- var permissions = e.currentTarget.value;
+ 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
+ permissions: permissions,
+ cid: shareId
});
},
@@ -386,46 +414,21 @@
&& this.model.createPermissionPossible()
&& this.configModel.isPublicUploadEnabled();
- var publicUploadRWChecked = '';
- var publicUploadRChecked = '';
- var publicUploadWChecked = '';
-
- switch (this.model.linkSharePermissions()) {
- 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 publicEditingChecked = '';
if(this.model.isPublicEditingAllowed()) {
publicEditingChecked = 'checked="checked"';
}
- var isLinkShare = this.model.get('linkShare').isLinkShare;
- var isPasswordSet = !!this.model.get('linkShare').password;
var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink');
var isPasswordEnabledByDefault = this.configModel.get('enableLinkPasswordByDefault') === true;
- var showPasswordCheckBox = isLinkShare
- && ( !this.configModel.get('enforcePasswordForPublicLink')
- || !this.model.get('linkShare').password);
var passwordPlaceholderInitial = this.configModel.get('enforcePasswordForPublicLink')
? PASSWORD_PLACEHOLDER_MESSAGE : PASSWORD_PLACEHOLDER_MESSAGE_OPTIONAL;
- var showHideDownloadCheckbox = !this.model.isFolder();
- var hideDownload = this.model.get('linkShare').hideDownload;
-
var publicEditable =
!this.model.isFolder()
- && isLinkShare
&& this.model.updatePermissionPossible();
- var link = this.model.get('linkShare').link;
var social = [];
OC.Share.Social.Collection.each(function(model) {
var url = model.get('url');
@@ -439,60 +442,28 @@
newWindow: model.get('newWindow')
});
});
-
- var defaultExpireDays = this.configModel.get('defaultExpireDate');
var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced');
- var hasExpireDate = !!this.model.get('linkShare').expiration || isExpirationEnforced;
-
- var expireDate;
- if (hasExpireDate) {
- expireDate = moment(this.model.get('linkShare').expiration, 'YYYY-MM-DD').format('DD-MM-YYYY');
- }
-
+
// what if there is another date picker on that page?
var minDate = new Date();
- var maxDate = null;
// min date should always be the next day
minDate.setDate(minDate.getDate()+1);
- if(hasExpireDate) {
- if(isExpirationEnforced) {
- // TODO: hack: backend returns string instead of integer
- var shareTime = this.model.get('linkShare').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);
- }
- }
$.datepicker.setDefaults({
- minDate: minDate,
- maxDate: maxDate
+ minDate: minDate
});
this.$el.find('.datepicker').datepicker({dateFormat : 'dd-mm-yy'});
- var popover = this.popoverMenuTemplate({
- cid: this.model.get('linkShare').id,
+ var popoverBase = {
copyLabel: t('core', 'Copy link'),
social: social,
-
- shareLinkURL: this.model.get('linkShare').link,
urlLabel: t('core', 'Link'),
- showHideDownloadCheckbox: showHideDownloadCheckbox,
- hideDownload: hideDownload,
hideDownloadLabel: t('core', 'Hide download'),
enablePasswordLabel: t('core', 'Password protect'),
passwordLabel: t('core', 'Password'),
- passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE,
passwordPlaceholderInitial: passwordPlaceholderInitial,
- isPasswordSet: isPasswordSet || isPasswordEnabledByDefault || isPasswordEnforced,
- showPasswordCheckBox: showPasswordCheckBox,
- publicUpload: publicUpload && isLinkShare,
+ publicUpload: publicUpload,
publicEditing: publicEditable,
publicEditingChecked: publicEditingChecked,
publicEditingLabel: t('core', 'Allow editing'),
@@ -504,41 +475,40 @@
publicUploadRWValue: OC.PERMISSION_UPDATE | OC.PERMISSION_CREATE | OC.PERMISSION_READ | OC.PERMISSION_DELETE,
publicUploadRValue: OC.PERMISSION_READ,
publicUploadWValue: OC.PERMISSION_CREATE,
- publicUploadRWChecked: publicUploadRWChecked,
- publicUploadRChecked: publicUploadRChecked,
- publicUploadWChecked: publicUploadWChecked,
expireDateLabel: t('core', 'Set expiration date'),
expirationLabel: t('core', 'Expiration'),
expirationDatePlaceholder: t('core', 'Expiration date'),
- hasExpireDate: hasExpireDate,
isExpirationEnforced: isExpirationEnforced,
isPasswordEnforced: isPasswordEnforced,
- expireDate: expireDate,
defaultExpireDate: moment().add(1, 'day').format('DD-MM-YYYY'), // Can't expire today
- shareNote: this.model.get('linkShare').note,
addNoteLabel: t('core', 'Note to recipient'),
- });
+ unshareLabel: t('core', 'Unshare'),
+ newShareLabel: t('core', 'New share link'),
+ };
- var pendingPopover = this.pendingPopoverMenuTemplate({
- cid: this.model.get('linkShare').id,
+ var pendingPopoverBase = {
enablePasswordLabel: t('core', 'Password protect'),
passwordLabel: t('core', 'Password'),
- passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE,
passwordPlaceholderInitial: passwordPlaceholderInitial,
- showPasswordCheckBox: showPasswordCheckBox,
isPasswordEnforced: isPasswordEnforced,
- });
+ };
+
+ var linkShares = this.getShareeList();
+ if(_.isArray(linkShares)) {
+ for (var i = 0; i < linkShares.length; i++) {
+ var popover = this.getPopoverObject(linkShares[i])
+ var pendingPopover = this.getPendingPopoverObject(linkShares[i])
+ linkShares[i].popoverMenu = this.popoverMenuTemplate(_.extend({}, popoverBase, popover));
+ linkShares[i].pendingPopoverMenu = this.pendingPopoverMenuTemplate(_.extend({}, pendingPopoverBase, pendingPopover));
+ }
+ }
this.$el.html(linkShareTemplate({
- cid: this.model.get('linkShare').id,
+ linkShares: linkShares,
shareAllowed: true,
- isLinkShare: isLinkShare,
- linkShareLabel: t('core', 'Share link'),
- linkShareEnableLabel: t('core', 'Enable'),
- popoverMenu: popover,
- pendingPopoverMenu: pendingPopover,
- showMenu: isLinkShare || this.showPending,
- showPending: this.showPending && !isLinkShare
+ nolinkShares: linkShares.length === 0,
+ newShareLabel: t('core', 'Share link'),
+ newShareTitle: t('core', 'New share link'),
}));
this.delegateEvents();
@@ -555,9 +525,10 @@
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);
- this._menuOpen = $li.data('share-id');
+ this._menuOpen = shareId;
},
/**
@@ -635,24 +606,188 @@
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);
- }
+ self.setExpirationDate(expireDate, shareId);
+ },
+ maxDate: maxDate
});
$(expirationDatePicker).datepicker('show');
$(expirationDatePicker).focus();
},
- setExpirationDate: function(expireDate) {
- this.model.saveLinkShare({expireDate: expireDate});
+ setExpirationDate: function(expireDate, shareId) {
+ this.model.saveLinkShare({expireDate: expireDate, cid: shareId});
},
+ /**
+ * 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: {},
+ pendingPopoverMenu: {},
+ showPending: this.showPending
+ })
+ },
+
+ 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 showPasswordCheckBox = !this.configModel.get('enforcePasswordForPublicLink') || !share.password;
+ var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced');
+ var defaultExpireDays = this.configModel.get('defaultExpireDate');
+ var hasExpireDate = !!share.expiration || isExpirationEnforced;
+ var hasExpireDate = false;
+
+ var expireDate;
+ if (hasExpireDate) {
+ expireDate = moment(share.expiration, 'YYYY-MM-DD').format('DD-MM-YYYY');
+ }
+
+ var showHideDownloadCheckbox = !this.model.isFolder();
+ 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,
+ showPasswordCheckBox: showPasswordCheckBox,
+ publicUploadRWChecked: publicUploadRWChecked,
+ publicUploadRChecked: publicUploadRChecked,
+ publicUploadWChecked: publicUploadWChecked,
+ hasExpireDate: hasExpireDate,
+ expireDate: expireDate,
+ shareNote: share.note,
+ hasNote: share.note !== '',
+ maxDate: maxDate,
+ showHideDownloadCheckbox: showHideDownloadCheckbox,
+ hideDownload: hideDownload,
+ newShareTitle: t('core', 'New share link'),
+ }
+ },
+
+ getPendingPopoverObject: function(share) {
+ var isPasswordSet = !!share.password;
+ var showPasswordCheckBox = !this.configModel.get('enforcePasswordForPublicLink') || !share.password;
+ var isPasswordEnforced = this.configModel.get('enforcePasswordForPublicLink');
+
+ return {
+ cid: share.id,
+ enablePasswordLabel: t('core', 'Password protect'),
+ passwordLabel: t('core', 'Password'),
+ passwordPlaceholder: isPasswordSet ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE,
+ showPasswordCheckBox: showPasswordCheckBox,
+ isPasswordEnforced: isPasswordEnforced,
+ }
+
+ },
+
+ 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;
diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js
index 3f92a8591e5..ce7bc56ab8a 100644
--- a/core/js/shareitemmodel.js
+++ b/core/js/shareitemmodel.js
@@ -16,11 +16,9 @@
/**
* @typedef {object} OC.Share.Types.LinkShareInfo
- * @property {bool} isLinkShare
* @property {string} token
* @property {bool} hideDownload
* @property {string|null} password
- * @property {string} link
* @property {number} permissions
* @property {Date} expiration
* @property {number} stime share time
@@ -100,7 +98,7 @@
defaults: {
allowPublicUploadStatus: false,
permissions: 0,
- linkShare: {}
+ linkShares: []
},
/**
@@ -130,8 +128,11 @@
delete attributes.expiration;
}
- if (this.get('linkShare') && this.get('linkShare').isLinkShare) {
- shareId = this.get('linkShare').id;
+ var linkShares = this.get('linkShares');
+ var shareIndex = _.findIndex(linkShares, function(share) {return share.id === attributes.cid})
+
+ if (linkShares.length > 0 && shareIndex !== -1) {
+ shareId = linkShares[shareIndex].id;
// note: update can only update a single value at a time
call = this.updateShare(shareId, attributes, options);
@@ -151,12 +152,6 @@
return call;
},
- removeLinkShare: function() {
- if (this.get('linkShare')) {
- return this.removeShare(this.get('linkShare').id);
- }
- },
-
addShare: function(attributes, options) {
var shareType = attributes.shareType;
attributes = _.extend({}, attributes);
@@ -316,13 +311,13 @@
},
/**
- * Returns whether this item has a link share
+ * Returns whether this item has link shares
*
* @return {bool} true if a link share exists, false otherwise
*/
- hasLinkShare: function() {
- var linkShare = this.get('linkShare');
- if (linkShare && linkShare.isLinkShare) {
+ hasLinkShares: function() {
+ var linkShares = this.get('linkShares');
+ if (linkShares && linkShares.length > 0) {
return true;
}
return false;
@@ -630,12 +625,16 @@
/**
* @returns {int}
*/
- linkSharePermissions: function() {
- if (!this.hasLinkShare()) {
+ linkSharePermissions: function(shareId) {
+ var linkShares = this.get('linkShares');
+ var shareIndex = _.findIndex(linkShares, function(share) {return share.id === shareId})
+
+ if (!this.hasLinkShares()) {
return -1;
- } else {
- return this.get('linkShare').permissions;
+ } else if (linkShares.length > 0 && shareIndex !== -1) {
+ return linkShares[shareIndex].permissions;
}
+ return -1;
},
_getUrl: function(base, params) {
@@ -831,7 +830,7 @@
this._legacyFillCurrentShares(shares);
- var linkShare = { isLinkShare: false };
+ var linkShares = [];
// filter out the share by link
shares = _.reject(shares,
/**
@@ -844,7 +843,7 @@
|| share.item_source === this.get('itemSource'));
if (isShareLink) {
- /*
+ /**
* Ignore reshared link shares for now
* FIXME: Find a way to display properly
*/
@@ -864,20 +863,12 @@
} else {
link += OC.generateUrl('/s/') + share.token;
}
- linkShare = {
- isLinkShare: true,
- id: share.id,
- token: share.token,
+ linkShares.push(_.extend({}, share, {
// hide_download is returned as an int, so force it
// to a boolean
hideDownload: !!share.hide_download,
- password: share.share_with,
- link: link,
- permissions: share.permissions,
- // currently expiration is only effective for link shares.
- expiration: share.expiration,
- stime: share.stime
- };
+ password: share.share_with
+ }));
return share;
}
@@ -888,7 +879,7 @@
return {
reshare: data.reshare,
shares: shares,
- linkShare: linkShare,
+ linkShares: linkShares,
permissions: permissions,
allowPublicUploadStatus: allowPublicUploadStatus,
allowPublicEditingStatus: allowPublicEditingStatus,
@@ -924,7 +915,7 @@
getShareTypes: function() {
var result;
result = _.pluck(this.getSharesWithCurrentItem(), 'share_type');
- if (this.hasLinkShare()) {
+ if (this.hasLinkShares()) {
result.push(OC.Share.SHARE_TYPE_LINK);
}
return _.uniq(result);
diff --git a/core/js/sharetemplates.js b/core/js/sharetemplates.js
index 0c1fee37455..dfda54a853e 100644
--- a/core/js/sharetemplates.js
+++ b/core/js/sharetemplates.js
@@ -1,33 +1,32 @@
(function() {
var template = Handlebars.template, templates = OC.Share.Templates = OC.Share.Templates || {};
templates['sharedialoglinkshareview'] = template({"1":function(container,depth0,helpers,partials,data) {
+ var stack1, alias1=depth0 != null ? depth0 : (container.nullContext || {});
+
+ return "<ul id=\"shareLink\" class=\"shareWithList\">\n"
+ + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.nolinkShares : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
+ + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.linkShares : depth0),{"name":"each","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
+ + "</ul>\n";
+},"2":function(container,depth0,helpers,partials,data) {
+ var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;
+
+ return " <li>\n <div class=\"avatar icon-public-white\"></div>\n <span class=\"username\">"
+ + alias4(((helper = (helper = helpers.newShareLabel || (depth0 != null ? depth0.newShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newShareLabel","hash":{},"data":data}) : helper)))
+ + "</span>\n <span class=\"sharingOptionsGroup\">\n <span class=\"icon icon-add new-share\" title=\""
+ + alias4(((helper = (helper = helpers.newShareTitle || (depth0 != null ? depth0.newShareTitle : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newShareTitle","hash":{},"data":data}) : helper)))
+ + "\"></span>\n <span class=\"icon icon-loading-small hidden\"></span>\n </span>\n </li>\n";
+},"4":function(container,depth0,helpers,partials,data) {
var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;
- return "<ul id=\"shareLink\" class=\"shareWithList\">\n <li data-share-id=\""
+ return " <li data-share-id=\""
+ alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper)))
- + "\">\n <div class=\"avatar icon-public-white\"></div><span class=\"username\" title=\""
+ + "\">\n <div class=\"avatar icon-public-white\"></div><span class=\"username\" title=\""
+ alias4(((helper = (helper = helpers.linkShareLabel || (depth0 != null ? depth0.linkShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareLabel","hash":{},"data":data}) : helper)))
+ "\">"
+ alias4(((helper = (helper = helpers.linkShareLabel || (depth0 != null ? depth0.linkShareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareLabel","hash":{},"data":data}) : helper)))
- + "</span>\n <span class=\"sharingOptionsGroup\">\n <span class=\"shareOption\">\n <span class=\"icon-loading-small hidden\"></span>\n <input id=\"linkCheckbox-"
- + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper)))
- + "\" "
- + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isLinkShare : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + " type=\"checkbox\" name=\"linkCheckbox\" class=\"linkCheckbox permissions checkbox\">\n <label for=\"linkCheckbox-"
- + alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper)))
- + "\">"
- + alias4(((helper = (helper = helpers.linkShareEnableLabel || (depth0 != null ? depth0.linkShareEnableLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"linkShareEnableLabel","hash":{},"data":data}) : helper)))
- + "</label>\n </span>\n"
- + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showMenu : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + " </span>\n </li>\n</ul>\n";
-},"2":function(container,depth0,helpers,partials,data) {
- return "checked=\"checked\"";
-},"4":function(container,depth0,helpers,partials,data) {
- var stack1;
-
- return " <div class=\"share-menu\" tabindex=\"0\"><span class=\"icon icon-more\"></span>\n"
- + ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.showPending : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.program(7, data, 0),"data":data})) != null ? stack1 : "")
- + " </div>\n";
+ + "</span>\n <span class=\"sharingOptionsGroup\">\n <div class=\"share-menu\" tabindex=\"0\"><span class=\"icon icon-more\"></span>\n"
+ + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.showPending : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.program(7, data, 0),"data":data})) != null ? stack1 : "")
+ + " </div>\n </span>\n </li>\n";
},"5":function(container,depth0,helpers,partials,data) {
var stack1, helper;
@@ -169,6 +168,8 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont
+ alias4(((helper = (helper = helpers.shareLinkURL || (depth0 != null ? depth0.shareLinkURL : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareLinkURL","hash":{},"data":data}) : helper)))
+ "\">\n <span class=\"icon icon-clippy\" ></span>\n <span>"
+ alias4(((helper = (helper = helpers.copyLabel || (depth0 != null ? depth0.copyLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"copyLabel","hash":{},"data":data}) : helper)))
+ + "</span>\n </a>\n </li>\n <li>\n <a href=\"#\" class=\"new-share\">\n <span class=\"icon-loading-small hidden\"></span>\n <span class=\"icon icon-add\"></span>\n <span>"
+ + alias4(((helper = (helper = helpers.newShareTitle || (depth0 != null ? depth0.newShareTitle : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"newShareTitle","hash":{},"data":data}) : helper)))
+ "</span>\n </a>\n </li>\n <li class=\"hidden linkTextMenu\">\n <span class=\"menuitem icon-link-text\">\n <input id=\"linkText-"
+ alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper)))
+ "\" class=\"linkText\" type=\"text\" readonly=\"readonly\" value=\""
@@ -184,7 +185,7 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasExpireDate : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
+ " "
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isExpirationEnforced : depth0),{"name":"if","hash":{},"fn":container.program(9, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + "\" />\n <label for=\"expireDate-"
+ + " />\n <label for=\"expireDate-"
+ alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper)))
+ "\">"
+ alias4(((helper = (helper = helpers.expireDateLabel || (depth0 != null ? depth0.expireDateLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"expireDateLabel","hash":{},"data":data}) : helper)))
@@ -202,17 +203,23 @@ templates['sharedialoglinkshareview_popover_menu'] = template({"1":function(cont
+ alias4(((helper = (helper = helpers.cid || (depth0 != null ? depth0.cid : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"cid","hash":{},"data":data}) : helper)))
+ "\" class=\"datepicker\" type=\"text\" placeholder=\""
+ alias4(((helper = (helper = helpers.expirationDatePlaceholder || (depth0 != null ? depth0.expirationDatePlaceholder : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"expirationDatePlaceholder","hash":{},"data":data}) : helper)))
- + "\" value=\""
+ + "\"\n value=\""
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasExpireDate : depth0),{"name":"if","hash":{},"fn":container.program(13, data, 0),"inverse":container.program(15, data, 0),"data":data})) != null ? stack1 : "")
+ + "\" data-max-date=\""
+ + alias4(((helper = (helper = helpers.maxDate || (depth0 != null ? depth0.maxDate : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"maxDate","hash":{},"data":data}) : helper)))
+ "\" />\n </span>\n </li>\n <li>\n <a href=\"#\" class=\"share-add\">\n <span class=\"icon-loading-small hidden\"></span>\n <span class=\"icon icon-edit\"></span>\n <span>"
+ alias4(((helper = (helper = helpers.addNoteLabel || (depth0 != null ? depth0.addNoteLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"addNoteLabel","hash":{},"data":data}) : helper)))
- + "</span>\n <input type=\"button\" class=\"share-note-delete icon-delete\">\n </a>\n </li>\n <li class=\"share-note-form share-note-link hidden\">\n <span class=\"menuitem icon-note\">\n <textarea class=\"share-note\">"
+ + "</span>\n <input type=\"button\" class=\"share-note-delete icon-delete\">\n </a>\n </li>\n <li class=\"share-note-form share-note-link "
+ + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.hasNote : depth0),{"name":"unless","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
+ + "\">\n <span class=\"menuitem icon-note\">\n <textarea class=\"share-note\">"
+ alias4(((helper = (helper = helpers.shareNote || (depth0 != null ? depth0.shareNote : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareNote","hash":{},"data":data}) : helper)))
+ "</textarea>\n <input type=\"submit\" class=\"icon-confirm share-note-submit\" value=\"\" id=\"add-note-"
+ alias4(((helper = (helper = helpers.shareId || (depth0 != null ? depth0.shareId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shareId","hash":{},"data":data}) : helper)))
+ "\" />\n </span>\n </li>\n"
+ ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.social : depth0),{"name":"each","hash":{},"fn":container.program(17, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
- + " </ul>\n</div>\n";
+ + " <li>\n <a href=\"#\" class=\"unshare\"><span class=\"icon-loading-small hidden\"></span><span class=\"icon icon-delete\"></span><span>"
+ + alias4(((helper = (helper = helpers.unshareLabel || (depth0 != null ? depth0.unshareLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"unshareLabel","hash":{},"data":data}) : helper)))
+ + "</span></a>\n </li>\n </ul>\n</div>\n";
},"useData":true});
templates['sharedialoglinkshareview_popover_menu_pending'] = template({"1":function(container,depth0,helpers,partials,data) {
var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;