diff options
author | Morris Jobke <hey@morrisjobke.de> | 2014-06-04 17:04:30 +0200 |
---|---|---|
committer | Morris Jobke <hey@morrisjobke.de> | 2014-06-04 17:04:30 +0200 |
commit | ca43fba513b34a60c905d526abd34f56661b6b6e (patch) | |
tree | d226b8ad4adf8e2d09ebf648ebf863419f75f6d2 /core/js | |
parent | c6196c022d137f092af3c9857e6124af5abb5521 (diff) | |
parent | af6a65cbf3a122f92d91fe302e7d60e6c6a5416d (diff) | |
download | nextcloud-server-ca43fba513b34a60c905d526abd34f56661b6b6e.tar.gz nextcloud-server-ca43fba513b34a60c905d526abd34f56661b6b6e.zip |
Merge pull request #8791 from owncloud/share-overview-sharewithstatus
Update share action text to display owner/recipients
Diffstat (limited to 'core/js')
-rw-r--r-- | core/js/share.js | 135 | ||||
-rw-r--r-- | core/js/tests/specs/shareSpec.js | 138 |
2 files changed, 235 insertions, 38 deletions
diff --git a/core/js/share.js b/core/js/share.js index bcc04225b9f..7e3b0d8c65d 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -3,8 +3,25 @@ OC.Share={ SHARE_TYPE_GROUP:1, SHARE_TYPE_LINK:3, SHARE_TYPE_EMAIL:4, + /** + * @deprecated use OC.Share.currentShares instead + */ itemShares:[], + /** + * Full list of all share statuses + */ statuses:{}, + /** + * Shares for the currently selected file. + * (for which the dropdown is open) + * + * Key is item type and value is an array or + * shares of the given item type. + */ + currentShares: {}, + /** + * Whether the share dropdown is opened. + */ droppedDown:false, /** * Loads ALL share statuses from server, stores them in @@ -54,8 +71,9 @@ OC.Share={ $fileList = fileList.$fileList; currentDir = fileList.getCurrentDirectory(); } + // TODO: iterating over the files might be more efficient for (item in OC.Share.statuses){ - var image = OC.imagePath('core', 'actions/shared'); + var image = OC.imagePath('core', 'actions/share'); var data = OC.Share.statuses[item]; var hasLink = data.link; // Links override shared in terms of icon display @@ -63,20 +81,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(' <span>'+t('core', 'Shared')+'</span>').prepend(img); + this.markFileAsShared(file, true, hasLink); } else { var dir = currentDir; if (dir.length > 1) { @@ -89,6 +101,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,35 +138,19 @@ OC.Share={ } } else if (OC.Share.itemShares[index].length > 0) { shares = true; - image = OC.imagePath('core', 'actions/shared'); + image = OC.imagePath('core', 'actions/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(' <span>'+ escapeHTML(t('core', 'Shared'))+'</span>').prepend(img); - } else { - action.removeClass('permanent'); - action.html(' <span>'+ escapeHTML(t('core', 'Share'))+'</span>').prepend(img); - } + var $tr = $('tr').filterAttr('data-id', String(itemSource)); + if ($tr.length > 0) { + // it might happen that multiple lists exist in the DOM + // with the same id + $tr.each(function() { + OC.Share.markFileAsShared($(this), shares, link); }); } } @@ -164,6 +161,60 @@ OC.Share={ delete OC.Share.statuses[itemSource]; } }, + /** + * Marks/unmarks a given file as shared by changing its action icon + * and folder icon. + * + * @param $tr file element to mark as shared + * @param hasShares whether shares are available + * @param hasLink whether link share is available + */ + markFileAsShared: function($tr, hasShares, hasLink) { + 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 = $tr.attr('data-share-owner'); + var shareFolderIcon; + var image = OC.imagePath('core', 'actions/share'); + // update folder icon + if (type === 'dir' && (hasShares || hasLink)) { + if (hasLink) { + shareFolderIcon = OC.imagePath('core', 'filetypes/folder-public'); + } + else { + 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 + ')'); + } + // update share action text / icon + if (hasShares || owner) { + recipients = $tr.attr('data-share-recipients'); + + action.addClass('permanent'); + message = t('core', 'Shared'); + // even if reshared, only show "Shared by" + if (owner) { + message = t('files_sharing', 'Shared by {owner}', {owner: owner}); + } + else if (recipients) { + message = t('core', 'Shared with {recipients}', {recipients: recipients}); + } + action.html(' <span>'+ message + '</span>').prepend(img); + } + else { + action.removeClass('permanent'); + action.html(' <span>'+ escapeHTML(t('core', 'Share'))+'</span>').prepend(img); + } + if (hasLink) { + image = OC.imagePath('core', 'actions/public'); + } + img.attr('src', image); + }, loadItem:function(itemType, itemSource) { var data = ''; var checkReshare = true; @@ -319,6 +370,7 @@ OC.Share={ dropDownEl = dropDownEl.appendTo(appendTo); // Reset item shares OC.Share.itemShares = []; + OC.Share.currentShares = {}; if (data.shares) { $.each(data.shares, function(index, share) { if (share.share_type == OC.Share.SHARE_TYPE_LINK) { @@ -392,6 +444,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', {shares: OC.Share.currentShares})); OC.Share.updateIcon(itemType, itemSource); }); return false; @@ -448,6 +501,7 @@ OC.Share={ $('#shareWith').focus(); }, hideDropDown:function(callback) { + OC.Share.currentShares = null; $('#dropdown').hide('blind', function() { OC.Share.droppedDown = false; $('#dropdown').remove(); @@ -460,6 +514,12 @@ OC.Share={ }); }, addShareWith:function(shareType, shareWith, shareWithDisplayName, permissions, possiblePermissions, mailSend, collection) { + var shareItem = { + share_type: shareType, + share_with: shareWith, + share_with_displayname: shareWithDisplayName, + permissions: permissions + }; if (shareType === 1) { shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'group') + ')'; } @@ -538,6 +598,10 @@ OC.Share={ html.find('.cruds').before(showCrudsButton); } $('#expiration').show(); + if (!OC.Share.currentShares[shareType]) { + OC.Share.currentShares[shareType] = []; + } + OC.Share.currentShares[shareType].push(shareItem); } }, showLink:function(token, password, itemSource) { @@ -673,6 +737,9 @@ $(document).ready(function() { $li.remove(); var index = OC.Share.itemShares[shareType].indexOf(shareWith); OC.Share.itemShares[shareType].splice(index, 1); + // updated list of shares + OC.Share.currentShares[shareType].splice(index, 1); + $('#dropdown').trigger(new $.Event('sharesChanged', {shares: OC.Share.currentShares})); OC.Share.updateIcon(itemType, itemSource); if (typeof OC.Share.statuses[itemSource] === 'undefined') { $('#expiration').hide('blind'); @@ -731,6 +798,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', {shares: OC.Share.currentShares})); OC.Share.updateIcon(itemType, itemSource); }); } else { @@ -743,6 +811,7 @@ $(document).ready(function() { if ($('#linkText').val() !== '') { OC.Share.unshare(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, '', function() { OC.Share.itemShares[OC.Share.SHARE_TYPE_LINK] = false; + $('#dropdown').trigger(new $.Event('sharesChanged', {shares: OC.Share.currentShares})); OC.Share.updateIcon(itemType, itemSource); if (typeof OC.Share.statuses[itemSource] === 'undefined') { $('#expiration').hide('blind'); diff --git a/core/js/tests/specs/shareSpec.js b/core/js/tests/specs/shareSpec.js index a487b71fdbb..458bc41b6a1 100644 --- a/core/js/tests/specs/shareSpec.js +++ b/core/js/tests/specs/shareSpec.js @@ -26,13 +26,17 @@ describe('OC.Share tests', function() { var oldAppConfig; var loadItemStub; var autocompleteStub; + beforeEach(function() { $('#testArea').append($('<div id="shareContainer"></div>')); + // horrible parameters + $('#testArea').append('<input id="allowShareWithLink" type="hidden" value="yes">'); $container = $('#shareContainer'); /* jshint camelcase:false */ - oldAppConfig = oc_appconfig.core; - loadItemStub = sinon.stub(OC.Share, 'loadItem'); + oldAppConfig = _.extend({}, oc_appconfig.core); + oc_appconfig.core.enforcePasswordForPublicLink = false; + loadItemStub = sinon.stub(OC.Share, 'loadItem'); loadItemStub.returns({ reshare: [], shares: [] @@ -89,9 +93,133 @@ describe('OC.Share tests', function() { oc_appconfig.core.defaultExpireDate = ''; // TODO: expect that default date was NOT set }); - // TODO: test password field visibility (whenever enforced or not) - // TODO: check link share field visibility based on whether it is allowed - // TODO: check public upload visibility based on config + describe('Share with link', function() { + // TODO: test ajax calls + // TODO: test password field visibility (whenever enforced or not) + // TODO: check public upload visibility based on config + it('shows share with link checkbox when allowed', function() { + $('#allowShareWithLink').val('yes'); + OC.Share.showDropDown( + 'file', + 123, + $container, + 'http://localhost/dummylink', + 31, + 'shared_file_name.txt' + ); + expect($('#dropdown #linkCheckbox').length).toEqual(1); + }); + it('does not show share with link checkbox when not allowed', function() { + $('#allowShareWithLink').val('no'); + OC.Share.showDropDown( + 'file', + 123, + $container, + 'http://localhost/dummylink', + 31, + 'shared_file_name.txt' + ); + expect($('#dropdown #linkCheckbox').length).toEqual(0); + }); + }); + describe('"sharesChanged" event', function() { + var autocompleteOptions; + var handler; + beforeEach(function() { + handler = sinon.stub(); + loadItemStub.returns({ + reshare: [], + shares: [{ + id: 100, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + share_with_displayname: 'User One' + }] + }); + OC.Share.showDropDown( + 'file', + 123, + $container, + 'http://localhost/dummylink', + 31, + 'shared_file_name.txt' + ); + $('#dropdown').on('sharesChanged', handler); + autocompleteOptions = autocompleteStub.getCall(0).args[0]; + }); + afterEach(function() { + autocompleteOptions = null; + handler = null; + }); + it('triggers "sharesChanged" event when adding shares', function() { + // simulate autocomplete selection + autocompleteOptions.select(new $.Event('select'), { + item: { + label: 'User Two', + value: { + shareType: OC.Share.SHARE_TYPE_USER, + shareWith: 'user2' + } + } + }); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + expect(handler.calledOnce).toEqual(true); + var shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); + expect(shares[OC.Share.SHARE_TYPE_USER][1].share_with_displayname).toEqual('User Two'); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + }); + it('triggers "sharesChanged" event when deleting shares', function() { + $('#dropdown .unshare:eq(0)').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + expect(handler.calledOnce).toEqual(true); + var shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER]).toEqual([]); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + }); + it('triggers "sharesChanged" event when toggling link share', function() { + // simulate autocomplete selection + $('#dropdown #linkCheckbox').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success', data: { token: 'abc' }}) + ); + expect(handler.calledOnce).toEqual(true); + var shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + + handler.reset(); + + // uncheck checkbox + $('#dropdown #linkCheckbox').click(); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + expect(handler.calledOnce).toEqual(true); + shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + }); + }); }); }); |