diff options
author | Arthur Schiwon <blizzz@owncloud.com> | 2015-07-31 00:07:41 +0200 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2015-09-16 07:23:25 +0200 |
commit | edd163a6113664921a2fda730037dcf68bfe08ae (patch) | |
tree | 2e5b7b0911e121c5e2b019259d3a0247c31ee1c9 | |
parent | 2fc19635f6a98c0acbd223b3f9d0028ff2755585 (diff) | |
download | nextcloud-server-edd163a6113664921a2fda730037dcf68bfe08ae.tar.gz nextcloud-server-edd163a6113664921a2fda730037dcf68bfe08ae.zip |
refactor share dialog for multi-purpose use (dropdown, sidebar) and better maintainability
-rw-r--r-- | apps/files_sharing/appinfo/app.php | 3 | ||||
-rw-r--r-- | apps/files_sharing/css/sharetabview.css | 69 | ||||
-rw-r--r-- | core/js/share.js | 25 | ||||
-rw-r--r-- | core/js/sharedialogview.js | 253 | ||||
-rw-r--r-- | core/js/shareitemmodel.js | 113 | ||||
-rw-r--r-- | lib/private/share/share.php | 2 |
6 files changed, 462 insertions, 3 deletions
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 20f1b046d35..3049dc6a263 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -55,8 +55,9 @@ $application->setupPropagation(); \OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file'); \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( diff --git a/apps/files_sharing/css/sharetabview.css b/apps/files_sharing/css/sharetabview.css index 42c9bee7173..8b9af852531 100644 --- a/apps/files_sharing/css/sharetabview.css +++ b/apps/files_sharing/css/sharetabview.css @@ -1,3 +1,72 @@ .app-files .shareTabView { 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; +} diff --git a/core/js/share.js b/core/js/share.js index cd4a614e9d1..5d3253e6d5c 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -3,7 +3,7 @@ /** * @namespace */ -OC.Share={ +OC.Share = _.extend(OC.Share, { SHARE_TYPE_USER:0, SHARE_TYPE_GROUP:1, SHARE_TYPE_LINK:3, @@ -289,6 +289,12 @@ OC.Share={ } img.attr('src', image); }, + /** + * + * @param itemType + * @param itemSource + * @returns {OC.Share.Types.ShareInfo} + */ loadItem:function(itemType, itemSource) { var data = ''; var checkReshare = true; @@ -371,6 +377,21 @@ OC.Share={ }); }, 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 dropDownEl; var html = '<div id="dropdown" class="drop shareDropDown" data-item-type="'+itemType+'" data-item-source="'+itemSource+'">'; @@ -897,7 +918,7 @@ OC.Share={ } return expireDateString; } -}; +}); $(document).ready(function() { diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js new file mode 100644 index 00000000000..cbab9694afe --- /dev/null +++ b/core/js/sharedialogview.js @@ -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; + +})(); diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js new file mode 100644 index 00000000000..1db49536db5 --- /dev/null +++ b/core/js/shareitemmodel.js @@ -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; +})(); diff --git a/lib/private/share/share.php b/lib/private/share/share.php index 6ad36d60fe8..65968f581f5 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -83,6 +83,8 @@ class Share extends Constants { 'supportedFileExtensions' => $supportedFileExtensions ); if(count(self::$backendTypes) === 1) { + \OC_Util::addScript('core', 'shareitemmodel'); + \OC_Util::addScript('core', 'sharedialogview'); \OC_Util::addScript('core', 'share'); \OC_Util::addStyle('core', 'share'); } |