Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[For 10.4] Add dir/path sharing infos #36254

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8105173
Add dir/path sharing info
felixheidecke Oct 8, 2019
0f4ce7c
Add method documentation
felixheidecke Oct 8, 2019
729717e
Add fileShare indicator method
felixheidecke Oct 11, 2019
7a43227
WIP
felixheidecke Oct 17, 2019
e3969f9
in share-tree icon
felixheidecke Oct 17, 2019
845bf20
[WIP] Append shareTree Info in shareTab
felixheidecke Oct 21, 2019
055dea2
Adding icons and tree info in sidebar
felixheidecke Oct 23, 2019
f9387dd
Fix IE11 JS compatibility issues
felixheidecke Oct 23, 2019
774e8f3
Prevent reduntant API calls
felixheidecke Oct 25, 2019
402cdee
Adds OC.Apps.AppSidebarVisible()
felixheidecke Oct 25, 2019
9e155f3
Comment out code for shareIndicator (Usage TBD)
felixheidecke Oct 25, 2019
6606f0c
Minor cleanup
felixheidecke Oct 25, 2019
e900982
Revert templates changes made in dialogviews
felixheidecke Oct 25, 2019
996b880
Store shareInfo by path as key
felixheidecke Oct 28, 2019
ea7a0c2
Use existing share icon in file indicator
felixheidecke Oct 28, 2019
7e66f37
Prevent adding shareTabView multiple times
felixheidecke Oct 28, 2019
ebcc07c
Remove unused methods and styles
felixheidecke Oct 29, 2019
c5ff1a6
Propper share_type check
felixheidecke Oct 30, 2019
9509462
Add icon on rendering-row
felixheidecke Oct 30, 2019
c8941e3
Delete shareinfo.svg
felixheidecke Oct 30, 2019
43f7a32
Rework shareTreeCache
felixheidecke Oct 30, 2019
410f6ef
Add info (i) about shareTree
felixheidecke Nov 4, 2019
1da9ff0
Use build in functions
felixheidecke Nov 4, 2019
fc593bc
Propper diff cache and current dir
felixheidecke Nov 4, 2019
922bb99
Fix typos
felixheidecke Nov 4, 2019
9de5f64
Add event system OCE
felixheidecke Nov 12, 2019
0c9614b
Separate user/group- and link-shares in sidebar
felixheidecke Nov 12, 2019
9f4dc49
Use OC.Share events
felixheidecke Nov 13, 2019
0538e87
Use OC.Share events
felixheidecke Nov 13, 2019
eeae701
Revert event based solution
felixheidecke Nov 20, 2019
eb73610
Fix js tests
felixheidecke Nov 20, 2019
5b3f970
Remove log message
felixheidecke Nov 22, 2019
1d38b3b
Add shareTree tests
felixheidecke Nov 25, 2019
36750d9
ShareTree check requires additional Propfind
felixheidecke Nov 25, 2019
8970f86
Add acceptance test for sharing a folder with internal user and check…
kiranparajuli589 Nov 29, 2019
cfbc35c
PHP Style Fix
kiranparajuli589 Nov 29, 2019
f413df3
Add acceptance test for checking the share indicators on created-shar…
kiranparajuli589 Dec 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions apps/files/css/files.css
Original file line number Diff line number Diff line change
Expand Up @@ -512,21 +512,29 @@ table td.filename .uploadtext {
}

/* File checkboxes */
html:not(.ie8) #fileList tr td.filename > .selectCheckBox + label:before {
#fileList tr td.filename > .selectCheckBox + label:before {
opacity: 0;
position: absolute;
bottom: 4px;
right: 0;
z-index: 10;
}

html.ie8 #fileList tr td.filename > .selectCheckBox {
filter: alpha(opacity=0);
opacity: 0;
float: left;
top: 0;
margin: 32px 0 4px 32px;
/* bigger clickable area doesn’t work in FF width:2.8em; height:2.4em;*/
#fileList tr:not(:hover):not(.selected) td.filename .thumbnail.sharetree-item:after {
position: absolute;
felixheidecke marked this conversation as resolved.
Show resolved Hide resolved
display: block;
content: '';
bottom: 0px;
right: -5px;
z-index: 10;
background-image: url(../../../core/img/actions/shared.svg);
width: 14px;
height: 14px;
background-repeat: no-repeat;
background-position: center;
background-size: 10px;
background-color: #bfbfbf;
border-radius: 50%;
}

/* Show checkbox when hovering, checked, or selected */
Expand Down
235 changes: 225 additions & 10 deletions apps/files/js/filelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@
*/
_sortComparator: null,

/**
* Stores shareTree items and infos
*
* @type Array
*/
_shareTreeCache: {},

/**
* Whether to do a client side sort.
* When false, clicking on a table header will call reload().
Expand Down Expand Up @@ -379,6 +386,7 @@
// remove summary
this.$el.find('tfoot tr.summary').remove();
this.$fileList.empty();

},

/**
Expand Down Expand Up @@ -1048,6 +1056,7 @@
$(window).scrollTop(0);

this.$fileList.trigger(jQuery.Event('updated'));

_.defer(function() {
self.$el.closest('#app-content').trigger(jQuery.Event('apprendered'));
});
Expand Down Expand Up @@ -1389,6 +1398,10 @@
tr.addClass('hidden-file');
}

if(_.keys(this._shareTreeCache).length) {
filenameTd.find('.thumbnail:not(.sharetree-item)').addClass('sharetree-item');
}

// display actions
this.fileActions.display(filenameTd, !options.silent, this);

Expand Down Expand Up @@ -1445,17 +1458,28 @@
var self = this;
var currentDir = this.getCurrentDirectory();
targetDir = targetDir || '/';
if (!force && currentDir === targetDir) {
return;
}
this._setCurrentDir(targetDir, changeUrl, fileId);
// discard finished uploads list, we'll get it through a regular reload
this._uploads = {};
this.reload().then(function(success){
if (!success) {
self.changeDirectory(currentDir, true);

return new Promise(function(resolve, reject) {

if (!force && currentDir === targetDir) {
resolve()
return
}
});
self._setCurrentDir(targetDir, changeUrl, fileId);
// discard finished uploads list, we'll get it through a regular reload
self._uploads = {};
self.reload().then(function(success){
if (!success) {
self.changeDirectory(currentDir, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no risk of infinite loop here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing I did was wrapping it in a Promise so I could act after the reload was done.
This seems to have worked for the last 5 years ;-)

reject()
}
resolve()
});

self._updateShareTree().then(function() {
self._setShareTreeIcons();
})
})
},
linkTo: function(dir) {
return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/');
Expand Down Expand Up @@ -1723,6 +1747,197 @@
return OC.linkToRemoteBase('dav') + '/files/' + uid + encodedPath;
},

/**
* Fetch shareTypes of a certain directory
* @param {String} dir directory string
* @return {Promise} object with name and shareTypes
*/
getDirShareInfo: function(dir) {
felixheidecke marked this conversation as resolved.
Show resolved Hide resolved
// Dir can't be empty
if (typeof dir !== 'string' || dir.length === 0) {
return Promise.reject('getDirShareInfo(). param must be typeof string and can not be empty!')
}

// avoiding a unnessesary API calls
if (typeof this._shareTreeCache[dir] !== 'undefined' || dir === '/') {
return Promise.resolve()
}

// trim trailing slashes
dir = dir.replace(/\/$/, "")

var self = this;
var client = this.filesClient;
var options = {
properties : ['{' + OC.Files.Client.NS_OWNCLOUD + '}share-types']
}

return new Promise( function(resolve, reject) {
client.getFileInfo(dir, options).done(function(s, dir) {
felixheidecke marked this conversation as resolved.
Show resolved Hide resolved

var path = OC.joinPaths(dir.path, dir.name)

if (dir.shareTypes !== undefined) {
// Fetch all shares for directory in question
$.get( OC.linkToOCS('apps/files_sharing/api/v1', 2) + 'shares?' + OC.buildQueryString({format: 'json', path: path }), function(e) {
self._shareTreeCache[path] = {
name : dir.name,
shares : e.ocs.data
}
resolve()
})
}
else {
resolve()
}
}).fail(function(error) {
reject(error)
})
})
},

/**
* Fetch shareInfos recursively from current
* directory down to root
* @param {String} dir directory string
* @return {Promise} array of objects with name and shareTypes
*/
getPathShareInfo: function(path) {
felixheidecke marked this conversation as resolved.
Show resolved Hide resolved
if (typeof path !== 'string') {
console.error('getDirShareInfo(). param must be typeof string!')
return false
}

var crumbs = [];
var pathToHere = '';
var parts = (path === '/' || path.length === 0) ? ['/'] : path.split('/')

for (var i = 0; i < parts.length; i++) {
var part = parts[i];
pathToHere += part + '/';

crumbs.push(this.getDirShareInfo(pathToHere))
}

return Promise.all(crumbs)
},

_updateShareTree: function() {
var self = this;
var dir = this.getCurrentDirectory();

// Purge shareTreeCache in root dir
if (dir === '/') {
this._purgeShareTreeCache()
return Promise.resolve()
}

return this.getPathShareInfo(dir).then(function () {
var breadcrumbs = dir.split('/')

// Diff keys in shareTreeCache agains the current dir
// removing deeper nested shares
var cache = _.omit(self._shareTreeCache, function(value, key) {
var diffs = _.difference(key.split('/'), breadcrumbs)
return diffs.length > 0
});

self._setShareTreeCache(cache)
})

},

_setShareTreeCache: function(data) {
this._shareTreeCache = data;
},

_purgeShareTreeCache: function() {
this._setShareTreeCache({});
},

_setShareTreeIcons: function() {
// Add share-tree icon to files and folders
// each per <tr> in the table

if (_.keys(this._shareTreeCache).length > 0)
this.$fileList.find('tr td.filename .thumbnail:not(.sharetree-item)').addClass('sharetree-item')
else
this.$fileList.find('tr td.filename .thumbnail.sharetree-item').removeClass('sharetree-item')

},

_setShareTreeUserGroupView: function() {
var self = this;
var $list = $('<ul>', { id : 'shareTreeUserGroupList' });

if (! _.keys(self._shareTreeCache).length > 0)
return

$('.shareeTreeUserGroupListView').html($list)

// Shared folders
_.each(self._shareTreeCache, function(folder) {

var shares = _.filter(folder.shares, function(share) {
return (
share.share_type === OC.Share.SHARE_TYPE_USER ||
share.share_type === OC.Share.SHARE_TYPE_GROUP ||
share.share_type === OC.Share.SHARE_TYPE_GUEST ||
share.share_type === OC.Share.SHARE_TYPE_REMOTE )
})

_.each(shares, function(share) {

var $path = $('<span>', { class : 'shareTree-item-path', text : t('core', 'via') + " " + folder.name })
var $name = $('<strong>', { class : 'shareTree-item-name', text : share.share_with_displayname })
var $icon = $('<div>', { class : 'shareTree-item-avatar' })

$icon.avatar(share.share_with, 32)

$('<li class="shareTree-item">').append( $icon, $name, $path).appendTo($list).click(function() {
self.changeDirectory(share.path.replace(folder.name, ''), true).then(function() {
self._updateDetailsView(folder.name, true)
}).catch(function(e) {
console.error(e)
})
})
})
})
},

_setShareTreeLinkView: function() {
var self = this;
var $list = $('<ul>', { id : 'shareTreeLinkList' });

if (! _.keys(self._shareTreeCache).length > 0)
return

$('.shareeTreeLinkListView').html($list)

// Shared folders
_.each(self._shareTreeCache, function(folder) {

var shares = _.filter(folder.shares, function(share) {
return share.share_type === OC.Share.SHARE_TYPE_LINK
})

_.each(shares, function(share) {

var $path = $('<span>', { class : 'shareTree-item-path', text : t('core', 'via') + " " + folder.name })
var $name = $('<strong>', { class : 'shareTree-item-name', text : share.name })
var $icon = $('<span>', { class : 'shareTree-item-icon link-entry--icon icon-public-white' })

$('<li class="shareTree-item">').append( $icon, $name, $path).appendTo($list).click(function() {
self.changeDirectory(share.path.replace(folder.name, ''), true).then(function() {
self._updateDetailsView(folder.name, true)
}).catch(function(e) {
console.error(e)
})
})
})
})
},

/**
* Generates a preview URL based on the URL space.
* @param urlSpec attributes for the URL
Expand Down
18 changes: 18 additions & 0 deletions apps/files/tests/js/filelistSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,24 @@ describe('OCA.Files.FileList tests', function() {
expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
expect($summary.find('.fileinfo').text()).toEqual('1 file');
});
it('shows icon for shareTree items if parent is shared', function() {
fileList._setShareTreeCache({
'/folder' : {
name: "folder",
shares : [{
share_type: 0,
share_with_displayname: "Demo user",
}]
}
});
fileList.setFiles(testFiles)
expect($('#fileList tr:first-of-type td .sharetree-item').length).toEqual(1)
});
it('does not show shareTree items if shareTree is empty', function() {
fileList._purgeShareTreeCache()
fileList.setFiles(testFiles)
expect($('#fileList tr td .sharetree-item').length).toEqual(0)
})
});
describe('Filtered list rendering', function() {
it('filters the list of files using filter()', function() {
Expand Down
32 changes: 32 additions & 0 deletions apps/files_sharing/css/sharetabview.css
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,38 @@
margin-right: 8px;
}

#shareDialogLinkList .link-shares + #shareTreeUserGroupList {
margin-top: -20px;
}

#shareWithList + #shareTreeUserGroupList {
margin-top: -16px;
}

#shareTreeLinkList .shareTree-item,
#shareTreeUserGroupList .shareTree-item {
display: flex;
justify-content: flex-start;
align-items: center;

padding-top: 5px;
padding-bottom: 5px;
}

.shareTree-item * {
cursor: pointer;
}

.shareTree-item-avatar {
border-radius: 50%;
float: left;
}

.shareTree-item-avatar + .shareTree-item-name,
.shareTree-item-name + .shareTree-item-path {
margin-left: 8px;
}

.shareTabView .icon-loading-small {
display : inline-block;
z-index : 1;
Expand Down
3 changes: 3 additions & 0 deletions apps/files_sharing/js/share.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@
// (FIXME: yes, this is hacky)
icon: $tr.attr('data-icon')
});

fileList._setShareTreeLinkView();
fileList._setShareTreeUserGroupView();
});
fileList.registerTabView(shareTab);
},
Expand Down
2 changes: 1 addition & 1 deletion apps/files_sharing/tests/js/publicAppSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('OCA.Sharing.PublicApp tests', function() {
// uploader function messes up with fakeServer
var uploaderDetectStub = sinon.stub(OC.Uploader.prototype, '_supportAjaxUploadWithProgress');
App.initialize($('#preview'));
expect(fakeServer.requests.length).toEqual(1);
expect(fakeServer.requests.length).toEqual(2);
expect(fakeServer.requests[0].method).toEqual('PROPFIND');
expect(fakeServer.requests[0].url).toEqual('https://example.com:9876/owncloud/public.php/webdav/subdir');
expect(fakeServer.requests[0].requestHeaders.Authorization).toEqual('Basic c2g0dG9rOm51bGw=');
Expand Down
Loading