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

Share dialog files sidebar #18185

Merged
merged 59 commits into from
Sep 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
edd163a
refactor share dialog for multi-purpose use (dropdown, sidebar) and b…
blizzz Jul 30, 2015
e7b5921
share dialog view takes advantage of OC.Backbone.View
blizzz Aug 7, 2015
ea6e380
remove possibly unreliable code and fix JSdoc
blizzz Aug 10, 2015
1651b82
started to port the Model to Backbone`s
blizzz Aug 10, 2015
7971bc1
model now extends Backbone's model and isadjusted
blizzz Aug 11, 2015
e6edc3e
make loadItems work async if a callback is provided
blizzz Aug 11, 2015
97b5fe0
switch to async item loading, take care stuff is updated subsequently
blizzz Aug 11, 2015
b015eff
improve reshare rendering part and move permission calculation to model
blizzz Aug 11, 2015
83d91dd
further work on reimplementing the dialog layout
blizzz Aug 13, 2015
a57ff13
move remaining global settings to configModel
blizzz Aug 18, 2015
e3fd96f
improve doc
blizzz Aug 18, 2015
1bd6942
show tooltips and load avatar
blizzz Aug 18, 2015
dcb084a
split ShareDialogResharerInfoView from base view
blizzz Aug 18, 2015
277b786
ShareDialogResharerInfoView improvements
blizzz Aug 21, 2015
f9c232c
split off linkShareView
blizzz Aug 21, 2015
ffd4e0d
split off expirationView
blizzz Aug 21, 2015
8f38841
less stupid initalization of subviews
blizzz Aug 21, 2015
6af6024
integraton noshare part into ShareDialogLinkShareView
blizzz Aug 21, 2015
018d07b
Add share dialog into share tab
Aug 24, 2015
f709022
Fix share permissions for share tab
Aug 24, 2015
fdb9561
simplification, and throwing where throwing is needed
blizzz Aug 24, 2015
f2fb20e
no auto-fetch in model
blizzz Aug 24, 2015
755d401
set default value and remove now superflous method
blizzz Aug 24, 2015
f62a3be
cleanup
blizzz Aug 25, 2015
c17d022
started to implement sharee list view. not completed yet, do not cry …
blizzz Aug 25, 2015
5db1db3
continue to reimplement sharee list view. still WIP
blizzz Sep 1, 2015
44ecdde
sharee list view: better handle collections
blizzz Sep 2, 2015
60abfcd
old OC.Share.addShareWith now reimplemented
blizzz Sep 2, 2015
5dc2c35
fixed set of possible permissions for remote shares
blizzz Sep 2, 2015
ce1b0c6
show link share
blizzz Sep 3, 2015
858a2a4
display expiration info
blizzz Sep 4, 2015
258a2e2
now you even can share
blizzz Sep 5, 2015
5fad379
remove obsolete file action
blizzz Sep 12, 2015
4c702aa
format groups and remotes in autocomplete list
blizzz Sep 12, 2015
f29b516
share and unshare via link (not yet password). also some internal cha…
blizzz Sep 12, 2015
5dfaa0c
mark url on click
blizzz Sep 12, 2015
9fe6d7c
implements setting and removing password for link shares, including f…
blizzz Sep 12, 2015
6d83235
fix allow upload checkbox appeareance
blizzz Sep 13, 2015
7ae84e0
make 'Allow editing' (aka public upload) checkbox work
blizzz Sep 13, 2015
a5b0ea0
make unshare work
blizzz Sep 13, 2015
d4bbc06
cleanup
blizzz Sep 13, 2015
c7453b4
toggle visibility of detailed cruds permissions
blizzz Sep 13, 2015
a0fa718
make permission/cruds checkboxes work
blizzz Sep 14, 2015
c2ff2ca
cleanup
blizzz Sep 14, 2015
8194d09
Add expiration date handling in share tab
Sep 14, 2015
e900658
Bring back the share icon and update its status
Sep 14, 2015
06b11dd
Fix shares list events
Sep 14, 2015
e0a2004
Clear field after adding user
Sep 14, 2015
aeee19b
Implement "notify by email" checkbox in share dialog
Sep 14, 2015
62ff787
Implement email share link
Sep 14, 2015
1933bcf
Implement email autocomplete for link share
Sep 14, 2015
41f16e8
Remove unused/obsoleted OC.Share code
Sep 14, 2015
886f1ed
Update JS unit tests for share dialog (WIP)
Sep 15, 2015
996639f
More unit tests for share dialog
Sep 15, 2015
f439c07
Fix allow reshare for owner when sharing with self through group
Sep 15, 2015
02d68d0
Removed obsolete tests
Sep 15, 2015
36e452a
Fix cruds button in share dialog
Sep 15, 2015
6141ea1
Port share.css styles to the sidebar panel
Sep 15, 2015
e7e0cfe
Properly show sidebar when clicking on share button
Sep 15, 2015
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
15 changes: 15 additions & 0 deletions apps/files/js/filelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,21 @@
return model;
},

/**
* Displays the details view for the given file and
* selects the given tab
*
* @param {string} fileName file name for which to show details
* @param {string} [tabId] optional tab id to select
*/
showDetailsView: function(fileName, tabId) {
this._updateDetailsView(fileName);
if (tabId) {
this._detailsView.selectTab(tabId);
}
OC.Apps.showAppSidebar();
},

/**
* Update the details view to display the given file
*
Expand Down
15 changes: 12 additions & 3 deletions apps/files_sharing/appinfo/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,18 @@
\OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
\OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');

\OCP\Util::addScript('files_sharing', 'share');
\OCP\Util::addScript('files_sharing', 'external');
\OCP\Util::addStyle('files_sharing', 'sharetabview');
$eventDispatcher = \OC::$server->getEventDispatcher();
$eventDispatcher->addListener(
'OCA\Files::loadAdditionalScripts',
function() {
\OCP\Util::addScript('files_sharing', 'share');
\OCP\Util::addScript('files_sharing', 'sharetabview');
\OCP\Util::addScript('files_sharing', 'external');
\OCP\Util::addStyle('files_sharing', 'sharetabview');
}
);

// \OCP\Util::addStyle('files_sharing', 'sharetabview');

\OC::$server->getActivityManager()->registerExtension(function() {
return new \OCA\Files_Sharing\Activity(
Expand Down
72 changes: 72 additions & 0 deletions apps/files_sharing/css/sharetabview.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,75 @@
.app-files .shareTabView {
min-height: 100px;
}

.shareTabView .oneline { white-space: nowrap; }

.shareTabView .shareWithLoading {
padding-left: 10px;
position: relative;
right: 30px;
top: 2px;
}

.shareTabView .shareWithRemoteInfo {
padding: 11px 0 11px 10px
}

.shareTabView label {
font-weight:400;
white-space: nowrap;
}

.shareTabView input[type="checkbox"] {
margin:0 3px 0 8px;
vertical-align: middle;
}

.shareTabView input[type="text"], .shareTabView input[type="password"] {
width: 91%;
margin-left: 7px;
}

.shareTabView form {
font-size: 100%;
margin-left: 0;
margin-right: 0;
}

#shareWithList {
list-style-type:none;
padding:8px;
}

#shareWithList li {
padding-top: 10px;
padding-bottom: 10px;
font-weight: bold;
line-height: 21px;
white-space: normal;
}

#shareWithList .unshare img, #shareWithList .showCruds img {
vertical-align:text-bottom; /* properly align icons */
}

#shareWithList label input[type=checkbox]{
margin-left: 0;
position: relative;
}
#shareWithList .username{
padding-right: 8px;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 254px;
display: inline-block;
overflow: hidden;
vertical-align: middle;
}
#shareWithList li label{
margin-right: 8px;
}

.shareTabView .icon-loading-small {
margin-left: -30px;
}
96 changes: 44 additions & 52 deletions apps/files_sharing/js/share.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@
$files = fileList.$fileList.find('tr');
}
_.each($files, function(file) {
OCA.Sharing.Util.updateFileActionIcon($(file));
var $tr = $(file);
var shareStatus = OC.Share.statuses[$tr.data('id')];
OCA.Sharing.Util._updateFileActionIcon($tr, !!shareStatus, shareStatus && shareStatus.link);
});
}

Expand All @@ -104,71 +106,59 @@
permissions: OC.PERMISSION_SHARE,
icon: OC.imagePath('core', 'actions/share'),
type: OCA.Files.FileActions.TYPE_INLINE,
actionHandler: function(filename, context) {
var $tr = context.$file;
var itemType = 'file';
if ($tr.data('type') === 'dir') {
itemType = 'folder';
}
var possiblePermissions = $tr.data('share-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.attr('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) {
// files app current cannot show recipients on load, so we don't update the
// icon when changed for consistency
if (context.fileList.$el.closest('#app-content-files').length) {
return;
}
var recipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_USER], 'share_with_displayname');
var groupRecipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_GROUP], 'share_with_displayname');
recipients = recipients.concat(groupRecipients);
// note: we only update the data attribute because updateIcon()
// is called automatically after this event
if (recipients.length) {
$tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients));
}
else {
$tr.removeAttr('data-share-recipients');
}
});
actionHandler: function(fileName) {
fileList.showDetailsView(fileName, 'shareTabView');
}
});

OC.addScript('files_sharing', 'sharetabview').done(function() {
fileList.registerTabView(new OCA.Sharing.ShareTabView('shareTabView'));
var shareTab = new OCA.Sharing.ShareTabView('shareTabView');
// detect changes and change the matching list entry
shareTab.on('sharesChanged', function(shareModel) {
var fileInfoModel = shareModel.fileInfoModel;
var $tr = fileList.findFileEl(fileInfoModel.get('name'));
OCA.Sharing.Util._updateFileListDataAttributes(fileList, $tr, shareModel);
if (!OCA.Sharing.Util._updateFileActionIcon($tr, shareModel.hasUserShares(), shareModel.hasLinkShare())) {
// remove icon, if applicable
OC.Share.markFileAsShared($tr, false, false);
}
});
fileList.registerTabView(shareTab);
},

/**
* Update file list data attributes
*/
_updateFileListDataAttributes: function(fileList, $tr, shareModel) {
// files app current cannot show recipients on load, so we don't update the
// icon when changed for consistency
if (fileList.id === 'files') {
return;
}
var recipients = _.pluck(shareModel.get('shares'), 'share_with_displayname');
// note: we only update the data attribute because updateIcon()
if (recipients.length) {
$tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients));
}
else {
$tr.removeAttr('data-share-recipients');
}
},

/**
* Update the file action share icon for the given file
*
* @param $tr file element of the file to update
* @param {bool} hasUserShares true if a user share exists
* @param {bool} hasLinkShare true if a link share exists
*
* @return {bool} true if the icon was set, false otherwise
*/
updateFileActionIcon: function($tr) {
_updateFileActionIcon: function($tr, hasUserShares, hasLinkShare) {
// if the statuses are loaded already, use them for the icon
// (needed when scrolling to the next page)
var shareStatus = OC.Share.statuses[$tr.data('id')];
if (shareStatus || $tr.attr('data-share-recipients') || $tr.attr('data-share-owner')) {
if (hasUserShares || hasLinkShare || $tr.attr('data-share-recipients') || $tr.attr('data-share-owner')) {
var permissions = $tr.data('permissions');
var hasLink = !!(shareStatus && shareStatus.link);
OC.Share.markFileAsShared($tr, true, hasLink);
OC.Share.markFileAsShared($tr, true, hasLinkShare);
if ((permissions & OC.PERMISSION_SHARE) === 0 && $tr.attr('data-share-owner')) {
// 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
Expand All @@ -187,7 +177,9 @@
return $result;
});
}
return true;
}
return false;
},

/**
Expand Down
52 changes: 38 additions & 14 deletions apps/files_sharing/js/sharetabview.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

(function() {
var TEMPLATE =
'<div><ul>{{#if owner}}<li>Owner: {{owner}}</li>{{/if}}</ul></div>';
'<div>' +
'<div class="dialogContainer"></div>' +
'</div>';

/**
* @memberof OCA.Sharing
Expand All @@ -20,7 +22,12 @@
id: 'shareTabView',
className: 'tab shareTabView',

_template: null,
template: function(params) {
if (!this._template) {
this._template = Handlebars.compile(TEMPLATE);
}
return this._template(params);
},

getLabel: function() {
return t('files_sharing', 'Sharing');
Expand All @@ -30,23 +37,40 @@
* Renders this details view
*/
render: function() {
this.$el.empty();

if (!this._template) {
this._template = Handlebars.compile(TEMPLATE);
var self = this;
if (this._dialog) {
// remove/destroy older instance
this._dialog.model.off();
this._dialog.remove();
this._dialog = null;
}

if (this.model) {
console.log(this.model);
var owner = this.model.get('shareOwner');
if (owner === OC.currentUser) {
owner = null;
}
this.$el.append(this._template({
owner: owner
}));
this.$el.html(this.template());

// TODO: the model should read these directly off the passed fileInfoModel
var attributes = {
itemType: this.model.isDirectory() ? 'folder' : 'file',
itemSource: this.model.get('id'),
possiblePermissions: this.model.get('sharePermissions')
};
var configModel = new OC.Share.ShareConfigModel();
var shareModel = new OC.Share.ShareItemModel(attributes, {
configModel: configModel,
fileInfoModel: this.model
});
this._dialog = new OC.Share.ShareDialogView({
configModel: configModel,
model: shareModel
});
this.$el.find('.dialogContainer').append(this._dialog.$el);
this._dialog.render();
this._dialog.model.fetch();
this._dialog.model.on('change', function() {
self.trigger('sharesChanged', shareModel);
});
} else {
this.$el.empty();
// TODO: render placeholder text?
}
}
Expand Down
Loading