refactor share dialog for multi-purpose use (dropdown, sidebar) and better maintainability
This commit is contained in:
parent
2fc19635f6
commit
edd163a611
|
@ -55,8 +55,9 @@ $application->setupPropagation();
|
||||||
\OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
|
\OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
|
||||||
|
|
||||||
\OCP\Util::addScript('files_sharing', 'share');
|
\OCP\Util::addScript('files_sharing', 'share');
|
||||||
|
\OCP\Util::addScript('files_sharing', 'sharetabview');
|
||||||
\OCP\Util::addScript('files_sharing', 'external');
|
\OCP\Util::addScript('files_sharing', 'external');
|
||||||
\OCP\Util::addStyle('files_sharing', 'sharetabview');
|
// \OCP\Util::addStyle('files_sharing', 'sharetabview');
|
||||||
|
|
||||||
\OC::$server->getActivityManager()->registerExtension(function() {
|
\OC::$server->getActivityManager()->registerExtension(function() {
|
||||||
return new \OCA\Files_Sharing\Activity(
|
return new \OCA\Files_Sharing\Activity(
|
||||||
|
|
|
@ -1,3 +1,72 @@
|
||||||
.app-files .shareTabView {
|
.app-files .shareTabView {
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shareTabView .oneline { white-space: nowrap; }
|
||||||
|
|
||||||
|
.shareTabView .shareWithLoading {
|
||||||
|
display: inline-block !important;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* @namespace
|
* @namespace
|
||||||
*/
|
*/
|
||||||
OC.Share={
|
OC.Share = _.extend(OC.Share, {
|
||||||
SHARE_TYPE_USER:0,
|
SHARE_TYPE_USER:0,
|
||||||
SHARE_TYPE_GROUP:1,
|
SHARE_TYPE_GROUP:1,
|
||||||
SHARE_TYPE_LINK:3,
|
SHARE_TYPE_LINK:3,
|
||||||
|
@ -289,6 +289,12 @@ OC.Share={
|
||||||
}
|
}
|
||||||
img.attr('src', image);
|
img.attr('src', image);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param itemType
|
||||||
|
* @param itemSource
|
||||||
|
* @returns {OC.Share.Types.ShareInfo}
|
||||||
|
*/
|
||||||
loadItem:function(itemType, itemSource) {
|
loadItem:function(itemType, itemSource) {
|
||||||
var data = '';
|
var data = '';
|
||||||
var checkReshare = true;
|
var checkReshare = true;
|
||||||
|
@ -371,6 +377,21 @@ OC.Share={
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showDropDown:function(itemType, itemSource, appendTo, link, possiblePermissions, filename) {
|
showDropDown:function(itemType, itemSource, appendTo, link, possiblePermissions, filename) {
|
||||||
|
var itemModel = new OC.Share.ShareItemModel(itemType, itemSource);
|
||||||
|
var dialogView = new OC.Share.ShareDialogView('dropdown');
|
||||||
|
dialogView.setContainerClasses('drop shareDropDown');
|
||||||
|
dialogView.setShowLink(link);
|
||||||
|
dialogView.setPossiblePermissions(possiblePermissions);
|
||||||
|
dialogView.setItemModel(itemModel);
|
||||||
|
var $dialog = dialogView.render();
|
||||||
|
$dialog.appendTo(appendTo);
|
||||||
|
$dialog.attr('data-item-source-name', filename);
|
||||||
|
$dialog.slideDown(OC.menuSpeed, function() {
|
||||||
|
OC.Share.droppedDown = true;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
var data = OC.Share.loadItem(itemType, itemSource);
|
var data = OC.Share.loadItem(itemType, itemSource);
|
||||||
var dropDownEl;
|
var dropDownEl;
|
||||||
var html = '<div id="dropdown" class="drop shareDropDown" data-item-type="'+itemType+'" data-item-source="'+itemSource+'">';
|
var html = '<div id="dropdown" class="drop shareDropDown" data-item-type="'+itemType+'" data-item-source="'+itemSource+'">';
|
||||||
|
@ -897,7 +918,7 @@ OC.Share={
|
||||||
}
|
}
|
||||||
return expireDateString;
|
return expireDateString;
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3
|
||||||
|
* or later.
|
||||||
|
*
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
if(!OC.Share) {
|
||||||
|
OC.Share = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var TEMPLATE_BASE =
|
||||||
|
'<div id="{{containerID}}" {{{containerClasses}}}>' +
|
||||||
|
' {{{resharerInfo}}}' +
|
||||||
|
' <label for="shareWith" class="hidden-visually">{{shareLabel}}</label>' +
|
||||||
|
' <div class="oneline">' +
|
||||||
|
' <input id="shareWith" type="text" placeholder="{{sharePlaceholder}}" />' +
|
||||||
|
' <span class="shareWithLoading icon-loading-small hidden"></span>'+
|
||||||
|
' </div>' +
|
||||||
|
// FIXME: find a good position for remoteShareInfo
|
||||||
|
' {{{remoteShareInfo}}}' +
|
||||||
|
' <ul id="shareWithList">' +
|
||||||
|
' </ul>' +
|
||||||
|
' {{{linkShare}}}' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
var TEMPLATE_RESHARER_INFO =
|
||||||
|
'<span class="reshare">' +
|
||||||
|
' {{#if avatarEnabled}}' +
|
||||||
|
' <div class="avatar"></div>' +
|
||||||
|
' {{/if}}' +
|
||||||
|
' {{sharedByText}}' +
|
||||||
|
'</span><br />';
|
||||||
|
|
||||||
|
var TEMPLATE_REMOTE_SHARE_INFO =
|
||||||
|
'<a target="_blank" class="icon-info svg shareWithRemoteInfo" href="{{docLink}}" ' +
|
||||||
|
'title="{{tooltip}}"></a>';
|
||||||
|
|
||||||
|
var TEMPLATE_LINK_SHARE =
|
||||||
|
'<div id="link" class="linkShare">' +
|
||||||
|
' <span class="icon-loading-small hidden"></span>' +
|
||||||
|
' <input type="checkbox" name="linkCheckbox" id="linkCheckbox" value="1" /><label for="linkCheckbox">{{linkShareLabel}}</label>' +
|
||||||
|
' <br />' +
|
||||||
|
' <label for="linkText" class="hidden-visually">{{urlLabel}}</label>' +
|
||||||
|
' <input id="linkText" type="text" readonly="readonly" />' +
|
||||||
|
' <input type="checkbox" name="showPassword" id="showPassword" value="1" class="hidden" /><label for="showPassword" class="hidden-visually">{{enablePasswordLabel}}</label>' +
|
||||||
|
' <div id="linkPass">' +
|
||||||
|
' <label for="linkPassText" class="hidden-visually">{{passwordLabel}}</label>' +
|
||||||
|
' <input id="linkPassText" type="password" placeholder="passwordPlaceholder" />' +
|
||||||
|
' <span class="icon-loading-small hidden"></span>' +
|
||||||
|
' </div>'
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class OCA.Share.ShareDialogView
|
||||||
|
* @classdesc
|
||||||
|
*
|
||||||
|
* Represents the GUI of the share dialogue
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
var ShareDialogView = function(id) {
|
||||||
|
this.initialize(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof OCA.Sharing
|
||||||
|
*/
|
||||||
|
ShareDialogView.prototype = {
|
||||||
|
/** @member {OC.Share.ShareItemModel} **/
|
||||||
|
_itemModel: null,
|
||||||
|
|
||||||
|
/** @var {string} **/
|
||||||
|
_id: null,
|
||||||
|
|
||||||
|
/** @var {Object} **/
|
||||||
|
_templates: {},
|
||||||
|
|
||||||
|
/** @var {string} **/
|
||||||
|
_containerClasses: '',
|
||||||
|
|
||||||
|
/** @var {boolean} **/
|
||||||
|
_showLink: true,
|
||||||
|
|
||||||
|
/** @var {unknown} **/
|
||||||
|
_possiblePermissions: null,
|
||||||
|
|
||||||
|
initialize: function (id) {
|
||||||
|
this._id = id;
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
var baseTemplate = this._getTemplate('base', TEMPLATE_BASE);
|
||||||
|
|
||||||
|
var $dialog = $(baseTemplate({
|
||||||
|
containerID: this._id,
|
||||||
|
containerClasses: this._renderContainerClasses(),
|
||||||
|
shareLabel: t('core', 'Share'),
|
||||||
|
resharerInfo: this._renderResharerInfo(),
|
||||||
|
sharePlaceholder: this._renderSharePlaceholderPart(),
|
||||||
|
remoteShareInfo: this._renderRemoteShareInfoPart(),
|
||||||
|
linkShare: this._renderLinkSharePart()
|
||||||
|
}));
|
||||||
|
|
||||||
|
return $dialog;
|
||||||
|
},
|
||||||
|
|
||||||
|
setItemModel: function(model) {
|
||||||
|
if(model instanceof OC.Share.ShareItemModel) {
|
||||||
|
this._itemModel = model;
|
||||||
|
} else {
|
||||||
|
console.warn('model is not an instance of OC.Share.ShareItemModel');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the classes the main container should get additionally
|
||||||
|
* TODO:: figure out whether this is really necessary
|
||||||
|
*
|
||||||
|
* @param {string} classes whitespace seperated
|
||||||
|
*/
|
||||||
|
setContainerClasses: function(classes) {
|
||||||
|
this._containerClasses = classes;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets whether share by link should be displayed or not. Default is
|
||||||
|
* true.
|
||||||
|
*
|
||||||
|
* @param {bool} showLink
|
||||||
|
*/
|
||||||
|
setShowLink: function(showLink) {
|
||||||
|
this._showLink = (typeof showLink === 'boolean') ? showLink : true;
|
||||||
|
},
|
||||||
|
|
||||||
|
setPossiblePermissions: function(permissions) {
|
||||||
|
//TODO: maybe move to model? Whatever this is.
|
||||||
|
this._possiblePermissions = permissions;
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderResharerInfo: function() {
|
||||||
|
var resharerInfo = '';
|
||||||
|
if ( this._itemModel.hasReshare()
|
||||||
|
&& this._itemModel.getReshareOwner() !== OC.currentUser)
|
||||||
|
{
|
||||||
|
var reshareTemplate = this._getReshareTemplate();
|
||||||
|
var sharedByText = '';
|
||||||
|
if (this._itemModel.getReshareType() === OC.Share.SHARE_TYPE_GROUP) {
|
||||||
|
sharedByText = t(
|
||||||
|
'core',
|
||||||
|
'Shared with you and the group {group} by {owner}',
|
||||||
|
{
|
||||||
|
group: this._itemModel.getReshareWith(),
|
||||||
|
owner: this._itemModel.getReshareOwnerDisplayname()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sharedByText = t(
|
||||||
|
'core',
|
||||||
|
'Shared with you by {owner}',
|
||||||
|
{ owner: this._itemModel.getReshareOwnerDisplayname() }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
resharerInfo = reshareTemplate({
|
||||||
|
avatarEnabled: oc_config.enable_avatars === true,
|
||||||
|
sharedByText: sharedByText
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderContainerClasses: function() {
|
||||||
|
var classes = '';
|
||||||
|
if(this._containerClasses) {
|
||||||
|
classes = 'class="' + this._containerClasses + '"';
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderRemoteShareInfoPart: function() {
|
||||||
|
var remoteShareInfo = '';
|
||||||
|
if(oc_appconfig.core.remoteShareAllowed) {
|
||||||
|
var infoTemplate = this._getRemoteShareInfoTemplate();
|
||||||
|
remoteShareInfo = infoTemplate({
|
||||||
|
docLink: oc_appconfig.core.federatedCloudShareDoc,
|
||||||
|
tooltip: t('core', 'Share with people on other ownClouds using the syntax username@example.com/owncloud')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return remoteShareInfo;
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderLinkSharePart: function() {
|
||||||
|
var linkShare = '';
|
||||||
|
if(this._showLink && $('#allowShareWithLink').val() === 'yes') {
|
||||||
|
var linkShareTemplate = this._getLinkShareTemplate();
|
||||||
|
linkShare = linkShareTemplate({
|
||||||
|
linkShareLabel: t('core', 'Share link'),
|
||||||
|
urlLabel: t('core', 'Link'),
|
||||||
|
enablePasswordLabel: t('core', 'Password protect'),
|
||||||
|
passwordLabel: t('core', 'Password'),
|
||||||
|
passwordPlaceholder: t('core', 'Choose a password for the public link')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return linkShare;
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderSharePlaceholderPart: function () {
|
||||||
|
var sharePlaceholder = t('core', 'Share with users or groups …');
|
||||||
|
if (oc_appconfig.core.remoteShareAllowed) {
|
||||||
|
sharePlaceholder = t('core', 'Share with users, groups or remote users …');
|
||||||
|
}
|
||||||
|
return sharePlaceholder;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getTemplate: function (key, template) {
|
||||||
|
if (!this._templates[key]) {
|
||||||
|
this._templates[key] = Handlebars.compile(template);
|
||||||
|
}
|
||||||
|
return this._templates[key];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the info template for remote sharing
|
||||||
|
*
|
||||||
|
* @returns {Handlebars}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_getRemoteShareInfoTemplate: function() {
|
||||||
|
return this._getTemplate('remoteShareInfo', TEMPLATE_REMOTE_SHARE_INFO);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the info template for link sharing
|
||||||
|
*
|
||||||
|
* @returns {Handlebars}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_getLinkShareTemplate: function() {
|
||||||
|
return this._getTemplate('linkShare', TEMPLATE_LINK_SHARE);
|
||||||
|
},
|
||||||
|
|
||||||
|
_getReshareTemplate: function() {
|
||||||
|
return this._getTemplate('reshare', TEMPLATE_RESHARER_INFO);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
OC.Share.ShareDialogView = ShareDialogView;
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3
|
||||||
|
* or later.
|
||||||
|
*
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
if(!OC.Share) {
|
||||||
|
OC.Share = {};
|
||||||
|
OC.Share.Types = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} OC.Share.Types.Reshare
|
||||||
|
* @property {string} uid_owner
|
||||||
|
* @property {number} share_type
|
||||||
|
* @property {string} share_with
|
||||||
|
* @property {string} displayname_owner
|
||||||
|
* @property {number} permissions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} OC.Share.Types.ShareInfo
|
||||||
|
* @property {number} share_type
|
||||||
|
* @property {number} permissions
|
||||||
|
* @property {number} file_source optional
|
||||||
|
* @property {number} item_source
|
||||||
|
* @property {string} token
|
||||||
|
* @property {string} share_with
|
||||||
|
* @property {string} share_with_displayname
|
||||||
|
* @property {string} share_mail_send
|
||||||
|
* @property {bool} collection //TODO: verify
|
||||||
|
* @property {Date} expiration optional?
|
||||||
|
* @property {number} stime optional?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} OC.Share.Types.ShareItemInfo
|
||||||
|
* @property {OC.Share.Types.Reshare} reshare
|
||||||
|
* @property {OC.Share.Types.ShareInfo[]} shares
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class OCA.Share.ShareItemModel
|
||||||
|
* @classdesc
|
||||||
|
*
|
||||||
|
* Represents the GUI of the share dialogue
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
var ShareItemModel = function(itemType, itemSource) {
|
||||||
|
this.initialize(itemType, itemSource);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof OCA.Sharing
|
||||||
|
*/
|
||||||
|
ShareItemModel.prototype = {
|
||||||
|
/** @var {string} **/
|
||||||
|
_itemType: null,
|
||||||
|
/** @var {mixed} **/ //TODO: what type?
|
||||||
|
_itemSource: null,
|
||||||
|
|
||||||
|
/** @var {OC.Share.Types.Reshare} **/
|
||||||
|
_reshare: null,
|
||||||
|
|
||||||
|
/** @var {OC.Share.Types.ShareInfo[]} **/
|
||||||
|
_shares: null,
|
||||||
|
|
||||||
|
initialize: function(itemType, itemSource) {
|
||||||
|
this._itemType = itemType;
|
||||||
|
this._itemSource = itemSource;
|
||||||
|
this._retrieveData();
|
||||||
|
},
|
||||||
|
|
||||||
|
hasReshare: function() {
|
||||||
|
return _.isObject(this._reshare) && !_.isUndefined(this._reshare.uid_owner);
|
||||||
|
},
|
||||||
|
|
||||||
|
getReshareOwner: function() {
|
||||||
|
return this._reshare.uid_owner;
|
||||||
|
},
|
||||||
|
|
||||||
|
getReshareOwnerDisplayname: function() {
|
||||||
|
return this._reshare.displayname_owner;
|
||||||
|
},
|
||||||
|
|
||||||
|
getReshareWith: function() {
|
||||||
|
return this._reshare.share_with;
|
||||||
|
},
|
||||||
|
|
||||||
|
getReshareType: function() {
|
||||||
|
return this._reshare.share_type;
|
||||||
|
},
|
||||||
|
|
||||||
|
_retrieveData: function() {
|
||||||
|
/** var {OC.Share.Types.ShareItemInfo} **/
|
||||||
|
var data = OC.Share.loadItem(this._itemType, this._itemSource);
|
||||||
|
if(data === false) {
|
||||||
|
console.warn('no data was returned');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._reshare = data.reshare;
|
||||||
|
this._shares = data.shares;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OC.Share.ShareItemModel = ShareItemModel;
|
||||||
|
})();
|
|
@ -83,6 +83,8 @@ class Share extends Constants {
|
||||||
'supportedFileExtensions' => $supportedFileExtensions
|
'supportedFileExtensions' => $supportedFileExtensions
|
||||||
);
|
);
|
||||||
if(count(self::$backendTypes) === 1) {
|
if(count(self::$backendTypes) === 1) {
|
||||||
|
\OC_Util::addScript('core', 'shareitemmodel');
|
||||||
|
\OC_Util::addScript('core', 'sharedialogview');
|
||||||
\OC_Util::addScript('core', 'share');
|
\OC_Util::addScript('core', 'share');
|
||||||
\OC_Util::addStyle('core', 'share');
|
\OC_Util::addStyle('core', 'share');
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue