diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js
index 3764328a5d..800873cd63 100644
--- a/apps/files_sharing/js/app.js
+++ b/apps/files_sharing/js/app.js
@@ -8,7 +8,9 @@
*
*/
-OCA.Sharing = {};
+if (!OCA.Sharing) {
+ OCA.Sharing = {};
+}
OCA.Sharing.App = {
_inFileList: null,
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index 5a42604c86..db770ad150 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -8,103 +8,154 @@
*
*/
-$(document).ready(function() {
- if (!_.isUndefined(OC.Share) && !_.isUndefined(OCA.Files)) {
- // TODO: make a separate class for this or a hook or jQuery event ?
- if (OCA.Files.FileList) {
- var oldCreateRow = OCA.Files.FileList.prototype._createRow;
- OCA.Files.FileList.prototype._createRow = function(fileData) {
- var tr = oldCreateRow.apply(this, arguments);
- if (fileData.shareOwner) {
- tr.attr('data-share-owner', fileData.shareOwner);
- // user should always be able to rename a mount point
- if (fileData.isShareMountPoint) {
- tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE);
- tr.attr('data-reshare-permissions', fileData.permissions);
- }
+(function() {
+ if (!OCA.Sharing) {
+ OCA.Sharing = {};
+ }
+ OCA.Sharing.Util = {
+ initialize: function() {
+ if (!_.isUndefined(OC.Share) && !_.isUndefined(OCA.Files)) {
+ // TODO: make a separate class for this or a hook or jQuery event ?
+ if (OCA.Files.FileList) {
+ var oldCreateRow = OCA.Files.FileList.prototype._createRow;
+ OCA.Files.FileList.prototype._createRow = function(fileData) {
+ var tr = oldCreateRow.apply(this, arguments);
+ if (fileData.shareOwner) {
+ tr.attr('data-share-owner', fileData.shareOwner);
+ // user should always be able to rename a mount point
+ if (fileData.isShareMountPoint) {
+ tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE);
+ tr.attr('data-reshare-permissions', fileData.permissions);
+ }
+ }
+ return tr;
+ };
}
- return tr;
- };
- }
- // use delegate to catch the case with multiple file lists
- $('#content').delegate('#fileList', 'fileActionsReady',function(ev){
- // if no share action exists because the admin disabled sharing for this user
- // we create a share notification action to inform the user about files
- // shared with him otherwise we just update the existing share action.
- var fileList = ev.fileList;
- var $fileList = $(this);
- $fileList.find('[data-share-owner]').each(function() {
- var $tr = $(this);
- var $action;
- var owner;
- var message;
- var permissions = $tr.data('permissions');
- if(permissions & OC.PERMISSION_SHARE) {
- $action = $tr.find('[data-Action="Share"]');
- $action.addClass('permanent');
- owner = $tr.closest('tr').attr('data-share-owner');
- message = ' ' + t('files_sharing', 'Shared by {owner}', {owner: owner});
- $action.find('span').text(message);
- } else {
- var shareNotification = '' +
- ' ';
- $tr.find('.fileactions').append(function() {
- var owner = $(this).closest('tr').attr('data-share-owner');
- var shareBy = t('files_sharing', 'Shared by {owner}', {owner: owner});
- var $result = $(shareNotification + ' ' + shareBy + '');
- $result.on('click', function() {
- return false;
- });
- return $result;
+ // use delegate to catch the case with multiple file lists
+ $('#content').delegate('#fileList', 'fileActionsReady',function(ev){
+ // if no share action exists because the admin disabled sharing for this user
+ // we create a share notification action to inform the user about files
+ // shared with him otherwise we just update the existing share action.
+ var fileList = ev.fileList;
+ var $fileList = $(this);
+ $fileList.find('[data-share-owner]').each(function() {
+ var $tr = $(this);
+ var permissions = $tr.data('permissions');
+ if(permissions & OC.PERMISSION_SHARE) {
+ OC.Share.markFileAsShared($tr, true);
+ } else {
+ // TODO: make this work like/with OC.Share.markFileAsShared()
+ var shareNotification = '' +
+ ' ';
+ $tr.find('.fileactions').append(function() {
+ var owner = $(this).closest('tr').attr('data-share-owner');
+ var shareBy = t('files_sharing', 'Shared by {owner}', {owner: owner});
+ var $result = $(shareNotification + ' ' + shareBy + '');
+ $result.on('click', function() {
+ return false;
+ });
+ return $result;
+ });
+ }
});
- }
- });
- if (!OCA.Sharing.sharesLoaded){
- OC.Share.loadIcons('file', fileList);
- // assume that we got all shares, so switching directories
- // will not invalidate that list
- OCA.Sharing.sharesLoaded = true;
- }
- else{
- OC.Share.updateIcons('file', fileList);
- }
- });
+ if (!OCA.Sharing.sharesLoaded){
+ OC.Share.loadIcons('file', fileList);
+ // assume that we got all shares, so switching directories
+ // will not invalidate that list
+ OCA.Sharing.sharesLoaded = true;
+ }
+ else{
+ OC.Share.updateIcons('file', fileList);
+ }
+ });
- OCA.Files.fileActions.register(
- 'all',
- 'Share',
- OC.PERMISSION_SHARE,
- OC.imagePath('core', 'actions/share'),
- function(filename, context) {
+ OCA.Files.fileActions.register(
+ 'all',
+ 'Share',
+ OC.PERMISSION_SHARE,
+ OC.imagePath('core', 'actions/share'),
+ function(filename, context) {
- var $tr = context.$file;
- var itemType = 'file';
- if ($tr.data('type') === 'dir') {
- itemType = 'folder';
- }
- var possiblePermissions = $tr.data('reshare-permissions');
- if (_.isUndefined(possiblePermissions)) {
- possiblePermissions = $tr.data('permissions');
- }
+ var $tr = context.$file;
+ var itemType = 'file';
+ if ($tr.data('type') === 'dir') {
+ itemType = 'folder';
+ }
+ var possiblePermissions = $tr.data('reshare-permissions');
+ if (_.isUndefined(possiblePermissions)) {
+ possiblePermissions = $tr.data('permissions');
+ }
- var appendTo = $tr.find('td.filename');
- // Check if drop down is already visible for a different file
- if (OC.Share.droppedDown) {
- if ($tr.data('id') !== $('#dropdown').attr('data-item-source')) {
- OC.Share.hideDropDown(function () {
+ var appendTo = $tr.find('td.filename');
+ // Check if drop down is already visible for a different file
+ if (OC.Share.droppedDown) {
+ if ($tr.data('id') !== $('#dropdown').attr('data-item-source')) {
+ OC.Share.hideDropDown(function () {
+ $tr.addClass('mouseOver');
+ OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
+ });
+ } else {
+ OC.Share.hideDropDown();
+ }
+ } else {
$tr.addClass('mouseOver');
OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
+ }
+ $('#dropdown').on('sharesChanged', function(ev) {
+ // note: we only update the data attribute because updateIcon()
+ // is called automatically after this event
+ var userShares = ev.itemShares[OC.Share.SHARE_TYPE_USER] || [];
+ var groupShares = ev.itemShares[OC.Share.SHARE_TYPE_GROUP] || [];
+ var linkShares = ev.itemShares[OC.Share.SHARE_TYPE_LINK] || [];
+ var recipients = _.union(userShares, groupShares);
+ if (linkShares.length > 0) {
+ recipients.unshift(t('files_sharing', 'Public'));
+ }
+ // only update the recipients if they existed before
+ // (some file lists don't have them)
+ if (!_.isUndefined($tr.attr('data-share-recipients'))) {
+ // FIXME: use display names from users, we currently only got user ids
+ if (recipients.length) {
+ $tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients));
+ }
+ else {
+ $tr.attr('data-share-recipients', '');
+ }
+ }
});
- } else {
- OC.Share.hideDropDown();
- }
- } else {
- $tr.addClass('mouseOver');
- OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
+ });
}
- });
- }
+ },
+
+ /**
+ * Formats a recipient array to be displayed.
+ * The first four recipients will be shown and the
+ * other ones will be shown as "+x" where "x" is the number of
+ * remaining recipients.
+ *
+ * @param recipients recipients array
+ * @param count optional total recipients count (in case the array was shortened)
+ * @return formatted recipients display text
+ */
+ formatRecipients: function(recipients, count) {
+ var maxRecipients = 4;
+ var text;
+ if (!_.isNumber(count)) {
+ count = recipients.length;
+ }
+ text = _.first(recipients, maxRecipients).join(', ');
+ if (count > maxRecipients) {
+ text += ', +' + (count - maxRecipients);
+ }
+ return text;
+ }
+ };
+})();
+
+$(document).ready(function() {
+ OCA.Sharing.Util.initialize();
});
+
diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js
index ef1034ecfd..9cf74abf67 100644
--- a/apps/files_sharing/js/sharedfilelist.js
+++ b/apps/files_sharing/js/sharedfilelist.js
@@ -48,6 +48,9 @@
if (this._sharedWithUser) {
$tr.attr('data-share-owner', fileData.shares[0].ownerDisplayName);
}
+ if (fileData.recipientsDisplayName) {
+ $tr.attr('data-share-recipients', fileData.recipientsDisplayName);
+ }
return $tr;
},
@@ -179,15 +182,15 @@
// inside the same file object (by file id).
.reduce(function(memo, file) {
var data = memo[file.id];
- var counterPart = file.share.ownerDisplayName || file.share.targetDisplayName;
+ var recipient = file.share.targetDisplayName;
if (!data) {
data = memo[file.id] = file;
data.shares = [file.share];
// using a hash to make them unique,
// this is only a list to be displayed
- data.counterParts = {};
+ data.recipients = {};
// counter is cheaper than calling _.keys().length
- data.counterPartsCount = 0;
+ data.recipientsCount = 0;
data.mtime = file.share.stime;
}
else {
@@ -200,10 +203,14 @@
if (file.share.type === OC.Share.SHARE_TYPE_LINK) {
data.hasLinkShare = true;
- } else if (counterPart && data.counterPartsCount < 10) {
+ } else if (recipient) {
// limit counterparts for output
- data.counterParts[counterPart] = true;
- data.counterPartsCount++;
+ if (data.recipientsCount < 3) {
+ // only store the first ones, they will be the only ones
+ // displayed
+ data.recipients[recipient] = true;
+ }
+ data.recipientsCount++;
}
delete file.share;
@@ -213,14 +220,18 @@
.values()
// Clean up
.each(function(data) {
- // convert the counterParts map to a flat
+ // convert the recipients map to a flat
// array of sorted names
- data.counterParts = _.chain(data.counterParts).keys().sort().value();
+ data.recipients = _.chain(data.recipients).keys().sort().value();
if (data.hasLinkShare) {
- data.counterParts.unshift(t('files_sharing', 'link'));
+ data.recipients.unshift(t('files_sharing', 'Public'));
delete data.hasLinkShare;
}
- delete data.counterPartsCount;
+ data.recipientsDisplayName = OCA.Sharing.Util.formatRecipients(
+ data.recipients,
+ data.recipientsCount
+ );
+ delete data.recipientsCount;
})
// Sort by expected sort comparator
.sortBy(this._sortComparator)
diff --git a/core/js/share.js b/core/js/share.js
index 0c6d39e446..d802053176 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -56,20 +56,14 @@ OC.Share={
image = OC.imagePath('core', 'actions/public');
}
if (itemType !== 'file' && itemType !== 'folder') {
- $fileList.find('a.share[data-item="'+item+'"]').css('background', 'url('+image+') no-repeat center');
+ $('a.share[data-item="'+item+'"]').css('background', 'url('+image+') no-repeat center');
} else {
+ // TODO: ultimately this part should be moved to files_sharing app
var file = $fileList.find('tr[data-id="'+item+'"]');
var shareFolder = OC.imagePath('core', 'filetypes/folder-shared');
var img;
if (file.length > 0) {
- var type = file.data('type');
- if (type === 'dir') {
- file.children('.filename').css('background-image', 'url('+shareFolder+')');
- }
- var action = $(file).find('.fileactions .action[data-action="Share"]');
- img = action.find('img').attr('src', image);
- action.addClass('permanent');
- action.html(' '+t('core', 'Shared')+'').prepend(img);
+ this.markFileAsShared(file, true, image);
} else {
var dir = currentDir;
if (dir.length > 1) {
@@ -82,6 +76,7 @@ OC.Share={
var files = $fileList.find('.filename');
var i;
for (i = 0; i < actions.length; i++) {
+ // TODO: use this.markFileAsShared()
img = $(actions[i]).find('img');
if (img.attr('src') !== OC.imagePath('core', 'actions/public')) {
img.attr('src', image);
@@ -125,29 +120,9 @@ OC.Share={
if (itemType != 'file' && itemType != 'folder') {
$('a.share[data-item="'+itemSource+'"]').css('background', 'url('+image+') no-repeat center');
} else {
- var file = $('tr').filterAttr('data-id', String(itemSource));
- if (file.length > 0) {
- var type = file.data('type');
- var shareFolder = OC.imagePath('core', 'filetypes/folder');
- if (type === 'dir' && shares) {
- shareFolder = OC.imagePath('core', 'filetypes/folder-shared');
- file.children('.filename').css('background-image', 'url('+shareFolder+')');
- } else if (type === 'dir') {
- file.children('.filename').css('background-image', 'url('+shareFolder+')');
- }
- var action = $(file).find('.fileactions .action').filterAttr('data-action', 'Share');
- // in case of multiple lists/rows, there might be more than one visible
- action.each(function() {
- var action = $(this);
- var img = action.find('img').attr('src', image);
- if (shares) {
- action.addClass('permanent');
- action.html(' '+ escapeHTML(t('core', 'Shared'))+'').prepend(img);
- } else {
- action.removeClass('permanent');
- action.html(' '+ escapeHTML(t('core', 'Share'))+'').prepend(img);
- }
- });
+ var $tr = $('tr').filterAttr('data-id', String(itemSource));
+ if ($tr.length > 0) {
+ this.markFileAsShared($tr, shares, image);
}
}
if (shares) {
@@ -157,6 +132,59 @@ OC.Share={
delete OC.Share.statuses[itemSource];
}
},
+ /**
+ * Marks/unmarks a given file as shared
+ *
+ * @param $tr file element to mark as shared
+ * @param state true to mark as shared, false to unmark
+ * @param image image to use for the icon
+ */
+ markFileAsShared: function($tr, state, image) {
+ var action = $tr.find('.fileactions .action[data-action="Share"]');
+ var type = $tr.data('type');
+ var img = action.find('img');
+ var message;
+ var recipients;
+ var owner;
+ var shareFolderIcon;
+ if (type === 'dir' && state) {
+ shareFolderIcon = OC.imagePath('core', 'filetypes/folder-shared');
+ $tr.children('.filename').css('background-image', 'url(' + shareFolderIcon + ')');
+ } else if (type === 'dir') {
+ shareFolderIcon = OC.imagePath('core', 'filetypes/folder');
+ $tr.children('.filename').css('background-image', 'url(' + shareFolderIcon + ')');
+ }
+ if (state) {
+ recipients = $tr.attr('data-share-recipients');
+ owner = $tr.attr('data-share-owner');
+
+ action.addClass('permanent');
+ message = t('core', 'Shared');
+ if (owner && !recipients) {
+ message = t('files_sharing', 'Shared by {owner}', {owner: owner});
+ image = image || OC.imagePath('core', 'actions/share');
+ }
+ if (recipients) {
+ image = image || OC.imagePath('core', 'actions/shared');
+ if (owner) {
+ message = ' ' + t(
+ 'files_sharing',
+ 'Shared by {owner} with You, {recipients}',
+ {owner: owner, recipients: recipients}
+ );
+ }
+ else {
+ message = t('core', 'Shared with {recipients}', {recipients: recipients});
+ }
+ }
+ action.html(' '+ message + '').prepend(img);
+ }
+ else {
+ action.removeClass('permanent');
+ action.html(' '+ escapeHTML(t('core', 'Share'))+'').prepend(img);
+ }
+ img.attr('src', image);
+ },
loadItem:function(itemType, itemSource) {
var data = '';
var checkReshare = true;
@@ -384,6 +412,7 @@ OC.Share={
OC.Share.share(itemType, itemSource, shareType, shareWith, permissions, itemSourceName, expirationDate, function() {
OC.Share.addShareWith(shareType, shareWith, selected.item.label, permissions, possiblePermissions);
$('#shareWith').val('');
+ $('#dropdown').trigger(new $.Event('sharesChanged', {itemShares: OC.Share.itemShares}));
OC.Share.updateIcon(itemType, itemSource);
});
return false;
@@ -665,6 +694,7 @@ $(document).ready(function() {
$li.remove();
var index = OC.Share.itemShares[shareType].indexOf(shareWith);
OC.Share.itemShares[shareType].splice(index, 1);
+ $('#dropdown').trigger(new $.Event('sharesChanged', {itemShares: OC.Share.itemShares}));
OC.Share.updateIcon(itemType, itemSource);
if (typeof OC.Share.statuses[itemSource] === 'undefined') {
$('#expiration').hide('blind');
@@ -723,6 +753,7 @@ $(document).ready(function() {
if (oc_appconfig.core.enforcePasswordForPublicLink === false) {
OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, '', OC.PERMISSION_READ, itemSourceName, expirationDate, function(data) {
OC.Share.showLink(data.token, null, itemSource);
+ $('#dropdown').trigger(new $.Event('sharesChanged', {itemShares: OC.Share.itemShares}));
OC.Share.updateIcon(itemType, itemSource);
});
} else {